diff options
author | Laszlo Agocs <laszlo.agocs@theqtcompany.com> | 2015-12-06 15:17:34 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@theqtcompany.com> | 2015-12-07 08:04:36 +0000 |
commit | 1daff642404ea00d04aab96951c72eb20f7dc3c0 (patch) | |
tree | e6fa253181f00760bb9a793417e91729645b1459 /src | |
parent | 17d1ae7b4d35d0698d307a3a21cd4ad2c21fc361 (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.cpp | 1 | ||||
-rw-r--r-- | src/render/materialsystem/qshaderprogram.cpp | 11 | ||||
-rw-r--r-- | src/render/render.qrc | 1 | ||||
-rw-r--r-- | src/render/shaders/es2/light.inc.frag | 116 | ||||
-rw-r--r-- | src/render/shaders/es2/light.inc.frag100 | 257 |
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; +} |