GLES2 / GLES3 - Use gl_FragColor temporary

On some hardware, modifying gl_FragColor multiple times can cause large performance drops. This PR writes to a standard temporary variable instead, and copies across to gl_FragColor once only at the end of the fragment shader.

This could potentially lead to large gains in performance on affected hardware.
This commit is contained in:
lawnjelly 2023-11-06 14:31:53 +00:00 committed by Relintai
parent e53dcc1432
commit 3a04d5adfe
3 changed files with 37 additions and 20 deletions

View File

@ -126,6 +126,13 @@ uniform float camera_z_far;
uniform float camera_z_near; uniform float camera_z_near;
void main() { void main() {
// Instead of writing directly to gl_FragColor,
// we use an intermediate, and only write
// to gl_FragColor ONCE at the end of the shader.
// This is because some hardware can have huge
// slowdown if you modify gl_FragColor multiple times.
vec4 frag_color;
#ifdef GLOW_GAUSSIAN_HORIZONTAL #ifdef GLOW_GAUSSIAN_HORIZONTAL
vec2 pix_size = pixel_size; vec2 pix_size = pixel_size;
pix_size *= 0.5; //reading from larger buffer, so use more samples pix_size *= 0.5; //reading from larger buffer, so use more samples
@ -164,7 +171,7 @@ void main() {
#endif //USE_GLOW_HIGH_QUALITY #endif //USE_GLOW_HIGH_QUALITY
color *= glow_strength; color *= glow_strength;
gl_FragColor = color; frag_color = color;
#endif //GLOW_GAUSSIAN_HORIZONTAL #endif //GLOW_GAUSSIAN_HORIZONTAL
#ifdef GLOW_GAUSSIAN_VERTICAL #ifdef GLOW_GAUSSIAN_VERTICAL
@ -174,7 +181,7 @@ void main() {
color += texture2DLod(source_color, uv_interp + vec2(0.0, -1.0) * pixel_size, lod) * 0.233062; color += texture2DLod(source_color, uv_interp + vec2(0.0, -1.0) * pixel_size, lod) * 0.233062;
color += texture2DLod(source_color, uv_interp + vec2(0.0, -2.0) * pixel_size, lod) * 0.122581; color += texture2DLod(source_color, uv_interp + vec2(0.0, -2.0) * pixel_size, lod) * 0.122581;
color *= glow_strength; color *= glow_strength;
gl_FragColor = color; frag_color = color;
#endif #endif
#ifndef USE_GLES_OVER_GL #ifndef USE_GLES_OVER_GL
@ -280,7 +287,7 @@ void main() {
color_accum /= k_accum; color_accum /= k_accum;
} }
gl_FragColor = color_accum; ///k_accum; frag_color = color_accum; ///k_accum;
#endif #endif
@ -330,16 +337,17 @@ void main() {
color_accum.a = max(color_accum.a, sqrt(max_accum)); color_accum.a = max(color_accum.a, sqrt(max_accum));
gl_FragColor = color_accum; frag_color = color_accum;
#endif #endif
#ifdef GLOW_FIRST_PASS #ifdef GLOW_FIRST_PASS
float luminance = max(gl_FragColor.r, max(gl_FragColor.g, gl_FragColor.b)); float luminance = max(frag_color.r, max(frag_color.g, frag_color.b));
float feedback = max(smoothstep(glow_hdr_threshold, glow_hdr_threshold + glow_hdr_scale, luminance), glow_bloom); float feedback = max(smoothstep(glow_hdr_threshold, glow_hdr_threshold + glow_hdr_scale, luminance), glow_bloom);
gl_FragColor = min(gl_FragColor * feedback, vec4(luminance_cap)); frag_color = min(frag_color * feedback, vec4(luminance_cap));
#endif #endif
gl_FragColor = frag_color;
} }

View File

@ -2236,11 +2236,18 @@ FRAGMENT_SHADER_CODE
#endif // !USE_SHADOW_TO_OPACITY #endif // !USE_SHADOW_TO_OPACITY
// Instead of writing directly to gl_FragColor,
// we use an intermediate, and only write
// to gl_FragColor ONCE at the end of the shader.
// This is because some hardware can have huge
// slowdown if you modify gl_FragColor multiple times.
vec4 frag_color;
#ifndef RENDER_DEPTH #ifndef RENDER_DEPTH
#ifdef SHADELESS #ifdef SHADELESS
gl_FragColor = vec4(albedo, alpha); frag_color = vec4(albedo, alpha);
#else #else
ambient_light *= albedo; ambient_light *= albedo;
@ -2255,13 +2262,13 @@ FRAGMENT_SHADER_CODE
diffuse_light *= 1.0 - metallic; diffuse_light *= 1.0 - metallic;
ambient_light *= 1.0 - metallic; ambient_light *= 1.0 - metallic;
gl_FragColor = vec4(ambient_light + diffuse_light + specular_light, alpha); frag_color = vec4(ambient_light + diffuse_light + specular_light, alpha);
//add emission if in base pass //add emission if in base pass
#ifdef BASE_PASS #ifdef BASE_PASS
gl_FragColor.rgb += emission; frag_color.rgb += emission;
#endif #endif
// gl_FragColor = vec4(normal, 1.0); // frag_color = vec4(normal, 1.0);
//apply fog //apply fog
#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) #if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED)
@ -2269,9 +2276,9 @@ FRAGMENT_SHADER_CODE
#if defined(USE_VERTEX_LIGHTING) #if defined(USE_VERTEX_LIGHTING)
#if defined(BASE_PASS) #if defined(BASE_PASS)
gl_FragColor.rgb = mix(gl_FragColor.rgb, fog_interp.rgb, fog_interp.a); frag_color.rgb = mix(frag_color.rgb, fog_interp.rgb, fog_interp.a);
#else #else
gl_FragColor.rgb *= (1.0 - fog_interp.a); frag_color.rgb *= (1.0 - fog_interp.a);
#endif // BASE_PASS #endif // BASE_PASS
#else //pixel based fog #else //pixel based fog
@ -2292,7 +2299,7 @@ FRAGMENT_SHADER_CODE
fog_amount = pow(fog_z, fog_depth_curve) * fog_color_base.a; fog_amount = pow(fog_z, fog_depth_curve) * fog_color_base.a;
if (fog_transmit_enabled) { if (fog_transmit_enabled) {
vec3 total_light = gl_FragColor.rgb; vec3 total_light = frag_color.rgb;
float transmit = pow(fog_z, fog_transmit_curve); float transmit = pow(fog_z, fog_transmit_curve);
fog_color = mix(max(total_light, fog_color), fog_color, transmit); fog_color = mix(max(total_light, fog_color), fog_color, transmit);
} }
@ -2307,9 +2314,9 @@ FRAGMENT_SHADER_CODE
#endif #endif
#if defined(BASE_PASS) #if defined(BASE_PASS)
gl_FragColor.rgb = mix(gl_FragColor.rgb, fog_color, fog_amount); frag_color.rgb = mix(frag_color.rgb, fog_color, fog_amount);
#else #else
gl_FragColor.rgb *= (1.0 - fog_amount); frag_color.rgb *= (1.0 - fog_amount);
#endif // BASE_PASS #endif // BASE_PASS
#endif //use vertex lit #endif //use vertex lit
@ -2320,7 +2327,7 @@ FRAGMENT_SHADER_CODE
#ifdef OUTPUT_LINEAR #ifdef OUTPUT_LINEAR
// sRGB -> linear // sRGB -> linear
gl_FragColor.rgb = mix(pow((gl_FragColor.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), gl_FragColor.rgb * (1.0 / 12.92), vec3(lessThan(gl_FragColor.rgb, vec3(0.04045)))); frag_color.rgb = mix(pow((frag_color.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), frag_color.rgb * (1.0 / 12.92), vec3(lessThan(frag_color.rgb, vec3(0.04045))));
#endif #endif
#else // not RENDER_DEPTH #else // not RENDER_DEPTH
@ -2330,8 +2337,10 @@ FRAGMENT_SHADER_CODE
highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0; // bias highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0; // bias
highp vec4 comp = fract(depth * vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0)); highp vec4 comp = fract(depth * vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0));
comp -= comp.xxyz * vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0); comp -= comp.xxyz * vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);
gl_FragColor = comp; frag_color = comp;
#endif #endif
#endif #endif
gl_FragColor = frag_color;
} }

View File

@ -378,9 +378,9 @@ void main() {
color.rgb = apply_color_correction(color.rgb, color_correction); color.rgb = apply_color_correction(color.rgb, color_correction);
#endif #endif
gl_FragColor = color;
#ifdef DISABLE_ALPHA #ifdef DISABLE_ALPHA
gl_FragColor.a = 1.0; color.a = 1.0;
#endif #endif
gl_FragColor = color;
} }