Support transparent texture

Add alpha channel support for color texture. The transparency is supported in render preview, export texture preview and glTF exporter.
master
Jeremy Hu 2019-11-02 12:13:23 +09:30
parent 4bd14b935d
commit 1d3c4142d4
12 changed files with 100 additions and 32 deletions

View File

@ -787,6 +787,10 @@ Tips:
<source>Hollow</source> <source>Hollow</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Transparency</source>
<translation></translation>
</message>
</context> </context>
<context> <context>
<name>PoseEditWidget</name> <name>PoseEditWidget</name>

View File

@ -1,25 +1,27 @@
attribute vec4 vertex; attribute highp vec4 vertex;
attribute vec3 normal; attribute highp vec3 normal;
attribute vec3 color; attribute highp vec3 color;
attribute vec2 texCoord; attribute highp vec2 texCoord;
attribute float metalness; attribute highp float metalness;
attribute float roughness; attribute highp float roughness;
attribute vec3 tangent; attribute highp vec3 tangent;
varying vec3 vert; attribute highp float alpha;
varying vec3 vertRaw; varying highp vec3 vert;
varying vec3 vertNormal; varying highp vec3 vertRaw;
varying vec3 vertColor; varying highp vec3 vertNormal;
varying vec2 vertTexCoord; varying highp vec3 vertColor;
varying float vertMetalness; varying highp vec2 vertTexCoord;
varying float vertRoughness; varying highp float vertMetalness;
varying vec3 cameraPos; varying highp float vertRoughness;
varying vec3 firstLightPos; varying highp vec3 cameraPos;
varying vec3 secondLightPos; varying highp vec3 firstLightPos;
varying vec3 thirdLightPos; varying highp vec3 secondLightPos;
uniform mat4 projectionMatrix; varying highp vec3 thirdLightPos;
uniform mat4 modelMatrix; varying highp float vertAlpha;
uniform mat3 normalMatrix; uniform highp mat4 projectionMatrix;
uniform mat4 viewMatrix; uniform highp mat4 modelMatrix;
uniform highp mat3 normalMatrix;
uniform highp mat4 viewMatrix;
uniform highp int normalMapEnabled; uniform highp int normalMapEnabled;
mat3 transpose(mat3 m) mat3 transpose(mat3 m)
@ -35,6 +37,7 @@ void main()
vertRaw = vert; vertRaw = vert;
vertNormal = normalize((modelMatrix * vec4(normal, 1.0)).xyz); vertNormal = normalize((modelMatrix * vec4(normal, 1.0)).xyz);
vertColor = color; vertColor = color;
vertAlpha = alpha;
cameraPos = vec3(0, 0, -4.0); cameraPos = vec3(0, 0, -4.0);
firstLightPos = vec3(5.0, 5.0, 5.0); firstLightPos = vec3(5.0, 5.0, 5.0);

View File

@ -67,6 +67,7 @@ varying highp vec3 cameraPos;
varying highp vec3 firstLightPos; varying highp vec3 firstLightPos;
varying highp vec3 secondLightPos; varying highp vec3 secondLightPos;
varying highp vec3 thirdLightPos; varying highp vec3 thirdLightPos;
varying highp float vertAlpha;
uniform highp vec3 lightPos; uniform highp vec3 lightPos;
uniform highp sampler2D textureId; uniform highp sampler2D textureId;
uniform highp int textureEnabled; uniform highp int textureEnabled;
@ -280,7 +281,7 @@ highp vec4 metalRoughFunction(const in highp vec4 baseColor,
// Apply gamma correction prior to display // Apply gamma correction prior to display
highp vec3 cGamma = gammaCorrect(cToneMapped); highp vec3 cGamma = gammaCorrect(cToneMapped);
return vec4(cGamma, 1.0); return vec4(cGamma, baseColor.a);
} }
void main() void main()
@ -321,8 +322,11 @@ void main()
lights[2].quadraticAttenuation = 0.0; lights[2].quadraticAttenuation = 0.0;
highp vec3 color = vertColor; highp vec3 color = vertColor;
highp float alpha = vertAlpha;
if (textureEnabled == 1) { if (textureEnabled == 1) {
color = texture2D(textureId, vertTexCoord).rgb; highp vec4 textColor = texture2D(textureId, vertTexCoord);
color = textColor.rgb;
alpha = textColor.a;
} }
if (mousePickEnabled == 1) { if (mousePickEnabled == 1) {
if (distance(mousePickTargetPosition, vertRaw) <= mousePickRadius) { if (distance(mousePickTargetPosition, vertRaw) <= mousePickRadius) {
@ -358,7 +362,7 @@ void main()
roughness = min(0.99, roughness); roughness = min(0.99, roughness);
gl_FragColor = metalRoughFunction(vec4(color, 1.0), gl_FragColor = metalRoughFunction(vec4(color, alpha),
metalness, metalness,
roughness, roughness,
ambientOcclusion, ambientOcclusion,

View File

@ -1064,7 +1064,7 @@ void Document::toSnapshot(Snapshot *snapshot, const std::set<QUuid> &limitNodeId
} }
part["dirty"] = partIt.second.dirty ? "true" : "false"; part["dirty"] = partIt.second.dirty ? "true" : "false";
if (partIt.second.hasColor) if (partIt.second.hasColor)
part["color"] = partIt.second.color.name(); part["color"] = partIt.second.color.name(QColor::HexArgb);
if (partIt.second.colorSolubilityAdjusted()) if (partIt.second.colorSolubilityAdjusted())
part["colorSolubility"] = QString::number(partIt.second.colorSolubility); part["colorSolubility"] = QString::number(partIt.second.colorSolubility);
if (partIt.second.deformThicknessAdjusted()) if (partIt.second.deformThicknessAdjusted())

View File

@ -169,6 +169,7 @@ GlbFileWriter::GlbFileWriter(Outcome &outcome,
m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["baseColorTexture"]["index"] = textureIndex++; m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["baseColorTexture"]["index"] = textureIndex++;
m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["metallicFactor"] = MeshLoader::m_defaultMetalness; m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["metallicFactor"] = MeshLoader::m_defaultMetalness;
m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["roughnessFactor"] = MeshLoader::m_defaultRoughness; m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["roughnessFactor"] = MeshLoader::m_defaultRoughness;
m_json["materials"][primitiveIndex]["alphaMode"] = "BLEND";
if (normalImage) { if (normalImage) {
m_json["materials"][primitiveIndex]["normalTexture"]["index"] = textureIndex++; m_json["materials"][primitiveIndex]["normalTexture"]["index"] = textureIndex++;
} }

View File

@ -82,6 +82,7 @@ MeshLoader::MeshLoader(const std::vector<QVector3D> &vertices, const std::vector
dest->colorR = color.redF(); dest->colorR = color.redF();
dest->colorG = color.greenF(); dest->colorG = color.greenF();
dest->colorB = color.blueF(); dest->colorB = color.blueF();
dest->alpha = color.alphaF();
dest->posX = srcVert->x(); dest->posX = srcVert->x();
dest->posY = srcVert->y(); dest->posY = srcVert->y();
dest->posZ = srcVert->z(); dest->posZ = srcVert->z();
@ -138,6 +139,7 @@ MeshLoader::MeshLoader(Outcome &outcome) :
dest->colorR = triangleColor->redF(); dest->colorR = triangleColor->redF();
dest->colorG = triangleColor->greenF(); dest->colorG = triangleColor->greenF();
dest->colorB = triangleColor->blueF(); dest->colorB = triangleColor->blueF();
dest->alpha = triangleColor->alphaF();
dest->posX = srcVert->x(); dest->posX = srcVert->x();
dest->posY = srcVert->y(); dest->posY = srcVert->y();
dest->posZ = srcVert->z(); dest->posZ = srcVert->z();
@ -155,7 +157,6 @@ MeshLoader::MeshLoader(Outcome &outcome) :
} }
} }
// Uncomment out to show wireframes
size_t edgeCount = 0; size_t edgeCount = 0;
for (const auto &face: outcome.triangleAndQuads) { for (const auto &face: outcome.triangleAndQuads) {
edgeCount += face.size(); edgeCount += face.size();

View File

@ -118,6 +118,7 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
f->glEnableVertexAttribArray(4); f->glEnableVertexAttribArray(4);
f->glEnableVertexAttribArray(5); f->glEnableVertexAttribArray(5);
f->glEnableVertexAttribArray(6); f->glEnableVertexAttribArray(6);
f->glEnableVertexAttribArray(7);
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), 0); f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), 0);
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(3 * sizeof(GLfloat))); f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(6 * sizeof(GLfloat))); f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(6 * sizeof(GLfloat)));
@ -125,6 +126,7 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(11 * sizeof(GLfloat))); f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(11 * sizeof(GLfloat)));
f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(12 * sizeof(GLfloat))); f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(12 * sizeof(GLfloat)));
f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(13 * sizeof(GLfloat))); f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(13 * sizeof(GLfloat)));
f->glVertexAttribPointer(7, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(16 * sizeof(GLfloat)));
m_vboTriangle.release(); m_vboTriangle.release();
} }
{ {
@ -143,6 +145,7 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
f->glEnableVertexAttribArray(4); f->glEnableVertexAttribArray(4);
f->glEnableVertexAttribArray(5); f->glEnableVertexAttribArray(5);
f->glEnableVertexAttribArray(6); f->glEnableVertexAttribArray(6);
f->glEnableVertexAttribArray(7);
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), 0); f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), 0);
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(3 * sizeof(GLfloat))); f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(6 * sizeof(GLfloat))); f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(6 * sizeof(GLfloat)));
@ -150,6 +153,7 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(11 * sizeof(GLfloat))); f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(11 * sizeof(GLfloat)));
f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(12 * sizeof(GLfloat))); f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(12 * sizeof(GLfloat)));
f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(13 * sizeof(GLfloat))); f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(13 * sizeof(GLfloat)));
f->glVertexAttribPointer(7, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(16 * sizeof(GLfloat)));
m_vboEdge.release(); m_vboEdge.release();
} }
if (m_toolEnabled) { if (m_toolEnabled) {
@ -168,6 +172,7 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
f->glEnableVertexAttribArray(4); f->glEnableVertexAttribArray(4);
f->glEnableVertexAttribArray(5); f->glEnableVertexAttribArray(5);
f->glEnableVertexAttribArray(6); f->glEnableVertexAttribArray(6);
f->glEnableVertexAttribArray(7);
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), 0); f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), 0);
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(3 * sizeof(GLfloat))); f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(6 * sizeof(GLfloat))); f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(6 * sizeof(GLfloat)));
@ -175,6 +180,7 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(11 * sizeof(GLfloat))); f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(11 * sizeof(GLfloat)));
f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(12 * sizeof(GLfloat))); f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(12 * sizeof(GLfloat)));
f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(13 * sizeof(GLfloat))); f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(13 * sizeof(GLfloat)));
f->glVertexAttribPointer(7, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(16 * sizeof(GLfloat)));
m_vboTool.release(); m_vboTool.release();
} else { } else {
m_renderToolVertexCount = 0; m_renderToolVertexCount = 0;

View File

@ -37,6 +37,7 @@ ModelShaderProgram::ModelShaderProgram(bool usePBR)
this->bindAttributeLocation("metalness", 4); this->bindAttributeLocation("metalness", 4);
this->bindAttributeLocation("roughness", 5); this->bindAttributeLocation("roughness", 5);
this->bindAttributeLocation("tangent", 6); this->bindAttributeLocation("tangent", 6);
this->bindAttributeLocation("alpha", 7);
this->link(); this->link();
this->bind(); this->bind();

View File

@ -146,6 +146,8 @@ void ModelWidget::initializeGL()
void ModelWidget::paintGL() void ModelWidget::paintGL()
{ {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 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_DEPTH_TEST);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
#ifdef GL_LINE_SMOOTH #ifdef GL_LINE_SMOOTH

View File

@ -376,11 +376,44 @@ void PartWidget::showColorSettingPopup(const QPoint &pos)
QColor color = QColorDialog::getColor(part->color, this); QColor color = QColorDialog::getColor(part->color, this);
emit enableBackgroundBlur(); emit enableBackgroundBlur();
if (color.isValid()) { 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 setPartColorState(m_partId, true, color);
emit groupOperationAdded(); 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; FloatNumberWidget *colorSolubilityWidget = new FloatNumberWidget;
colorSolubilityWidget->setItemName(tr("Solubility")); colorSolubilityWidget->setItemName(tr("Solubility"));
colorSolubilityWidget->setRange(0.0, 1.0); colorSolubilityWidget->setRange(0.0, 1.0);
@ -405,6 +438,7 @@ void PartWidget::showColorSettingPopup(const QPoint &pos)
QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(colorLayout); mainLayout->addLayout(colorLayout);
mainLayout->addLayout(colorTransparencyLayout);
mainLayout->addLayout(colorSolubilityLayout); mainLayout->addLayout(colorSolubilityLayout);
if (m_document->materialIdList.empty()) { if (m_document->materialIdList.empty()) {

View File

@ -22,6 +22,7 @@ typedef struct
GLfloat tangentX; GLfloat tangentX;
GLfloat tangentY; GLfloat tangentY;
GLfloat tangentZ; GLfloat tangentZ;
GLfloat alpha = 1.0;
} ShaderVertex; } ShaderVertex;
#pragma pack(pop) #pragma pack(pop)

View File

@ -11,7 +11,7 @@
#include "material.h" #include "material.h"
int TextureGenerator::m_textureSize = 1024; 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) : TextureGenerator::TextureGenerator(const Outcome &outcome, Snapshot *snapshot) :
m_resultTextureGuideImage(nullptr), m_resultTextureGuideImage(nullptr),
@ -540,11 +540,22 @@ void TextureGenerator::generate()
m_resultTextureImage = new QImage(*m_resultTextureColorImage); m_resultTextureImage = new QImage(*m_resultTextureColorImage);
QImage uvCheckImage(":/resources/checkuv.png");
m_resultTextureGuideImage = new QImage(*m_resultTextureImage); m_resultTextureGuideImage = new QImage(*m_resultTextureImage);
{
QPainter mergeTextureGuidePainter(m_resultTextureGuideImage);
mergeTextureGuidePainter.setCompositionMode(QPainter::CompositionMode_DestinationOver);
mergeTextureGuidePainter.drawImage(0, 0, uvCheckImage);
mergeTextureGuidePainter.end();
}
{
QPainter mergeTextureGuidePainter(m_resultTextureGuideImage); QPainter mergeTextureGuidePainter(m_resultTextureGuideImage);
mergeTextureGuidePainter.setCompositionMode(QPainter::CompositionMode_Multiply); mergeTextureGuidePainter.setCompositionMode(QPainter::CompositionMode_Multiply);
mergeTextureGuidePainter.drawImage(0, 0, *m_resultTextureBorderImage); mergeTextureGuidePainter.drawImage(0, 0, *m_resultTextureBorderImage);
mergeTextureGuidePainter.end(); mergeTextureGuidePainter.end();
}
auto createResultBeginTime = countTimeConsumed.elapsed(); auto createResultBeginTime = countTimeConsumed.elapsed();
m_resultMesh = new MeshLoader(*m_outcome); m_resultMesh = new MeshLoader(*m_outcome);