diff options
Diffstat (limited to 'src/extras')
-rw-r--r-- | src/extras/defaults/qmorphphongmaterial.cpp | 26 | ||||
-rw-r--r-- | src/extras/defaults/qmorphphongmaterial_p.h | 3 | ||||
-rw-r--r-- | src/extras/defaults/qorbitcameracontroller.cpp | 2 | ||||
-rw-r--r-- | src/extras/extras.qrc | 3 | ||||
-rw-r--r-- | src/extras/shaders/es2/morphphong.vert | 2 | ||||
-rw-r--r-- | src/extras/shaders/es3/default.vert | 82 | ||||
-rw-r--r-- | src/extras/shaders/es3/light.inc.frag | 25 | ||||
-rw-r--r-- | src/extras/shaders/es3/metalrough.inc.frag | 348 | ||||
-rw-r--r-- | src/extras/shaders/gl3/morphphong.vert | 2 | ||||
-rw-r--r-- | src/extras/text/qtext2dentity.cpp | 15 | ||||
-rw-r--r-- | src/extras/text/qtext2dentity_p.h | 1 |
11 files changed, 499 insertions, 10 deletions
diff --git a/src/extras/defaults/qmorphphongmaterial.cpp b/src/extras/defaults/qmorphphongmaterial.cpp index ade9f8542..1711a21dd 100644 --- a/src/extras/defaults/qmorphphongmaterial.cpp +++ b/src/extras/defaults/qmorphphongmaterial.cpp @@ -44,6 +44,7 @@ #include <Qt3DRender/qparameter.h> #include <Qt3DRender/qrenderpass.h> #include <Qt3DRender/qgraphicsapifilter.h> +#include <Qt3DRender/qshaderprogrambuilder.h> #include <QUrl> #include <QVector3D> #include <QVector4D> @@ -57,9 +58,9 @@ namespace Qt3DExtras { QMorphPhongMaterialPrivate::QMorphPhongMaterialPrivate() : QMaterialPrivate() , m_phongEffect(new QEffect()) - , m_ambientParameter(new QParameter(QStringLiteral("ka"), QColor::fromRgbF(0.05f, 0.05f, 0.05f, 1.0f))) - , m_diffuseParameter(new QParameter(QStringLiteral("kd"), QColor::fromRgbF(0.7f, 0.7f, 0.7f, 1.0f))) - , m_specularParameter(new QParameter(QStringLiteral("ks"), QColor::fromRgbF(0.01f, 0.01f, 0.01f, 1.0f))) + , m_ambientParameter(new QParameter(QStringLiteral("ka"), QColor::fromRgbF(0.05, 0.05, 0.05, 1.0))) + , m_diffuseParameter(new QParameter(QStringLiteral("kd"), QColor::fromRgbF(0.7, 0.7, 0.7, 1.0))) + , m_specularParameter(new QParameter(QStringLiteral("ks"), QColor::fromRgbF(0.01, 0.01, 0.01, 1.0))) , m_shininessParameter(new QParameter(QStringLiteral("shininess"), 150.0f)) , m_interpolatorParameter(new QParameter(QStringLiteral("interpolator"), 0.0f)) , m_phongGL3Technique(new QTechnique()) @@ -70,12 +71,16 @@ QMorphPhongMaterialPrivate::QMorphPhongMaterialPrivate() , m_phongES2RenderPass(new QRenderPass()) , m_phongGL3Shader(new QShaderProgram()) , m_phongGL2ES2Shader(new QShaderProgram()) + , m_phongGL3ShaderBuilder(new QShaderProgramBuilder()) + , m_phongGL2ES2ShaderBuilder(new QShaderProgramBuilder()) , m_filterKey(new QFilterKey) { } void QMorphPhongMaterialPrivate::init() { + Q_Q(QMorphPhongMaterial); + connect(m_ambientParameter, &Qt3DRender::QParameter::valueChanged, this, &QMorphPhongMaterialPrivate::handleAmbientChanged); connect(m_diffuseParameter, &Qt3DRender::QParameter::valueChanged, @@ -88,9 +93,19 @@ void QMorphPhongMaterialPrivate::init() this, &QMorphPhongMaterialPrivate::handleInterpolatorChanged); m_phongGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/morphphong.vert")))); - m_phongGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/phong.frag")))); + m_phongGL3ShaderBuilder->setParent(q); + m_phongGL3ShaderBuilder->setShaderProgram(m_phongGL3Shader); + m_phongGL3ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_phongGL3ShaderBuilder->setEnabledLayers({QStringLiteral("diffuse"), + QStringLiteral("specular"), + QStringLiteral("normal")}); m_phongGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/morphphong.vert")))); - m_phongGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/phong.frag")))); + m_phongGL2ES2ShaderBuilder->setParent(q); + m_phongGL2ES2ShaderBuilder->setShaderProgram(m_phongGL2ES2Shader); + m_phongGL2ES2ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_phongGL2ES2ShaderBuilder->setEnabledLayers({QStringLiteral("diffuse"), + QStringLiteral("specular"), + QStringLiteral("normal")}); m_phongGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); m_phongGL3Technique->graphicsApiFilter()->setMajorVersion(3); @@ -115,7 +130,6 @@ void QMorphPhongMaterialPrivate::init() m_phongGL2Technique->addRenderPass(m_phongGL2RenderPass); m_phongES2Technique->addRenderPass(m_phongES2RenderPass); - Q_Q(QMorphPhongMaterial); m_filterKey->setParent(q); m_filterKey->setName(QStringLiteral("renderingStyle")); m_filterKey->setValue(QStringLiteral("forward")); diff --git a/src/extras/defaults/qmorphphongmaterial_p.h b/src/extras/defaults/qmorphphongmaterial_p.h index 25bff9042..28b7750d9 100644 --- a/src/extras/defaults/qmorphphongmaterial_p.h +++ b/src/extras/defaults/qmorphphongmaterial_p.h @@ -60,6 +60,7 @@ class QTechnique; class QParameter; class QShaderProgram; class QRenderPass; +class QShaderProgramBuilder; } // namespace Qt3DRender @@ -94,6 +95,8 @@ public: Qt3DRender::QRenderPass *m_phongES2RenderPass; Qt3DRender::QShaderProgram *m_phongGL3Shader; Qt3DRender::QShaderProgram *m_phongGL2ES2Shader; + Qt3DRender::QShaderProgramBuilder *m_phongGL3ShaderBuilder; + Qt3DRender::QShaderProgramBuilder *m_phongGL2ES2ShaderBuilder; Qt3DRender::QFilterKey *m_filterKey; Q_DECLARE_PUBLIC(QMorphPhongMaterial) diff --git a/src/extras/defaults/qorbitcameracontroller.cpp b/src/extras/defaults/qorbitcameracontroller.cpp index 6d3e83bcb..aff91f6cf 100644 --- a/src/extras/defaults/qorbitcameracontroller.cpp +++ b/src/extras/defaults/qorbitcameracontroller.cpp @@ -186,7 +186,7 @@ void QOrbitCameraController::moveCamera(const QAbstractCameraController::InputSt } else if (state.shiftKeyActive) { if (zoomDistance(camera()->position(), theCamera->viewCenter()) > d->m_zoomInLimit * d->m_zoomInLimit) { // Dolly - theCamera->translate(QVector3D(0, 0, state.tyAxisValue * linearSpeed() * dt), theCamera->DontTranslateViewCenter); + theCamera->translate(QVector3D(0, 0, state.tzAxisValue * linearSpeed() * dt), theCamera->DontTranslateViewCenter); } else { theCamera->translate(QVector3D(0, 0, -0.5), theCamera->DontTranslateViewCenter); } diff --git a/src/extras/extras.qrc b/src/extras/extras.qrc index bfb14f3f9..8bbffd272 100644 --- a/src/extras/extras.qrc +++ b/src/extras/extras.qrc @@ -5,14 +5,17 @@ <file>shaders/gl3/light.inc.frag</file> <file>shaders/es2/light.inc.frag</file> <file>shaders/es2/light.inc.frag100</file> + <file>shaders/es3/light.inc.frag</file> <file>shaders/gl3/phong.inc.frag</file> <file>shaders/es2/phong.inc.frag</file> <file>shaders/es2/phong.inc.frag100</file> <file>shaders/gl3/metalrough.inc.frag</file> + <file>shaders/es3/metalrough.inc.frag</file> <file>shaders/gl3/coordinatesystems.inc</file> <file>shaders/es2/coordinatesystems.inc</file> <file>shaders/gl3/default.vert</file> <file>shaders/es2/default.vert</file> + <file>shaders/es3/default.vert</file> <file>shaders/gl3/pervertexcolor.frag</file> <file>shaders/gl3/pervertexcolor.vert</file> <file>shaders/es2/pervertexcolor.frag</file> diff --git a/src/extras/shaders/es2/morphphong.vert b/src/extras/shaders/es2/morphphong.vert index d091e87c0..89877dca8 100644 --- a/src/extras/shaders/es2/morphphong.vert +++ b/src/extras/shaders/es2/morphphong.vert @@ -25,7 +25,7 @@ void main() morphNormal = normalize(vertexNormal + vertexNormalTarget * abs(interpolator)); } - worldNormal = normalize( modelNormalMatrix * morphPos ); + worldNormal = normalize( modelNormalMatrix * morphNormal ); worldPosition = vec3( modelMatrix * vec4( morphPos, 1.0 ) ); gl_Position = modelViewProjection * vec4( morphPos, 1.0 ); diff --git a/src/extras/shaders/es3/default.vert b/src/extras/shaders/es3/default.vert new file mode 100644 index 000000000..7641882f2 --- /dev/null +++ b/src/extras/shaders/es3/default.vert @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#version 300 es + +in vec3 vertexPosition; +in vec3 vertexNormal; +in vec4 vertexTangent; +in vec2 vertexTexCoord; + +out vec3 worldPosition; +out vec3 worldNormal; +out vec4 worldTangent; +out vec2 texCoord; + +uniform mat4 modelMatrix; +uniform mat3 modelNormalMatrix; +uniform mat4 modelViewProjection; + +uniform float texCoordScale; + +void main() +{ + // Pass through scaled texture coordinates + texCoord = vertexTexCoord * texCoordScale; + + // Transform position, normal, and tangent to world space + worldPosition = vec3(modelMatrix * vec4(vertexPosition, 1.0)); + worldNormal = normalize(modelNormalMatrix * vertexNormal); + worldTangent.xyz = normalize(vec3(modelMatrix * vec4(vertexTangent.xyz, 0.0))); + worldTangent.w = vertexTangent.w; + + // Calculate vertex position in clip coordinates + gl_Position = modelViewProjection * vec4(vertexPosition, 1.0); +} diff --git a/src/extras/shaders/es3/light.inc.frag b/src/extras/shaders/es3/light.inc.frag new file mode 100644 index 000000000..9d03fca54 --- /dev/null +++ b/src/extras/shaders/es3/light.inc.frag @@ -0,0 +1,25 @@ +const int MAX_LIGHTS = 8; +const int TYPE_POINT = 0; +const int TYPE_DIRECTIONAL = 1; +const int TYPE_SPOT = 2; +struct Light { + int type; + vec3 position; + vec3 color; + float intensity; + vec3 direction; + float constantAttenuation; + float linearAttenuation; + float quadraticAttenuation; + float cutOffAngle; +}; +uniform Light lights[MAX_LIGHTS]; +uniform int lightCount; + +// Pre-convolved environment maps +struct EnvironmentLight { + highp samplerCube irradiance; // For diffuse contribution + highp samplerCube specular; // For specular contribution +}; +uniform EnvironmentLight envLight; +uniform int envLightCount; diff --git a/src/extras/shaders/es3/metalrough.inc.frag b/src/extras/shaders/es3/metalrough.inc.frag new file mode 100644 index 000000000..85f392f4c --- /dev/null +++ b/src/extras/shaders/es3/metalrough.inc.frag @@ -0,0 +1,348 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +precision highp float; + +// Exposure correction +uniform float exposure; +// Gamma correction +const float gamma = 2.2; + +#pragma include light.inc.frag + +int mipLevelCount(const in samplerCube cube) +{ + int baseSize = textureSize(cube, 0).x; + int nMips = int(log2(float(baseSize > 0 ? baseSize : 1))) + 1; + return nMips; +} + +float remapRoughness(const in float roughness) +{ + // As per page 14 of + // http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf + // we remap the roughness to give a more perceptually linear response + // of "bluriness" as a function of the roughness specified by the user. + // r = roughness^2 + const float maxSpecPower = 999999.0; + const float minRoughness = sqrt(2.0 / (maxSpecPower + 2.0)); + return max(roughness * roughness, minRoughness); +} + +float alphaToMipLevel(float alpha) +{ + float specPower = 2.0 / (alpha * alpha) - 2.0; + + // We use the mip level calculation from Lys' default power drop, which in + // turn is a slight modification of that used in Marmoset Toolbag. See + // https://docs.knaldtech.com/doku.php?id=specular_lys for details. + // For now we assume a max specular power of 999999 which gives + // maxGlossiness = 1. + const float k0 = 0.00098; + const float k1 = 0.9921; + float glossiness = (pow(2.0, -10.0 / sqrt(specPower)) - k0) / k1; + + // TODO: Optimize by doing this on CPU and set as + // uniform int envLight.specularMipLevels say (if present in shader). + // Lookup the number of mips in the specular envmap + int mipLevels = mipLevelCount(envLight.specular); + + // Offset of smallest miplevel we should use (corresponds to specular + // power of 1). I.e. in the 32x32 sized mip. + const float mipOffset = 5.0; + + // The final factor is really 1 - g / g_max but as mentioned above g_max + // is 1 by definition here so we can avoid the division. If we make the + // max specular power for the spec map configurable, this will need to + // be handled properly. + float mipLevel = (float(mipLevels) - 1.0 - mipOffset) * (1.0 - glossiness); + return mipLevel; +} + +float normalDistribution(const in vec3 n, const in vec3 h, const in float alpha) +{ + // Blinn-Phong approximation - see + // http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html + float specPower = 2.0 / (alpha * alpha) - 2.0; + return (specPower + 2.0) / (2.0 * 3.14159) * pow(max(dot(n, h), 0.0), specPower); +} + +vec3 fresnelFactor(const in vec3 color, const in float cosineFactor) +{ + // Calculate the Fresnel effect value + vec3 f = color; + vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0); + return clamp(F, f, vec3(1.0)); +} + +float geometricModel(const in float lDotN, + const in float vDotN, + const in vec3 h) +{ + // Implicit geometric model (equal to denominator in specular model). + // This currently assumes that there is no attenuation by geometric shadowing or + // masking according to the microfacet theory. + return lDotN * vDotN; +} + +vec3 specularModel(const in vec3 F0, + const in float sDotH, + const in float sDotN, + const in float vDotN, + const in vec3 n, + const in vec3 h) +{ + // Clamp sDotN and vDotN to small positive value to prevent the + // denominator in the reflection equation going to infinity. Balance this + // by using the clamped values in the geometric factor function to + // avoid ugly seams in the specular lighting. + float sDotNPrime = max(sDotN, 0.001); + float vDotNPrime = max(vDotN, 0.001); + + vec3 F = fresnelFactor(F0, sDotH); + float G = geometricModel(sDotNPrime, vDotNPrime, h); + + vec3 cSpec = F * G / (4.0 * sDotNPrime * vDotNPrime); + return clamp(cSpec, vec3(0.0), vec3(1.0)); +} + +vec3 pbrModel(const in int lightIndex, + const in vec3 wPosition, + const in vec3 wNormal, + const in vec3 wView, + const in vec3 baseColor, + const in float metalness, + const in float alpha, + const in float ambientOcclusion) +{ + // Calculate some useful quantities + vec3 n = wNormal; + vec3 s = vec3(0.0); + vec3 v = wView; + vec3 h = vec3(0.0); + + float vDotN = dot(v, n); + float sDotN = 0.0; + float sDotH = 0.0; + float att = 1.0; + + if (lights[lightIndex].type != TYPE_DIRECTIONAL) { + // Point and Spot lights + vec3 sUnnormalized = vec3(lights[lightIndex].position) - wPosition; + s = normalize(sUnnormalized); + + // Calculate the attenuation factor + sDotN = dot(s, n); + if (sDotN > 0.0) { + if (lights[lightIndex].constantAttenuation != 0.0 + || lights[lightIndex].linearAttenuation != 0.0 + || lights[lightIndex].quadraticAttenuation != 0.0) { + float dist = length(sUnnormalized); + att = 1.0 / (lights[lightIndex].constantAttenuation + + lights[lightIndex].linearAttenuation * dist + + lights[lightIndex].quadraticAttenuation * dist * dist); + } + + // The light direction is in world space already + if (lights[lightIndex].type == TYPE_SPOT) { + // Check if fragment is inside or outside of the spot light cone + if (degrees(acos(dot(-s, lights[lightIndex].direction))) > lights[lightIndex].cutOffAngle) + sDotN = 0.0; + } + } + } else { + // Directional lights + // The light direction is in world space already + s = normalize(-lights[lightIndex].direction); + sDotN = dot(s, n); + } + + h = normalize(s + v); + sDotH = dot(s, h); + + // Calculate diffuse component + vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color; + vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159; + + // Calculate specular component + vec3 dielectricColor = vec3(0.04); + vec3 F0 = mix(dielectricColor, baseColor, metalness); + vec3 specularFactor = vec3(0.0); + if (sDotN > 0.0) { + specularFactor = specularModel(F0, sDotH, sDotN, vDotN, n, h); + specularFactor *= normalDistribution(n, h, alpha); + } + vec3 specularColor = lights[lightIndex].color; + vec3 specular = specularColor * specularFactor; + + // Blend between diffuse and specular to conserver energy + vec3 color = att * lights[lightIndex].intensity * (specular + diffuse * (vec3(1.0) - specular)); + + // Reduce by ambient occlusion amount + color *= ambientOcclusion; + + return color; +} + +vec3 pbrIblModel(const in vec3 wNormal, + const in vec3 wView, + const in vec3 baseColor, + const in float metalness, + const in float alpha, + const in float ambientOcclusion) +{ + // Calculate reflection direction of view vector about surface normal + // vector in world space. This is used in the fragment shader to sample + // from the environment textures for a light source. This is equivalent + // to the l vector for punctual light sources. Armed with this, calculate + // the usual factors needed + vec3 n = wNormal; + vec3 l = reflect(-wView, n); + vec3 v = wView; + vec3 h = normalize(l + v); + float vDotN = dot(v, n); + float lDotN = dot(l, n); + float lDotH = dot(l, h); + + // Calculate diffuse component + vec3 diffuseColor = (1.0 - metalness) * baseColor; + vec3 diffuse = diffuseColor * texture(envLight.irradiance, l).rgb; + + // Calculate specular component + vec3 dielectricColor = vec3(0.04); + vec3 F0 = mix(dielectricColor, baseColor, metalness); + vec3 specularFactor = specularModel(F0, lDotH, lDotN, vDotN, n, h); + + float lod = alphaToMipLevel(alpha); +//#define DEBUG_SPECULAR_LODS +#ifdef DEBUG_SPECULAR_LODS + if (lod > 7.0) + return vec3(1.0, 0.0, 0.0); + else if (lod > 6.0) + return vec3(1.0, 0.333, 0.0); + else if (lod > 5.0) + return vec3(1.0, 1.0, 0.0); + else if (lod > 4.0) + return vec3(0.666, 1.0, 0.0); + else if (lod > 3.0) + return vec3(0.0, 1.0, 0.666); + else if (lod > 2.0) + return vec3(0.0, 0.666, 1.0); + else if (lod > 1.0) + return vec3(0.0, 0.0, 1.0); + else if (lod > 0.0) + return vec3(1.0, 0.0, 1.0); +#endif + vec3 specularSkyColor = textureLod(envLight.specular, l, lod).rgb; + vec3 specular = specularSkyColor * specularFactor; + + // Blend between diffuse and specular to conserve energy + vec3 color = specular + diffuse * (vec3(1.0) - specularFactor); + + // Reduce by ambient occlusion amount + color *= ambientOcclusion; + + return color; +} + +vec3 toneMap(const in vec3 c) +{ + return c / (c + vec3(1.0)); +} + +vec3 gammaCorrect(const in vec3 color) +{ + return pow(color, vec3(1.0 / gamma)); +} + +vec4 metalRoughFunction(const in vec4 baseColor, + const in float metalness, + const in float roughness, + const in float ambientOcclusion, + const in vec3 worldPosition, + const in vec3 worldView, + const in vec3 worldNormal) +{ + vec3 cLinear = vec3(0.0); + + // Remap roughness for a perceptually more linear correspondence + float alpha = remapRoughness(roughness); + + for (int i = 0; i < envLightCount; ++i) { + cLinear += pbrIblModel(worldNormal, + worldView, + baseColor.rgb, + metalness, + alpha, + ambientOcclusion); + } + + for (int i = 0; i < lightCount; ++i) { + cLinear += pbrModel(i, + worldPosition, + worldNormal, + worldView, + baseColor.rgb, + metalness, + alpha, + ambientOcclusion); + } + + // Apply exposure correction + cLinear *= pow(2.0, exposure); + + // Apply simple (Reinhard) tonemap transform to get into LDR range [0, 1] + vec3 cToneMapped = toneMap(cLinear); + + // Apply gamma correction prior to display + vec3 cGamma = gammaCorrect(cToneMapped); + + return vec4(cGamma, 1.0); +} diff --git a/src/extras/shaders/gl3/morphphong.vert b/src/extras/shaders/gl3/morphphong.vert index c74fbdcff..7a8bdd097 100644 --- a/src/extras/shaders/gl3/morphphong.vert +++ b/src/extras/shaders/gl3/morphphong.vert @@ -27,7 +27,7 @@ void main() morphNormal = normalize(vertexNormal + vertexNormalTarget * abs(interpolator)); } - worldNormal = normalize( modelNormalMatrix * morphPos ); + worldNormal = normalize( modelNormalMatrix * morphNormal ); worldPosition = vec3( modelMatrix * vec4( morphPos, 1.0 ) ); gl_Position = modelViewProjection * vec4( morphPos, 1.0 ); diff --git a/src/extras/text/qtext2dentity.cpp b/src/extras/text/qtext2dentity.cpp index 10939a1e2..ae25e8ecc 100644 --- a/src/extras/text/qtext2dentity.cpp +++ b/src/extras/text/qtext2dentity.cpp @@ -92,10 +92,17 @@ void QText2DEntityPrivate::setScene(Qt3DCore::QScene *scene) // Unref old glyph cache if it exists if (m_scene != nullptr) { + // Ensure we don't keep reference to glyphs + // if we are changing the cache + if (m_glyphCache != nullptr) + clearCurrentGlyphRuns(); + m_glyphCache = nullptr; + QText2DEntityPrivate::CacheEntry &entry = QText2DEntityPrivate::m_glyphCacheInstances[m_scene]; --entry.count; if (entry.count == 0 && entry.glyphCache != nullptr) { + delete entry.glyphCache; entry.glyphCache = nullptr; } @@ -149,7 +156,6 @@ void QText2DEntityPrivate::setCurrentGlyphRuns(const QVector<QGlyphRun> &runs) // For each distinct texture, we need a separate DistanceFieldTextRenderer, // for which we need vertex and index data QHash<Qt3DRender::QAbstractTexture*, RenderData> renderData; - const float scale = computeActualScale(); // process glyph runs @@ -248,6 +254,13 @@ void QText2DEntityPrivate::setCurrentGlyphRuns(const QVector<QGlyphRun> &runs) m_currentGlyphRuns = runs; } +void QText2DEntityPrivate::clearCurrentGlyphRuns() +{ + for (int i = 0; i < m_currentGlyphRuns.size(); i++) + m_glyphCache->derefGlyphs(m_currentGlyphRuns[i]); + m_currentGlyphRuns.clear(); +} + void QText2DEntityPrivate::update() { if (m_glyphCache == nullptr) diff --git a/src/extras/text/qtext2dentity_p.h b/src/extras/text/qtext2dentity_p.h index 934e2087f..b98c62ce3 100644 --- a/src/extras/text/qtext2dentity_p.h +++ b/src/extras/text/qtext2dentity_p.h @@ -104,6 +104,7 @@ public: float computeActualScale() const; void setCurrentGlyphRuns(const QVector<QGlyphRun> &runs); + void clearCurrentGlyphRuns(); void update(); struct CacheEntry |