diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dummy/rasterizer_dummy.h | 2 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_scene_gles2.cpp | 71 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_scene_gles2.h | 4 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.cpp | 9 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.h | 1 | ||||
-rw-r--r-- | drivers/gles2/shaders/copy.glsl | 29 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 68 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 4 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 9 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.h | 1 | ||||
-rw-r--r-- | drivers/gles3/shaders/copy.glsl | 36 |
11 files changed, 233 insertions, 1 deletions
diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index 253936ca34..6f91fc4949 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -61,6 +61,7 @@ public: void environment_set_bg_energy(RID p_env, float p_energy) {} void environment_set_canvas_max_layer(RID p_env, int p_max_layer) {} void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0) {} + void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id){}; void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {} void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {} @@ -216,6 +217,7 @@ public: uint32_t texture_get_height(RID p_texture) const { return 0; } uint32_t texture_get_depth(RID p_texture) const { return 0; } void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth_3d) {} + void texture_bind(RID p_texture, uint32_t p_texture_no) {} void texture_set_path(RID p_texture, const String &p_path) { DummyTexture *t = texture_owner.getornull(p_texture); diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index 0231bb5837..a07c6832dc 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -36,6 +36,7 @@ #include "core/project_settings.h" #include "core/vmap.h" #include "rasterizer_canvas_gles2.h" +#include "servers/camera/camera_feed.h" #include "servers/visual/visual_server_raster.h" #ifndef GLES_OVER_GL @@ -769,6 +770,13 @@ void RasterizerSceneGLES2::environment_set_ambient_light(RID p_env, const Color env->ambient_sky_contribution = p_sky_contribution; } +void RasterizerSceneGLES2::environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) { + Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->camera_feed_id = p_camera_feed_id; +} + void RasterizerSceneGLES2::environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -2843,6 +2851,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const // clear color Color clear_color(0, 0, 0, 1); + Ref<CameraFeed> feed; if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { clear_color = Color(0, 0, 0, 0); @@ -2855,6 +2864,9 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const } else if (env->bg_mode == VS::ENV_BG_CANVAS || env->bg_mode == VS::ENV_BG_COLOR || env->bg_mode == VS::ENV_BG_COLOR_SKY) { clear_color = env->bg_color; storage->frame.clear_request = false; + } else if (env->bg_mode == VS::ENV_BG_CAMERA_FEED) { + feed = CameraServer::get_singleton()->get_feed_by_id(env->camera_feed_id); + storage->frame.clear_request = false; } else { storage->frame.clear_request = false; } @@ -2891,7 +2903,66 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const env_radiance_tex = sky->radiance; } } break; + case VS::ENV_BG_CAMERA_FEED: { + if (feed.is_valid() && (feed->get_base_width() > 0) && (feed->get_base_height() > 0)) { + // copy our camera feed to our background + + glDisable(GL_BLEND); + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_NO_ALPHA, true); + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_DISPLAY_TRANSFORM, true); + + if (feed->get_datatype() == CameraFeed::FEED_RGB) { + RID camera_RGBA = feed->get_texture(CameraServer::FEED_RGBA_IMAGE); + + VS::get_singleton()->texture_bind(camera_RGBA, 0); + + } else if (feed->get_datatype() == CameraFeed::FEED_YCbCr) { + RID camera_YCbCr = feed->get_texture(CameraServer::FEED_YCbCr_IMAGE); + + VS::get_singleton()->texture_bind(camera_YCbCr, 0); + storage->shaders.copy.set_conditional(CopyShaderGLES2::YCBCR_TO_RGB, true); + + } else if (feed->get_datatype() == CameraFeed::FEED_YCbCr_Sep) { + RID camera_Y = feed->get_texture(CameraServer::FEED_Y_IMAGE); + RID camera_CbCr = feed->get_texture(CameraServer::FEED_CbCr_IMAGE); + + VS::get_singleton()->texture_bind(camera_Y, 0); + VS::get_singleton()->texture_bind(camera_CbCr, 1); + + storage->shaders.copy.set_conditional(CopyShaderGLES2::SEP_CBCR_TEXTURE, true); + storage->shaders.copy.set_conditional(CopyShaderGLES2::YCBCR_TO_RGB, true); + }; + + storage->shaders.copy.bind(); + storage->shaders.copy.set_uniform(CopyShaderGLES2::DISPLAY_TRANSFORM, feed->get_transform()); + + storage->bind_quad_array(); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDisableVertexAttribArray(VS::ARRAY_VERTEX); + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + // turn off everything used + storage->shaders.copy.set_conditional(CopyShaderGLES2::SEP_CBCR_TEXTURE, false); + storage->shaders.copy.set_conditional(CopyShaderGLES2::YCBCR_TO_RGB, false); + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_NO_ALPHA, false); + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_DISPLAY_TRANSFORM, false); + + //restore + glEnable(GL_BLEND); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + } else { + // don't have a feed, just show greenscreen :) + clear_color = Color(0.0, 1.0, 0.0, 1.0); + } + } break; default: { // FIXME: implement other background modes } break; diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h index d5a691d0b9..c95385eb24 100644 --- a/drivers/gles2/rasterizer_scene_gles2.h +++ b/drivers/gles2/rasterizer_scene_gles2.h @@ -354,6 +354,8 @@ public: float bg_energy; float sky_ambient; + int camera_feed_id; + Color ambient_color; float ambient_energy; float ambient_sky_contribution; @@ -381,6 +383,7 @@ public: sky_custom_fov(0.0), bg_energy(1.0), sky_ambient(0), + camera_feed_id(0), ambient_energy(1.0), ambient_sky_contribution(0.0), canvas_max_layer(0), @@ -413,6 +416,7 @@ public: virtual void environment_set_bg_energy(RID p_env, float p_energy); virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer); virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0); + virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id); virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality); virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality); diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index e4b47814b2..70f1173a7d 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -968,6 +968,15 @@ uint32_t RasterizerStorageGLES2::texture_get_texid(RID p_texture) const { return texture->tex_id; } +void RasterizerStorageGLES2::texture_bind(RID p_texture, uint32_t p_texture_no) { + Texture *texture = texture_owner.getornull(p_texture); + + ERR_FAIL_COND(!texture); + + glActiveTexture(GL_TEXTURE0 + p_texture_no); + glBindTexture(texture->target, texture->tex_id); +} + uint32_t RasterizerStorageGLES2::texture_get_width(RID p_texture) const { Texture *texture = texture_owner.getornull(p_texture); diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index af57aa3d9b..d139697b86 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -350,6 +350,7 @@ public: virtual uint32_t texture_get_height(RID p_texture) const; virtual uint32_t texture_get_depth(RID p_texture) const; virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth); + virtual void texture_bind(RID p_texture, uint32_t p_texture_no); virtual void texture_set_path(RID p_texture, const String &p_path); virtual String texture_get_path(RID p_texture) const; diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl index 931b3f3708..195db7c45f 100644 --- a/drivers/gles2/shaders/copy.glsl +++ b/drivers/gles2/shaders/copy.glsl @@ -28,8 +28,15 @@ varying vec2 uv_interp; #endif varying vec2 uv2_interp; +// These definitions are here because the shader-wrapper builder does +// not understand `#elif defined()` +#ifdef USE_DISPLAY_TRANSFORM +#endif + #ifdef USE_COPY_SECTION uniform highp vec4 copy_section; +#elif defined(USE_DISPLAY_TRANSFORM) +uniform highp mat4 display_transform; #endif void main() { @@ -48,6 +55,8 @@ void main() { #ifdef USE_COPY_SECTION uv_interp = copy_section.xy + uv_interp * copy_section.zw; gl_Position.xy = (copy_section.xy + (gl_Position.xy * 0.5 + 0.5) * copy_section.zw) * 2.0 - 1.0; +#elif defined(USE_DISPLAY_TRANSFORM) + uv_interp = (display_transform * vec4(uv_in, 1.0, 1.0)).xy; #endif } @@ -88,6 +97,10 @@ uniform samplerCube source_cube; // texunit:0 uniform sampler2D source; // texunit:0 #endif +#ifdef SEP_CBCR_TEXTURE +uniform sampler2D CbCr; //texunit:1 +#endif + varying vec2 uv2_interp; #ifdef USE_MULTIPLIER @@ -145,10 +158,26 @@ void main() { #elif defined(USE_CUBEMAP) vec4 color = textureCube(source_cube, normalize(cube_interp)); +#elif defined(SEP_CBCR_TEXTURE) + vec4 color; + color.r = texture2D(source, uv_interp).r; + color.gb = texture2D(CbCr, uv_interp).rg - vec2(0.5, 0.5); + color.a = 1.0; #else vec4 color = texture2D(source, uv_interp); #endif +#ifdef YCBCR_TO_RGB + // YCbCr -> RGB conversion + + // Using BT.601, which is the standard for SDTV is provided as a reference + color.rgb = mat3( + vec3(1.00000, 1.00000, 1.00000), + vec3(0.00000, -0.34413, 1.77200), + vec3(1.40200, -0.71414, 0.00000)) * + color.rgb; +#endif + #ifdef USE_NO_ALPHA color.a = 1.0; #endif diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 7e02f2f3f5..7acb8a22bc 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -34,6 +34,7 @@ #include "core/os/os.h" #include "core/project_settings.h" #include "rasterizer_canvas_gles3.h" +#include "servers/camera/camera_feed.h" #include "servers/visual/visual_server_raster.h" #ifndef GLES_OVER_GL @@ -830,6 +831,12 @@ void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color env->ambient_energy = p_energy; env->ambient_sky_contribution = p_sky_contribution; } +void RasterizerSceneGLES3::environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) { + Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->camera_feed_id = p_camera_feed_id; +} void RasterizerSceneGLES3::environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) { @@ -4342,6 +4349,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const Color clear_color(0, 0, 0, 0); RasterizerStorageGLES3::Sky *sky = NULL; + Ref<CameraFeed> feed; GLuint env_radiance_tex = 0; if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { @@ -4376,6 +4384,9 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const clear_color = env->bg_color.to_linear(); storage->frame.clear_request = false; + } else if (env->bg_mode == VS::ENV_BG_CAMERA_FEED) { + feed = CameraServer::get_singleton()->get_feed_by_id(env->camera_feed_id); + storage->frame.clear_request = false; } else { storage->frame.clear_request = false; } @@ -4426,6 +4437,63 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); break; + case VS::ENV_BG_CAMERA_FEED: + if (feed.is_valid() && (feed->get_base_width() > 0) && (feed->get_base_height() > 0)) { + // copy our camera feed to our background + + glDisable(GL_BLEND); + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_DISPLAY_TRANSFORM, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, true); + + if (feed->get_datatype() == CameraFeed::FEED_RGB) { + RID camera_RGBA = feed->get_texture(CameraServer::FEED_RGBA_IMAGE); + + VS::get_singleton()->texture_bind(camera_RGBA, 0); + } else if (feed->get_datatype() == CameraFeed::FEED_YCbCr) { + RID camera_YCbCr = feed->get_texture(CameraServer::FEED_YCbCr_IMAGE); + + VS::get_singleton()->texture_bind(camera_YCbCr, 0); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, true); + + } else if (feed->get_datatype() == CameraFeed::FEED_YCbCr_Sep) { + RID camera_Y = feed->get_texture(CameraServer::FEED_Y_IMAGE); + RID camera_CbCr = feed->get_texture(CameraServer::FEED_CbCr_IMAGE); + + VS::get_singleton()->texture_bind(camera_Y, 0); + VS::get_singleton()->texture_bind(camera_CbCr, 1); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::SEP_CBCR_TEXTURE, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, true); + }; + + storage->shaders.copy.bind(); + storage->shaders.copy.set_uniform(CopyShaderGLES3::DISPLAY_TRANSFORM, feed->get_transform()); + + _copy_screen(true, true); + + //turn off everything used + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_DISPLAY_TRANSFORM, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::SEP_CBCR_TEXTURE, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, false); + + //restore + glEnable(GL_BLEND); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + } else { + // don't have a feed, just show greenscreen :) + clear_color = Color(0.0, 1.0, 0.0, 1.0); + } + break; default: { } } diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 59e23e5ac9..910f90edc2 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -376,6 +376,8 @@ public: float bg_energy; float sky_ambient; + int camera_feed_id; + Color ambient_color; float ambient_energy; float ambient_sky_contribution; @@ -461,6 +463,7 @@ public: sky_custom_fov(0.0), bg_energy(1.0), sky_ambient(0), + camera_feed_id(0), ambient_energy(1.0), ambient_sky_contribution(0.0), canvas_max_layer(0), @@ -542,6 +545,7 @@ public: virtual void environment_set_bg_energy(RID p_env, float p_energy); virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer); virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0); + virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id); virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality); virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 01b85458c2..f8a3283869 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1437,6 +1437,15 @@ uint32_t RasterizerStorageGLES3::texture_get_texid(RID p_texture) const { return texture->tex_id; } +void RasterizerStorageGLES3::texture_bind(RID p_texture, uint32_t p_texture_no) { + + Texture *texture = texture_owner.getornull(p_texture); + + ERR_FAIL_COND(!texture); + + glActiveTexture(GL_TEXTURE0 + p_texture_no); + glBindTexture(texture->target, texture->tex_id); +} uint32_t RasterizerStorageGLES3::texture_get_width(RID p_texture) const { Texture *texture = texture_owner.get(p_texture); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 3d86558407..badb656e96 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -358,6 +358,7 @@ public: virtual uint32_t texture_get_height(RID p_texture) const; virtual uint32_t texture_get_depth(RID p_texture) const; virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth); + virtual void texture_bind(RID p_texture, uint32_t p_texture_no); virtual void texture_set_path(RID p_texture, const String &p_path); virtual String texture_get_path(RID p_texture) const; diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index e1a0813efc..232b9ce7c0 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -18,10 +18,19 @@ out vec2 uv_interp; out vec2 uv2_interp; +// These definitions are here because the shader-wrapper builder does +// not understand `#elif defined()` +#ifdef USE_DISPLAY_TRANSFORM +#endif + #ifdef USE_COPY_SECTION uniform vec4 copy_section; +#elif defined(USE_DISPLAY_TRANSFORM) + +uniform highp mat4 display_transform; + #endif void main() { @@ -44,6 +53,9 @@ void main() { uv_interp = copy_section.xy + uv_interp * copy_section.zw; gl_Position.xy = (copy_section.xy + (gl_Position.xy * 0.5 + 0.5) * copy_section.zw) * 2.0 - 1.0; +#elif defined(USE_DISPLAY_TRANSFORM) + + uv_interp = (display_transform * vec4(uv_in, 1.0, 1.0)).xy; #endif } @@ -73,6 +85,8 @@ uniform highp vec4 asym_proj; #endif #ifdef USE_TEXTURE2DARRAY #endif +#ifdef YCBCR_TO_SRGB +#endif #ifdef USE_CUBEMAP uniform samplerCube source_cube; //texunit:0 @@ -84,6 +98,10 @@ uniform sampler2DArray source_2d_array; //texunit:0 uniform sampler2D source; //texunit:0 #endif +#ifdef SEP_CBCR_TEXTURE +uniform sampler2D CbCr; //texunit:1 +#endif + /* clang-format on */ #if defined(USE_TEXTURE3D) || defined(USE_TEXTURE2DARRAY) @@ -166,14 +184,30 @@ void main() { vec4 color = textureLod(source_3d, vec3(uv_interp, layer), 0.0); #elif defined(USE_TEXTURE2DARRAY) vec4 color = textureLod(source_2d_array, vec3(uv_interp, layer), 0.0); +#elif defined(SEP_CBCR_TEXTURE) + vec4 color; + color.r = textureLod(source, uv_interp, 0.0).r; + color.gb = textureLod(CbCr, uv_interp, 0.0).rg - vec2(0.5, 0.5); + color.a = 1.0; #else vec4 color = textureLod(source, uv_interp, 0.0); #endif #ifdef LINEAR_TO_SRGB - //regular Linear -> SRGB conversion + // 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))); + +#elif defined(YCBCR_TO_SRGB) + + // YCbCr -> SRGB conversion + // Using BT.709 which is the standard for HDTV + color.rgb = mat3( + vec3(1.00000, 1.00000, 1.00000), + vec3(0.00000, -0.18732, 1.85560), + vec3(1.57481, -0.46813, 0.00000)) * + color.rgb; + #endif #ifdef SRGB_TO_LINEAR |