summaryrefslogtreecommitdiffstats
path: root/src/extras/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'src/extras/shaders')
-rw-r--r--src/extras/shaders/es2/phong.inc.frag1008
-rw-r--r--src/extras/shaders/es3/light.inc.frag1
-rw-r--r--src/extras/shaders/es3/metalrough.inc.frag11
-rw-r--r--src/extras/shaders/gl3/light.inc.frag1
-rw-r--r--src/extras/shaders/gl3/metalrough.inc.frag11
-rw-r--r--src/extras/shaders/graphs/phong.graph466
-rw-r--r--src/extras/shaders/rhi/coordinatesystems.inc70
-rw-r--r--src/extras/shaders/rhi/default.vert107
-rw-r--r--src/extras/shaders/rhi/defaultuniforms.inc30
-rw-r--r--src/extras/shaders/rhi/distancefieldtext.frag41
-rw-r--r--src/extras/shaders/rhi/distancefieldtext.vert26
-rw-r--r--src/extras/shaders/rhi/gooch.frag111
-rw-r--r--src/extras/shaders/rhi/gooch.vert25
-rw-r--r--src/extras/shaders/rhi/light.inc.frag28
-rw-r--r--src/extras/shaders/rhi/metalrough.inc.frag341
-rw-r--r--src/extras/shaders/rhi/morphphong.vert43
-rw-r--r--src/extras/shaders/rhi/pervertexcolor.frag150
-rw-r--r--src/extras/shaders/rhi/pervertexcolor.vert28
-rw-r--r--src/extras/shaders/rhi/phong.inc.frag138
-rw-r--r--src/extras/shaders/rhi/skybox.frag44
-rw-r--r--src/extras/shaders/rhi/skybox.vert39
-rw-r--r--src/extras/shaders/rhi/unlittexture.frag13
-rw-r--r--src/extras/shaders/rhi/unlittexture.vert47
23 files changed, 1755 insertions, 24 deletions
diff --git a/src/extras/shaders/es2/phong.inc.frag100 b/src/extras/shaders/es2/phong.inc.frag100
index 0c326d0b6..c68c8e41a 100644
--- a/src/extras/shaders/es2/phong.inc.frag100
+++ b/src/extras/shaders/es2/phong.inc.frag100
@@ -66,8 +66,8 @@ void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3
if ( lights[0].type != TYPE_DIRECTIONAL ) {
s = lights[0].position - vpos;
if (lights[0].constantAttenuation != 0.0
- || light[0].linearAttenuation != 0.0
- || light[0].quadraticAttenuation != 0.0) {
+ || lights[0].linearAttenuation != 0.0
+ || lights[0].quadraticAttenuation != 0.0) {
FP float dist = length(s);
att = 1.0 / (lights[0].constantAttenuation + lights[0].linearAttenuation * dist + lights[0].quadraticAttenuation * dist * dist);
}
@@ -99,8 +99,8 @@ void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3
if ( lights[1].type != TYPE_DIRECTIONAL ) {
s = lights[1].position - vpos;
if (lights[1].constantAttenuation != 0.0
- || light[1].linearAttenuation != 0.0
- || light[1].quadraticAttenuation != 0.0) {
+ || lights[1].linearAttenuation != 0.0
+ || lights[1].quadraticAttenuation != 0.0) {
FP float dist = length(s);
att = 1.0 / (lights[1].constantAttenuation + lights[1].linearAttenuation * dist + lights[1].quadraticAttenuation * dist * dist);
}
diff --git a/src/extras/shaders/es3/light.inc.frag b/src/extras/shaders/es3/light.inc.frag
index 18012ccc1..7b6bf3bc5 100644
--- a/src/extras/shaders/es3/light.inc.frag
+++ b/src/extras/shaders/es3/light.inc.frag
@@ -20,6 +20,7 @@ uniform int lightCount;
struct EnvironmentLight {
highp samplerCube irradiance; // For diffuse contribution
highp samplerCube specular; // For specular contribution
+ int specularMipLevels;
};
uniform EnvironmentLight envLight;
uniform int envLightCount;
diff --git a/src/extras/shaders/es3/metalrough.inc.frag b/src/extras/shaders/es3/metalrough.inc.frag
index 188a367f5..fc014b81b 100644
--- a/src/extras/shaders/es3/metalrough.inc.frag
+++ b/src/extras/shaders/es3/metalrough.inc.frag
@@ -59,13 +59,6 @@ const FP float gamma = 2.2;
#pragma include light.inc.frag
-int mipLevelCount(const in FP samplerCube cube)
-{
- int baseSize = textureSize(cube, 0).x;
- int nMips = int(log2(float(baseSize > 0 ? baseSize : 1))) + 1;
- return nMips;
-}
-
FP float remapRoughness(const in FP float roughness)
{
// As per page 14 of
@@ -91,10 +84,8 @@ FP float alphaToMipLevel(FP float alpha)
const FP float k1 = 0.9921;
FP 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);
+ int mipLevels = envLight.specularMipLevels;
// Offset of smallest miplevel we should use (corresponds to specular
// power of 1). I.e. in the 32x32 sized mip.
diff --git a/src/extras/shaders/gl3/light.inc.frag b/src/extras/shaders/gl3/light.inc.frag
index 0b642638f..a1b07a976 100644
--- a/src/extras/shaders/gl3/light.inc.frag
+++ b/src/extras/shaders/gl3/light.inc.frag
@@ -20,6 +20,7 @@ uniform int lightCount;
struct EnvironmentLight {
samplerCube irradiance; // For diffuse contribution
samplerCube specular; // For specular contribution
+ int specularMipLevels;
};
uniform EnvironmentLight envLight;
uniform int envLightCount = 0;
diff --git a/src/extras/shaders/gl3/metalrough.inc.frag b/src/extras/shaders/gl3/metalrough.inc.frag
index f7e3eecb7..f5fb81f51 100644
--- a/src/extras/shaders/gl3/metalrough.inc.frag
+++ b/src/extras/shaders/gl3/metalrough.inc.frag
@@ -55,13 +55,6 @@ uniform 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
@@ -87,10 +80,8 @@ float alphaToMipLevel(float alpha)
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);
+ int mipLevels = envLight.specularMipLevels;
// Offset of smallest miplevel we should use (corresponds to specular
// power of 1). I.e. in the 32x32 sized mip.
diff --git a/src/extras/shaders/graphs/phong.graph b/src/extras/shaders/graphs/phong.graph
new file mode 100644
index 000000000..dedeb1067
--- /dev/null
+++ b/src/extras/shaders/graphs/phong.graph
@@ -0,0 +1,466 @@
+{
+ "nodes": [
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000001}",
+ "type": "input",
+ "parameters": {
+ "name": "worldPosition",
+ "qualifier": {
+ "type": "QShaderLanguage::StorageQualifier",
+ "value": "QShaderLanguage::Input"
+ },
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec3"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000002}",
+ "type": "eyePosition"
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000003}",
+ "type": "input",
+ "parameters": {
+ "name": "worldNormal",
+ "qualifier": {
+ "type": "QShaderLanguage::StorageQualifier",
+ "value": "QShaderLanguage::Input"
+ },
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec3"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000004}",
+ "type": "input",
+ "layers": ["normalTexture"],
+ "parameters": {
+ "name": "worldTangent",
+ "qualifier": {
+ "type": "QShaderLanguage::StorageQualifier",
+ "value": "QShaderLanguage::Input"
+ },
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec4"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000005}",
+ "type": "input",
+ "layers": ["diffuseTexture", "specularTexture", "normalTexture"],
+ "parameters": {
+ "name": "texCoord",
+ "qualifier": {
+ "type": "QShaderLanguage::StorageQualifier",
+ "value": "QShaderLanguage::Input"
+ },
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec2"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000006}",
+ "type": "input",
+ "parameters": {
+ "name": "ka",
+ "qualifier": {
+ "type": "QShaderLanguage::StorageQualifier",
+ "value": "QShaderLanguage::Uniform"
+ },
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec4"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000007}",
+ "type": "input",
+ "layers": ["diffuse"],
+ "parameters": {
+ "name": "kd",
+ "qualifier": {
+ "type": "QShaderLanguage::StorageQualifier",
+ "value": "QShaderLanguage::Uniform"
+ },
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec4"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000008}",
+ "type": "sampleTexture",
+ "layers": ["diffuseTexture"],
+ "parameters": {
+ "name": "diffuseTexture"
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000009}",
+ "type": "input",
+ "layers": ["specular"],
+ "parameters": {
+ "name": "ks",
+ "qualifier": {
+ "type": "QShaderLanguage::StorageQualifier",
+ "value": "QShaderLanguage::Uniform"
+ },
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec4"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000010}",
+ "layers": ["specularTexture"],
+ "type": "sampleTexture",
+ "parameters": {
+ "name": "specularTexture"
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000011}",
+ "type": "input",
+ "parameters": {
+ "name": "shininess",
+ "qualifier": {
+ "type": "QShaderLanguage::StorageQualifier",
+ "value": "QShaderLanguage::Uniform"
+ },
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Float"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000012}",
+ "type": "subtract",
+ "parameters": {
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec3"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000013}",
+ "type": "normalize",
+ "parameters": {
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec3"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000014}",
+ "type": "normalize",
+ "parameters": {
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec3"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000015}",
+ "type": "worldSpaceToTangentSpaceMatrix",
+ "layers": ["normalTexture"]
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000016}",
+ "type": "transpose",
+ "layers": ["normalTexture"],
+ "parameters": {
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Mat3"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000017}",
+ "type": "sampleTexture",
+ "layers": ["normalTexture"],
+ "parameters": {
+ "name": "normalTexture"
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000018}",
+ "type": "swizzle",
+ "layers": ["normalTexture"],
+ "parameters": {
+ "fields": "rgb",
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec3"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000019}",
+ "type": "constant",
+ "layers": ["normalTexture"],
+ "parameters": {
+ "constant": "2.0",
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Float"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000020}",
+ "type": "multiply",
+ "layers": ["normalTexture"],
+ "parameters": {
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec3"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000021}",
+ "type": "constant",
+ "layers": ["normalTexture"],
+ "parameters": {
+ "constant": "1.0",
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec3"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000022}",
+ "type": "subtract",
+ "parameters": {
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec3"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000023}",
+ "type": "multiply",
+ "parameters": {
+ "type": {
+ "type": "QShaderLanguage::VariableType",
+ "value": "QShaderLanguage::Vec3"
+ }
+ }
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000024}",
+ "type": "phongFunction"
+ },
+ {
+ "uuid": "{00000000-0000-0000-0000-000000000025}",
+ "type": "fragColor"
+ }
+ ],
+ "edges": [
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000001}",
+ "sourcePort": "value",
+ "targetUuid": "{00000000-0000-0000-0000-000000000024}",
+ "targetPort": "worldPosition"
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000001}",
+ "sourcePort": "value",
+ "targetUuid": "{00000000-0000-0000-0000-000000000012}",
+ "targetPort": "subtrahend"
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000002}",
+ "sourcePort": "eyePosition",
+ "targetUuid": "{00000000-0000-0000-0000-000000000012}",
+ "targetPort": "minuend"
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000012}",
+ "sourcePort": "difference",
+ "targetUuid": "{00000000-0000-0000-0000-000000000013}",
+ "targetPort": "input"
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000013}",
+ "sourcePort": "output",
+ "targetUuid": "{00000000-0000-0000-0000-000000000024}",
+ "targetPort": "worldView"
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000003}",
+ "sourcePort": "value",
+ "targetUuid": "{00000000-0000-0000-0000-000000000014}",
+ "targetPort": "input",
+ "layers": ["normal"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000003}",
+ "sourcePort": "value",
+ "targetUuid": "{00000000-0000-0000-0000-000000000015}",
+ "targetPort": "worldNormal",
+ "layers": ["normalTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000004}",
+ "sourcePort": "value",
+ "targetUuid": "{00000000-0000-0000-0000-000000000015}",
+ "targetPort": "worldTangent",
+ "layers": ["normalTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000015}",
+ "sourcePort": "matrix",
+ "targetUuid": "{00000000-0000-0000-0000-000000000016}",
+ "targetPort": "input",
+ "layers": ["normalTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000016}",
+ "sourcePort": "output",
+ "targetUuid": "{00000000-0000-0000-0000-000000000023}",
+ "targetPort": "first",
+ "layers": ["normalTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000005}",
+ "sourcePort": "value",
+ "targetUuid": "{00000000-0000-0000-0000-000000000017}",
+ "targetPort": "coord",
+ "layers": ["normalTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000017}",
+ "sourcePort": "color",
+ "targetUuid": "{00000000-0000-0000-0000-000000000018}",
+ "targetPort": "input",
+ "layers": ["normalTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000018}",
+ "sourcePort": "output",
+ "targetUuid": "{00000000-0000-0000-0000-000000000020}",
+ "targetPort": "first",
+ "layers": ["normalTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000019}",
+ "sourcePort": "value",
+ "targetUuid": "{00000000-0000-0000-0000-000000000020}",
+ "targetPort": "second",
+ "layers": ["normalTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000020}",
+ "sourcePort": "product",
+ "targetUuid": "{00000000-0000-0000-0000-000000000022}",
+ "targetPort": "minuend",
+ "layers": ["normalTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000021}",
+ "sourcePort": "value",
+ "targetUuid": "{00000000-0000-0000-0000-000000000022}",
+ "targetPort": "subtrahend",
+ "layers": ["normalTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000022}",
+ "sourcePort": "difference",
+ "targetUuid": "{00000000-0000-0000-0000-000000000023}",
+ "targetPort": "second",
+ "layers": ["normalTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000023}",
+ "sourcePort": "product",
+ "targetUuid": "{00000000-0000-0000-0000-000000000014}",
+ "targetPort": "input",
+ "layers": ["normalTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000014}",
+ "sourcePort": "output",
+ "targetUuid": "{00000000-0000-0000-0000-000000000024}",
+ "targetPort": "worldNormal"
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000006}",
+ "sourcePort": "value",
+ "targetUuid": "{00000000-0000-0000-0000-000000000024}",
+ "targetPort": "ambient"
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000007}",
+ "sourcePort": "value",
+ "targetUuid": "{00000000-0000-0000-0000-000000000024}",
+ "targetPort": "diffuse",
+ "layers": ["diffuse"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000005}",
+ "sourcePort": "value",
+ "targetUuid": "{00000000-0000-0000-0000-000000000008}",
+ "targetPort": "coord",
+ "layers": ["diffuseTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000008}",
+ "sourcePort": "color",
+ "targetUuid": "{00000000-0000-0000-0000-000000000024}",
+ "targetPort": "diffuse",
+ "layers": ["diffuseTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000009}",
+ "sourcePort": "value",
+ "targetUuid": "{00000000-0000-0000-0000-000000000024}",
+ "targetPort": "specular",
+ "layers": ["specular"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000005}",
+ "sourcePort": "value",
+ "targetUuid": "{00000000-0000-0000-0000-000000000010}",
+ "targetPort": "coord",
+ "layers": ["specularTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000010}",
+ "sourcePort": "color",
+ "targetUuid": "{00000000-0000-0000-0000-000000000024}",
+ "targetPort": "specular",
+ "layers": ["specularTexture"]
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000011}",
+ "sourcePort": "value",
+ "targetUuid": "{00000000-0000-0000-0000-000000000024}",
+ "targetPort": "shininess"
+ },
+ {
+ "sourceUuid": "{00000000-0000-0000-0000-000000000024}",
+ "sourcePort": "outputColor",
+ "targetUuid": "{00000000-0000-0000-0000-000000000025}",
+ "targetPort": "fragColor"
+ }
+ ]
+}
diff --git a/src/extras/shaders/rhi/coordinatesystems.inc b/src/extras/shaders/rhi/coordinatesystems.inc
new file mode 100644
index 000000000..ed3d2cb92
--- /dev/null
+++ b/src/extras/shaders/rhi/coordinatesystems.inc
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+mat3 calcWorldSpaceToTangentSpaceMatrix(const in vec3 wNormal, const in vec4 wTangent)
+{
+ // Make the tangent truly orthogonal to the normal by using Gram-Schmidt.
+ // This allows to build the tangentMatrix below by simply transposing the
+ // tangent -> eyespace matrix (which would now be orthogonal)
+ vec3 wFixedTangent = normalize(wTangent.xyz - dot(wTangent.xyz, wNormal) * wNormal);
+
+ // Calculate binormal vector. No "real" need to renormalize it,
+ // as built by crossing two normal vectors.
+ // To orient the binormal correctly, use the fourth coordinate of the tangent,
+ // which is +1 for a right hand system, and -1 for a left hand system.
+ vec3 wBinormal = cross(wNormal, wFixedTangent.xyz) * wTangent.w;
+
+ // Construct matrix to transform from world space to tangent space
+ // This is the transpose of the tangentToWorld transformation matrix
+ mat3 tangentToWorldMatrix = mat3(wFixedTangent, wBinormal, wNormal);
+ mat3 worldToTangentMatrix = transpose(tangentToWorldMatrix);
+ return worldToTangentMatrix;
+}
+
diff --git a/src/extras/shaders/rhi/default.vert b/src/extras/shaders/rhi/default.vert
new file mode 100644
index 000000000..5679d8681
--- /dev/null
+++ b/src/extras/shaders/rhi/default.vert
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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 450
+
+layout(location = 0) in vec3 vertexPosition;
+layout(location = 1) in vec3 vertexNormal;
+layout(location = 2) in vec4 vertexTangent;
+layout(location = 3) in vec2 vertexTexCoord;
+
+layout(location = 0) out vec3 worldPosition;
+layout(location = 1) out vec3 worldNormal;
+layout(location = 2) out vec4 worldTangent;
+layout(location = 3) out vec2 texCoord;
+
+layout(std140, binding = 0) uniform qt3d_render_view_uniforms {
+ mat4 viewMatrix;
+ mat4 projectionMatrix;
+ mat4 viewProjectionMatrix;
+ mat4 inverseViewMatrix;
+ mat4 inverseProjectionMatrix;
+ mat4 inverseViewProjectionMatrix;
+ mat4 viewportMatrix;
+ mat4 inverseViewportMatrix;
+ vec4 textureTransformMatrix;
+ vec3 eyePosition;
+ float aspectRatio;
+ float gamma;
+ float exposure;
+ float time;
+};
+
+layout(std140, binding = 1) uniform qt3d_command_uniforms {
+ mat4 modelMatrix;
+ mat4 inverseModelMatrix;
+ mat4 modelViewMatrix;
+ mat3 modelNormalMatrix;
+ mat4 inverseModelViewMatrix;
+ mat4 modelViewProjection;
+ mat4 inverseModelViewProjectionMatrix;
+};
+
+layout(std140, binding = 2) uniform qt3d_extras_uniforms {
+ 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);
+ vec3 wt = normalize(vec3(modelMatrix * vec4(vertexTangent.xyz, 0.0)));
+ worldTangent = vec4(wt, vertexTangent.w);
+
+ // Calculate vertex position in clip coordinates
+ gl_Position = modelViewProjection * vec4(vertexPosition, 1.0);
+}
diff --git a/src/extras/shaders/rhi/defaultuniforms.inc b/src/extras/shaders/rhi/defaultuniforms.inc
new file mode 100644
index 000000000..ad2c51d50
--- /dev/null
+++ b/src/extras/shaders/rhi/defaultuniforms.inc
@@ -0,0 +1,30 @@
+layout(std140, binding = auto) uniform qt3d_render_view_uniforms {
+ mat4 viewMatrix;
+ mat4 projectionMatrix;
+ mat4 viewProjectionMatrix;
+ mat4 inverseViewMatrix;
+ mat4 inverseProjectionMatrix;
+ mat4 inverseViewProjectionMatrix;
+ mat4 viewportMatrix;
+ mat4 inverseViewportMatrix;
+ vec4 textureTransformMatrix;
+ vec3 eyePosition;
+ float aspectRatio;
+ float gamma;
+ float exposure;
+ float time;
+};
+
+layout(std140, binding = auto) uniform qt3d_command_uniforms {
+ mat4 modelMatrix;
+ mat4 inverseModelMatrix;
+ mat4 modelViewMatrix;
+ mat3 modelNormalMatrix;
+ mat4 inverseModelViewMatrix;
+ mat4 mvp;
+ mat4 inverseModelViewProjectionMatrix;
+};
+
+layout(std140, binding = auto) uniform qt3d_extras_uniforms {
+ float texCoordScale;
+};
diff --git a/src/extras/shaders/rhi/distancefieldtext.frag b/src/extras/shaders/rhi/distancefieldtext.frag
new file mode 100644
index 000000000..ec42f5056
--- /dev/null
+++ b/src/extras/shaders/rhi/distancefieldtext.frag
@@ -0,0 +1,41 @@
+#version 450
+
+layout(location = 0) in vec2 texCoord;
+layout(location = 1) in float zValue;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 2) uniform qt3d_custom_uniforms {
+ float minAlpha;
+ float maxAlpha;
+ float textureSize;
+ vec4 color;
+};
+layout(binding = 3) uniform sampler2D distanceFieldTexture;
+
+void main()
+{
+ // determine the scale of the glyph texture within pixel-space coordinates
+ // (that is, how many pixels are drawn for each texel)
+ vec2 texelDeltaX = abs(dFdx(texCoord));
+ vec2 texelDeltaY = abs(dFdy(texCoord));
+ float avgTexelDelta = textureSize * 0.5 * (texelDeltaX.x + texelDeltaX.y + texelDeltaY.x + texelDeltaY.y);
+ float texScale = 1.0 / avgTexelDelta;
+
+ // scaled to interval [0.0, 0.15]
+ float devScaleMin = 0.00;
+ float devScaleMax = 0.15;
+ float scaled = (clamp(texScale, devScaleMin, devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin);
+
+ // thickness of glyphs should increase a lot for very small glyphs to make them readable
+ float base = 0.5;
+ float threshold = base * scaled;
+ float range = 0.06 / texScale;
+
+ float minAlpha = threshold - range;
+ float maxAlpha = threshold + range;
+
+ float distVal = texture(distanceFieldTexture, texCoord).r;
+ fragColor = vec4(color.rgb, color.a * smoothstep(minAlpha, maxAlpha, distVal));
+ gl_FragDepth = gl_FragCoord.z - zValue * 0.000001;
+}
diff --git a/src/extras/shaders/rhi/distancefieldtext.vert b/src/extras/shaders/rhi/distancefieldtext.vert
new file mode 100644
index 000000000..02efc898f
--- /dev/null
+++ b/src/extras/shaders/rhi/distancefieldtext.vert
@@ -0,0 +1,26 @@
+#version 450
+
+layout(location = 0) in vec3 vertexPosition;
+layout(location = 1) in vec2 vertexTexCoord;
+
+layout(location = 0) out vec2 texCoord;
+layout(location = 1) out float zValue;
+
+layout(std140, binding = 1) uniform qt3d_command_uniforms {
+ mat4 modelMatrix;
+ mat4 inverseModelMatrix;
+ mat4 modelViewMatrix;
+ mat3 modelNormalMatrix;
+ mat4 inverseModelViewMatrix;
+ mat4 mvp;
+ mat4 inverseModelViewProjectionMatrix;
+};
+
+void main()
+{
+ texCoord = vertexTexCoord;
+ zValue = vertexPosition.z;
+
+ gl_Position = mvp * vec4(vertexPosition.xy, 0.0, 1.0);
+}
+
diff --git a/src/extras/shaders/rhi/gooch.frag b/src/extras/shaders/rhi/gooch.frag
new file mode 100644
index 000000000..8a0a32f18
--- /dev/null
+++ b/src/extras/shaders/rhi/gooch.frag
@@ -0,0 +1,111 @@
+#version 450
+
+layout(location = 0) in vec3 worldPosition;
+layout(location = 1) in vec3 worldNormal;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform qt3d_render_view_uniforms {
+ mat4 viewMatrix;
+ mat4 projectionMatrix;
+ mat4 viewProjectionMatrix;
+ mat4 inverseViewMatrix;
+ mat4 inverseProjectionMatrix;
+ mat4 inverseViewProjectionMatrix;
+ mat4 viewportMatrix;
+ mat4 inverseViewportMatrix;
+ vec4 textureTransformMatrix;
+ vec3 eyePosition;
+ float aspectRatio;
+ float gamma;
+ float exposure;
+ float time;
+};
+
+layout(std140, binding = 1) uniform qt3d_command_uniforms {
+ mat4 modelMatrix;
+ mat4 inverseModelMatrix;
+ mat4 modelViewMatrix;
+ mat3 modelNormalMatrix;
+ mat4 inverseModelViewMatrix;
+ mat4 mvp;
+ mat4 inverseModelViewProjectionMatrix;
+};
+
+layout(std140, binding = 2) uniform qt3d_custom_uniforms {
+ vec3 kd; // Diffuse reflectivity
+ vec3 ks; // Specular reflectivity
+ vec3 kblue; // Cool color
+ vec3 kyellow; // Warm color
+ float alpha; // Fraction of diffuse added to kblue
+ float beta; // Fraction of diffuse added to kyellow
+ float shininess; // Specular shininess factor
+};
+
+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;
+};
+
+layout(std140, binding = 3) uniform qt3d_light_uniforms {
+ uniform Light lights[MAX_LIGHTS];
+ uniform int lightCount;
+ uniform int envLightCount;
+};
+
+
+vec3 goochModel( const in vec3 pos, const in vec3 n )
+{
+ // Based upon the original Gooch lighting model paper at:
+ // http://www.cs.northwestern.edu/~ago820/SIG98/abstract.html
+
+ // Calculate kcool and kwarm from equation (3)
+ vec3 kcool = clamp(kblue + alpha * kd, 0.0, 1.0);
+ vec3 kwarm = clamp(kyellow + beta * kd, 0.0, 1.0);
+
+ vec3 result = vec3(0.0);
+ for (int i = 0; i < lightCount; ++i) {
+ // Calculate the vector from the light to the fragment
+ vec3 s = normalize( vec3( lights[i].position ) - pos );
+
+ // Calculate the cos theta factor mapped onto the range [0,1]
+ float sDotNFactor = ( 1.0 + dot( s, n ) ) / 2.0;
+
+ // Calculate the tone by blending the kcool and kwarm contributions
+ // as per equation (2)
+ vec3 intensity = mix( kcool, kwarm, sDotNFactor );
+
+ // Calculate the vector from the fragment to the eye position
+ vec3 v = normalize( eyePosition - pos );
+
+ // Reflect the light beam using the normal at this fragment
+ vec3 r = reflect( -s, n );
+
+ // Calculate the specular component
+ float specular = 0.0;
+ if ( dot( s, n ) > 0.0 )
+ specular = pow( max( dot( r, v ), 0.0 ), shininess );
+
+ // Sum the blended tone and specular highlight
+ result += intensity + ks * specular;
+ }
+
+ return result;
+}
+
+void main()
+{
+ fragColor = vec4( goochModel( worldPosition, normalize( worldNormal ) ), 1.0 );
+}
diff --git a/src/extras/shaders/rhi/gooch.vert b/src/extras/shaders/rhi/gooch.vert
new file mode 100644
index 000000000..0da69bce5
--- /dev/null
+++ b/src/extras/shaders/rhi/gooch.vert
@@ -0,0 +1,25 @@
+#version 450
+
+layout(location = 0) in vec3 vertexPosition;
+layout(location = 1) in vec3 vertexNormal;
+
+layout(location = 0) out vec3 worldPosition;
+layout(location = 1) out vec3 worldNormal;
+
+layout(std140, binding = 1) uniform qt3d_command_uniforms {
+ mat4 modelMatrix;
+ mat4 inverseModelMatrix;
+ mat4 modelViewMatrix;
+ mat3 modelNormalMatrix;
+ mat4 inverseModelViewMatrix;
+ mat4 mvp;
+ mat4 inverseModelViewProjectionMatrix;
+};
+
+void main()
+{
+ worldNormal = normalize( modelNormalMatrix * vertexNormal );
+ worldPosition = vec3( modelMatrix * vec4( vertexPosition, 1.0 ) );
+
+ gl_Position = mvp * vec4( vertexPosition, 1.0 );
+}
diff --git a/src/extras/shaders/rhi/light.inc.frag b/src/extras/shaders/rhi/light.inc.frag
new file mode 100644
index 000000000..8079ae8a3
--- /dev/null
+++ b/src/extras/shaders/rhi/light.inc.frag
@@ -0,0 +1,28 @@
+#pragma include defaultuniforms.inc
+
+const int MAX_LIGHTS = 8;
+const int TYPE_POINT = 0;
+const int TYPE_DIRECTIONAL = 1;
+const int TYPE_SPOT = 2;
+
+struct Light {
+ vec3 position;
+ float intensity;
+ vec3 color;
+ float constantAttenuation;
+ vec3 direction;
+ float linearAttenuation;
+ float quadraticAttenuation;
+ float cutOffAngle;
+ int type;
+};
+
+layout(std140, binding = auto) uniform qt3d_light_uniforms {
+ Light lights[MAX_LIGHTS];
+ int lightCount;
+ int envLightCount;
+};
+
+// Pre-convolved environment maps
+layout(binding = auto) uniform samplerCube envLight_irradiance; // For diffuse contribution
+layout(binding = auto) uniform samplerCube envLight_specular; // For specular contribution
diff --git a/src/extras/shaders/rhi/metalrough.inc.frag b/src/extras/shaders/rhi/metalrough.inc.frag
new file mode 100644
index 000000000..817e1192c
--- /dev/null
+++ b/src/extras/shaders/rhi/metalrough.inc.frag
@@ -0,0 +1,341 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#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));
+ 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 = (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/rhi/morphphong.vert b/src/extras/shaders/rhi/morphphong.vert
new file mode 100644
index 000000000..826145b20
--- /dev/null
+++ b/src/extras/shaders/rhi/morphphong.vert
@@ -0,0 +1,43 @@
+#version 450
+
+layout(location = 0) in vec3 vertexPosition;
+layout(location = 1) in vec3 vertexNormal;
+layout(location = 2) in vec3 vertexPositionTarget;
+layout(location = 3) in vec3 vertexNormalTarget;
+
+layout(location = 0) out vec3 worldPosition;
+layout(location = 1) out vec3 worldNormal;
+
+layout(std140, binding = 1) uniform qt3d_command_uniforms {
+ mat4 modelMatrix;
+ mat4 inverseModelMatrix;
+ mat4 modelViewMatrix;
+ mat3 modelNormalMatrix;
+ mat4 inverseModelViewMatrix;
+ mat4 modelViewProjection;
+ mat4 inverseModelViewProjectionMatrix;
+};
+
+layout(std140, binding = 3) uniform qt3d_morph_uniforms {
+ float interpolator;
+};
+
+void main()
+{
+ vec3 morphPos;
+ vec3 morphNormal;
+ if (interpolator > 0.0) {
+ // normalized
+ morphPos = mix(vertexPosition, vertexPositionTarget, interpolator);
+ morphNormal = normalize(mix(vertexNormal, vertexNormalTarget, interpolator));
+ } else {
+ // relative
+ morphPos = vertexPosition + vertexPositionTarget * abs(interpolator);
+ morphNormal = normalize(vertexNormal + vertexNormalTarget * abs(interpolator));
+ }
+
+ worldNormal = normalize( modelNormalMatrix * morphNormal );
+ worldPosition = vec3( modelMatrix * vec4( morphPos, 1.0 ) );
+
+ gl_Position = modelViewProjection * vec4( morphPos, 1.0 );
+}
diff --git a/src/extras/shaders/rhi/pervertexcolor.frag b/src/extras/shaders/rhi/pervertexcolor.frag
new file mode 100644
index 000000000..da3ea149e
--- /dev/null
+++ b/src/extras/shaders/rhi/pervertexcolor.frag
@@ -0,0 +1,150 @@
+#version 450
+
+layout(location = 0) in vec3 worldPosition;
+layout(location = 1) in vec3 worldNormal;
+layout(location = 2) in vec4 color;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform qt3d_render_view_uniforms {
+ mat4 viewMatrix;
+ mat4 projectionMatrix;
+ mat4 viewProjectionMatrix;
+ mat4 inverseViewMatrix;
+ mat4 inverseProjectionMatrix;
+ mat4 inverseViewProjectionMatrix;
+ mat4 viewportMatrix;
+ mat4 inverseViewportMatrix;
+ vec4 textureTransformMatrix;
+ vec3 eyePosition;
+ float aspectRatio;
+ float gamma;
+ float exposure;
+ float time;
+};
+
+layout(std140, binding = 1) uniform qt3d_command_uniforms {
+ mat4 modelMatrix;
+ mat4 inverseModelMatrix;
+ mat4 modelViewMatrix;
+ mat3 modelNormalMatrix;
+ mat4 inverseModelViewMatrix;
+ mat4 mvp;
+ mat4 inverseModelViewProjectionMatrix;
+};
+
+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;
+};
+
+layout(std140, binding = 2) uniform qt3d_light_uniforms {
+ uniform Light lights[MAX_LIGHTS];
+ uniform int lightCount;
+ uniform int envLightCount;
+};
+
+void adsModel(const in vec3 worldPos,
+ const in vec3 worldNormal,
+ const in vec3 worldView,
+ const in float shininess,
+ out vec3 diffuseColor,
+ out vec3 specularColor)
+{
+ diffuseColor = vec3(0.0);
+ specularColor = vec3(0.0);
+
+ // We perform all work in world space
+ vec3 n = normalize(worldNormal);
+ vec3 s = vec3(0.0);
+
+ for (int i = 0; i < lightCount; ++i) {
+ float att = 1.0;
+ float sDotN = 0.0;
+
+ if (lights[i].type != TYPE_DIRECTIONAL) {
+ // Point and Spot lights
+
+ // Light position is already in world space
+ vec3 sUnnormalized = lights[i].position - worldPos;
+ s = normalize(sUnnormalized); // Light direction
+
+ // Calculate the attenuation factor
+ sDotN = dot(s, n);
+ if (sDotN > 0.0) {
+ if (lights[i].constantAttenuation != 0.0
+ || lights[i].linearAttenuation != 0.0
+ || lights[i].quadraticAttenuation != 0.0) {
+ float dist = length(sUnnormalized);
+ att = 1.0 / (lights[i].constantAttenuation +
+ lights[i].linearAttenuation * dist +
+ lights[i].quadraticAttenuation * dist * dist);
+ }
+
+ // The light direction is in world space already
+ if (lights[i].type == TYPE_SPOT) {
+ // Check if fragment is inside or outside of the spot light cone
+ if (degrees(acos(dot(-s, lights[i].direction))) > lights[i].cutOffAngle)
+ sDotN = 0.0;
+ }
+ }
+ } else {
+ // Directional lights
+ // The light direction is in world space already
+ s = normalize(-lights[i].direction);
+ sDotN = dot(s, n);
+ }
+
+ // Calculate the diffuse factor
+ float diffuse = max(sDotN, 0.0);
+
+ // Calculate the specular factor
+ float specular = 0.0;
+ if (diffuse > 0.0 && shininess > 0.0) {
+ float normFactor = (shininess + 2.0) / 2.0;
+ vec3 r = reflect(-s, n); // Reflection direction in world space
+ specular = normFactor * pow(max(dot(r, worldView), 0.0), shininess);
+ }
+
+ // Accumulate the diffuse and specular contributions
+ diffuseColor += att * lights[i].intensity * diffuse * lights[i].color;
+ specularColor += att * lights[i].intensity * specular * lights[i].color;
+ }
+}
+
+vec4 phongFunction(const in vec4 ambient,
+ const in vec4 diffuse,
+ const in vec4 specular,
+ const in float shininess,
+ const in vec3 worldPosition,
+ const in vec3 worldView,
+ const in vec3 worldNormal)
+{
+ // Calculate the lighting model, keeping the specular component separate
+ vec3 diffuseColor, specularColor;
+ adsModel(worldPosition, worldNormal, worldView, shininess, diffuseColor, specularColor);
+
+ // Combine spec with ambient+diffuse for final fragment color
+ vec3 color = (ambient.rgb + diffuseColor) * diffuse.rgb
+ + specularColor * specular.rgb;
+
+ return vec4(color, diffuse.a);
+}
+
+void main()
+{
+ vec3 worldView = normalize(eyePosition - worldPosition);
+ fragColor = phongFunction(color, color, vec4(0.0), 0.0, worldPosition, worldView, worldNormal);
+}
diff --git a/src/extras/shaders/rhi/pervertexcolor.vert b/src/extras/shaders/rhi/pervertexcolor.vert
new file mode 100644
index 000000000..3ae1c9fb0
--- /dev/null
+++ b/src/extras/shaders/rhi/pervertexcolor.vert
@@ -0,0 +1,28 @@
+#version 450
+
+layout(location = 0) in vec3 vertexPosition;
+layout(location = 1) in vec3 vertexNormal;
+layout(location = 2) in vec4 vertexColor;
+
+layout(location = 0) out vec3 worldPosition;
+layout(location = 1) out vec3 worldNormal;
+layout(location = 2) out vec4 color;
+
+layout(std140, binding = 1) uniform qt3d_command_uniforms {
+ mat4 modelMatrix;
+ mat4 inverseModelMatrix;
+ mat4 modelViewMatrix;
+ mat3 modelNormalMatrix;
+ mat4 inverseModelViewMatrix;
+ mat4 mvp;
+ mat4 inverseModelViewProjectionMatrix;
+};
+
+void main()
+{
+ worldNormal = normalize( modelNormalMatrix * vertexNormal );
+ worldPosition = vec3( modelMatrix * vec4( vertexPosition, 1.0 ) );
+ color = vertexColor;
+
+ gl_Position = mvp * vec4( vertexPosition, 1.0 );
+}
diff --git a/src/extras/shaders/rhi/phong.inc.frag b/src/extras/shaders/rhi/phong.inc.frag
new file mode 100644
index 000000000..47a6ecd4a
--- /dev/null
+++ b/src/extras/shaders/rhi/phong.inc.frag
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#pragma include light.inc.frag
+
+void adsModel(const in vec3 worldPos,
+ const in vec3 worldNormal,
+ const in vec3 worldView,
+ const in float shininess,
+ out vec3 diffuseColor,
+ out vec3 specularColor)
+{
+ diffuseColor = vec3(0.0);
+ specularColor = vec3(0.0);
+
+ // We perform all work in world space
+ vec3 n = normalize(worldNormal);
+ vec3 s = vec3(0.0);
+
+ for (int i = 0; i < lightCount; ++i) {
+ float att = 1.0;
+ float sDotN = 0.0;
+
+ if (lights[i].type != TYPE_DIRECTIONAL) {
+ // Point and Spot lights
+
+ // Light position is already in world space
+ vec3 sUnnormalized = lights[i].position - worldPos;
+ s = normalize(sUnnormalized); // Light direction
+
+ // Calculate the attenuation factor
+ sDotN = dot(s, n);
+ if (sDotN > 0.0) {
+ if (lights[i].constantAttenuation != 0.0
+ || lights[i].linearAttenuation != 0.0
+ || lights[i].quadraticAttenuation != 0.0) {
+ float dist = length(sUnnormalized);
+ att = 1.0 / (lights[i].constantAttenuation +
+ lights[i].linearAttenuation * dist +
+ lights[i].quadraticAttenuation * dist * dist);
+ }
+
+ // The light direction is in world space already
+ if (lights[i].type == TYPE_SPOT) {
+ // Check if fragment is inside or outside of the spot light cone
+ if (degrees(acos(dot(-s, lights[i].direction))) > lights[i].cutOffAngle)
+ sDotN = 0.0;
+ }
+ }
+ } else {
+ // Directional lights
+ // The light direction is in world space already
+ s = normalize(-lights[i].direction);
+ sDotN = dot(s, n);
+ }
+
+ // Calculate the diffuse factor
+ float diffuse = max(sDotN, 0.0);
+
+ // Calculate the specular factor
+ float specular = 0.0;
+ if (diffuse > 0.0 && shininess > 0.0) {
+ float normFactor = (shininess + 2.0) / 2.0;
+ vec3 r = reflect(-s, n); // Reflection direction in world space
+ specular = normFactor * pow(max(dot(r, worldView), 0.0), shininess);
+ }
+
+ // Accumulate the diffuse and specular contributions
+ diffuseColor += att * lights[i].intensity * diffuse * lights[i].color;
+ specularColor += att * lights[i].intensity * specular * lights[i].color;
+ }
+}
+
+vec4 phongFunction(const in vec4 ambient,
+ const in vec4 diffuse,
+ const in vec4 specular,
+ const in float shininess,
+ const in vec3 worldPosition,
+ const in vec3 worldView,
+ const in vec3 worldNormal)
+{
+ // Calculate the lighting model, keeping the specular component separate
+ vec3 diffuseColor, specularColor;
+ adsModel(worldPosition, worldNormal, worldView, shininess, diffuseColor, specularColor);
+
+ // Combine spec with ambient+diffuse for final fragment color
+ vec3 color = (ambient.rgb + diffuseColor) * diffuse.rgb
+ + specularColor * specular.rgb;
+
+ return vec4(color, diffuse.a);
+}
diff --git a/src/extras/shaders/rhi/skybox.frag b/src/extras/shaders/rhi/skybox.frag
new file mode 100644
index 000000000..649894b15
--- /dev/null
+++ b/src/extras/shaders/rhi/skybox.frag
@@ -0,0 +1,44 @@
+#version 450
+
+layout(location = 0) in vec3 texCoord0;
+layout(location = 0) out vec4 fragColor;
+
+
+// Gamma correction
+
+layout(std140, binding = 0) uniform qt3d_render_view_uniforms {
+ mat4 viewMatrix;
+ mat4 projectionMatrix;
+ mat4 viewProjectionMatrix;
+ mat4 inverseViewMatrix;
+ mat4 inverseProjectionMatrix;
+ mat4 inverseViewProjectionMatrix;
+ mat4 viewportMatrix;
+ mat4 inverseViewportMatrix;
+ vec4 textureTransformMatrix;
+ vec3 eyePosition;
+ float aspectRatio;
+ float gamma;
+ float exposure;
+ float time;
+};
+
+layout(std140, binding = 2) uniform qt3d_morph_uniforms {
+ float gammaStrength;
+};
+
+layout(binding = 3) uniform samplerCube skyboxTexture;
+
+vec3 gammaCorrect(const in vec3 color)
+{
+ return pow(color, vec3(1.0 / gamma));
+}
+
+void main()
+{
+ vec4 baseColor = texture(skyboxTexture, texCoord0);
+ vec4 gammaColor = vec4(gammaCorrect(baseColor.rgb), 1.0);
+ // This is an odd way to enable or not gamma correction,
+ // but this is a way to avoid branching until we can generate shaders
+ fragColor = mix(baseColor, gammaColor, gammaStrength);
+}
diff --git a/src/extras/shaders/rhi/skybox.vert b/src/extras/shaders/rhi/skybox.vert
new file mode 100644
index 000000000..8f3de6f62
--- /dev/null
+++ b/src/extras/shaders/rhi/skybox.vert
@@ -0,0 +1,39 @@
+#version 450
+
+layout(location = 0) in vec3 vertexPosition;
+layout(location = 0) out vec3 texCoord0;
+
+layout(std140, binding = 0) uniform qt3d_render_view_uniforms {
+ mat4 viewMatrix;
+ mat4 projectionMatrix;
+ mat4 viewProjectionMatrix;
+ mat4 inverseViewMatrix;
+ mat4 inverseProjectionMatrix;
+ mat4 inverseViewProjectionMatrix;
+ mat4 viewportMatrix;
+ mat4 inverseViewportMatrix;
+ vec4 textureTransformMatrix;
+ vec3 eyePosition;
+ float aspectRatio;
+ float gamma;
+ float exposure;
+ float time;
+};
+
+layout(std140, binding = 1) uniform qt3d_command_uniforms {
+ mat4 modelMatrix;
+ mat4 inverseModelMatrix;
+ mat4 modelViewMatrix;
+ mat3 modelNormalMatrix;
+ mat4 inverseModelViewMatrix;
+ mat4 modelViewProjection;
+ mat4 inverseModelViewProjectionMatrix;
+};
+
+void main()
+{
+ texCoord0 = vertexPosition.xyz;
+ // Converting the viewMatrix to a mat3, then back to a mat4
+ // removes the translation component from it
+ gl_Position = vec4(projectionMatrix * mat4(mat3(viewMatrix)) * modelMatrix * vec4(vertexPosition, 1.0)).xyww;
+}
diff --git a/src/extras/shaders/rhi/unlittexture.frag b/src/extras/shaders/rhi/unlittexture.frag
new file mode 100644
index 000000000..e2b2c8fe2
--- /dev/null
+++ b/src/extras/shaders/rhi/unlittexture.frag
@@ -0,0 +1,13 @@
+#version 450
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec2 texCoord;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 3) uniform sampler2D diffuseTexture;
+
+void main()
+{
+ fragColor = texture( diffuseTexture, texCoord );
+}
diff --git a/src/extras/shaders/rhi/unlittexture.vert b/src/extras/shaders/rhi/unlittexture.vert
new file mode 100644
index 000000000..08f06e817
--- /dev/null
+++ b/src/extras/shaders/rhi/unlittexture.vert
@@ -0,0 +1,47 @@
+#version 450
+
+layout(location = 0) in vec3 vertexPosition;
+layout(location = 1) in vec2 vertexTexCoord;
+
+layout(location = 0) out vec3 position;
+layout(location = 1) out vec2 texCoord;
+
+layout(std140, binding = 0) uniform qt3d_render_view_uniforms {
+ mat4 viewMatrix;
+ mat4 projectionMatrix;
+ mat4 viewProjectionMatrix;
+ mat4 inverseViewMatrix;
+ mat4 inverseProjectionMatrix;
+ mat4 inverseViewProjectionMatrix;
+ mat4 viewportMatrix;
+ mat4 inverseViewportMatrix;
+ vec4 textureTransformMatrix;
+ vec3 eyePosition;
+ float aspectRatio;
+ float gamma;
+ float exposure;
+ float time;
+};
+
+layout(std140, binding = 1) uniform qt3d_command_uniforms {
+ mat4 modelMatrix;
+ mat4 inverseModelMatrix;
+ mat4 modelView;
+ mat3 modelNormalMatrix;
+ mat4 inverseModelViewMatrix;
+ mat4 mvp;
+ mat4 inverseModelViewProjectionMatrix;
+};
+
+layout(std140, binding = 2) uniform qt3d_custom_uniforms {
+ mat3 texCoordTransform;
+};
+
+void main()
+{
+ vec3 tt = texCoordTransform * vec3(vertexTexCoord, 1.0);
+ texCoord = (tt / tt.z).xy;
+ position = vec3( modelView * vec4( vertexPosition, 1.0 ) );
+
+ gl_Position = mvp * vec4( vertexPosition, 1.0 );
+}