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>
<pre>
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>
<h1>David Rosen</h1>

View File

@ -86,6 +86,7 @@ uniform samplerCube environmentIrradianceMapId;
uniform int environmentIrradianceMapEnabled;
uniform samplerCube environmentSpecularMapId;
uniform int environmentSpecularMapEnabled;
uniform int tongShadingEnabled;
const int MAX_LIGHTS = 8;
const int TYPE_POINT = 0;
@ -352,6 +353,25 @@ vec3 gammaCorrect(const in vec3 color)
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,
const in float metalness,
const in float roughness,
@ -365,6 +385,7 @@ vec4 metalRoughFunction(const in vec4 baseColor,
// Remap roughness for a perceptually more linear correspondence
float alpha = remapRoughness(roughness);
if (tongShadingEnabled != 1) {
if (environmentIrradianceMapEnabled == 1) {
cLinear += pbrIblModel(worldNormal,
worldView,
@ -384,6 +405,16 @@ vec4 metalRoughFunction(const in vec4 baseColor,
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
cLinear *= pow(2.0, exposure);

View File

@ -80,6 +80,7 @@ uniform int ambientOcclusionMapEnabled;
uniform int mousePickEnabled;
uniform vec3 mousePickTargetPosition;
uniform float mousePickRadius;
uniform int tongShadingEnabled;
const int MAX_LIGHTS = 8;
const int TYPE_POINT = 0;
@ -248,6 +249,25 @@ vec3 gammaCorrect(const in vec3 color)
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,
const in float metalness,
const in float roughness,
@ -261,6 +281,7 @@ vec4 metalRoughFunction(const in vec4 baseColor,
// Remap roughness for a perceptually more linear correspondence
float alpha = remapRoughness(roughness);
if (tongShadingEnabled != 1) {
for (int i = 0; i < lightCount; ++i) {
cLinear += pbrModel(i,
worldPosition,
@ -271,6 +292,16 @@ vec4 metalRoughFunction(const in vec4 baseColor,
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
cLinear *= pow(2.0, exposure);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -65,6 +65,12 @@ PreferencesWidget::PreferencesWidget(const Document *document, QWidget *parent)
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;
textureSizeSelectBox->addItem("512");
textureSizeSelectBox->addItem("1024");
@ -78,12 +84,14 @@ PreferencesWidget::PreferencesWidget(const Document *document, QWidget *parent)
formLayout->addRow(tr("Part color:"), colorLayout);
formLayout->addRow(tr("Combine mode:"), combineModeSelectBox);
formLayout->addRow(tr("Flat shading:"), flatShadingBox);
formLayout->addRow(tr("Tong shading:"), tongShadingBox);
formLayout->addRow(tr("Texture size:"), textureSizeSelectBox);
auto loadFromPreferences = [=]() {
updatePickButtonColor();
combineModeSelectBox->setCurrentIndex((int)Preferences::instance().componentCombineMode());
flatShadingBox->setChecked(Preferences::instance().flatShading());
tongShadingBox->setChecked(Preferences::instance().tongShading());
textureSizeSelectBox->setCurrentIndex(
textureSizeSelectBox->findText(QString::number(Preferences::instance().textureSize()))
);