summaryrefslogtreecommitdiff
path: root/drivers/gles3/shaders
diff options
context:
space:
mode:
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