summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dummy/rasterizer_dummy.h2
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp71
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.h4
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp9
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h1
-rw-r--r--drivers/gles2/shaders/copy.glsl29
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp68
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h4
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp9
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h1
-rw-r--r--drivers/gles3/shaders/copy.glsl36
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