Shader simplification: Share some variables between lights to help bad register allocators

This commit is contained in:
Henrik Rydgard 2013-05-19 14:36:07 +02:00
parent 0ff8be1b1a
commit a1d549c59f

View file

@ -366,21 +366,30 @@ void GenerateVertexShader(int prim, char *buffer) {
WRITE(p, " lowp vec4 lightSum0 = u_ambient * %s + vec4(u_matemissive, 0.0);\n", ambient); WRITE(p, " lowp vec4 lightSum0 = u_ambient * %s + vec4(u_matemissive, 0.0);\n", ambient);
} }
bool lightSum1IsZero = true; bool diffuseIsZero = true;
bool specularIsZero = true;
bool distanceNeeded = false;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (doLight[i] != LIGHT_FULL) if (doLight[i] != LIGHT_FULL)
continue; continue;
diffuseIsZero = false;
GELightComputation comp = (GELightComputation)(gstate.ltype[i] & 3); GELightComputation comp = (GELightComputation)(gstate.ltype[i] & 3);
if (comp != GE_LIGHTCOMP_ONLYDIFFUSE) { if (comp != GE_LIGHTCOMP_ONLYDIFFUSE)
lightSum1IsZero = false; specularIsZero = false;
break; GELightType type = (GELightType)((gstate.ltype[i] >> 8) & 3);
} if (type != GE_LIGHTTYPE_DIRECTIONAL)
distanceNeeded = true;
} }
if (!lightSum1IsZero) { if (!specularIsZero) {
WRITE(p, " lowp vec3 lightSum1 = vec3(0.0);\n"); WRITE(p, " lowp vec3 lightSum1 = vec3(0.0);\n");
} }
if (distanceNeeded) {
WRITE(p, " float distance;\n");
WRITE(p, " lowp float lightScale;\n");
}
// Calculate lights if needed. If shade mapping is enabled, lights may need to be // Calculate lights if needed. If shade mapping is enabled, lights may need to be
// at least partially calculated. // at least partially calculated.
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
@ -405,7 +414,7 @@ void GenerateVertexShader(int prim, char *buffer) {
} }
char timesLightScale[128]; char timesLightScale[128];
sprintf(timesLightScale, " * lightScale%i", i); sprintf(timesLightScale, " * lightScale");
// Attenuation // Attenuation
switch (type) { switch (type) {
@ -413,16 +422,17 @@ void GenerateVertexShader(int prim, char *buffer) {
timesLightScale[0] = 0; timesLightScale[0] = 0;
break; break;
case GE_LIGHTTYPE_POINT: case GE_LIGHTTYPE_POINT:
WRITE(p, " float distance%i = length(toLight%i);\n", i, i); WRITE(p, " distance = length(toLight%i);\n", i, i);
WRITE(p, " lowp float lightScale%i = clamp(1.0 / dot(u_lightatt%i, vec3(1.0, distance%i, distance%i*distance%i)), 0.0, 1.0);\n", i, i, i, i, i); WRITE(p, " lightScale = clamp(1.0 / dot(u_lightatt%i, vec3(1.0, distance, distance*distance)), 0.0, 1.0);\n", i);
break; break;
case GE_LIGHTTYPE_SPOT: case GE_LIGHTTYPE_SPOT:
WRITE(p, " float distance%i = length(toLight%i);\n", i, i); WRITE(p, " distance = length(toLight%i);\n", i, i);
WRITE(p, " lowp float lightScale%i = 0.0;\n", i);
WRITE(p, " lowp float angle%i = dot(normalize(u_lightdir%i), normalize(toLight%i));\n", i, i, i); WRITE(p, " lowp float angle%i = dot(normalize(u_lightdir%i), normalize(toLight%i));\n", i, i, i);
WRITE(p, " if (angle%i >= u_lightangle%i) {\n", i, i); WRITE(p, " if (angle%i >= u_lightangle%i) {\n", i, i);
WRITE(p, " lightScale%i = clamp(1.0 / dot(u_lightatt%i, vec3(1.0, distance%i, distance%i*distance%i)), 0.0, 1.0) * pow(angle%i, u_lightspotCoef%i);\n", i, i, i, i, i, i, i); WRITE(p, " lightScale = clamp(1.0 / dot(u_lightatt%i, vec3(1.0, distance, distance*distance)), 0.0, 1.0) * pow(angle%i, u_lightspotCoef%i);\n", i, i, i);
WRITE(p, " }\n"); WRITE(p, " } else {\n");
WRITE(p, " lightScale = 0.0;\n");
WRITE(p, " }\n");
break; break;
default: default:
// ILLEGAL // ILLEGAL
@ -444,13 +454,13 @@ void GenerateVertexShader(int prim, char *buffer) {
if (lmode) { if (lmode) {
WRITE(p, " v_color0 = clamp(lightSum0, 0.0, 1.0);\n"); WRITE(p, " v_color0 = clamp(lightSum0, 0.0, 1.0);\n");
// v_color1 only exists when lmode = 1. // v_color1 only exists when lmode = 1.
if (lightSum1IsZero) { if (specularIsZero) {
WRITE(p, " v_color1 = vec3(0.0);\n"); WRITE(p, " v_color1 = vec3(0.0);\n");
} else { } else {
WRITE(p, " v_color1 = clamp(lightSum1, 0.0, 1.0);\n"); WRITE(p, " v_color1 = clamp(lightSum1, 0.0, 1.0);\n");
} }
} else { } else {
if (lightSum1IsZero) { if (specularIsZero) {
WRITE(p, " v_color0 = clamp(lightSum0, 0.0, 1.0);\n"); WRITE(p, " v_color0 = clamp(lightSum0, 0.0, 1.0);\n");
} else { } else {
WRITE(p, " v_color0 = clamp(clamp(lightSum0, 0.0, 1.0) + vec4(lightSum1, 0.0), 0.0, 1.0);\n"); WRITE(p, " v_color0 = clamp(clamp(lightSum0, 0.0, 1.0) + vec4(lightSum1, 0.0), 0.0, 1.0);\n");