Convert output of GLES2 to linear color space if keep_3d_linear is enabled
This commit is contained in:
@ -403,6 +403,7 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re
|
||||
canvas->_set_texture_rect_mode(true);
|
||||
|
||||
canvas->state.canvas_shader.set_custom_shader(0);
|
||||
canvas->state.canvas_shader.set_conditional(CanvasShaderGLES2::LINEAR_TO_SRGB, rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]);
|
||||
canvas->state.canvas_shader.bind();
|
||||
|
||||
canvas->canvas_begin();
|
||||
@ -421,6 +422,8 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
canvas->canvas_end();
|
||||
|
||||
canvas->state.canvas_shader.set_conditional(CanvasShaderGLES2::LINEAR_TO_SRGB, false);
|
||||
}
|
||||
|
||||
void RasterizerGLES2::output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) {
|
||||
|
||||
@ -2655,6 +2655,11 @@ void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const C
|
||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUBEMAP, false);
|
||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, false);
|
||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA, false);
|
||||
if (storage->frame.current_rt) {
|
||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::OUTPUT_LINEAR, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]);
|
||||
} else {
|
||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::OUTPUT_LINEAR, false);
|
||||
}
|
||||
storage->shaders.copy.bind();
|
||||
storage->shaders.copy.set_uniform(CopyShaderGLES2::MULTIPLIER, p_energy);
|
||||
|
||||
@ -2678,6 +2683,7 @@ void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const C
|
||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_PANORAMA, false);
|
||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_MULTIPLIER, false);
|
||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_CUBEMAP, false);
|
||||
storage->shaders.copy.set_conditional(CopyShaderGLES2::OUTPUT_LINEAR, false);
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p_cam_projection) {
|
||||
@ -3312,7 +3318,15 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
||||
}
|
||||
|
||||
if (!env || env->bg_mode != VS::ENV_BG_KEEP) {
|
||||
glClearColor(clear_color.r, clear_color.g, clear_color.b, clear_color.a);
|
||||
if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]) {
|
||||
// convert to linear here
|
||||
Color linear_color = clear_color.to_linear();
|
||||
glClearColor(linear_color.r, linear_color.g, linear_color.b, linear_color.a);
|
||||
|
||||
// leave clear_color in sRGB as most of the render pipeline remains in sRGB color space until writing out to frag_color
|
||||
} else {
|
||||
glClearColor(clear_color.r, clear_color.g, clear_color.b, clear_color.a);
|
||||
}
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
@ -3416,6 +3430,13 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
||||
state.default_bg = Color(0, 0, 0, 1); //black as default background for interior
|
||||
}
|
||||
|
||||
// make sure we set our output mode correctly
|
||||
if (storage->frame.current_rt) {
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::OUTPUT_LINEAR, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]);
|
||||
} else {
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::OUTPUT_LINEAR, false);
|
||||
}
|
||||
|
||||
// render opaque things first
|
||||
render_list.sort_by_key(false);
|
||||
_render_render_list(render_list.elements, render_list.element_count, cam_transform, p_cam_projection, p_eye, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, reverse_cull, false, false);
|
||||
@ -3519,6 +3540,9 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
||||
storage->_copy_screen();
|
||||
}
|
||||
#endif
|
||||
|
||||
// return to default
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::OUTPUT_LINEAR, false);
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
|
||||
@ -3736,6 +3760,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
|
||||
}
|
||||
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, true);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::OUTPUT_LINEAR, false); // just in case, should be false already
|
||||
|
||||
_render_render_list(render_list.elements, render_list.element_count, light_transform, light_projection, 0, RID(), nullptr, 0, bias, normal_bias, flip_facing, false, true);
|
||||
|
||||
|
||||
@ -701,5 +701,11 @@ FRAGMENT_SHADER_CODE
|
||||
//use lighting
|
||||
#endif
|
||||
|
||||
#ifdef LINEAR_TO_SRGB
|
||||
// regular Linear -> SRGB conversion
|
||||
vec3 a = vec3(0.055);
|
||||
color.rgb = mix((vec3(1.0) + a) * pow(color.rgb, vec3(1.0 / 2.4)) - a, 12.92 * color.rgb, vec3(lessThan(color.rgb, vec3(0.0031308))));
|
||||
#endif
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
|
||||
@ -187,5 +187,10 @@ void main() {
|
||||
color.rgb *= multiplier;
|
||||
#endif
|
||||
|
||||
#ifdef OUTPUT_LINEAR
|
||||
// sRGB -> linear
|
||||
color.rgb = mix(pow((color.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), color.rgb * (1.0 / 12.92), vec3(lessThan(color.rgb, vec3(0.04045))));
|
||||
#endif
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
|
||||
@ -2307,6 +2307,11 @@ FRAGMENT_SHADER_CODE
|
||||
|
||||
#endif //unshaded
|
||||
|
||||
#ifdef OUTPUT_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))));
|
||||
#endif
|
||||
|
||||
#else // not RENDER_DEPTH
|
||||
//depth render
|
||||
#ifdef USE_RGBA_SHADOWS
|
||||
|
||||
@ -334,15 +334,49 @@ void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target, const Re
|
||||
RasterizerStorageGLES3::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target);
|
||||
ERR_FAIL_COND(!rt);
|
||||
|
||||
Size2 win_size = OS::get_singleton()->get_window_size();
|
||||
if (rt->external.fbo != 0) {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->external.fbo);
|
||||
if (rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]) {
|
||||
// We need to add an sRGB conversion here as we kept our buffer linear (+ a little tone mapping).
|
||||
|
||||
canvas->_set_texture_rect_mode(true);
|
||||
|
||||
canvas->state.canvas_shader.set_custom_shader(0);
|
||||
canvas->state.canvas_shader.set_conditional(CanvasShaderGLES3::LINEAR_TO_SRGB, true);
|
||||
canvas->state.canvas_shader.bind();
|
||||
|
||||
canvas->canvas_begin();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
// render to our framebuffer
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
|
||||
|
||||
// output our texture
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if (rt->external.fbo != 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, rt->external.color);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, rt->color);
|
||||
}
|
||||
|
||||
canvas->draw_generic_textured_rect(p_screen_rect, Rect2(0, 0, 1, -1));
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
canvas->canvas_end();
|
||||
|
||||
canvas->state.canvas_shader.set_conditional(CanvasShaderGLES3::LINEAR_TO_SRGB, false);
|
||||
} else {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo);
|
||||
// No conversion needed, take the faster approach
|
||||
|
||||
Size2 win_size = OS::get_singleton()->get_window_size();
|
||||
if (rt->external.fbo != 0) {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->external.fbo);
|
||||
} else {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo);
|
||||
}
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
|
||||
glBlitFramebuffer(0, 0, rt->width, rt->height, p_screen_rect.position.x, win_size.height - p_screen_rect.position.y - p_screen_rect.size.height, p_screen_rect.position.x + p_screen_rect.size.width, win_size.height - p_screen_rect.position.y, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
|
||||
glBlitFramebuffer(0, 0, rt->width, rt->height, p_screen_rect.position.x, win_size.height - p_screen_rect.position.y - p_screen_rect.size.height, p_screen_rect.position.x + p_screen_rect.size.width, win_size.height - p_screen_rect.position.y, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
|
||||
void RasterizerGLES3::output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) {
|
||||
|
||||
@ -855,6 +855,13 @@ FRAGMENT_SHADER_CODE
|
||||
|
||||
//use lighting
|
||||
#endif
|
||||
|
||||
#ifdef LINEAR_TO_SRGB
|
||||
// regular Linear -> SRGB conversion
|
||||
vec3 a = vec3(0.055);
|
||||
color.rgb = mix((vec3(1.0) + a) * pow(color.rgb, vec3(1.0 / 2.4)) - a, 12.92 * color.rgb, lessThan(color.rgb, vec3(0.0031308)));
|
||||
#endif
|
||||
|
||||
//color.rgb *= color.a;
|
||||
frag_color = color;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user