From 7a5065865a1d11f5155a9322a437143d3928b9b0 Mon Sep 17 00:00:00 2001 From: Jeremy Hu Date: Sun, 22 Dec 2019 21:37:42 +0930 Subject: [PATCH] Set OpenGL core profile shader as default --- resources.qrc | 2 - shaders/default.core.frag | 369 +++++++++++++++++++++++++++++++++++- shaders/default.core.vert | 82 +++++--- shaders/default.frag | 367 +++++++++++++++++++++++++++++++++++- shaders/pbr-joey.frag | 154 --------------- shaders/pbr-qt.frag | 373 ------------------------------------- src/main.cpp | 3 +- src/modelshaderprogram.cpp | 8 +- src/modelshaderprogram.h | 2 +- 9 files changed, 789 insertions(+), 571 deletions(-) delete mode 100644 shaders/pbr-joey.frag delete mode 100644 shaders/pbr-qt.frag diff --git a/resources.qrc b/resources.qrc index fa25e175..0f0cd02e 100644 --- a/resources.qrc +++ b/resources.qrc @@ -26,8 +26,6 @@ shaders/default.frag shaders/default.core.vert shaders/default.core.frag - shaders/pbr-qt.frag - shaders/pbr-joey.frag thirdparty/three.js/dust3d.three.js languages/dust3d_zh_CN.qm ACKNOWLEDGEMENTS.html diff --git a/shaders/default.core.frag b/shaders/default.core.frag index 0e835ce0..3bf72812 100644 --- a/shaders/default.core.frag +++ b/shaders/default.core.frag @@ -1,20 +1,375 @@ -#version 150 +#version 330 +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +// Please note that, this file "pbr.frag" is copied and slightly modified from the Qt3D's pbr shader "metalrough.inc.frag" +// https://github.com/qt/qt3d/blob/5.11/src/extras/shaders/gl3/metalrough.inc.frag + +// Exposure correction +highp float exposure; +// Gamma correction +highp float gamma; + in highp vec3 vert; +in highp vec3 vertRaw; in highp vec3 vertNormal; in highp vec3 vertColor; in highp vec2 vertTexCoord; +in highp float vertMetalness; +in highp float vertRoughness; +in highp vec3 cameraPos; +in highp vec3 firstLightPos; +in highp vec3 secondLightPos; +in highp vec3 thirdLightPos; +in highp float vertAlpha; out highp vec4 fragColor; uniform highp vec3 lightPos; uniform highp sampler2D textureId; uniform highp int textureEnabled; +uniform highp sampler2D normalMapId; +uniform highp int normalMapEnabled; +uniform highp sampler2D metalnessRoughnessAmbientOcclusionMapId; +uniform highp int metalnessMapEnabled; +uniform highp int roughnessMapEnabled; +uniform highp int ambientOcclusionMapEnabled; +uniform highp int mousePickEnabled; +uniform highp vec3 mousePickTargetPosition; +uniform highp float mousePickRadius; + +const int MAX_LIGHTS = 8; +const int TYPE_POINT = 0; +const int TYPE_DIRECTIONAL = 1; +const int TYPE_SPOT = 2; +struct Light { + int type; + highp vec3 position; + highp vec3 color; + highp float intensity; + highp vec3 direction; + highp float constantAttenuation; + highp float linearAttenuation; + highp float quadraticAttenuation; + highp float cutOffAngle; +}; +int lightCount; +Light lights[MAX_LIGHTS]; + +highp float remapRoughness(const in highp 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 + highp float maxSpecPower; + highp float minRoughness; + maxSpecPower = 999999.0; + minRoughness = sqrt(2.0 / (maxSpecPower + 2.0)); + return max(roughness * roughness, minRoughness); +} + +highp float normalDistribution(const in highp vec3 n, const in highp vec3 h, const in highp float alpha) +{ + // Blinn-Phong approximation - see + // http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html + highp float specPower = 2.0 / (alpha * alpha) - 2.0; + return (specPower + 2.0) / (2.0 * 3.14159) * pow(max(dot(n, h), 0.0), specPower); +} + +highp vec3 fresnelFactor(const in highp vec3 color, const in highp float cosineFactor) +{ + // Calculate the Fresnel effect value + highp vec3 f = color; + highp vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0); + return clamp(F, f, vec3(1.0)); +} + +highp float geometricModel(const in highp float lDotN, + const in highp float vDotN, + const in highp 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; +} + +highp vec3 specularModel(const in highp vec3 F0, + const in highp float sDotH, + const in highp float sDotN, + const in highp float vDotN, + const in highp vec3 n, + const in highp 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. + highp float sDotNPrime = max(sDotN, 0.001); + highp float vDotNPrime = max(vDotN, 0.001); + + highp vec3 F = fresnelFactor(F0, sDotH); + highp float G = geometricModel(sDotNPrime, vDotNPrime, h); + + highp vec3 cSpec = F * G / (4.0 * sDotNPrime * vDotNPrime); + return clamp(cSpec, vec3(0.0), vec3(1.0)); +} + +highp vec3 pbrModel(const in int lightIndex, + const in highp vec3 wPosition, + const in highp vec3 wNormal, + const in highp vec3 wView, + const in highp vec3 baseColor, + const in highp float metalness, + const in highp float alpha, + const in highp float ambientOcclusion) +{ + // Calculate some useful quantities + highp vec3 n = wNormal; + highp vec3 s = vec3(0.0); + highp vec3 v = wView; + highp vec3 h = vec3(0.0); + + highp float vDotN = dot(v, n); + highp float sDotN = 0.0; + highp float sDotH = 0.0; + highp float att = 1.0; + + if (lights[lightIndex].type != TYPE_DIRECTIONAL) { + // Point and Spot lights + highp 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) { + highp 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 + highp vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color; + highp vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159; + + // Calculate specular component + highp vec3 dielectricColor = vec3(0.04); + highp vec3 F0 = mix(dielectricColor, baseColor, metalness); + highp vec3 specularFactor = vec3(0.0); + if (sDotN > 0.0) { + specularFactor = specularModel(F0, sDotH, sDotN, vDotN, n, h); + specularFactor *= normalDistribution(n, h, alpha); + } + highp vec3 specularColor = lights[lightIndex].color; + highp vec3 specular = specularColor * specularFactor; + + // Blend between diffuse and specular to conserver energy + highp vec3 color = att * lights[lightIndex].intensity * (specular + diffuse * (vec3(1.0) - specular)); + + // Reduce by ambient occlusion amount + color *= ambientOcclusion; + + return color; +} + +highp vec3 toneMap(const in highp vec3 c) +{ + return c / (c + vec3(1.0)); +} + +highp vec3 gammaCorrect(const in highp vec3 color) +{ + return pow(color, vec3(1.0 / gamma)); +} + +highp vec4 metalRoughFunction(const in highp vec4 baseColor, + const in highp float metalness, + const in highp float roughness, + const in highp float ambientOcclusion, + const in highp vec3 worldPosition, + const in highp vec3 worldView, + const in highp vec3 worldNormal) +{ + highp vec3 cLinear = vec3(0.0); + + // Remap roughness for a perceptually more linear correspondence + highp float alpha = remapRoughness(roughness); + + 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] + highp vec3 cToneMapped = toneMap(cLinear); + + // Apply gamma correction prior to display + highp vec3 cGamma = gammaCorrect(cToneMapped); + + return vec4(cGamma, baseColor.a); +} + void main() { - highp vec3 L = normalize(lightPos - vert); - highp float NL = max(dot(normalize(vertNormal), L), 0.0); + // FIXME: don't hard code here + exposure = 1.0; + gamma = 2.2; + + // Light settings: + // https://doc-snapshots.qt.io/qt5-5.12/qt3d-pbr-materials-lights-qml.html + lightCount = 3; + + // Key light + lights[0].type = TYPE_POINT; + lights[0].position = firstLightPos; + lights[0].color = vec3(1.0, 1.0, 1.0); + lights[0].intensity = 3.0; + lights[0].constantAttenuation = 0.0; + lights[0].linearAttenuation = 0.0; + lights[0].quadraticAttenuation = 0.0; + + // Fill light + lights[1].type = TYPE_POINT; + lights[1].position = secondLightPos; + lights[1].color = vec3(1.0, 1.0, 1.0); + lights[1].intensity = 1.0; + lights[1].constantAttenuation = 0.0; + lights[1].linearAttenuation = 0.0; + lights[1].quadraticAttenuation = 0.0; + + // Rim light + lights[2].type = TYPE_POINT; + lights[2].position = thirdLightPos; + lights[2].color = vec3(1.0, 1.0, 1.0); + lights[2].intensity = 0.5; + lights[2].constantAttenuation = 0.0; + lights[2].linearAttenuation = 0.0; + lights[2].quadraticAttenuation = 0.0; + highp vec3 color = vertColor; + highp float alpha = vertAlpha; if (textureEnabled == 1) { - color = texture(textureId, vertTexCoord).rgb; + highp vec4 textColor = texture(textureId, vertTexCoord); + color = textColor.rgb; + alpha = textColor.a; } - highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0); - fragColor = vec4(col, 1.0); -} \ No newline at end of file + if (mousePickEnabled == 1) { + if (distance(mousePickTargetPosition, vertRaw) <= mousePickRadius) { + color = color + vec3(0.99, 0.4, 0.13); + } + } + color = pow(color, vec3(gamma)); + + highp vec3 normal = vertNormal; + if (normalMapEnabled == 1) { + normal = texture(normalMapId, vertTexCoord).rgb; + normal = normalize(normal * 2.0 - 1.0); + } + + // Red: Ambient Occlusion + // Green: Roughness + // Blue: Metallic + + highp float metalness = vertMetalness; + if (metalnessMapEnabled == 1) { + metalness = texture(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).b; + } + + highp float roughness = vertRoughness; + if (roughnessMapEnabled == 1) { + roughness = texture(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).g; + } + + highp float ambientOcclusion = 1.0; + if (ambientOcclusionMapEnabled == 1) { + ambientOcclusion = texture(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).r; + } + + roughness = min(0.99, roughness); + metalness = min(0.99, metalness); + + fragColor = metalRoughFunction(vec4(color, alpha), + metalness, + roughness, + ambientOcclusion, + vert, + normalize(cameraPos - vert), + normal); +} diff --git a/shaders/default.core.vert b/shaders/default.core.vert index c607e107..2955b5c1 100644 --- a/shaders/default.core.vert +++ b/shaders/default.core.vert @@ -1,27 +1,67 @@ -#version 150 -in vec4 vertex; -in vec3 normal; -in vec3 color; -in vec2 texCoord; -in float metalness; -in float roughness; -in vec3 tangent; -out vec3 vert; -out vec3 vertNormal; -out vec3 vertColor; -out vec2 vertTexCoord; -out float vertMetalness; -out float vertRoughness; -uniform mat4 projMatrix; -uniform mat4 mvMatrix; -uniform mat3 normalMatrix; -void main() +#version 330 +layout(location = 0) in highp vec4 vertex; +layout(location = 1) in highp vec3 normal; +layout(location = 2) in highp vec3 color; +layout(location = 3) in highp vec2 texCoord; +layout(location = 4) in highp float metalness; +layout(location = 5) in highp float roughness; +layout(location = 6) in highp vec3 tangent; +layout(location = 7) in highp float alpha; +out highp vec3 vert; +out highp vec3 vertRaw; +out highp vec3 vertNormal; +out highp vec3 vertColor; +out highp vec2 vertTexCoord; +out highp float vertMetalness; +out highp float vertRoughness; +out highp vec3 cameraPos; +out highp vec3 firstLightPos; +out highp vec3 secondLightPos; +out highp vec3 thirdLightPos; +out 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) { - vert = vertex.xyz; - vertNormal = normalMatrix * normal; + return mat3(m[0][0], m[1][0], m[2][0], + m[0][1], m[1][1], m[2][1], + m[0][2], m[1][2], m[2][2]); +} + +void main() +{ + vert = (modelMatrix * vertex).xyz; + 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); + secondLightPos = vec3(-5.0, 5.0, 5.0); + thirdLightPos = vec3(0.0, -5.0, -5.0); + + gl_Position = projectionMatrix * viewMatrix * vec4(vert, 1.0); + + if (normalMapEnabled == 1) { + vec3 T = normalize(normalMatrix * tangent); + vec3 N = normalize(normalMatrix * normal); + T = normalize(T - dot(T, N) * N); + vec3 B = cross(N, T); + + mat3 TBN = transpose(mat3(T, B, N)); + firstLightPos = TBN * firstLightPos; + secondLightPos = TBN * secondLightPos; + thirdLightPos = TBN * thirdLightPos; + cameraPos = TBN * cameraPos; + vert = TBN * vert; + } + vertTexCoord = texCoord; vertMetalness = metalness; vertRoughness = roughness; - gl_Position = projMatrix * mvMatrix * vertex; } \ No newline at end of file diff --git a/shaders/default.frag b/shaders/default.frag index 4f460ab1..401f7b56 100644 --- a/shaders/default.frag +++ b/shaders/default.frag @@ -1,18 +1,373 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +// Please note that, this file "pbr.frag" is copied and slightly modified from the Qt3D's pbr shader "metalrough.inc.frag" +// https://github.com/qt/qt3d/blob/5.11/src/extras/shaders/gl3/metalrough.inc.frag + +// Exposure correction +highp float exposure; +// Gamma correction +highp float gamma; + 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 vec3 lightPos; uniform highp sampler2D textureId; uniform highp int textureEnabled; +uniform highp sampler2D normalMapId; +uniform highp int normalMapEnabled; +uniform highp sampler2D metalnessRoughnessAmbientOcclusionMapId; +uniform highp int metalnessMapEnabled; +uniform highp int roughnessMapEnabled; +uniform highp int ambientOcclusionMapEnabled; +uniform highp int mousePickEnabled; +uniform highp vec3 mousePickTargetPosition; +uniform highp float mousePickRadius; + +const int MAX_LIGHTS = 8; +const int TYPE_POINT = 0; +const int TYPE_DIRECTIONAL = 1; +const int TYPE_SPOT = 2; +struct Light { + int type; + highp vec3 position; + highp vec3 color; + highp float intensity; + highp vec3 direction; + highp float constantAttenuation; + highp float linearAttenuation; + highp float quadraticAttenuation; + highp float cutOffAngle; +}; +int lightCount; +Light lights[MAX_LIGHTS]; + +highp float remapRoughness(const in highp 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 + highp float maxSpecPower; + highp float minRoughness; + maxSpecPower = 999999.0; + minRoughness = sqrt(2.0 / (maxSpecPower + 2.0)); + return max(roughness * roughness, minRoughness); +} + +highp float normalDistribution(const in highp vec3 n, const in highp vec3 h, const in highp float alpha) +{ + // Blinn-Phong approximation - see + // http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html + highp float specPower = 2.0 / (alpha * alpha) - 2.0; + return (specPower + 2.0) / (2.0 * 3.14159) * pow(max(dot(n, h), 0.0), specPower); +} + +highp vec3 fresnelFactor(const in highp vec3 color, const in highp float cosineFactor) +{ + // Calculate the Fresnel effect value + highp vec3 f = color; + highp vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0); + return clamp(F, f, vec3(1.0)); +} + +highp float geometricModel(const in highp float lDotN, + const in highp float vDotN, + const in highp 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; +} + +highp vec3 specularModel(const in highp vec3 F0, + const in highp float sDotH, + const in highp float sDotN, + const in highp float vDotN, + const in highp vec3 n, + const in highp 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. + highp float sDotNPrime = max(sDotN, 0.001); + highp float vDotNPrime = max(vDotN, 0.001); + + highp vec3 F = fresnelFactor(F0, sDotH); + highp float G = geometricModel(sDotNPrime, vDotNPrime, h); + + highp vec3 cSpec = F * G / (4.0 * sDotNPrime * vDotNPrime); + return clamp(cSpec, vec3(0.0), vec3(1.0)); +} + +highp vec3 pbrModel(const in int lightIndex, + const in highp vec3 wPosition, + const in highp vec3 wNormal, + const in highp vec3 wView, + const in highp vec3 baseColor, + const in highp float metalness, + const in highp float alpha, + const in highp float ambientOcclusion) +{ + // Calculate some useful quantities + highp vec3 n = wNormal; + highp vec3 s = vec3(0.0); + highp vec3 v = wView; + highp vec3 h = vec3(0.0); + + highp float vDotN = dot(v, n); + highp float sDotN = 0.0; + highp float sDotH = 0.0; + highp float att = 1.0; + + if (lights[lightIndex].type != TYPE_DIRECTIONAL) { + // Point and Spot lights + highp 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) { + highp 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 + highp vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color; + highp vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159; + + // Calculate specular component + highp vec3 dielectricColor = vec3(0.04); + highp vec3 F0 = mix(dielectricColor, baseColor, metalness); + highp vec3 specularFactor = vec3(0.0); + if (sDotN > 0.0) { + specularFactor = specularModel(F0, sDotH, sDotN, vDotN, n, h); + specularFactor *= normalDistribution(n, h, alpha); + } + highp vec3 specularColor = lights[lightIndex].color; + highp vec3 specular = specularColor * specularFactor; + + // Blend between diffuse and specular to conserver energy + highp vec3 color = att * lights[lightIndex].intensity * (specular + diffuse * (vec3(1.0) - specular)); + + // Reduce by ambient occlusion amount + color *= ambientOcclusion; + + return color; +} + +highp vec3 toneMap(const in highp vec3 c) +{ + return c / (c + vec3(1.0)); +} + +highp vec3 gammaCorrect(const in highp vec3 color) +{ + return pow(color, vec3(1.0 / gamma)); +} + +highp vec4 metalRoughFunction(const in highp vec4 baseColor, + const in highp float metalness, + const in highp float roughness, + const in highp float ambientOcclusion, + const in highp vec3 worldPosition, + const in highp vec3 worldView, + const in highp vec3 worldNormal) +{ + highp vec3 cLinear = vec3(0.0); + + // Remap roughness for a perceptually more linear correspondence + highp float alpha = remapRoughness(roughness); + + 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] + highp vec3 cToneMapped = toneMap(cLinear); + + // Apply gamma correction prior to display + highp vec3 cGamma = gammaCorrect(cToneMapped); + + return vec4(cGamma, baseColor.a); +} + void main() { - highp vec3 L = normalize(lightPos - vert); - highp float NL = max(dot(normalize(vertNormal), L), 0.0); + // FIXME: don't hard code here + exposure = 1.0; + gamma = 2.2; + + // Light settings: + // https://doc-snapshots.qt.io/qt5-5.12/qt3d-pbr-materials-lights-qml.html + lightCount = 3; + + // Key light + lights[0].type = TYPE_POINT; + lights[0].position = firstLightPos; + lights[0].color = vec3(1.0, 1.0, 1.0); + lights[0].intensity = 3.0; + lights[0].constantAttenuation = 0.0; + lights[0].linearAttenuation = 0.0; + lights[0].quadraticAttenuation = 0.0; + + // Fill light + lights[1].type = TYPE_POINT; + lights[1].position = secondLightPos; + lights[1].color = vec3(1.0, 1.0, 1.0); + lights[1].intensity = 1.0; + lights[1].constantAttenuation = 0.0; + lights[1].linearAttenuation = 0.0; + lights[1].quadraticAttenuation = 0.0; + + // Rim light + lights[2].type = TYPE_POINT; + lights[2].position = thirdLightPos; + lights[2].color = vec3(1.0, 1.0, 1.0); + lights[2].intensity = 0.5; + lights[2].constantAttenuation = 0.0; + lights[2].linearAttenuation = 0.0; + 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; } - highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0); - gl_FragColor = vec4(col, 1.0); -} \ No newline at end of file + if (mousePickEnabled == 1) { + if (distance(mousePickTargetPosition, vertRaw) <= mousePickRadius) { + color = color + vec3(0.99, 0.4, 0.13); + } + } + color = pow(color, vec3(gamma)); + + highp vec3 normal = vertNormal; + if (normalMapEnabled == 1) { + normal = texture2D(normalMapId, vertTexCoord).rgb; + normal = normalize(normal * 2.0 - 1.0); + } + + // Red: Ambient Occlusion + // Green: Roughness + // Blue: Metallic + + highp float metalness = vertMetalness; + if (metalnessMapEnabled == 1) { + metalness = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).b; + } + + highp float roughness = vertRoughness; + if (roughnessMapEnabled == 1) { + roughness = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).g; + } + + highp float ambientOcclusion = 1.0; + if (ambientOcclusionMapEnabled == 1) { + ambientOcclusion = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).r; + } + + roughness = min(0.99, roughness); + metalness = min(0.99, metalness); + + gl_FragColor = metalRoughFunction(vec4(color, alpha), + metalness, + roughness, + ambientOcclusion, + vert, + normalize(cameraPos - vert), + normal); +} diff --git a/shaders/pbr-joey.frag b/shaders/pbr-joey.frag deleted file mode 100644 index 03fa0df5..00000000 --- a/shaders/pbr-joey.frag +++ /dev/null @@ -1,154 +0,0 @@ -// Copy and modified from Joey's code -// https://github.com/JoeyDeVries/LearnOpenGL/blob/master/src/6.pbr/1.1.lighting/1.1.pbr.fs - -const float PI = 3.14159265359; - -// ---------------------------------------------------------------------------- -float DistributionGGX(vec3 N, vec3 H, float roughness) -{ - float a = roughness*roughness; - float a2 = a*a; - float NdotH = max(dot(N, H), 0.0); - float NdotH2 = NdotH*NdotH; - - float nom = a2; - float denom = (NdotH2 * (a2 - 1.0) + 1.0); - denom = PI * denom * denom; - - return nom / max(denom, 0.001); // prevent divide by zero for roughness=0.0 and NdotH=1.0 -} -// ---------------------------------------------------------------------------- -float GeometrySchlickGGX(float NdotV, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - - float nom = NdotV; - float denom = NdotV * (1.0 - k) + k; - - return nom / denom; -} -// ---------------------------------------------------------------------------- -float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) -{ - float NdotV = max(dot(N, V), 0.0); - float NdotL = max(dot(N, L), 0.0); - float ggx2 = GeometrySchlickGGX(NdotV, roughness); - float ggx1 = GeometrySchlickGGX(NdotL, roughness); - - return ggx1 * ggx2; -} -// ---------------------------------------------------------------------------- -vec3 fresnelSchlick(float cosTheta, vec3 F0) -{ - return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); -} - -varying highp vec3 vert; -varying highp vec3 vertNormal; -varying highp vec3 vertColor; -varying highp vec2 vertTexCoord; -varying highp float vertMetalness; -varying highp float vertRoughness; -varying highp vec3 cameraPos; -uniform highp vec3 lightPos; -uniform highp sampler2D textureId; -uniform highp int textureEnabled; - -const int MAX_LIGHTS = 8; -struct Light { - vec3 position; - vec3 color; - float intensity; -}; -int lightCount; -Light lights[MAX_LIGHTS]; - -void main() -{ - const highp float vertAmbientOcclusion = 1.0; - - vec3 albedo = vertColor; - if (textureEnabled == 1) { - albedo = texture2D(textureId, vertTexCoord).rgb; - } - albedo = pow(albedo, vec3(2.2)); - - lightCount = 3; - float roughness = vertRoughness; - float metalness = vertMetalness; - - // Key light - lights[0].position = vec3(5.0, 5.0, 5.0); - lights[0].color = vec3(150.0, 150.0, 150.0); - lights[0].intensity = 0.8; - - // Fill light - lights[1].position = vec3(-5.0, 5.0, 5.0); - lights[1].color = vec3(150.0, 150.0, 150.0); - lights[1].intensity = 0.4; - - // Rim light - lights[2].position = vec3(0.0, -2.5, -5.0); - lights[2].color = vec3(150.0, 150.0, 150.0); - lights[2].intensity = 0.2; - - vec3 N = normalize(vertNormal); - vec3 V = normalize(cameraPos - vert); - - // calculate reflectance at normal incidence; if dia-electric (like plastic) use F0 - // of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow) - vec3 F0 = vec3(0.04); - F0 = mix(F0, albedo, metalness); - - // reflectance equation - vec3 Lo = vec3(0.0); - for (int i = 0; i < lightCount; ++i) - { - // calculate per-light radiance - vec3 L = normalize(lights[i].position - vert); - vec3 H = normalize(V + L); - float distance = length(lights[i].position - vert); - float attenuation = 1.0 / (distance * distance); - vec3 radiance = lights[i].color * attenuation; - - // Cook-Torrance BRDF - float NDF = DistributionGGX(N, H, roughness); - float G = GeometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0); - - vec3 nominator = NDF * G * F; - float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0); - vec3 specular = nominator / max(denominator, 0.001); // prevent divide by zero for NdotV=0.0 or NdotL=0.0 - - // kS is equal to Fresnel - vec3 kS = F; - // for energy conservation, the diffuse and specular light can't - // be above 1.0 (unless the surface emits light); to preserve this - // relationship the diffuse component (kD) should equal 1.0 - kS. - vec3 kD = vec3(1.0) - kS; - // multiply kD by the inverse metalness such that only non-metals - // have diffuse lighting, or a linear blend if partly metal (pure metals - // have no diffuse light). - kD *= 1.0 - metalness; - - // scale light by NdotL - float NdotL = max(dot(N, L), 0.0); - - // add to outgoing radiance Lo - Lo += lights[i].intensity * (kD * albedo / PI + specular) * radiance * NdotL; // note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again - } - - // ambient lighting (note that the next IBL tutorial will replace - // this ambient lighting with environment lighting). - vec3 ambient = vec3(0.03) * albedo * vertAmbientOcclusion; - - vec3 color = ambient + Lo; - - // HDR tonemapping - color = color / (color + vec3(1.0)); - // gamma correct - color = pow(color, vec3(1.0/2.2)); - - gl_FragColor = vec4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/pbr-qt.frag b/shaders/pbr-qt.frag deleted file mode 100644 index 401f7b56..00000000 --- a/shaders/pbr-qt.frag +++ /dev/null @@ -1,373 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -// Please note that, this file "pbr.frag" is copied and slightly modified from the Qt3D's pbr shader "metalrough.inc.frag" -// https://github.com/qt/qt3d/blob/5.11/src/extras/shaders/gl3/metalrough.inc.frag - -// Exposure correction -highp float exposure; -// Gamma correction -highp float gamma; - -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 vec3 lightPos; -uniform highp sampler2D textureId; -uniform highp int textureEnabled; -uniform highp sampler2D normalMapId; -uniform highp int normalMapEnabled; -uniform highp sampler2D metalnessRoughnessAmbientOcclusionMapId; -uniform highp int metalnessMapEnabled; -uniform highp int roughnessMapEnabled; -uniform highp int ambientOcclusionMapEnabled; -uniform highp int mousePickEnabled; -uniform highp vec3 mousePickTargetPosition; -uniform highp float mousePickRadius; - -const int MAX_LIGHTS = 8; -const int TYPE_POINT = 0; -const int TYPE_DIRECTIONAL = 1; -const int TYPE_SPOT = 2; -struct Light { - int type; - highp vec3 position; - highp vec3 color; - highp float intensity; - highp vec3 direction; - highp float constantAttenuation; - highp float linearAttenuation; - highp float quadraticAttenuation; - highp float cutOffAngle; -}; -int lightCount; -Light lights[MAX_LIGHTS]; - -highp float remapRoughness(const in highp 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 - highp float maxSpecPower; - highp float minRoughness; - maxSpecPower = 999999.0; - minRoughness = sqrt(2.0 / (maxSpecPower + 2.0)); - return max(roughness * roughness, minRoughness); -} - -highp float normalDistribution(const in highp vec3 n, const in highp vec3 h, const in highp float alpha) -{ - // Blinn-Phong approximation - see - // http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html - highp float specPower = 2.0 / (alpha * alpha) - 2.0; - return (specPower + 2.0) / (2.0 * 3.14159) * pow(max(dot(n, h), 0.0), specPower); -} - -highp vec3 fresnelFactor(const in highp vec3 color, const in highp float cosineFactor) -{ - // Calculate the Fresnel effect value - highp vec3 f = color; - highp vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0); - return clamp(F, f, vec3(1.0)); -} - -highp float geometricModel(const in highp float lDotN, - const in highp float vDotN, - const in highp 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; -} - -highp vec3 specularModel(const in highp vec3 F0, - const in highp float sDotH, - const in highp float sDotN, - const in highp float vDotN, - const in highp vec3 n, - const in highp 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. - highp float sDotNPrime = max(sDotN, 0.001); - highp float vDotNPrime = max(vDotN, 0.001); - - highp vec3 F = fresnelFactor(F0, sDotH); - highp float G = geometricModel(sDotNPrime, vDotNPrime, h); - - highp vec3 cSpec = F * G / (4.0 * sDotNPrime * vDotNPrime); - return clamp(cSpec, vec3(0.0), vec3(1.0)); -} - -highp vec3 pbrModel(const in int lightIndex, - const in highp vec3 wPosition, - const in highp vec3 wNormal, - const in highp vec3 wView, - const in highp vec3 baseColor, - const in highp float metalness, - const in highp float alpha, - const in highp float ambientOcclusion) -{ - // Calculate some useful quantities - highp vec3 n = wNormal; - highp vec3 s = vec3(0.0); - highp vec3 v = wView; - highp vec3 h = vec3(0.0); - - highp float vDotN = dot(v, n); - highp float sDotN = 0.0; - highp float sDotH = 0.0; - highp float att = 1.0; - - if (lights[lightIndex].type != TYPE_DIRECTIONAL) { - // Point and Spot lights - highp 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) { - highp 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 - highp vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color; - highp vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159; - - // Calculate specular component - highp vec3 dielectricColor = vec3(0.04); - highp vec3 F0 = mix(dielectricColor, baseColor, metalness); - highp vec3 specularFactor = vec3(0.0); - if (sDotN > 0.0) { - specularFactor = specularModel(F0, sDotH, sDotN, vDotN, n, h); - specularFactor *= normalDistribution(n, h, alpha); - } - highp vec3 specularColor = lights[lightIndex].color; - highp vec3 specular = specularColor * specularFactor; - - // Blend between diffuse and specular to conserver energy - highp vec3 color = att * lights[lightIndex].intensity * (specular + diffuse * (vec3(1.0) - specular)); - - // Reduce by ambient occlusion amount - color *= ambientOcclusion; - - return color; -} - -highp vec3 toneMap(const in highp vec3 c) -{ - return c / (c + vec3(1.0)); -} - -highp vec3 gammaCorrect(const in highp vec3 color) -{ - return pow(color, vec3(1.0 / gamma)); -} - -highp vec4 metalRoughFunction(const in highp vec4 baseColor, - const in highp float metalness, - const in highp float roughness, - const in highp float ambientOcclusion, - const in highp vec3 worldPosition, - const in highp vec3 worldView, - const in highp vec3 worldNormal) -{ - highp vec3 cLinear = vec3(0.0); - - // Remap roughness for a perceptually more linear correspondence - highp float alpha = remapRoughness(roughness); - - 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] - highp vec3 cToneMapped = toneMap(cLinear); - - // Apply gamma correction prior to display - highp vec3 cGamma = gammaCorrect(cToneMapped); - - return vec4(cGamma, baseColor.a); -} - -void main() -{ - // FIXME: don't hard code here - exposure = 1.0; - gamma = 2.2; - - // Light settings: - // https://doc-snapshots.qt.io/qt5-5.12/qt3d-pbr-materials-lights-qml.html - lightCount = 3; - - // Key light - lights[0].type = TYPE_POINT; - lights[0].position = firstLightPos; - lights[0].color = vec3(1.0, 1.0, 1.0); - lights[0].intensity = 3.0; - lights[0].constantAttenuation = 0.0; - lights[0].linearAttenuation = 0.0; - lights[0].quadraticAttenuation = 0.0; - - // Fill light - lights[1].type = TYPE_POINT; - lights[1].position = secondLightPos; - lights[1].color = vec3(1.0, 1.0, 1.0); - lights[1].intensity = 1.0; - lights[1].constantAttenuation = 0.0; - lights[1].linearAttenuation = 0.0; - lights[1].quadraticAttenuation = 0.0; - - // Rim light - lights[2].type = TYPE_POINT; - lights[2].position = thirdLightPos; - lights[2].color = vec3(1.0, 1.0, 1.0); - lights[2].intensity = 0.5; - lights[2].constantAttenuation = 0.0; - lights[2].linearAttenuation = 0.0; - lights[2].quadraticAttenuation = 0.0; - - highp vec3 color = vertColor; - highp float alpha = vertAlpha; - if (textureEnabled == 1) { - highp vec4 textColor = texture2D(textureId, vertTexCoord); - color = textColor.rgb; - alpha = textColor.a; - } - if (mousePickEnabled == 1) { - if (distance(mousePickTargetPosition, vertRaw) <= mousePickRadius) { - color = color + vec3(0.99, 0.4, 0.13); - } - } - color = pow(color, vec3(gamma)); - - highp vec3 normal = vertNormal; - if (normalMapEnabled == 1) { - normal = texture2D(normalMapId, vertTexCoord).rgb; - normal = normalize(normal * 2.0 - 1.0); - } - - // Red: Ambient Occlusion - // Green: Roughness - // Blue: Metallic - - highp float metalness = vertMetalness; - if (metalnessMapEnabled == 1) { - metalness = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).b; - } - - highp float roughness = vertRoughness; - if (roughnessMapEnabled == 1) { - roughness = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).g; - } - - highp float ambientOcclusion = 1.0; - if (ambientOcclusionMapEnabled == 1) { - ambientOcclusion = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).r; - } - - roughness = min(0.99, roughness); - metalness = min(0.99, metalness); - - gl_FragColor = metalRoughFunction(vec4(color, alpha), - metalness, - roughness, - ambientOcclusion, - vert, - normalize(cameraPos - vert), - normal); -} diff --git a/src/main.cpp b/src/main.cpp index e376cb2e..1882165b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,7 +20,8 @@ int main(int argc, char ** argv) app.installTranslator(&translator); QSurfaceFormat format = QSurfaceFormat::defaultFormat(); - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); + format.setVersion(3, 3); QSurfaceFormat::setDefaultFormat(format); // QuantumCD/Qt 5 Dark Fusion Palette diff --git a/src/modelshaderprogram.cpp b/src/modelshaderprogram.cpp index fdde882d..5f268ef0 100644 --- a/src/modelshaderprogram.cpp +++ b/src/modelshaderprogram.cpp @@ -17,18 +17,14 @@ const QString &ModelShaderProgram::loadShaderSource(const QString &name) return insertResult.first->second; } -ModelShaderProgram::ModelShaderProgram(bool usePBR) +ModelShaderProgram::ModelShaderProgram() { if (QSurfaceFormat::defaultFormat().profile() == QSurfaceFormat::CoreProfile) { this->addShaderFromSourceCode(QOpenGLShader::Vertex, loadShaderSource(":/shaders/default.core.vert")); this->addShaderFromSourceCode(QOpenGLShader::Fragment, loadShaderSource(":/shaders/default.core.frag")); } else { this->addShaderFromSourceCode(QOpenGLShader::Vertex, loadShaderSource(":/shaders/default.vert")); - if (usePBR) { - this->addShaderFromSourceCode(QOpenGLShader::Fragment, loadShaderSource(":/shaders/pbr-qt.frag")); - } else { - this->addShaderFromSourceCode(QOpenGLShader::Fragment, loadShaderSource(":/shaders/default.frag")); - } + this->addShaderFromSourceCode(QOpenGLShader::Fragment, loadShaderSource(":/shaders/default.frag")); } this->bindAttributeLocation("vertex", 0); this->bindAttributeLocation("normal", 1); diff --git a/src/modelshaderprogram.h b/src/modelshaderprogram.h index abe42f72..7dec642d 100644 --- a/src/modelshaderprogram.h +++ b/src/modelshaderprogram.h @@ -6,7 +6,7 @@ class ModelShaderProgram : public QOpenGLShaderProgram { public: - ModelShaderProgram(bool usePBR=true); + ModelShaderProgram(); int projectionMatrixLoc(); int modelMatrixLoc(); int normalMatrixLoc();