Add tong shader

master
huxingyi 2020-03-29 19:36:45 +09:30
parent ae478fc064
commit 120b59b45f
10 changed files with 143 additions and 28 deletions

View File

@ -548,6 +548,7 @@ https://www.reddit.com/r/gamedev/comments/5iuf3h/i_am_writting_a_3d_monster_mode
<h1>Sam Hocevar</h1> <h1>Sam Hocevar</h1>
<pre> <pre>
https://gamedev.stackexchange.com/questions/98246/quaternion-slerp-and-lerp-implementation-with-overshoot https://gamedev.stackexchange.com/questions/98246/quaternion-slerp-and-lerp-implementation-with-overshoot
http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
</pre> </pre>
<h1>David Rosen</h1> <h1>David Rosen</h1>

View File

@ -86,6 +86,7 @@ uniform samplerCube environmentIrradianceMapId;
uniform int environmentIrradianceMapEnabled; uniform int environmentIrradianceMapEnabled;
uniform samplerCube environmentSpecularMapId; uniform samplerCube environmentSpecularMapId;
uniform int environmentSpecularMapEnabled; uniform int environmentSpecularMapEnabled;
uniform int tongShadingEnabled;
const int MAX_LIGHTS = 8; const int MAX_LIGHTS = 8;
const int TYPE_POINT = 0; const int TYPE_POINT = 0;
@ -352,6 +353,25 @@ vec3 gammaCorrect(const in vec3 color)
return pow(color, vec3(1.0 / gamma)); return pow(color, vec3(1.0 / gamma));
} }
// http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
vec4 metalRoughFunction(const in vec4 baseColor, vec4 metalRoughFunction(const in vec4 baseColor,
const in float metalness, const in float metalness,
const in float roughness, const in float roughness,
@ -365,24 +385,35 @@ vec4 metalRoughFunction(const in vec4 baseColor,
// Remap roughness for a perceptually more linear correspondence // Remap roughness for a perceptually more linear correspondence
float alpha = remapRoughness(roughness); float alpha = remapRoughness(roughness);
if (environmentIrradianceMapEnabled == 1) { if (tongShadingEnabled != 1) {
cLinear += pbrIblModel(worldNormal, if (environmentIrradianceMapEnabled == 1) {
worldView, cLinear += pbrIblModel(worldNormal,
baseColor.rgb, worldView,
metalness, baseColor.rgb,
alpha, metalness,
ambientOcclusion); alpha,
} ambientOcclusion);
}
for (int i = 0; i < lightCount; ++i) {
cLinear += pbrModel(i, for (int i = 0; i < lightCount; ++i) {
worldPosition, cLinear += pbrModel(i,
worldNormal, worldPosition,
worldView, worldNormal,
baseColor.rgb, worldView,
metalness, baseColor.rgb,
alpha, metalness,
ambientOcclusion); alpha,
ambientOcclusion);
}
} else {
float intensity;
intensity = dot(vec3(1.0, 1.0, 1.0), worldNormal);
vec3 hsv = rgb2hsv(baseColor.rgb);
if (intensity > 0.966)
cLinear = hsv2rgb(vec3(hsv.r, hsv.g, hsv.b * 2.0));
else
cLinear = hsv2rgb(vec3(hsv.r, hsv.g, hsv.b * 0.1));
} }
// Apply exposure correction // Apply exposure correction

View File

@ -80,6 +80,7 @@ uniform int ambientOcclusionMapEnabled;
uniform int mousePickEnabled; uniform int mousePickEnabled;
uniform vec3 mousePickTargetPosition; uniform vec3 mousePickTargetPosition;
uniform float mousePickRadius; uniform float mousePickRadius;
uniform int tongShadingEnabled;
const int MAX_LIGHTS = 8; const int MAX_LIGHTS = 8;
const int TYPE_POINT = 0; const int TYPE_POINT = 0;
@ -248,6 +249,25 @@ vec3 gammaCorrect(const in vec3 color)
return pow(color, vec3(1.0 / gamma)); return pow(color, vec3(1.0 / gamma));
} }
// http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
vec4 metalRoughFunction(const in vec4 baseColor, vec4 metalRoughFunction(const in vec4 baseColor,
const in float metalness, const in float metalness,
const in float roughness, const in float roughness,
@ -260,16 +280,27 @@ vec4 metalRoughFunction(const in vec4 baseColor,
// Remap roughness for a perceptually more linear correspondence // Remap roughness for a perceptually more linear correspondence
float alpha = remapRoughness(roughness); float alpha = remapRoughness(roughness);
for (int i = 0; i < lightCount; ++i) { if (tongShadingEnabled != 1) {
cLinear += pbrModel(i, for (int i = 0; i < lightCount; ++i) {
worldPosition, cLinear += pbrModel(i,
worldNormal, worldPosition,
worldView, worldNormal,
baseColor.rgb, worldView,
metalness, baseColor.rgb,
alpha, metalness,
ambientOcclusion); alpha,
ambientOcclusion);
}
} else {
float intensity;
intensity = dot(vec3(1.0, 1.0, 1.0), worldNormal);
vec3 hsv = rgb2hsv(baseColor.rgb);
if (intensity > 0.966)
cLinear = hsv2rgb(vec3(hsv.r, hsv.g, hsv.b * 2.0));
else
cLinear = hsv2rgb(vec3(hsv.r, hsv.g, hsv.b * 0.1));
} }
// Apply exposure correction // Apply exposure correction

View File

@ -58,6 +58,7 @@ ModelShaderProgram::ModelShaderProgram(bool isCoreProfile)
m_mousePickEnabledLoc = this->uniformLocation("mousePickEnabled"); m_mousePickEnabledLoc = this->uniformLocation("mousePickEnabled");
m_mousePickTargetPositionLoc = this->uniformLocation("mousePickTargetPosition"); m_mousePickTargetPositionLoc = this->uniformLocation("mousePickTargetPosition");
m_mousePickRadiusLoc = this->uniformLocation("mousePickRadius"); m_mousePickRadiusLoc = this->uniformLocation("mousePickRadius");
m_tongShadingEnabledLoc = this->uniformLocation("tongShadingEnabled");
if (m_isCoreProfile) { if (m_isCoreProfile) {
m_environmentIrradianceMapIdLoc = this->uniformLocation("environmentIrradianceMapId"); m_environmentIrradianceMapIdLoc = this->uniformLocation("environmentIrradianceMapId");
m_environmentIrradianceMapEnabledLoc = this->uniformLocation("environmentIrradianceMapEnabled"); m_environmentIrradianceMapEnabledLoc = this->uniformLocation("environmentIrradianceMapEnabled");
@ -166,3 +167,7 @@ int ModelShaderProgram::environmentSpecularMapEnabledLoc()
return m_environmentSpecularMapEnabledLoc; return m_environmentSpecularMapEnabledLoc;
} }
int ModelShaderProgram::tongShadingEnabledLoc()
{
return m_tongShadingEnabledLoc;
}

View File

@ -27,6 +27,7 @@ public:
int environmentIrradianceMapEnabledLoc(); int environmentIrradianceMapEnabledLoc();
int environmentSpecularMapIdLoc(); int environmentSpecularMapIdLoc();
int environmentSpecularMapEnabledLoc(); int environmentSpecularMapEnabledLoc();
int tongShadingEnabledLoc();
bool isCoreProfile(); bool isCoreProfile();
static const QString &loadShaderSource(const QString &name); static const QString &loadShaderSource(const QString &name);
private: private:
@ -51,6 +52,7 @@ private:
int m_environmentIrradianceMapEnabledLoc = 0; int m_environmentIrradianceMapEnabledLoc = 0;
int m_environmentSpecularMapIdLoc = 0; int m_environmentSpecularMapIdLoc = 0;
int m_environmentSpecularMapEnabledLoc = 0; int m_environmentSpecularMapEnabledLoc = 0;
int m_tongShadingEnabledLoc = 0;
}; };
#endif #endif

View File

@ -7,6 +7,7 @@
#include <QSurfaceFormat> #include <QSurfaceFormat>
#include "modelwidget.h" #include "modelwidget.h"
#include "util.h" #include "util.h"
#include "preferences.h"
// Modifed from http://doc.qt.io/qt-5/qtopengl-hellogl2-glwidget-cpp.html // Modifed from http://doc.qt.io/qt-5/qtopengl-hellogl2-glwidget-cpp.html
@ -46,6 +47,13 @@ ModelWidget::ModelWidget(QWidget *parent) :
} }
setContextMenuPolicy(Qt::CustomContextMenu); setContextMenuPolicy(Qt::CustomContextMenu);
zoom(200); zoom(200);
connect(&Preferences::instance(), &Preferences::tongShadingChanged, this, &ModelWidget::reRender);
}
void ModelWidget::reRender()
{
update();
} }
int ModelWidget::xRot() int ModelWidget::xRot()
@ -173,6 +181,7 @@ void ModelWidget::paintGL()
m_world.rotate(m_zRot / 16.0f, 0, 0, 1); m_world.rotate(m_zRot / 16.0f, 0, 0, 1);
m_program->bind(); m_program->bind();
m_program->setUniformValue(m_program->tongShadingEnabledLoc(), Preferences::instance().tongShading() ? 1 : 0);
m_program->setUniformValue(m_program->projectionMatrixLoc(), m_projection); m_program->setUniformValue(m_program->projectionMatrixLoc(), m_projection);
m_program->setUniformValue(m_program->modelMatrixLoc(), m_world); m_program->setUniformValue(m_program->modelMatrixLoc(), m_world);
QMatrix3x3 normalMatrix = m_world.normalMatrix(); QMatrix3x3 normalMatrix = m_world.normalMatrix();

View File

@ -56,6 +56,7 @@ public slots:
void zoom(float delta); void zoom(float delta);
void setMousePickTargetPositionInModelSpace(QVector3D position); void setMousePickTargetPositionInModelSpace(QVector3D position);
void setMousePickRadius(float radius); void setMousePickRadius(float radius);
void reRender();
signals: signals:
void xRotationChanged(int angle); void xRotationChanged(int angle);
void yRotationChanged(int angle); void yRotationChanged(int angle);

View File

@ -15,6 +15,7 @@ void Preferences::loadDefault()
m_componentCombineMode = CombineMode::Normal; m_componentCombineMode = CombineMode::Normal;
m_partColor = Qt::white; m_partColor = Qt::white;
m_flatShading = true; m_flatShading = true;
m_tongShading = false;
m_textureSize = 1024; m_textureSize = 1024;
} }
@ -38,6 +39,13 @@ Preferences::Preferences()
else else
m_flatShading = isTrueValueString(value); m_flatShading = isTrueValueString(value);
} }
{
QString value = m_settings.value("tongShading").toString();
if (value.isEmpty())
m_tongShading = false;
else
m_tongShading = isTrueValueString(value);
}
{ {
QString value = m_settings.value("textureSize").toString(); QString value = m_settings.value("textureSize").toString();
if (!value.isEmpty()) if (!value.isEmpty())
@ -60,6 +68,11 @@ bool Preferences::flatShading() const
return m_flatShading; return m_flatShading;
} }
bool Preferences::tongShading() const
{
return m_tongShading;
}
int Preferences::textureSize() const int Preferences::textureSize() const
{ {
return m_textureSize; return m_textureSize;
@ -92,6 +105,15 @@ void Preferences::setFlatShading(bool flatShading)
emit flatShadingChanged(); emit flatShadingChanged();
} }
void Preferences::setTongShading(bool tongShading)
{
if (m_tongShading == tongShading)
return;
m_tongShading = tongShading;
m_settings.setValue("tongShading", tongShading ? "true" : "false");
emit tongShadingChanged();
}
void Preferences::setTextureSize(int textureSize) void Preferences::setTextureSize(int textureSize)
{ {
if (m_textureSize == textureSize) if (m_textureSize == textureSize)
@ -118,5 +140,6 @@ void Preferences::reset()
emit componentCombineModeChanged(); emit componentCombineModeChanged();
emit partColorChanged(); emit partColorChanged();
emit flatShadingChanged(); emit flatShadingChanged();
emit tongShadingChanged();
emit textureSizeChanged(); emit textureSizeChanged();
} }

View File

@ -14,6 +14,7 @@ public:
CombineMode componentCombineMode() const; CombineMode componentCombineMode() const;
const QColor &partColor() const; const QColor &partColor() const;
bool flatShading() const; bool flatShading() const;
bool tongShading() const;
QSize documentWindowSize() const; QSize documentWindowSize() const;
void setDocumentWindowSize(const QSize&); void setDocumentWindowSize(const QSize&);
int textureSize() const; int textureSize() const;
@ -21,17 +22,20 @@ signals:
void componentCombineModeChanged(); void componentCombineModeChanged();
void partColorChanged(); void partColorChanged();
void flatShadingChanged(); void flatShadingChanged();
void tongShadingChanged();
void textureSizeChanged(); void textureSizeChanged();
public slots: public slots:
void setComponentCombineMode(CombineMode mode); void setComponentCombineMode(CombineMode mode);
void setPartColor(const QColor &color); void setPartColor(const QColor &color);
void setFlatShading(bool flatShading); void setFlatShading(bool flatShading);
void setTongShading(bool tongShading);
void setTextureSize(int textureSize); void setTextureSize(int textureSize);
void reset(); void reset();
private: private:
CombineMode m_componentCombineMode; CombineMode m_componentCombineMode;
QColor m_partColor; QColor m_partColor;
bool m_flatShading; bool m_flatShading;
bool m_tongShading;
QSettings m_settings; QSettings m_settings;
int m_textureSize; int m_textureSize;
private: private:

View File

@ -65,6 +65,12 @@ PreferencesWidget::PreferencesWidget(const Document *document, QWidget *parent)
Preferences::instance().setFlatShading(flatShadingBox->isChecked()); Preferences::instance().setFlatShading(flatShadingBox->isChecked());
}); });
QCheckBox *tongShadingBox = new QCheckBox();
Theme::initCheckbox(tongShadingBox);
connect(tongShadingBox, &QCheckBox::stateChanged, this, [=]() {
Preferences::instance().setTongShading(tongShadingBox->isChecked());
});
QComboBox *textureSizeSelectBox = new QComboBox; QComboBox *textureSizeSelectBox = new QComboBox;
textureSizeSelectBox->addItem("512"); textureSizeSelectBox->addItem("512");
textureSizeSelectBox->addItem("1024"); textureSizeSelectBox->addItem("1024");
@ -78,12 +84,14 @@ PreferencesWidget::PreferencesWidget(const Document *document, QWidget *parent)
formLayout->addRow(tr("Part color:"), colorLayout); formLayout->addRow(tr("Part color:"), colorLayout);
formLayout->addRow(tr("Combine mode:"), combineModeSelectBox); formLayout->addRow(tr("Combine mode:"), combineModeSelectBox);
formLayout->addRow(tr("Flat shading:"), flatShadingBox); formLayout->addRow(tr("Flat shading:"), flatShadingBox);
formLayout->addRow(tr("Tong shading:"), tongShadingBox);
formLayout->addRow(tr("Texture size:"), textureSizeSelectBox); formLayout->addRow(tr("Texture size:"), textureSizeSelectBox);
auto loadFromPreferences = [=]() { auto loadFromPreferences = [=]() {
updatePickButtonColor(); updatePickButtonColor();
combineModeSelectBox->setCurrentIndex((int)Preferences::instance().componentCombineMode()); combineModeSelectBox->setCurrentIndex((int)Preferences::instance().componentCombineMode());
flatShadingBox->setChecked(Preferences::instance().flatShading()); flatShadingBox->setChecked(Preferences::instance().flatShading());
tongShadingBox->setChecked(Preferences::instance().tongShading());
textureSizeSelectBox->setCurrentIndex( textureSizeSelectBox->setCurrentIndex(
textureSizeSelectBox->findText(QString::number(Preferences::instance().textureSize())) textureSizeSelectBox->findText(QString::number(Preferences::instance().textureSize()))
); );