summaryrefslogtreecommitdiff
path: root/drivers/gles3/shaders
diff options
context:
space:
mode:
authorclayjohn <claynjohn@gmail.com>2022-05-16 11:56:03 -0700
committerclayjohn <claynjohn@gmail.com>2022-05-16 15:07:09 -0700
commit9b61c855ef00e14925cfdf8a5d61f854c51d92f4 (patch)
tree8f4e02ccf198e5dfd0ad2ca156549f4da3dacfbd /drivers/gles3/shaders
parent23207fcfddf47f17a749c1fa8424c11769610b31 (diff)
Add basic lighting to GLES3 renderer.
This includes all three light types and IBL, but does not include shadows or any form of GI
Diffstat (limited to 'drivers/gles3/shaders')
-rw-r--r--drivers/gles3/shaders/SCsub13
-rw-r--r--drivers/gles3/shaders/cubemap_filter.glsl216
-rw-r--r--drivers/gles3/shaders/scene.glsl384
-rw-r--r--drivers/gles3/shaders/sky.glsl35
-rw-r--r--drivers/gles3/shaders/stdlib_inc.glsl6
-rw-r--r--drivers/gles3/shaders/tonemap_inc.glsl16
6 files changed, 369 insertions, 301 deletions
diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub
index ec32badc19..d8dd573f57 100644
--- a/drivers/gles3/shaders/SCsub
+++ b/drivers/gles3/shaders/SCsub
@@ -2,11 +2,18 @@
Import("env")
-env.Depends("#drivers/gles3/shaders/copy.glsl.gen.h", "#core/math/basis.h")
-env.Depends("#drivers/gles3/shaders/copy.glsl.gen.h", "#core/math/transform_2d.h")
-
if "GLES3_GLSL" in env["BUILDERS"]:
+ # find all include files
+ gl_include_files = [str(f) for f in Glob("*_inc.glsl")]
+
+ # find all shader code(all glsl files excluding our include files)
+ glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
+
+ # make sure we recompile shaders if include files change
+ env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files)
+
env.GLES3_GLSL("canvas.glsl")
env.GLES3_GLSL("copy.glsl")
env.GLES3_GLSL("scene.glsl")
env.GLES3_GLSL("sky.glsl")
+ env.GLES3_GLSL("cubemap_filter.glsl")
diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl
index 2081abfef6..81e66c956c 100644
--- a/drivers/gles3/shaders/cubemap_filter.glsl
+++ b/drivers/gles3/shaders/cubemap_filter.glsl
@@ -1,136 +1,102 @@
/* clang-format off */
-[vertex]
+#[modes]
-#ifdef USE_GLES_OVER_GL
-#define lowp
-#define mediump
-#define highp
-#else
-precision highp float;
-precision highp int;
-#endif
+mode_default =
+mode_copy = #define MODE_DIRECT_WRITE
+
+#[specializations]
-layout(location = 0) in highp vec2 vertex;
+#[vertex]
+
+layout(location = 0) in highp vec2 vertex_attrib;
/* clang-format on */
-layout(location = 4) in highp vec2 uv;
out highp vec2 uv_interp;
void main() {
- uv_interp = uv;
- gl_Position = vec4(vertex, 0, 1);
+ uv_interp = vertex_attrib;
+ gl_Position = vec4(uv_interp, 0.0, 1.0);
}
/* clang-format off */
-[fragment]
+#[fragment]
-#ifdef USE_GLES_OVER_GL
-#define lowp
-#define mediump
-#define highp
-#else
-#if defined(USE_HIGHP_PRECISION)
-precision highp float;
-precision highp int;
-#else
-precision mediump float;
-precision mediump int;
-#endif
-#endif
+#define M_PI 3.14159265359
-#ifdef USE_SOURCE_PANORAMA
-uniform sampler2D source_panorama; //texunit:0
-#else
uniform samplerCube source_cube; //texunit:0
-#endif
+
/* clang-format on */
uniform int face_id;
uniform float roughness;
-in highp vec2 uv_interp;
-
-uniform sampler2D radical_inverse_vdc_cache; // texunit:1
-
-#define M_PI 3.14159265359
-
-#ifdef LOW_QUALITY
-
-#define SAMPLE_COUNT 64
-
-#else
-
-#define SAMPLE_COUNT 512
+uniform float face_size;
+uniform int sample_count;
+//Todo, profile on low end hardware to see if fixed loop is faster
+#ifdef USE_FIXED_SAMPLES
+#define FIXED_SAMPLE_COUNT 32
#endif
-#ifdef USE_SOURCE_PANORAMA
+in highp vec2 uv_interp;
-vec4 texturePanorama(sampler2D pano, vec3 normal) {
- vec2 st = vec2(
- atan(normal.x, normal.z),
- acos(normal.y));
+uniform sampler2D radical_inverse_vdc_cache; // texunit:1
- if (st.x < 0.0)
- st.x += M_PI * 2.0;
+layout(location = 0) out vec4 frag_color;
- st /= vec2(M_PI * 2.0, M_PI);
+#define M_PI 3.14159265359
- return textureLod(pano, st, 0.0);
+// Don't include tonemap_inc.glsl because all we want is these functions, we don't want the uniforms
+vec3 linear_to_srgb(vec3 color) {
+ return max(vec3(1.055) * pow(color, vec3(0.416666667)) - vec3(0.055), vec3(0.0));
}
-#endif
+vec3 srgb_to_linear(vec3 color) {
+ return color * (color * (color * 0.305306011 + 0.682171111) + 0.012522878);
+}
vec3 texelCoordToVec(vec2 uv, int faceID) {
mat3 faceUvVectors[6];
// -x
- faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z
- faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
- faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face
+ faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z
+ faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face
// +x
- faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z
- faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
- faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face
+ faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z
+ faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face
// -y
- faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
- faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z
- faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face
+ faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
+ faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z
+ faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face
// +y
- faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
- faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z
- faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face
+ faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
+ faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z
+ faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face
// -z
- faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
- faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
- faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face
+ faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
+ faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face
// +z
- faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x
- faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
- faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face
+ faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x
+ faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face
// out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
- vec3 result;
- for (int i = 0; i < 6; i++) {
- if (i == faceID) {
- result = (faceUvVectors[i][0] * uv.x) + (faceUvVectors[i][1] * uv.y) + faceUvVectors[i][2];
- break;
- }
- }
+ vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
return normalize(result);
}
-vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) {
- float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]
-
+vec3 ImportanceSampleGGX(vec2 xi, float roughness4) {
// Compute distribution direction
- float Phi = 2.0 * M_PI * Xi.x;
- float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));
+ float Phi = 2.0 * M_PI * xi.x;
+ float CosTheta = sqrt((1.0 - xi.y) / (1.0 + (roughness4 - 1.0) * xi.y));
float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
// Convert to spherical direction
@@ -139,12 +105,26 @@ vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) {
H.y = SinTheta * sin(Phi);
H.z = CosTheta;
- vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
- vec3 TangentX = normalize(cross(UpVector, N));
- vec3 TangentY = cross(N, TangentX);
+ return H;
+}
+
+float DistributionGGX(float NdotH, float roughness4) {
+ float NdotH2 = NdotH * NdotH;
+ float denom = (NdotH2 * (roughness4 - 1.0) + 1.0);
+ denom = M_PI * denom * denom;
+
+ return roughness4 / denom;
+}
+
+// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
+float GGX(float NdotV, float a) {
+ float k = a / 2.0;
+ return NdotV / (NdotV * (1.0 - k) + k);
+}
- // Tangent to world space
- return TangentX * H.x + TangentY * H.y + N * H.z;
+// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
+float G_Smith(float a, float nDotV, float nDotL) {
+ return GGX(nDotL, a * a) * GGX(nDotV, a * a);
}
float radical_inverse_VdC(int i) {
@@ -155,60 +135,54 @@ vec2 Hammersley(int i, int N) {
return vec2(float(i) / float(N), radical_inverse_VdC(i));
}
-uniform bool z_flip;
-
-layout(location = 0) out vec4 frag_color;
-
void main() {
vec3 color = vec3(0.0);
-
- vec2 uv = (uv_interp * 2.0) - 1.0;
+ vec2 uv = uv_interp;
vec3 N = texelCoordToVec(uv, face_id);
-#ifdef USE_DIRECT_WRITE
-
-#ifdef USE_SOURCE_PANORAMA
-
- frag_color = vec4(texturePanorama(source_panorama, N).rgb, 1.0);
-#else
-
- frag_color = vec4(textureCube(source_cube, N).rgb, 1.0);
-#endif //USE_SOURCE_PANORAMA
-
+#ifdef MODE_DIRECT_WRITE
+ frag_color = vec4(textureCubeLod(source_cube, N, 0.0).rgb, 1.0);
#else
vec4 sum = vec4(0.0);
+ float solid_angle_texel = 4.0 * M_PI / (6.0 * face_size * face_size);
+ float roughness2 = roughness * roughness;
+ float roughness4 = roughness2 * roughness2;
+ vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+ mat3 T;
+ T[0] = normalize(cross(UpVector, N));
+ T[1] = cross(N, T[0]);
+ T[2] = N;
- for (int sample_num = 0; sample_num < SAMPLE_COUNT; sample_num++) {
- vec2 xi = Hammersley(sample_num, SAMPLE_COUNT);
+ for (int sample_num = 0; sample_num < sample_count; sample_num++) {
+ vec2 xi = Hammersley(sample_num, sample_count);
- vec3 H = ImportanceSampleGGX(xi, roughness, N);
- vec3 V = N;
- vec3 L = (2.0 * dot(V, H) * H - V);
+ vec3 H = T * ImportanceSampleGGX(xi, roughness4);
+ float NdotH = dot(N, H);
+ vec3 L = (2.0 * NdotH * H - N);
float NdotL = clamp(dot(N, L), 0.0, 1.0);
if (NdotL > 0.0) {
+ float D = DistributionGGX(NdotH, roughness4);
+ float pdf = D * NdotH / (4.0 * NdotH) + 0.0001;
-#ifdef USE_SOURCE_PANORAMA
- vec3 val = texturePanorama(source_panorama, L).rgb;
-#else
- vec3 val = textureCubeLod(source_cube, L, 0.0).rgb;
-#endif
- //mix using Linear, to approximate high end back-end
- val = mix(pow((val + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), val * (1.0 / 12.92), vec3(lessThan(val, vec3(0.04045))));
+ float solid_angle_sample = 1.0 / (float(sample_count) * pdf + 0.0001);
- sum.rgb += val * NdotL;
+ float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(solid_angle_sample / solid_angle_texel);
+
+ vec3 val = textureCubeLod(source_cube, L, mipLevel).rgb;
+ // Mix using linear
+ val = srgb_to_linear(val);
+ sum.rgb += val * NdotL;
sum.a += NdotL;
}
}
sum /= sum.a;
- vec3 a = vec3(0.055);
- sum.rgb = mix((vec3(1.0) + a) * pow(sum.rgb, vec3(1.0 / 2.4)) - a, 12.92 * sum.rgb, vec3(lessThan(sum.rgb, vec3(0.0031308))));
-
+ sum.rgb = linear_to_srgb(sum.rgb);
frag_color = vec4(sum.rgb, 1.0);
#endif
}
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 12d70db7dd..198d1d9ec7 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -7,9 +7,12 @@ mode_depth = #define MODE_RENDER_DEPTH
#[specializations]
-USE_LIGHTMAP = false
-USE_LIGHT_DIRECTIONAL = false
-USE_LIGHT_POSITIONAL = false
+DISABLE_LIGHTMAP = false
+DISABLE_LIGHT_DIRECTIONAL = false
+DISABLE_LIGHT_OMNI = false
+DISABLE_LIGHT_SPOT = false
+DISABLE_FOG = false
+USE_RADIANCE_MAP = true
#[vertex]
@@ -109,12 +112,14 @@ layout(std140) uniform SceneData { // ubo:2
mediump vec4 ambient_light_color_energy;
mediump float ambient_color_sky_mix;
- uint ambient_flags;
bool material_uv2_mode;
- float opaque_prepass_threshold;
- //bool use_ambient_light;
- //bool use_ambient_cubemap;
- //bool use_reflection_cubemap;
+ float pad2;
+ bool use_ambient_light;
+ bool use_ambient_cubemap;
+ bool use_reflection_cubemap;
+
+ float fog_aerial_perspective;
+ float time;
mat3 radiance_inverse_xform;
@@ -130,13 +135,6 @@ layout(std140) uniform SceneData { // ubo:2
vec3 fog_light_color;
float fog_sun_scatter;
-
- float fog_aerial_perspective;
-
- float time;
- float reflection_multiplier; // one normally, zero when rendering reflections
-
- bool pancake_shadows;
}
scene_data;
@@ -169,7 +167,7 @@ out vec2 uv2_interp;
#endif
#endif
-#if defined(TANGENT_USED) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
+#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
out vec3 tangent_interp;
out vec3 binormal_interp;
#endif
@@ -191,9 +189,6 @@ layout(std140) uniform MaterialUniforms { // ubo:3
#GLOBALS
/* clang-format on */
-
-out highp vec4 position_interp;
-
invariant gl_Position;
void main() {
@@ -206,21 +201,16 @@ void main() {
#endif
highp mat3 model_normal_matrix = mat3(model_matrix);
-#if defined(TANGENT_USED) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
- vec3 tangent;
- float binormalf;
- tangent = normal_tangent_attrib.xyz;
- binormalf = normal_tangent_attrib.a;
+#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+ vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
+ float binormalf = tangent_attrib.a * 2.0 - 1.0;
+ vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
#if defined(COLOR_USED)
color_interp = color_attrib;
#endif
-#if defined(TANGENT_USED) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
- vec3 binormal = normalize(cross(normal, tangent) * binormalf);
-#endif
-
#if defined(UV_USED)
uv_interp = uv_attrib;
#endif
@@ -306,7 +296,7 @@ void main() {
normal_interp = normal;
#endif
-#if defined(TANGENT_USED) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
+#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
tangent_interp = tangent;
binormal_interp = binormal;
#endif
@@ -316,16 +306,6 @@ void main() {
#else
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
#endif
-
-#ifdef MODE_RENDER_DEPTH
- if (scene_data.pancake_shadows) {
- if (gl_Position.z <= 0.00001) {
- gl_Position.z = 0.00001;
- }
- }
-#endif
-
- position_interp = gl_Position;
}
/* clang-format off */
@@ -357,10 +337,9 @@ void main() {
*/
-uniform highp mat4 world_transform;
+#define M_PI 3.14159265359
/* clang-format on */
-#define M_PI 3.14159265359
#define SHADER_IS_SRGB true
/* Varyings */
@@ -381,7 +360,7 @@ in vec2 uv2_interp;
#endif
#endif
-#if defined(TANGENT_USED) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
+#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
in vec3 tangent_interp;
in vec3 binormal_interp;
#endif
@@ -392,29 +371,11 @@ in vec3 normal_interp;
in highp vec3 vertex_interp;
-/* PBR CHANNELS */
-
#ifdef USE_RADIANCE_MAP
-layout(std140) uniform Radiance { // ubo:4
-
- mat4 radiance_inverse_xform;
- float radiance_ambient_contribution;
-};
-
#define RADIANCE_MAX_LOD 5.0
-uniform sampler2D radiance_map; // texunit:-2
-
-vec3 textureDualParaboloid(sampler2D p_tex, vec3 p_vec, float p_roughness) {
- vec3 norm = normalize(p_vec);
- norm.xy /= 1.0 + abs(norm.z);
- norm.xy = norm.xy * vec2(0.5, 0.25) + vec2(0.5, 0.25);
- if (norm.z > 0.0) {
- norm.y = 0.5 - norm.y + 0.5;
- }
- return textureLod(p_tex, norm.xy, p_roughness * RADIANCE_MAX_LOD).xyz;
-}
+uniform samplerCube radiance_map; // texunit:-2
#endif
@@ -448,12 +409,14 @@ layout(std140) uniform SceneData { // ubo:2
mediump vec4 ambient_light_color_energy;
mediump float ambient_color_sky_mix;
- uint ambient_flags;
bool material_uv2_mode;
- float opaque_prepass_threshold;
- //bool use_ambient_light;
- //bool use_ambient_cubemap;
- //bool use_reflection_cubemap;
+ float pad2;
+ bool use_ambient_light;
+ bool use_ambient_cubemap;
+ bool use_reflection_cubemap;
+
+ float fog_aerial_perspective;
+ float time;
mat3 radiance_inverse_xform;
@@ -469,13 +432,6 @@ layout(std140) uniform SceneData { // ubo:2
vec3 fog_light_color;
float fog_sun_scatter;
-
- float fog_aerial_perspective;
-
- float time;
- float reflection_multiplier; // one normally, zero when rendering reflections
-
- bool pancake_shadows;
}
scene_data;
@@ -487,7 +443,7 @@ scene_data;
//directional light data
-#ifdef USE_LIGHT_DIRECTIONAL
+#ifndef DISABLE_LIGHT_DIRECTIONAL
struct DirectionalLightData {
mediump vec3 direction;
@@ -498,10 +454,14 @@ struct DirectionalLightData {
mediump float specular;
};
+layout(std140) uniform DirectionalLights { // ubo:7
+ DirectionalLightData directional_lights[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
+};
+
#endif
// omni and spot
-#ifdef USE_LIGHT_POSITIONAL
+#if !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT)
struct LightData { //this structure needs to be as packed as possible
highp vec3 position;
highp float inv_radius;
@@ -517,36 +477,38 @@ struct LightData { //this structure needs to be as packed as possible
mediump float specular_amount;
bool shadow_enabled;
};
-
+#ifndef DISABLE_LIGHT_OMNI
layout(std140) uniform OmniLightData { // ubo:5
LightData omni_lights[MAX_LIGHT_DATA_STRUCTS];
};
+uniform uint omni_light_indices[MAX_FORWARD_LIGHTS];
+uniform int omni_light_count;
+#endif
+
+#ifndef DISABLE_LIGHT_SPOT
layout(std140) uniform SpotLightData { // ubo:6
LightData spot_lights[MAX_LIGHT_DATA_STRUCTS];
};
-
-uniform highp samplerCubeShadow positional_shadow; // texunit:-6
-
-uniform int omni_light_indices[MAX_FORWARD_LIGHTS];
-uniform int omni_light_count;
-
-uniform int spot_light_indices[MAX_FORWARD_LIGHTS];
+uniform uint spot_light_indices[MAX_FORWARD_LIGHTS];
uniform int spot_light_count;
+#endif
-uniform int reflection_indices[MAX_FORWARD_LIGHTS];
-uniform int reflection_count;
-
+#ifdef USE_ADDITIVE_LIGHTING
+uniform highp samplerCubeShadow positional_shadow; // texunit:-4
#endif
+#endif // !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT)
+
uniform highp sampler2D screen_texture; // texunit:-5
uniform highp sampler2D depth_buffer; // texunit:-6
-layout(location = 0) out vec4 frag_color;
+uniform highp mat4 world_transform;
+uniform mediump float opaque_prepass_threshold;
-in highp vec4 position_interp;
+layout(location = 0) out vec4 frag_color;
vec3 F0(float metallic, float specular, vec3 albedo) {
float dielectric = 0.16 * specular * specular;
@@ -555,7 +517,7 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
return mix(vec3(dielectric), albedo, vec3(metallic));
}
-#if defined(USE_LIGHT_DIRECTIONAL) || defined(USE_LIGHT_POSITIONAL)
+#if !defined(DISABLE_LIGHT_DIRECTIONAL) || !defined(DISABLE_LIGHT_OMNI) || !defined(DISABLE_LIGHT_SPOT)
float D_GGX(float cos_theta_m, float alpha) {
float a = cos_theta_m * alpha;
float k = alpha / (1.0 - cos_theta_m * cos_theta_m + a * a);
@@ -588,7 +550,7 @@ float SchlickFresnel(float u) {
return m2 * m2 * m; // pow(m,5)
}
-void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount, vec3 albedo, inout float alpha,
+void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, float roughness, float metallic, float specular_amount, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
@@ -603,11 +565,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#endif
inout vec3 diffuse_light, inout vec3 specular_light) {
- vec4 orms_unpacked = unpackUnorm4x8(orms);
-
- float roughness = orms_unpacked.y;
- float metallic = orms_unpacked.z;
-
#if defined(USE_LIGHT_SHADER_CODE)
// light is written by the light shader
@@ -626,7 +583,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float NdotL = min(A + dot(N, L), 1.0);
float cNdotL = max(NdotL, 0.0); // clamped NdotL
float NdotV = dot(N, V);
- float cNdotV = max(NdotV, 0.0);
+ float cNdotV = max(NdotV, 1e-4);
#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
vec3 H = normalize(V + L);
@@ -752,15 +709,10 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {
return nd * pow(max(distance, 0.0001), -decay);
}
-void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha,
+void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, float roughness, float metallic, float shadow, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
-#ifdef LIGHT_TRANSMITTANCE_USED
- vec4 transmittance_color,
- float transmittance_depth,
- float transmittance_boost,
-#endif
#ifdef LIGHT_RIM_USED
float rim, float rim_tint,
#endif
@@ -774,16 +726,15 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
vec3 light_rel_vec = omni_lights[idx].position - vertex;
float light_length = length(light_rel_vec);
float omni_attenuation = get_omni_attenuation(light_length, omni_lights[idx].inv_radius, omni_lights[idx].attenuation);
- vec3 light_attenuation = vec3(omni_attenuation);
vec3 color = omni_lights[idx].color;
float size_A = 0.0;
- if (omni_lights.data[idx].size > 0.0) {
+ if (omni_lights[idx].size > 0.0) {
float t = omni_lights[idx].size / max(0.001, light_length);
size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
}
- light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights[idx].specular_amount, albedo, alpha,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, omni_attenuation, f0, roughness, metallic, omni_lights[idx].specular_amount, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -800,7 +751,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
specular_light);
}
-void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha,
+void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, float roughness, float metallic, float shadow, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
@@ -823,17 +774,16 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights[idx].cone_angle);
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights[idx].cone_angle));
spot_attenuation *= 1.0 - pow(spot_rim, spot_lights[idx].cone_attenuation);
- float light_attenuation = spot_attenuation;
vec3 color = spot_lights[idx].color;
float size_A = 0.0;
- if (spot_lights.data[idx].size > 0.0) {
- float t = spot_lights.data[idx].size / max(0.001, light_length);
+ if (spot_lights[idx].size > 0.0) {
+ float t = spot_lights[idx].size / max(0.001, light_length);
size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
}
- light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights[idx].specular_amount, albedo, alpha,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, spot_attenuation, f0, roughness, metallic, spot_lights[idx].specular_amount, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -848,7 +798,56 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
#endif
diffuse_light, specular_light);
}
-#endif // defined(USE_LIGHT_DIRECTIONAL) || defined(USE_LIGHT_POSITIONAL)
+#endif // !defined(DISABLE_LIGHT_DIRECTIONAL) || !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT)
+
+#ifndef MODE_RENDER_DEPTH
+vec4 fog_process(vec3 vertex) {
+ vec3 fog_color = scene_data.fog_light_color;
+
+#ifdef USE_RADIANCE_MAP
+/*
+ if (scene_data.fog_aerial_perspective > 0.0) {
+ vec3 sky_fog_color = vec3(0.0);
+ vec3 cube_view = scene_data.radiance_inverse_xform * vertex;
+ // mip_level always reads from the second mipmap and higher so the fog is always slightly blurred
+ float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, 1.0 - (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near));
+
+ sky_fog_color = textureCubeLod(radiance_map, cube_view, mip_level * RADIANCE_MAX_LOD).rgb;
+
+ fog_color = mix(fog_color, sky_fog_color, scene_data.fog_aerial_perspective);
+ }
+ */
+#endif
+
+#ifndef DISABLE_LIGHT_DIRECTIONAL
+ if (scene_data.fog_sun_scatter > 0.001) {
+ vec4 sun_scatter = vec4(0.0);
+ float sun_total = 0.0;
+ vec3 view = normalize(vertex);
+ for (uint i = uint(0); i < scene_data.directional_light_count; i++) {
+ vec3 light_color = directional_lights[i].color * directional_lights[i].energy;
+ float light_amount = pow(max(dot(view, directional_lights[i].direction), 0.0), 8.0);
+ fog_color += light_color * light_amount * scene_data.fog_sun_scatter;
+ }
+ }
+#endif // !DISABLE_LIGHT_DIRECTIONAL
+
+ float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density));
+
+ if (abs(scene_data.fog_height_density) >= 0.0001) {
+ float y = (scene_data.inv_view_matrix * vec4(vertex, 1.0)).y;
+
+ float y_dist = y - scene_data.fog_height;
+
+ float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density));
+
+ fog_amount = max(vfog_amount, fog_amount);
+ }
+
+ return vec4(fog_color, fog_amount);
+}
+
+#endif // !MODE_RENDER_DEPTH
void main() {
//lay out everything, whatever is unused is optimized away anyway
@@ -951,7 +950,7 @@ void main() {
#ifdef USE_OPAQUE_PREPASS
#if !defined(ALPHA_SCISSOR_USED)
- if (alpha < scene_data.opaque_prepass_threshold) {
+ if (alpha < opaque_prepass_threshold) {
discard;
}
@@ -982,9 +981,31 @@ void main() {
#endif
#ifndef MODE_RENDER_DEPTH
+
+#ifndef CUSTOM_FOG_USED
+#ifndef DISABLE_FOG
+ // fog must be processed as early as possible and then packed.
+ // to maximize VGPR usage
+
+ if (scene_data.fog_enabled) {
+ fog = fog_process(vertex);
+ }
+#endif // !DISABLE_FOG
+#endif //!CUSTOM_FOG_USED
+
+ uint fog_rg = packHalf2x16(fog.rg);
+ uint fog_ba = packHalf2x16(fog.ba);
+
+#endif //!MODE_RENDER_DEPTH
+
+#ifndef MODE_RENDER_DEPTH
+
+ // Convert colors to linear
+ albedo = srgb_to_linear(albedo);
+ emission = srgb_to_linear(emission);
+ // TODO Backlight and transmittance when used
+#ifndef MODE_UNSHADED
vec3 f0 = F0(metallic, specular, albedo);
- // Convert albedo to linear. Approximation from: http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
- albedo = albedo * (albedo * (albedo * 0.305306011 + 0.682171111) + 0.012522878);
vec3 specular_light = vec3(0.0, 0.0, 0.0);
vec3 diffuse_light = vec3(0.0, 0.0, 0.0);
vec3 ambient_light = vec3(0.0, 0.0, 0.0);
@@ -996,15 +1017,58 @@ void main() {
float ndotv = clamp(dot(normal, view), 0.0, 1.0);
vec3 F = f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - ndotv, 5.0);
- // Calculate IBL
+#ifdef USE_RADIANCE_MAP
+ if (scene_data.use_reflection_cubemap) {
+#ifdef LIGHT_ANISOTROPY_USED
+ // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
+ vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
+ vec3 anisotropic_tangent = cross(anisotropic_direction, view);
+ vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
+ vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
+ vec3 ref_vec = reflect(-view, bent_normal);
+#else
+ vec3 ref_vec = reflect(-view, normal);
+#endif
+ float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
+ ref_vec = scene_data.radiance_inverse_xform * ref_vec;
+ specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).rgb;
+ specular_light = srgb_to_linear(specular_light);
+ specular_light *= horizon * horizon;
+ specular_light *= scene_data.ambient_light_color_energy.a;
+ }
+#endif
+
// Calculate Reflection probes
- // Caclculate Lightmaps
+ // Calculate Lightmaps
- float specular_blob_intensity = 1.0;
+#if defined(CUSTOM_RADIANCE_USED)
+ specular_light = mix(specular_light, custom_radiance.rgb, custom_radiance.a);
+#endif // CUSTOM_RADIANCE_USED
-#if defined(SPECULAR_TOON)
- specular_blob_intensity *= specular * 2.0;
+#ifndef USE_LIGHTMAP
+ //lightmap overrides everything
+ if (scene_data.use_ambient_light) {
+ ambient_light = scene_data.ambient_light_color_energy.rgb;
+#ifdef USE_RADIANCE_MAP
+ if (scene_data.use_ambient_cubemap) {
+ vec3 ambient_dir = scene_data.radiance_inverse_xform * normal;
+ vec3 cubemap_ambient = textureCubeLod(radiance_map, ambient_dir, RADIANCE_MAX_LOD).rgb;
+ cubemap_ambient = srgb_to_linear(cubemap_ambient);
+ ambient_light = mix(ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix);
+ }
#endif
+ }
+#endif // USE_LIGHTMAP
+
+#if defined(CUSTOM_IRRADIANCE_USED)
+ ambient_light = mix(ambient_light, custom_irradiance.rgb, custom_irradiance.a);
+#endif // CUSTOM_IRRADIANCE_USED
+ ambient_light *= albedo.rgb;
+
+ ambient_light *= ao;
+
+ // convert ao to direct light ao
+ ao = mix(1.0, ao, ao_light_affect);
{
#if defined(DIFFUSE_TOON)
@@ -1029,36 +1093,34 @@ void main() {
#endif // BASE_PASS
- //this saves some VGPRs
- uint orms = packUnorm4x8(vec4(ao, roughness, metallic, specular));
-
-#ifdef USE_LIGHT_DIRECTIONAL
-
- float size_A = directional_lights[i].size;
-
- light_compute(normal, directional_lights[i].direction, normalize(view), size_A, directional_lights[i].color * directional_lights[i].energy, shadow, f0, orms, 1.0, albedo, alpha,
+#ifndef DISABLE_LIGHT_DIRECTIONAL
+ //diffuse_light = normal; //
+ for (uint i = uint(0); i < scene_data.directional_light_count; i++) {
+ light_compute(normal, normalize(directional_lights[i].direction), normalize(view), directional_lights[i].size, directional_lights[i].color * directional_lights[i].energy, 1.0, f0, roughness, metallic, 1.0, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
- backlight,
+ backlight,
#endif
#ifdef LIGHT_RIM_USED
- rim, rim_tint,
+ rim, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_roughness, normalize(normal_interp),
+ clearcoat, clearcoat_roughness, normalize(normal_interp),
#endif
#ifdef LIGHT_ANISOTROPY_USED
- binormal,
- tangent, anisotropy,
+ binormal,
+ tangent, anisotropy,
#endif
- diffuse_light,
- specular_light);
-
-#endif //#USE_LIGHT_DIRECTIONAL
+ diffuse_light,
+ specular_light);
+ }
+#endif //!DISABLE_LIGHT_DIRECTIONAL
-#ifdef USE_LIGHT_POSITIONAL
- float shadow = 0.0;
- for (int i = 0; i < omni_light_count; i++) {
- light_process_omni(omni_light_indices[i], vertex, view, normal, f0, orms, shadow, albedo, alpha,
+#ifndef DISABLE_LIGHT_OMNI
+ for (int i = 0; i < MAX_FORWARD_LIGHTS; i++) {
+ if (i >= omni_light_count) {
+ break;
+ }
+ light_process_omni(omni_light_indices[i], vertex, view, normal, f0, roughness, metallic, 0.0, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1070,13 +1132,18 @@ void main() {
clearcoat, clearcoat_roughness, normalize(normal_interp),
#endif
#ifdef LIGHT_ANISOTROPY_USED
- tangent, binormal, anisotropy,
+ binormal, tangent, anisotropy,
#endif
diffuse_light, specular_light);
}
+#endif // !DISABLE_LIGHT_OMNI
- for (int i = 0; i < spot_light_count; i++) {
- light_process_spot(spot_light_indices[i], vertex, view, normal, f0, orms, shadow, albedo, alpha,
+#ifndef DISABLE_LIGHT_SPOT
+ for (int i = 0; i < MAX_FORWARD_LIGHTS; i++) {
+ if (i >= spot_light_count) {
+ break;
+ }
+ light_process_spot(spot_light_indices[i], vertex, view, normal, f0, roughness, metallic, 0.0, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1094,8 +1161,9 @@ void main() {
diffuse_light, specular_light);
}
-#endif // USE_LIGHT_POSITIONAL
-#endif //!MODE_RENDER_DEPTH
+#endif // !DISABLE_LIGHT_SPOT
+#endif // !MODE_UNSHADED
+#endif // !MODE_RENDER_DEPTH
#if defined(USE_SHADOW_TO_OPACITY)
alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));
@@ -1122,21 +1190,31 @@ void main() {
//nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
#else // !MODE_RENDER_DEPTH
- specular_light *= scene_data.reflection_multiplier;
- ambient_light *= albedo; //ambient must be multiplied by albedo at the end
+#ifdef MODE_UNSHADED
+ frag_color = vec4(albedo, alpha);
+#else
+
+ diffuse_light *= albedo;
- // base color remapping
diffuse_light *= 1.0 - metallic;
ambient_light *= 1.0 - metallic;
-#ifdef MODE_UNSHADED
- frag_color = vec4(albedo, alpha);
-#else
- frag_color = vec4(ambient_light + diffuse_light + specular_light, alpha);
+ frag_color = vec4(diffuse_light + specular_light, alpha);
#ifdef BASE_PASS
- frag_color.rgb += emission;
+ frag_color.rgb += emission + ambient_light;
#endif
#endif //MODE_UNSHADED
+ fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba));
+
+#ifndef DISABLE_FOG
+ if (scene_data.fog_enabled) {
+#ifdef BASE_PASS
+ frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
+#else
+ frag_color.rgb *= (1.0 - fog.a);
+#endif // BASE_PASS
+ }
+#endif
// Tonemap before writing as we are writing to an sRGB framebuffer
frag_color.rgb *= exposure;
diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl
index 3a1bcd3b28..50ab38bc31 100644
--- a/drivers/gles3/shaders/sky.glsl
+++ b/drivers/gles3/shaders/sky.glsl
@@ -12,13 +12,13 @@ mode_cubemap_quarter_res = #define USE_CUBEMAP_PASS \n#define USE_QUARTER_RES_PA
#[vertex]
+layout(location = 0) in vec2 vertex_attrib;
+
out vec2 uv_interp;
/* clang-format on */
void main() {
- // One big triangle to cover the whole screen
- vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(3.0, -1.0), vec2(-1.0, 3.0));
- uv_interp = base_arr[gl_VertexID];
+ uv_interp = vertex_attrib;
gl_Position = vec4(uv_interp, 1.0, 1.0);
}
@@ -46,18 +46,13 @@ layout(std140) uniform GlobalVariableData { //ubo:1
vec4 global_variables[MAX_GLOBAL_VARIABLES];
};
-layout(std140) uniform SceneData { //ubo:2
- float pad1;
- float pad2;
-};
-
struct DirectionalLightData {
vec4 direction_energy;
vec4 color_size;
bool enabled;
};
-layout(std140) uniform DirectionalLights { //ubo:3
+layout(std140) uniform DirectionalLights { //ubo:4
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
}
directional_lights;
@@ -65,7 +60,7 @@ directional_lights;
/* clang-format off */
#ifdef MATERIAL_UNIFORMS_USED
-layout(std140) uniform MaterialUniforms{ //ubo:4
+layout(std140) uniform MaterialUniforms{ //ubo:3
#MATERIAL_UNIFORMS
@@ -98,6 +93,14 @@ uniform vec4 projection;
uniform vec3 position;
uniform float time;
+uniform float fog_aerial_perspective;
+uniform vec3 fog_light_color;
+uniform float fog_sun_scatter;
+uniform bool fog_enabled;
+uniform float fog_density;
+uniform float z_far;
+uniform uint directional_light_count;
+
layout(location = 0) out vec4 frag_color;
void main() {
@@ -106,12 +109,11 @@ void main() {
cube_normal.x = (uv_interp.x + projection.x) / projection.y;
cube_normal.y = (-uv_interp.y - projection.z) / projection.w;
cube_normal = mat3(orientation) * cube_normal;
- cube_normal.z = -cube_normal.z;
cube_normal = normalize(cube_normal);
vec2 uv = gl_FragCoord.xy; // uv_interp * 0.5 + 0.5;
- vec2 panorama_coords = vec2(atan(cube_normal.x, cube_normal.z), acos(cube_normal.y));
+ vec2 panorama_coords = vec2(atan(cube_normal.x, -cube_normal.z), acos(cube_normal.y));
if (panorama_coords.x < 0.0) {
panorama_coords.x += M_PI * 2.0;
@@ -126,13 +128,11 @@ void main() {
vec4 custom_fog = vec4(0.0);
#ifdef USE_CUBEMAP_PASS
- vec3 inverted_cube_normal = cube_normal;
- inverted_cube_normal.z *= -1.0;
#ifdef USES_HALF_RES_COLOR
- half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal);
+ half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal);
#endif
#ifdef USES_QUARTER_RES_COLOR
- quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal);
+ quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal);
#endif
#else
#ifdef USES_HALF_RES_COLOR
@@ -149,7 +149,8 @@ void main() {
}
- // Tonemap before writing as we are writing to an sRGB framebuffer
+ // Convert to Linear for tonemapping so color matches scene shader better
+ color = srgb_to_linear(color);
color *= exposure;
color = apply_tonemapping(color, white);
color = linear_to_srgb(color);
diff --git a/drivers/gles3/shaders/stdlib_inc.glsl b/drivers/gles3/shaders/stdlib_inc.glsl
index 6cce6c12bd..d5051760d7 100644
--- a/drivers/gles3/shaders/stdlib_inc.glsl
+++ b/drivers/gles3/shaders/stdlib_inc.glsl
@@ -42,11 +42,11 @@ vec2 unpackSnorm2x16(uint p) {
uint packUnorm4x8(vec4 v) {
uvec4 uv = uvec4(round(clamp(v, vec4(0.0), vec4(1.0)) * 255.0));
- return uv.x | uv.y << uint(8) | uv.z << uint(16) | uv.w << uint(24);
+ return uv.x | (uv.y << uint(8)) | (uv.z << uint(16)) | (uv.w << uint(24));
}
vec4 unpackUnorm4x8(uint p) {
- return vec4(float(p & uint(0xffff)), float((p >> uint(8)) & uint(0xffff)), float((p >> uint(16)) & uint(0xffff)), float(p >> uint(24))) * 0.00392156862; // 1.0 / 255.0
+ return vec4(float(p & uint(0xff)), float((p >> uint(8)) & uint(0xff)), float((p >> uint(16)) & uint(0xff)), float(p >> uint(24))) * 0.00392156862; // 1.0 / 255.0
}
uint packSnorm4x8(vec4 v) {
@@ -55,6 +55,6 @@ uint packSnorm4x8(vec4 v) {
}
vec4 unpackSnorm4x8(uint p) {
- vec4 v = vec4(float(p & uint(0xffff)), float((p >> uint(8)) & uint(0xffff)), float((p >> uint(16)) & uint(0xffff)), float(p >> uint(24)));
+ vec4 v = vec4(float(p & uint(0xff)), float((p >> uint(8)) & uint(0xff)), float((p >> uint(16)) & uint(0xff)), float(p >> uint(24)));
return clamp((v - vec4(127.0)) * vec4(0.00787401574), vec4(-1.0), vec4(1.0));
}
diff --git a/drivers/gles3/shaders/tonemap_inc.glsl b/drivers/gles3/shaders/tonemap_inc.glsl
index ea15c05359..f8f12760ec 100644
--- a/drivers/gles3/shaders/tonemap_inc.glsl
+++ b/drivers/gles3/shaders/tonemap_inc.glsl
@@ -92,11 +92,19 @@ vec3 tonemap_reinhard(vec3 color, float p_white) {
return (p_white * color + color) / (color * p_white + p_white);
}
+// This expects 0-1 range input.
vec3 linear_to_srgb(vec3 color) {
- //if going to srgb, clamp from 0 to 1.
- color = clamp(color, vec3(0.0), vec3(1.0));
- const vec3 a = vec3(0.055f);
- return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
+ //color = clamp(color, vec3(0.0), vec3(1.0));
+ //const vec3 a = vec3(0.055f);
+ //return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
+ // Approximation from http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
+ return max(vec3(1.055) * pow(color, vec3(0.416666667)) - vec3(0.055), vec3(0.0));
+}
+
+// This expects 0-1 range input, outside that range it behaves poorly.
+vec3 srgb_to_linear(vec3 color) {
+ // Approximation from http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
+ return color * (color * (color * 0.305306011 + 0.682171111) + 0.012522878);
}
#define TONEMAPPER_LINEAR 0