summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@theqtcompany.com>2015-12-06 15:17:34 +0100
committerLaszlo Agocs <laszlo.agocs@theqtcompany.com>2015-12-07 08:04:36 +0000
commit1daff642404ea00d04aab96951c72eb20f7dc3c0 (patch)
treee6fa253181f00760bb9a793417e91729645b1459 /src
parent17d1ae7b4d35d0698d307a3a21cd4ad2c21fc361 (diff)
Separate GLSL 1.00 and newer shader snippets for lights
Many but not all OpenGL ES 2.0 implementations support dynamic indexing. For these the normal for loop is fine. For simple GLSL 1.00 compilers without dynamic indexing support (e.g. RPi) a separate, limited version is provided that supports a lower number of lights and uses copy-paste instead of the loop. Right now there is no sane way to choose which snippet to use as that requires the OpenGL context at minimum (and even then we could only rely on vendor/renderer checks). Therefore a QT3D_GLSL100_WORKAROUND environment variable is used for now. This is temporary until we figure out something more sophisticated. The default GL2/ES2 lighting shader is now equivalent to the GL3 version, supporting up to 8 lights. Change-Id: I0244c920a1f2c2516b130991996afca68207a7db Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/render/backend/renderview.cpp1
-rw-r--r--src/render/materialsystem/qshaderprogram.cpp11
-rw-r--r--src/render/render.qrc1
-rw-r--r--src/render/shaders/es2/light.inc.frag116
-rw-r--r--src/render/shaders/es2/light.inc.frag100257
5 files changed, 331 insertions, 55 deletions
diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp
index fa02447b3..6c1f4b4e9 100644
--- a/src/render/backend/renderview.cpp
+++ b/src/render/backend/renderview.cpp
@@ -784,7 +784,6 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, RenderPass *rPass,
}
}
- // Shaders without dynamic indexing will not have lightCount
if (uniformNames.contains(LIGHT_COUNT_NAME))
setUniformValue(command->m_uniforms, LIGHT_COUNT_NAME, qMax(1, lightIdx));
diff --git a/src/render/materialsystem/qshaderprogram.cpp b/src/render/materialsystem/qshaderprogram.cpp
index 2dff5856f..51faac661 100644
--- a/src/render/materialsystem/qshaderprogram.cpp
+++ b/src/render/materialsystem/qshaderprogram.cpp
@@ -241,9 +241,16 @@ static QByteArray deincludify(const QString &filePath)
const QByteArray includeDirective = QByteArrayLiteral("#pragma include");
for (int i = 0; i < lines.count(); ++i) {
if (lines[i].startsWith(includeDirective)) {
- QByteArray includeFileName = lines[i].mid(includeDirective.count() + 1);
+ QString includeFileName = QFileInfo(filePath).absolutePath()
+ + QStringLiteral("/")
+ + QString::fromUtf8(lines[i].mid(includeDirective.count() + 1));
+ if (qEnvironmentVariableIsSet("QT3D_GLSL100_WORKAROUND")) {
+ QString candidate = includeFileName + QStringLiteral("100");
+ if (QFile::exists(candidate))
+ includeFileName = candidate;
+ }
lines.removeAt(i);
- QByteArray includedContents = deincludify(QFileInfo(filePath).absolutePath() + QStringLiteral("/") + QString::fromUtf8(includeFileName));
+ QByteArray includedContents = deincludify(includeFileName);
lines.insert(i, includedContents);
QString lineDirective = QString(QStringLiteral("#line %1")).arg(i + 2);
lines.insert(i + 1, lineDirective.toUtf8());
diff --git a/src/render/render.qrc b/src/render/render.qrc
index d479e5ef0..0cf54286b 100644
--- a/src/render/render.qrc
+++ b/src/render/render.qrc
@@ -2,6 +2,7 @@
<qresource prefix="/">
<file>shaders/gl3/light.inc.frag</file>
<file>shaders/es2/light.inc.frag</file>
+ <file>shaders/es2/light.inc.frag100</file>
<file>shaders/gl3/phong.vert</file>
<file>shaders/gl3/phong.frag</file>
<file>shaders/es2/phong.vert</file>
diff --git a/src/render/shaders/es2/light.inc.frag b/src/render/shaders/es2/light.inc.frag
index e4ab11938..bf8e3ff90 100644
--- a/src/render/shaders/es2/light.inc.frag
+++ b/src/render/shaders/es2/light.inc.frag
@@ -23,30 +23,34 @@ void adsModelNormalMapped(const in FP vec3 vpos, const in FP vec3 vnormal, const
FP vec3 n = normalize( vnormal );
- // TODO dynamic indexing may not be supported with GLSL 1.00 so take only the first light into account
- FP vec3 s = -lights[0].direction;
- FP float att = 1.0;
- if ( lights[0].type != TYPE_DIRECTIONAL ) {
- s = lights[0].position - vpos;
- if (length( lights[0].attenuation ) != 0.0) {
- FP float dist = length(s);
- att = 1.0 / (lights[0].attenuation.x + lights[0].attenuation.y * dist + lights[0].attenuation.z * dist * dist);
+ int i;
+ FP vec3 s;
+ for (i = 0; i < lightCount; ++i) {
+ FP float att = 1.0;
+ if ( lights[i].type != TYPE_DIRECTIONAL ) {
+ s = lights[i].position - vpos;
+ if (length( lights[i].attenuation ) != 0.0) {
+ FP float dist = length(s);
+ att = 1.0 / (lights[i].attenuation.x + lights[i].attenuation.y * dist + lights[i].attenuation.z * dist * dist);
+ }
+ } else {
+ s = -lights[i].direction;
}
- }
- s = normalize( tangentMatrix * s );
- FP float diffuse = max( dot( s, n ), 0.0 );
+ s = normalize( tangentMatrix * s );
+ FP float diffuse = max( dot( s, n ), 0.0 );
- FP float specular = 0.0;
- if (diffuse > 0.0 && shininess > 0.0) {
- FP vec3 r = reflect( -s, n );
- FP vec3 v = normalize( tangentMatrix * ( eye - vpos ) );
- FP float normFactor = ( shininess + 2.0 ) / 2.0;
- specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess );
- }
+ FP float specular = 0.0;
+ if (diffuse > 0.0 && shininess > 0.0) {
+ FP vec3 r = reflect( -s, n );
+ FP vec3 v = normalize( tangentMatrix * ( eye - vpos ) );
+ FP float normFactor = ( shininess + 2.0 ) / 2.0;
+ specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess );
+ }
- diffuseColor += att * lights[0].intensity * diffuse * lights[0].color;
- specularColor += specular;
+ diffuseColor += att * lights[i].intensity * diffuse * lights[i].color;
+ specularColor += specular;
+ }
}
void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3 eye, const in FP float shininess,
@@ -57,30 +61,34 @@ void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3
FP vec3 n = normalize( vnormal );
- // TODO dynamic indexing may not be supported with GLSL 1.00 so take only the first light into account
- FP vec3 s = -lights[0].direction;
- FP float att = 1.0;
- if ( lights[0].type != TYPE_DIRECTIONAL ) {
- s = lights[0].position - vpos;
- if (length( lights[0].attenuation ) != 0.0) {
- FP float dist = length(s);
- att = 1.0 / (lights[0].attenuation.x + lights[0].attenuation.y * dist + lights[0].attenuation.z * dist * dist);
+ int i;
+ FP vec3 s;
+ for (i = 0; i < lightCount; ++i) {
+ FP float att = 1.0;
+ if ( lights[i].type != TYPE_DIRECTIONAL ) {
+ s = lights[i].position - vpos;
+ if (length( lights[i].attenuation ) != 0.0) {
+ FP float dist = length(s);
+ att = 1.0 / (lights[i].attenuation.x + lights[i].attenuation.y * dist + lights[i].attenuation.z * dist * dist);
+ }
+ } else {
+ s = -lights[i].direction;
}
- }
- s = normalize( s );
- FP float diffuse = max( dot( s, n ), 0.0 );
+ s = normalize( s );
+ FP float diffuse = max( dot( s, n ), 0.0 );
- FP float specular = 0.0;
- if (diffuse > 0.0 && shininess > 0.0) {
- FP vec3 r = reflect( -s, n );
- FP vec3 v = normalize( eye - vpos );
- FP float normFactor = ( shininess + 2.0 ) / 2.0;
- specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess );
- }
+ FP float specular = 0.0;
+ if (diffuse > 0.0 && shininess > 0.0) {
+ FP vec3 r = reflect( -s, n );
+ FP vec3 v = normalize( eye - vpos );
+ FP float normFactor = ( shininess + 2.0 ) / 2.0;
+ specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess );
+ }
- diffuseColor += att * lights[0].intensity * diffuse * lights[0].color;
- specularColor += specular;
+ diffuseColor += att * lights[i].intensity * diffuse * lights[i].color;
+ specularColor += specular;
+ }
}
void adModel(const in FP vec3 vpos, const in FP vec3 vnormal, out FP vec3 diffuseColor)
@@ -89,19 +97,23 @@ void adModel(const in FP vec3 vpos, const in FP vec3 vnormal, out FP vec3 diffus
FP vec3 n = normalize( vnormal );
- // TODO dynamic indexing may not be supported with GLSL 1.00 so take only the first light into account
- FP vec3 s = -lights[0].direction;
- FP float att = 1.0;
- if ( lights[0].type != TYPE_DIRECTIONAL ) {
- s = lights[0].position - vpos;
- if (length( lights[0].attenuation ) != 0.0) {
- FP float dist = length(s);
- att = 1.0 / (lights[0].attenuation.x + lights[0].attenuation.y * dist + lights[0].attenuation.z * dist * dist);
+ int i;
+ FP vec3 s;
+ for (i = 0; i < lightCount; ++i) {
+ FP float att = 1.0;
+ if ( lights[i].type != TYPE_DIRECTIONAL ) {
+ s = lights[i].position - vpos;
+ if (length( lights[i].attenuation ) != 0.0) {
+ FP float dist = length(s);
+ att = 1.0 / (lights[i].attenuation.x + lights[i].attenuation.y * dist + lights[i].attenuation.z * dist * dist);
+ }
+ } else {
+ s = -lights[i].direction;
}
- }
- s = normalize( s );
- FP float diffuse = max( dot( s, n ), 0.0 );
+ s = normalize( s );
+ FP float diffuse = max( dot( s, n ), 0.0 );
- diffuseColor += att * lights[0].intensity * diffuse * lights[0].color;
+ diffuseColor += att * lights[i].intensity * diffuse * lights[i].color;
+ }
}
diff --git a/src/render/shaders/es2/light.inc.frag100 b/src/render/shaders/es2/light.inc.frag100
new file mode 100644
index 000000000..830b7e8b0
--- /dev/null
+++ b/src/render/shaders/es2/light.inc.frag100
@@ -0,0 +1,257 @@
+const int MAX_LIGHTS = 3;
+const int TYPE_POINT = 0;
+const int TYPE_DIRECTIONAL = 1;
+const int TYPE_SPOT = 2;
+struct Light {
+ int type;
+ FP vec3 position;
+ FP vec3 color;
+ FP float intensity;
+ FP vec3 direction;
+ FP vec3 attenuation;
+// FP float cutOffAngle;
+};
+uniform Light lights[MAX_LIGHTS];
+uniform int lightCount;
+
+void adsModelNormalMapped(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3 eye, const in FP float shininess,
+ const in FP mat3 tangentMatrix,
+ out FP vec3 diffuseColor, out FP vec3 specularColor)
+{
+ diffuseColor = vec3(0.0);
+ specularColor = vec3(0.0);
+
+ FP vec3 n = normalize( vnormal );
+
+ // 0
+ if (lightCount < 1)
+ return;
+ FP vec3 s = -lights[0].direction;
+ FP float att = 1.0;
+ if ( lights[0].type != TYPE_DIRECTIONAL ) {
+ s = lights[0].position - vpos;
+ if (length( lights[0].attenuation ) != 0.0) {
+ FP float dist = length(s);
+ att = 1.0 / (lights[0].attenuation.x + lights[0].attenuation.y * dist + lights[0].attenuation.z * dist * dist);
+ }
+ }
+
+ s = normalize( tangentMatrix * s );
+ FP float diffuse = max( dot( s, n ), 0.0 );
+
+ FP float specular = 0.0;
+ if (diffuse > 0.0 && shininess > 0.0) {
+ FP vec3 r = reflect( -s, n );
+ FP vec3 v = normalize( tangentMatrix * ( eye - vpos ) );
+ FP float normFactor = ( shininess + 2.0 ) / 2.0;
+ specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess );
+ }
+
+ diffuseColor += att * lights[0].intensity * diffuse * lights[0].color;
+ specularColor += specular;
+
+ // 1
+ if (lightCount < 2)
+ return;
+ s = -lights[1].direction;
+ att = 1.0;
+ if ( lights[1].type != TYPE_DIRECTIONAL ) {
+ s = lights[1].position - vpos;
+ if (length( lights[1].attenuation ) != 0.0) {
+ FP float dist = length(s);
+ att = 1.0 / (lights[1].attenuation.x + lights[1].attenuation.y * dist + lights[1].attenuation.z * dist * dist);
+ }
+ }
+
+ s = normalize( tangentMatrix * s );
+ diffuse = max( dot( s, n ), 0.0 );
+
+ specular = 0.0;
+ if (diffuse > 0.0 && shininess > 0.0) {
+ FP vec3 r = reflect( -s, n );
+ FP vec3 v = normalize( tangentMatrix * ( eye - vpos ) );
+ FP float normFactor = ( shininess + 2.0 ) / 2.0;
+ specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess );
+ }
+
+ diffuseColor += att * lights[1].intensity * diffuse * lights[1].color;
+ specularColor += specular;
+
+ // 2
+ if (lightCount < 3)
+ return;
+ s = -lights[2].direction;
+ att = 1.0;
+ if ( lights[2].type != TYPE_DIRECTIONAL ) {
+ s = lights[2].position - vpos;
+ if (length( lights[2].attenuation ) != 0.0) {
+ FP float dist = length(s);
+ att = 1.0 / (lights[2].attenuation.x + lights[2].attenuation.y * dist + lights[2].attenuation.z * dist * dist);
+ }
+ }
+
+ s = normalize( tangentMatrix * s );
+ diffuse = max( dot( s, n ), 0.0 );
+
+ specular = 0.0;
+ if (diffuse > 0.0 && shininess > 0.0) {
+ FP vec3 r = reflect( -s, n );
+ FP vec3 v = normalize( tangentMatrix * ( eye - vpos ) );
+ FP float normFactor = ( shininess + 2.0 ) / 2.0;
+ specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess );
+ }
+
+ diffuseColor += att * lights[2].intensity * diffuse * lights[2].color;
+ specularColor += specular;
+}
+
+void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3 eye, const in FP float shininess,
+ out FP vec3 diffuseColor, out FP vec3 specularColor)
+{
+ diffuseColor = vec3(0.0);
+ specularColor = vec3(0.0);
+
+ FP vec3 n = normalize( vnormal );
+
+ // 0
+ if (lightCount < 1)
+ return;
+ FP vec3 s = -lights[0].direction;
+ FP float att = 1.0;
+ if ( lights[0].type != TYPE_DIRECTIONAL ) {
+ s = lights[0].position - vpos;
+ if (length( lights[0].attenuation ) != 0.0) {
+ FP float dist = length(s);
+ att = 1.0 / (lights[0].attenuation.x + lights[0].attenuation.y * dist + lights[0].attenuation.z * dist * dist);
+ }
+ }
+
+ s = normalize( s );
+ FP float diffuse = max( dot( s, n ), 0.0 );
+
+ FP float specular = 0.0;
+ if (diffuse > 0.0 && shininess > 0.0) {
+ FP vec3 r = reflect( -s, n );
+ FP vec3 v = normalize( eye - vpos );
+ FP float normFactor = ( shininess + 2.0 ) / 2.0;
+ specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess );
+ }
+
+ diffuseColor += att * lights[0].intensity * diffuse * lights[0].color;
+ specularColor += specular;
+
+ // 1
+ if (lightCount < 2)
+ return;
+ s = -lights[1].direction;
+ att = 1.0;
+ if ( lights[1].type != TYPE_DIRECTIONAL ) {
+ s = lights[1].position - vpos;
+ if (length( lights[1].attenuation ) != 0.0) {
+ FP float dist = length(s);
+ att = 1.0 / (lights[1].attenuation.x + lights[1].attenuation.y * dist + lights[1].attenuation.z * dist * dist);
+ }
+ }
+
+ s = normalize( s );
+ diffuse = max( dot( s, n ), 0.0 );
+
+ specular = 0.0;
+ if (diffuse > 0.0 && shininess > 0.0) {
+ FP vec3 r = reflect( -s, n );
+ FP vec3 v = normalize( eye - vpos );
+ FP float normFactor = ( shininess + 2.0 ) / 2.0;
+ specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess );
+ }
+
+ diffuseColor += att * lights[1].intensity * diffuse * lights[1].color;
+ specularColor += specular;
+
+ // 2
+ if (lightCount < 3)
+ return;
+ s = -lights[2].direction;
+ att = 1.0;
+ if ( lights[2].type != TYPE_DIRECTIONAL ) {
+ s = lights[2].position - vpos;
+ if (length( lights[2].attenuation ) != 0.0) {
+ FP float dist = length(s);
+ att = 1.0 / (lights[2].attenuation.x + lights[2].attenuation.y * dist + lights[2].attenuation.z * dist * dist);
+ }
+ }
+
+ s = normalize( s );
+ diffuse = max( dot( s, n ), 0.0 );
+
+ specular = 0.0;
+ if (diffuse > 0.0 && shininess > 0.0) {
+ FP vec3 r = reflect( -s, n );
+ FP vec3 v = normalize( eye - vpos );
+ FP float normFactor = ( shininess + 2.0 ) / 2.0;
+ specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess );
+ }
+
+ diffuseColor += att * lights[2].intensity * diffuse * lights[2].color;
+ specularColor += specular;
+}
+
+void adModel(const in FP vec3 vpos, const in FP vec3 vnormal, out FP vec3 diffuseColor)
+{
+ diffuseColor = vec3(0.0);
+
+ FP vec3 n = normalize( vnormal );
+
+ // 0
+ if (lightCount < 1)
+ return;
+ FP vec3 s = -lights[0].direction;
+ FP float att = 1.0;
+ if ( lights[0].type != TYPE_DIRECTIONAL ) {
+ s = lights[0].position - vpos;
+ if (length( lights[0].attenuation ) != 0.0) {
+ FP float dist = length(s);
+ att = 1.0 / (lights[0].attenuation.x + lights[0].attenuation.y * dist + lights[0].attenuation.z * dist * dist);
+ }
+ }
+
+ s = normalize( s );
+ FP float diffuse = max( dot( s, n ), 0.0 );
+
+ diffuseColor += att * lights[0].intensity * diffuse * lights[0].color;
+
+ // 1
+ if (lightCount < 2)
+ return;
+ s = -lights[1].direction;
+ att = 1.0;
+ if ( lights[1].type != TYPE_DIRECTIONAL ) {
+ s = lights[1].position - vpos;
+ if (length( lights[1].attenuation ) != 0.0) {
+ FP float dist = length(s);
+ att = 1.0 / (lights[1].attenuation.x + lights[1].attenuation.y * dist + lights[1].attenuation.z * dist * dist);
+ }
+ }
+
+ s = normalize( s );
+ diffuse = max( dot( s, n ), 0.0 );
+
+ diffuseColor += att * lights[1].intensity * diffuse * lights[1].color;
+
+ // 2
+ if (lightCount < 3)
+ return;
+ s = -lights[2].direction;
+ att = 1.0;
+ if ( lights[2].type != TYPE_DIRECTIONAL ) {
+ s = lights[2].position - vpos;
+ if (length( lights[2].attenuation ) != 0.0) {
+ FP float dist = length(s);
+ att = 1.0 / (lights[2].attenuation.x + lights[2].attenuation.y * dist + lights[2].attenuation.z * dist * dist);
+ }
+ }
+
+ s = normalize( s );
+ diffuse = max( dot( s, n ), 0.0 );
+
+ diffuseColor += att * lights[2].intensity * diffuse * lights[2].color;
+}