summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Persano <mauro.persano@kdab.com>2017-01-11 18:41:15 -0200
committerSean Harmer <sean.harmer@kdab.com>2017-03-16 09:08:44 +0000
commitea33d6b0530ae3f2601f15fe1e4f63faebdb572c (patch)
treeff2b5fe22b74901d93b2173a95db11227330284b
parent7c59817810e74269a48b9f522a4b2013b426d3c2 (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.frag256
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);
}