diff options
author | Mauro Persano <mauro.persano@kdab.com> | 2017-01-11 18:41:15 -0200 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2017-03-16 09:08:44 +0000 |
commit | ea33d6b0530ae3f2601f15fe1e4f63faebdb572c (patch) | |
tree | ff2b5fe22b74901d93b2173a95db11227330284b | |
parent | 7c59817810e74269a48b9f522a4b2013b426d3c2 (diff) |
Unroll loops in ES2 shaders
The GLSL ES specification (up to at least 3.0) does not mandate support
of dynamic indexing of uniform block arrays. It is supported by some
implementations (Tegra, Adreno 5xx) but we can't count on it being
supported in general.
Unfortunately some mobile drivers don't seem to be smart enough to
automatically unroll loops at compile time when the condition is
constant.
Task-number: QTBUG-54994
Change-Id: I44e7fa18dc46f0a11204cf98e3c7b4f3ed446327
Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
Reviewed-by: Oleg Evseev <ev.mipt@gmail.com>
-rw-r--r-- | src/extras/shaders/es2/light.inc.frag | 256 |
1 files changed, 173 insertions, 83 deletions
diff --git a/src/extras/shaders/es2/light.inc.frag b/src/extras/shaders/es2/light.inc.frag index 02660f008..726340d7e 100644 --- a/src/extras/shaders/es2/light.inc.frag +++ b/src/extras/shaders/es2/light.inc.frag @@ -14,125 +14,215 @@ struct Light { uniform Light lights[MAX_LIGHTS]; uniform int lightCount; +void addLightAdsModelNormalMapped(const in FP vec3 vpos, + const in FP vec3 n, + const in FP vec3 eye, + const in FP float shininess, + const in FP mat3 tangentMatrix, + const in Light light, + inout FP vec3 diffuseColor, + inout FP vec3 specularColor) +{ + FP vec3 snormal = normalize( vec3( tangentMatrix[0][2], tangentMatrix[1][2], tangentMatrix[2][2] ) ); + + FP vec3 s, ts; + FP float att = 1.0; + if ( light.type != TYPE_DIRECTIONAL ) { + s = light.position - vpos; + if ( dot(snormal, s) < 0.0 ) + att = 0.0; + else { + ts = normalize( tangentMatrix * s ); + if (length( light.attenuation ) != 0.0) { + FP float dist = length(s); + att = 1.0 / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * dist * dist); + } + s = normalize( s ); + if ( light.type == TYPE_SPOT ) { + if ( degrees(acos(dot(-s, normalize(light.direction))) ) > light.cutOffAngle) + att = 0.0; + } + } + } else { + if ( dot(snormal, -light.direction) > 0.0 ) + s = normalize( tangentMatrix * -light.direction ); + else + att = 0.0; + } + + FP float diffuse = max( dot( ts, n ), 0.0 ); + + FP float specular = 0.0; + if (diffuse > 0.0 && shininess > 0.0 && att > 0.0) { + FP vec3 r = reflect( -ts, 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 * light.intensity * diffuse * light.color; + specularColor += att * light.intensity * specular * light.color; +} + 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 snormal = normalize( vec3( tangentMatrix[0][2], tangentMatrix[1][2], tangentMatrix[2][2] ) ); + if (lightCount < 1) return; FP vec3 n = normalize( vnormal ); + addLightAdsModelNormalMapped(vpos, n, eye, shininess, tangentMatrix, lights[0], diffuseColor, specularColor); + if (lightCount < 2) return; - FP vec3 s, ts; - for (int i = 0; i < lightCount; ++i) { - FP float att = 1.0; - if ( lights[i].type != TYPE_DIRECTIONAL ) { - s = lights[i].position - vpos; - if ( dot(snormal, s) < 0.0 ) - att = 0.0; - else { - ts = normalize( tangentMatrix * s ); - 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); - } - s = normalize( s ); - if ( lights[i].type == TYPE_SPOT ) { - if ( degrees(acos(dot(-s, normalize(lights[i].direction))) ) > lights[i].cutOffAngle) - att = 0.0; - } - } - } else { - if ( dot(snormal, -lights[i].direction) > 0.0 ) - s = normalize( tangentMatrix * -lights[i].direction ); - else - att = 0.0; - } + addLightAdsModelNormalMapped(vpos, n, eye, shininess, tangentMatrix, lights[1], diffuseColor, specularColor); + if (lightCount < 3) return; + + addLightAdsModelNormalMapped(vpos, n, eye, shininess, tangentMatrix, lights[2], diffuseColor, specularColor); + if (lightCount < 4) return; + + addLightAdsModelNormalMapped(vpos, n, eye, shininess, tangentMatrix, lights[3], diffuseColor, specularColor); + if (lightCount < 5) return; + + addLightAdsModelNormalMapped(vpos, n, eye, shininess, tangentMatrix, lights[4], diffuseColor, specularColor); + if (lightCount < 6) return; - FP float diffuse = max( dot( ts, n ), 0.0 ); + addLightAdsModelNormalMapped(vpos, n, eye, shininess, tangentMatrix, lights[5], diffuseColor, specularColor); + if (lightCount < 7) return; - FP float specular = 0.0; - if (diffuse > 0.0 && shininess > 0.0 && att > 0.0) { - FP vec3 r = reflect( -ts, 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 ); + addLightAdsModelNormalMapped(vpos, n, eye, shininess, tangentMatrix, lights[6], diffuseColor, specularColor); + if (lightCount < 8) return; + + addLightAdsModelNormalMapped(vpos, n, eye, shininess, tangentMatrix, lights[7], diffuseColor, specularColor); +} + +void addLightAdsModel(const in FP vec3 vpos, + const in FP vec3 n, + const in FP vec3 eye, + const in FP float shininess, + const in Light light, + inout FP vec3 diffuseColor, + inout FP vec3 specularColor) +{ + FP vec3 s; + + FP float att = 1.0; + if ( light.type != TYPE_DIRECTIONAL ) { + s = light.position - vpos; + if (length( light.attenuation ) != 0.0) { + FP float dist = length(s); + att = 1.0 / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * dist * dist); + } + s = normalize( s ); + if ( light.type == TYPE_SPOT ) { + if ( degrees(acos(dot(-s, normalize(light.direction))) ) > light.cutOffAngle) + att = 0.0; } + } else { + s = normalize( -light.direction ); + } - diffuseColor += att * lights[i].intensity * diffuse * lights[i].color; - specularColor += att * lights[i].intensity * specular * lights[i].color; + FP float diffuse = max( dot( s, n ), 0.0 ); + FP float specular = 0.0; + + if (diffuse > 0.0 && shininess > 0.0 && att > 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 * light.intensity * diffuse * light.color; + specularColor += att * light.intensity * specular * light.color; } + 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); + if (lightCount < 1) return; FP vec3 n = normalize( vnormal ); + addLightAdsModel(vpos, n, eye, shininess, lights[0], diffuseColor, specularColor); + if (lightCount < 2) return; - FP vec3 s; - for (int 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); - } - s = normalize( s ); - if ( lights[i].type == TYPE_SPOT ) { - if ( degrees(acos(dot(-s, normalize(lights[i].direction))) ) > lights[i].cutOffAngle) - att = 0.0; - } - } else { - s = normalize( -lights[i].direction ); - } + addLightAdsModel(vpos, n, eye, shininess, lights[1], diffuseColor, specularColor); + if (lightCount < 3) return; - FP float diffuse = max( dot( s, n ), 0.0 ); + addLightAdsModel(vpos, n, eye, shininess, lights[2], diffuseColor, specularColor); + if (lightCount < 4) return; - FP float specular = 0.0; - if (diffuse > 0.0 && shininess > 0.0 && att > 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 ); - } + addLightAdsModel(vpos, n, eye, shininess, lights[3], diffuseColor, specularColor); + if (lightCount < 5) return; + + addLightAdsModel(vpos, n, eye, shininess, lights[4], diffuseColor, specularColor); + if (lightCount < 6) return; + + addLightAdsModel(vpos, n, eye, shininess, lights[5], diffuseColor, specularColor); + if (lightCount < 7) return; + + addLightAdsModel(vpos, n, eye, shininess, lights[6], diffuseColor, specularColor); + if (lightCount < 8) return; - diffuseColor += att * lights[i].intensity * diffuse * lights[i].color; - specularColor += att * lights[i].intensity * specular * lights[i].color; + addLightAdsModel(vpos, n, eye, shininess, lights[7], diffuseColor, specularColor); +} + +void addLightAdModel(const in FP vec3 vpos, + const in FP vec3 n, + const in Light light, + inout FP vec3 diffuseColor) +{ + FP vec3 s; + FP float att = 1.0; + if ( light.type != TYPE_DIRECTIONAL ) { + s = light.position - vpos; + if (length( light.attenuation ) != 0.0) { + FP float dist = length(s); + att = 1.0 / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * dist * dist); + } + s = normalize( s ); + if ( light.type == TYPE_SPOT ) { + if ( degrees(acos(dot(-s, normalize(light.direction))) ) > light.cutOffAngle) + att = 0.0; + } + } else { + s = normalize( -light.direction ); } + + FP float diffuse = max( dot( s, n ), 0.0 ); + + diffuseColor += att * light.intensity * diffuse * light.color; } void adModel(const in FP vec3 vpos, const in FP vec3 vnormal, out FP vec3 diffuseColor) { diffuseColor = vec3(0.0); + if (lightCount < 1) return; FP vec3 n = normalize( vnormal ); + addLightAdModel(vpos, n, lights[0], diffuseColor); + if (lightCount < 2) return; - FP vec3 s; - for (int 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); - } - s = normalize( s ); - if ( lights[i].type == TYPE_SPOT ) { - if ( degrees(acos(dot(-s, normalize(lights[i].direction))) ) > lights[i].cutOffAngle) - att = 0.0; - } - } else { - s = normalize( -lights[i].direction ); - } + addLightAdModel(vpos, n, lights[1], diffuseColor); + if (lightCount < 3) return; - FP float diffuse = max( dot( s, n ), 0.0 ); + addLightAdModel(vpos, n, lights[2], diffuseColor); + if (lightCount < 4) return; - diffuseColor += att * lights[i].intensity * diffuse * lights[i].color; - } + addLightAdModel(vpos, n, lights[3], diffuseColor); + if (lightCount < 5) return; + + addLightAdModel(vpos, n, lights[4], diffuseColor); + if (lightCount < 6) return; + + addLightAdModel(vpos, n, lights[5], diffuseColor); + if (lightCount < 7) return; + + addLightAdModel(vpos, n, lights[6], diffuseColor); + if (lightCount < 8) return; + + addLightAdModel(vpos, n, lights[7], diffuseColor); } |