diff --git a/languages/dust3d_zh_CN.ts b/languages/dust3d_zh_CN.ts index 9543f7e5..3d4309c9 100644 --- a/languages/dust3d_zh_CN.ts +++ b/languages/dust3d_zh_CN.ts @@ -787,6 +787,10 @@ Tips: Hollow 空心 + + Transparency + 透明度 + PoseEditWidget diff --git a/shaders/default.vert b/shaders/default.vert index 2c3a575e..f0ccbf7c 100644 --- a/shaders/default.vert +++ b/shaders/default.vert @@ -1,25 +1,27 @@ -attribute vec4 vertex; -attribute vec3 normal; -attribute vec3 color; -attribute vec2 texCoord; -attribute float metalness; -attribute float roughness; -attribute vec3 tangent; -varying vec3 vert; -varying vec3 vertRaw; -varying vec3 vertNormal; -varying vec3 vertColor; -varying vec2 vertTexCoord; -varying float vertMetalness; -varying float vertRoughness; -varying vec3 cameraPos; -varying vec3 firstLightPos; -varying vec3 secondLightPos; -varying vec3 thirdLightPos; -uniform mat4 projectionMatrix; -uniform mat4 modelMatrix; -uniform mat3 normalMatrix; -uniform mat4 viewMatrix; +attribute highp vec4 vertex; +attribute highp vec3 normal; +attribute highp vec3 color; +attribute highp vec2 texCoord; +attribute highp float metalness; +attribute highp float roughness; +attribute highp vec3 tangent; +attribute highp float alpha; +varying highp vec3 vert; +varying highp vec3 vertRaw; +varying highp vec3 vertNormal; +varying highp vec3 vertColor; +varying highp vec2 vertTexCoord; +varying highp float vertMetalness; +varying highp float vertRoughness; +varying highp vec3 cameraPos; +varying highp vec3 firstLightPos; +varying highp vec3 secondLightPos; +varying highp vec3 thirdLightPos; +varying highp float vertAlpha; +uniform highp mat4 projectionMatrix; +uniform highp mat4 modelMatrix; +uniform highp mat3 normalMatrix; +uniform highp mat4 viewMatrix; uniform highp int normalMapEnabled; mat3 transpose(mat3 m) @@ -35,6 +37,7 @@ void main() vertRaw = vert; vertNormal = normalize((modelMatrix * vec4(normal, 1.0)).xyz); vertColor = color; + vertAlpha = alpha; cameraPos = vec3(0, 0, -4.0); firstLightPos = vec3(5.0, 5.0, 5.0); diff --git a/shaders/pbr-qt.frag b/shaders/pbr-qt.frag index d85877f9..773b1291 100644 --- a/shaders/pbr-qt.frag +++ b/shaders/pbr-qt.frag @@ -67,6 +67,7 @@ varying highp vec3 cameraPos; varying highp vec3 firstLightPos; varying highp vec3 secondLightPos; varying highp vec3 thirdLightPos; +varying highp float vertAlpha; uniform highp vec3 lightPos; uniform highp sampler2D textureId; uniform highp int textureEnabled; @@ -280,7 +281,7 @@ highp vec4 metalRoughFunction(const in highp vec4 baseColor, // Apply gamma correction prior to display highp vec3 cGamma = gammaCorrect(cToneMapped); - return vec4(cGamma, 1.0); + return vec4(cGamma, baseColor.a); } void main() @@ -321,8 +322,11 @@ void main() lights[2].quadraticAttenuation = 0.0; highp vec3 color = vertColor; + highp float alpha = vertAlpha; if (textureEnabled == 1) { - color = texture2D(textureId, vertTexCoord).rgb; + highp vec4 textColor = texture2D(textureId, vertTexCoord); + color = textColor.rgb; + alpha = textColor.a; } if (mousePickEnabled == 1) { if (distance(mousePickTargetPosition, vertRaw) <= mousePickRadius) { @@ -358,7 +362,7 @@ void main() roughness = min(0.99, roughness); - gl_FragColor = metalRoughFunction(vec4(color, 1.0), + gl_FragColor = metalRoughFunction(vec4(color, alpha), metalness, roughness, ambientOcclusion, diff --git a/src/document.cpp b/src/document.cpp index b8d9ae31..a2328ec2 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1064,7 +1064,7 @@ void Document::toSnapshot(Snapshot *snapshot, const std::set &limitNodeId } part["dirty"] = partIt.second.dirty ? "true" : "false"; if (partIt.second.hasColor) - part["color"] = partIt.second.color.name(); + part["color"] = partIt.second.color.name(QColor::HexArgb); if (partIt.second.colorSolubilityAdjusted()) part["colorSolubility"] = QString::number(partIt.second.colorSolubility); if (partIt.second.deformThicknessAdjusted()) diff --git a/src/glbfile.cpp b/src/glbfile.cpp index 016ff485..8c4616ae 100644 --- a/src/glbfile.cpp +++ b/src/glbfile.cpp @@ -169,6 +169,7 @@ GlbFileWriter::GlbFileWriter(Outcome &outcome, m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["baseColorTexture"]["index"] = textureIndex++; m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["metallicFactor"] = MeshLoader::m_defaultMetalness; m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["roughnessFactor"] = MeshLoader::m_defaultRoughness; + m_json["materials"][primitiveIndex]["alphaMode"] = "BLEND"; if (normalImage) { m_json["materials"][primitiveIndex]["normalTexture"]["index"] = textureIndex++; } diff --git a/src/meshloader.cpp b/src/meshloader.cpp index 6ef87d4e..f1c45ee2 100644 --- a/src/meshloader.cpp +++ b/src/meshloader.cpp @@ -82,6 +82,7 @@ MeshLoader::MeshLoader(const std::vector &vertices, const std::vector dest->colorR = color.redF(); dest->colorG = color.greenF(); dest->colorB = color.blueF(); + dest->alpha = color.alphaF(); dest->posX = srcVert->x(); dest->posY = srcVert->y(); dest->posZ = srcVert->z(); @@ -138,6 +139,7 @@ MeshLoader::MeshLoader(Outcome &outcome) : dest->colorR = triangleColor->redF(); dest->colorG = triangleColor->greenF(); dest->colorB = triangleColor->blueF(); + dest->alpha = triangleColor->alphaF(); dest->posX = srcVert->x(); dest->posY = srcVert->y(); dest->posZ = srcVert->z(); @@ -155,7 +157,6 @@ MeshLoader::MeshLoader(Outcome &outcome) : } } - // Uncomment out to show wireframes size_t edgeCount = 0; for (const auto &face: outcome.triangleAndQuads) { edgeCount += face.size(); diff --git a/src/modelmeshbinder.cpp b/src/modelmeshbinder.cpp index 061f41b3..2564af45 100644 --- a/src/modelmeshbinder.cpp +++ b/src/modelmeshbinder.cpp @@ -118,6 +118,7 @@ void ModelMeshBinder::paint(ModelShaderProgram *program) f->glEnableVertexAttribArray(4); f->glEnableVertexAttribArray(5); f->glEnableVertexAttribArray(6); + f->glEnableVertexAttribArray(7); f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), 0); f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(3 * sizeof(GLfloat))); f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(6 * sizeof(GLfloat))); @@ -125,6 +126,7 @@ void ModelMeshBinder::paint(ModelShaderProgram *program) f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(11 * sizeof(GLfloat))); f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(12 * sizeof(GLfloat))); f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(13 * sizeof(GLfloat))); + f->glVertexAttribPointer(7, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(16 * sizeof(GLfloat))); m_vboTriangle.release(); } { @@ -143,6 +145,7 @@ void ModelMeshBinder::paint(ModelShaderProgram *program) f->glEnableVertexAttribArray(4); f->glEnableVertexAttribArray(5); f->glEnableVertexAttribArray(6); + f->glEnableVertexAttribArray(7); f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), 0); f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(3 * sizeof(GLfloat))); f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(6 * sizeof(GLfloat))); @@ -150,6 +153,7 @@ void ModelMeshBinder::paint(ModelShaderProgram *program) f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(11 * sizeof(GLfloat))); f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(12 * sizeof(GLfloat))); f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(13 * sizeof(GLfloat))); + f->glVertexAttribPointer(7, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(16 * sizeof(GLfloat))); m_vboEdge.release(); } if (m_toolEnabled) { @@ -168,6 +172,7 @@ void ModelMeshBinder::paint(ModelShaderProgram *program) f->glEnableVertexAttribArray(4); f->glEnableVertexAttribArray(5); f->glEnableVertexAttribArray(6); + f->glEnableVertexAttribArray(7); f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), 0); f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(3 * sizeof(GLfloat))); f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(6 * sizeof(GLfloat))); @@ -175,6 +180,7 @@ void ModelMeshBinder::paint(ModelShaderProgram *program) f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(11 * sizeof(GLfloat))); f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(12 * sizeof(GLfloat))); f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(13 * sizeof(GLfloat))); + f->glVertexAttribPointer(7, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast(16 * sizeof(GLfloat))); m_vboTool.release(); } else { m_renderToolVertexCount = 0; diff --git a/src/modelshaderprogram.cpp b/src/modelshaderprogram.cpp index 1f3f80f2..fdde882d 100644 --- a/src/modelshaderprogram.cpp +++ b/src/modelshaderprogram.cpp @@ -37,6 +37,7 @@ ModelShaderProgram::ModelShaderProgram(bool usePBR) this->bindAttributeLocation("metalness", 4); this->bindAttributeLocation("roughness", 5); this->bindAttributeLocation("tangent", 6); + this->bindAttributeLocation("alpha", 7); this->link(); this->bind(); diff --git a/src/modelwidget.cpp b/src/modelwidget.cpp index 64fb4175..e1d47f9b 100644 --- a/src/modelwidget.cpp +++ b/src/modelwidget.cpp @@ -146,6 +146,8 @@ void ModelWidget::initializeGL() void ModelWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); #ifdef GL_LINE_SMOOTH diff --git a/src/partwidget.cpp b/src/partwidget.cpp index 7432402c..2d63773b 100644 --- a/src/partwidget.cpp +++ b/src/partwidget.cpp @@ -376,11 +376,44 @@ void PartWidget::showColorSettingPopup(const QPoint &pos) QColor color = QColorDialog::getColor(part->color, this); emit enableBackgroundBlur(); if (color.isValid()) { + const SkeletonPart *part = m_document->findPart(m_partId); + if (nullptr == part) { + return; + } + color.setAlphaF(part->color.alphaF()); emit setPartColorState(m_partId, true, color); emit groupOperationAdded(); } }); + FloatNumberWidget *colorTransparencyWidget = new FloatNumberWidget; + colorTransparencyWidget->setItemName(tr("Transparency")); + colorTransparencyWidget->setRange(0.0, 1.0); + colorTransparencyWidget->setValue(1.0 - part->color.alphaF()); + + connect(colorTransparencyWidget, &FloatNumberWidget::valueChanged, [=](float value) { + const SkeletonPart *part = m_document->findPart(m_partId); + if (nullptr == part) { + return; + } + QColor color = part->color; + color.setAlphaF(1.0 - value); + emit setPartColorState(m_partId, true, color); + emit groupOperationAdded(); + }); + + QPushButton *colorTransparencyEraser = new QPushButton(QChar(fa::eraser)); + initToolButton(colorTransparencyEraser); + + connect(colorTransparencyEraser, &QPushButton::clicked, [=]() { + colorTransparencyWidget->setValue(0.0); + emit groupOperationAdded(); + }); + + QHBoxLayout *colorTransparencyLayout = new QHBoxLayout; + colorTransparencyLayout->addWidget(colorTransparencyEraser); + colorTransparencyLayout->addWidget(colorTransparencyWidget); + FloatNumberWidget *colorSolubilityWidget = new FloatNumberWidget; colorSolubilityWidget->setItemName(tr("Solubility")); colorSolubilityWidget->setRange(0.0, 1.0); @@ -405,6 +438,7 @@ void PartWidget::showColorSettingPopup(const QPoint &pos) QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addLayout(colorLayout); + mainLayout->addLayout(colorTransparencyLayout); mainLayout->addLayout(colorSolubilityLayout); if (m_document->materialIdList.empty()) { diff --git a/src/shadervertex.h b/src/shadervertex.h index e3cbd7b4..c6bd976d 100644 --- a/src/shadervertex.h +++ b/src/shadervertex.h @@ -22,6 +22,7 @@ typedef struct GLfloat tangentX; GLfloat tangentY; GLfloat tangentZ; + GLfloat alpha = 1.0; } ShaderVertex; #pragma pack(pop) diff --git a/src/texturegenerator.cpp b/src/texturegenerator.cpp index 86917b0c..666c1004 100644 --- a/src/texturegenerator.cpp +++ b/src/texturegenerator.cpp @@ -11,7 +11,7 @@ #include "material.h" int TextureGenerator::m_textureSize = 1024; -QColor TextureGenerator::m_defaultTextureColor = Qt::white; //Qt::darkGray; +QColor TextureGenerator::m_defaultTextureColor = Qt::transparent; //Qt::darkGray; TextureGenerator::TextureGenerator(const Outcome &outcome, Snapshot *snapshot) : m_resultTextureGuideImage(nullptr), @@ -540,11 +540,22 @@ void TextureGenerator::generate() m_resultTextureImage = new QImage(*m_resultTextureColorImage); + QImage uvCheckImage(":/resources/checkuv.png"); + m_resultTextureGuideImage = new QImage(*m_resultTextureImage); - QPainter mergeTextureGuidePainter(m_resultTextureGuideImage); - mergeTextureGuidePainter.setCompositionMode(QPainter::CompositionMode_Multiply); - mergeTextureGuidePainter.drawImage(0, 0, *m_resultTextureBorderImage); - mergeTextureGuidePainter.end(); + { + QPainter mergeTextureGuidePainter(m_resultTextureGuideImage); + mergeTextureGuidePainter.setCompositionMode(QPainter::CompositionMode_DestinationOver); + mergeTextureGuidePainter.drawImage(0, 0, uvCheckImage); + mergeTextureGuidePainter.end(); + } + + { + QPainter mergeTextureGuidePainter(m_resultTextureGuideImage); + mergeTextureGuidePainter.setCompositionMode(QPainter::CompositionMode_Multiply); + mergeTextureGuidePainter.drawImage(0, 0, *m_resultTextureBorderImage); + mergeTextureGuidePainter.end(); + } auto createResultBeginTime = countTimeConsumed.elapsed(); m_resultMesh = new MeshLoader(*m_outcome);