summaryrefslogtreecommitdiff
path: root/drivers/gles3/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gles3/shaders')
-rw-r--r--drivers/gles3/shaders/SCsub1
-rw-r--r--drivers/gles3/shaders/canvas.glsl21
-rw-r--r--drivers/gles3/shaders/scene.glsl20
-rw-r--r--drivers/gles3/shaders/skeleton.glsl269
-rw-r--r--drivers/gles3/shaders/stdlib_inc.glsl18
5 files changed, 303 insertions, 26 deletions
diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub
index 2686b1aa48..34713e7e29 100644
--- a/drivers/gles3/shaders/SCsub
+++ b/drivers/gles3/shaders/SCsub
@@ -21,3 +21,4 @@ if "GLES3_GLSL" in env["BUILDERS"]:
env.GLES3_GLSL("canvas_sdf.glsl")
env.GLES3_GLSL("particles.glsl")
env.GLES3_GLSL("particles_copy.glsl")
+ env.GLES3_GLSL("skeleton.glsl")
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index cdae05a516..a61ea1587d 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -19,9 +19,6 @@ layout(location = 0) in vec2 vertex_attrib;
layout(location = 3) in vec4 color_attrib;
layout(location = 4) in vec2 uv_attrib;
-layout(location = 10) in uvec4 bone_attrib;
-layout(location = 11) in vec4 weight_attrib;
-
#ifdef USE_INSTANCING
layout(location = 1) in highp vec4 instance_xform0;
@@ -81,8 +78,6 @@ void main() {
uv = draw_data[draw_data_instance].uv_c;
color = vec4(unpackHalf2x16(draw_data[draw_data_instance].color_c_rg), unpackHalf2x16(draw_data[draw_data_instance].color_c_ba));
}
- uvec4 bones = uvec4(0, 0, 0, 0);
- vec4 bone_weights = vec4(0.0);
#elif defined(USE_ATTRIBUTES)
draw_data_instance = gl_InstanceID;
@@ -93,9 +88,6 @@ void main() {
vec4 color = color_attrib * draw_data[draw_data_instance].modulation;
vec2 uv = uv_attrib;
- uvec4 bones = bone_attrib;
- vec4 bone_weights = weight_attrib;
-
#ifdef USE_INSTANCING
vec4 instance_color = vec4(unpackHalf2x16(instance_color_custom_data.x), unpackHalf2x16(instance_color_custom_data.y));
color *= instance_color;
@@ -110,7 +102,6 @@ void main() {
vec2 uv = draw_data[draw_data_instance].src_rect.xy + abs(draw_data[draw_data_instance].src_rect.zw) * ((draw_data[draw_data_instance].flags & FLAGS_TRANSPOSE_RECT) != uint(0) ? vertex_base.yx : vertex_base.xy);
vec4 color = draw_data[draw_data_instance].modulation;
vec2 vertex = draw_data[draw_data_instance].dst_rect.xy + abs(draw_data[draw_data_instance].dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(draw_data[draw_data_instance].src_rect.zw, vec2(0.0, 0.0)));
- uvec4 bones = uvec4(0, 0, 0, 0);
#endif
@@ -297,11 +288,9 @@ vec3 light_normal_compute(vec3 light_vec, vec3 normal, vec3 base_color, vec3 lig
#endif
-#define SHADOW_TEST(m_uv) \
- { \
- highp float sd = SHADOW_DEPTH(m_uv); \
- shadow += step(sd, shadow_uv.z / shadow_uv.w); \
- }
+/* clang-format off */
+#define SHADOW_TEST(m_uv) { highp float sd = SHADOW_DEPTH(m_uv); shadow += step(sd, shadow_uv.z / shadow_uv.w); }
+/* clang-format on */
//float distance = length(shadow_pos);
vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv
@@ -341,7 +330,7 @@ vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv
shadow /= 13.0;
}
- vec4 shadow_color = unpackUnorm4x8(light_array[light_base].shadow_color);
+ vec4 shadow_color = godot_unpackUnorm4x8(light_array[light_base].shadow_color);
#ifdef LIGHT_CODE_USED
shadow_color.rgb *= shadow_modulate;
#endif
@@ -508,7 +497,7 @@ void main() {
if (specular_shininess_used || (using_light && normal_used && bool(draw_data[draw_data_instance].flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) {
specular_shininess = texture(specular_texture, uv);
- specular_shininess *= unpackUnorm4x8(draw_data[draw_data_instance].specular_shininess);
+ specular_shininess *= godot_unpackUnorm4x8(draw_data[draw_data_instance].specular_shininess);
specular_shininess_used = true;
} else {
specular_shininess = vec4(1.0);
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 04dba602dd..32557d3314 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -129,7 +129,7 @@ layout(std140) uniform SceneData { // ubo:2
mediump float ambient_color_sky_mix;
bool material_uv2_mode;
- float pad2;
+ float emissive_exposure_normalization;
bool use_ambient_light;
bool use_ambient_cubemap;
bool use_reflection_cubemap;
@@ -142,7 +142,7 @@ layout(std140) uniform SceneData { // ubo:2
uint directional_light_count;
float z_far;
float z_near;
- float pad;
+ float IBL_exposure_normalization;
bool fog_enabled;
float fog_density;
@@ -151,6 +151,10 @@ layout(std140) uniform SceneData { // ubo:2
vec3 fog_light_color;
float fog_sun_scatter;
+ uint camera_visible_layers;
+ uint pad3;
+ uint pad4;
+ uint pad5;
}
scene_data;
@@ -455,7 +459,7 @@ layout(std140) uniform SceneData { // ubo:2
mediump float ambient_color_sky_mix;
bool material_uv2_mode;
- float pad2;
+ float emissive_exposure_normalization;
bool use_ambient_light;
bool use_ambient_cubemap;
bool use_reflection_cubemap;
@@ -468,7 +472,7 @@ layout(std140) uniform SceneData { // ubo:2
uint directional_light_count;
float z_far;
float z_near;
- float pad;
+ float IBL_exposure_normalization;
bool fog_enabled;
float fog_density;
@@ -477,6 +481,10 @@ layout(std140) uniform SceneData { // ubo:2
vec3 fog_light_color;
float fog_sun_scatter;
+ uint camera_visible_layers;
+ uint pad3;
+ uint pad4;
+ uint pad5;
}
scene_data;
@@ -1100,7 +1108,7 @@ void main() {
ref_vec = mix(ref_vec, normal, roughness * roughness);
float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
- specular_light = textureLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).rgb;
+ specular_light = textureLod(radiance_map, ref_vec, sqrt(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;
@@ -1162,7 +1170,7 @@ void main() {
float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
- specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, 0.0, 1.0);
+ specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, metallic, 1.0);
#endif
}
diff --git a/drivers/gles3/shaders/skeleton.glsl b/drivers/gles3/shaders/skeleton.glsl
new file mode 100644
index 0000000000..a1e3c098f4
--- /dev/null
+++ b/drivers/gles3/shaders/skeleton.glsl
@@ -0,0 +1,269 @@
+/* clang-format off */
+#[modes]
+
+mode_base_pass =
+mode_blend_pass = #define MODE_BLEND_PASS
+
+#[specializations]
+
+MODE_2D = true
+USE_BLEND_SHAPES = false
+USE_SKELETON = false
+USE_NORMAL = false
+USE_TANGENT = false
+FINAL_PASS = false
+USE_EIGHT_WEIGHTS = false
+
+#[vertex]
+
+#include "stdlib_inc.glsl"
+
+#ifdef MODE_2D
+#define VFORMAT vec2
+#else
+#define VFORMAT vec3
+#endif
+
+#ifdef FINAL_PASS
+#define OFORMAT vec2
+#else
+#define OFORMAT uvec2
+#endif
+
+// These come from the source mesh and the output from previous passes.
+layout(location = 0) in highp VFORMAT in_vertex;
+#ifdef MODE_BLEND_PASS
+#ifdef USE_NORMAL
+layout(location = 1) in highp uvec2 in_normal;
+#endif
+#ifdef USE_TANGENT
+layout(location = 2) in highp uvec2 in_tangent;
+#endif
+#else // MODE_BLEND_PASS
+#ifdef USE_NORMAL
+layout(location = 1) in highp vec2 in_normal;
+#endif
+#ifdef USE_TANGENT
+layout(location = 2) in highp vec2 in_tangent;
+#endif
+#endif // MODE_BLEND_PASS
+
+#ifdef USE_SKELETON
+#ifdef USE_EIGHT_WEIGHTS
+layout(location = 10) in highp uvec4 in_bone_attrib;
+layout(location = 11) in highp uvec4 in_bone_attrib2;
+layout(location = 12) in mediump vec4 in_weight_attrib;
+layout(location = 13) in mediump vec4 in_weight_attrib2;
+#else
+layout(location = 10) in highp uvec4 in_bone_attrib;
+layout(location = 11) in mediump vec4 in_weight_attrib;
+#endif
+
+uniform mediump sampler2D skeleton_texture; // texunit:0
+#endif
+
+/* clang-format on */
+#ifdef MODE_BLEND_PASS
+layout(location = 3) in highp VFORMAT blend_vertex;
+#ifdef USE_NORMAL
+layout(location = 4) in highp vec2 blend_normal;
+#endif
+#ifdef USE_TANGENT
+layout(location = 5) in highp vec2 blend_tangent;
+#endif
+#endif // MODE_BLEND_PASS
+
+out highp VFORMAT out_vertex; //tfb:
+
+#ifdef USE_NORMAL
+flat out highp OFORMAT out_normal; //tfb:USE_NORMAL
+#endif
+#ifdef USE_TANGENT
+flat out highp OFORMAT out_tangent; //tfb:USE_TANGENT
+#endif
+
+#ifdef USE_BLEND_SHAPES
+uniform highp float blend_weight;
+uniform lowp float blend_shape_count;
+#endif
+
+vec2 signNotZero(vec2 v) {
+ return mix(vec2(-1.0), vec2(1.0), greaterThanEqual(v.xy, vec2(0.0)));
+}
+
+vec3 oct_to_vec3(vec2 oct) {
+ oct = oct * 2.0 - 1.0;
+ vec3 v = vec3(oct.xy, 1.0 - abs(oct.x) - abs(oct.y));
+ if (v.z < 0.0) {
+ v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);
+ }
+ return normalize(v);
+}
+
+vec2 vec3_to_oct(vec3 e) {
+ e /= abs(e.x) + abs(e.y) + abs(e.z);
+ vec2 oct = e.z >= 0.0f ? e.xy : (vec2(1.0f) - abs(e.yx)) * signNotZero(e.xy);
+ return oct * 0.5f + 0.5f;
+}
+
+vec4 oct_to_tang(vec2 oct_sign_encoded) {
+ // Binormal sign encoded in y component
+ vec2 oct = vec2(oct_sign_encoded.x, abs(oct_sign_encoded.y) * 2.0 - 1.0);
+ return vec4(oct_to_vec3(oct), sign(oct_sign_encoded.y));
+}
+
+vec2 tang_to_oct(vec4 base) {
+ vec2 oct = vec3_to_oct(base.xyz);
+ // Encode binormal sign in y component
+ oct.y = oct.y * 0.5f + 0.5f;
+ oct.y = base.w >= 0.0f ? oct.y : 1.0 - oct.y;
+ return oct;
+}
+
+// Our original input for normals and tangents is 2 16-bit floats.
+// Transform Feedback has to write out 32-bits per channel.
+// Octahedral compression requires normalized vectors, but we need to store
+// non-normalized vectors until the very end.
+// Therefore, we will compress our normals into 16 bits using signed-normalized
+// fixed point precision. This works well, because we know that each normal
+// is no larger than |1| so we can normalize by dividing by the number of blend
+// shapes.
+uvec2 vec4_to_vec2(vec4 p_vec) {
+ return uvec2(packSnorm2x16(p_vec.xy), packSnorm2x16(p_vec.zw));
+}
+
+vec4 vec2_to_vec4(uvec2 p_vec) {
+ return vec4(unpackSnorm2x16(p_vec.x), unpackSnorm2x16(p_vec.y));
+}
+
+void main() {
+#ifdef MODE_2D
+ out_vertex = in_vertex;
+
+#ifdef USE_BLEND_SHAPES
+#ifdef MODE_BLEND_PASS
+ out_vertex = in_vertex + blend_vertex * blend_weight;
+#else
+ out_vertex = in_vertex * blend_weight;
+#endif
+#ifdef FINAL_PASS
+ out_vertex = normalize(out_vertex);
+#endif
+#endif // USE_BLEND_SHAPES
+
+#ifdef USE_SKELETON
+
+#define TEX(m) texelFetch(skeleton_texture, ivec2(m % 256u, m / 256u), 0)
+#define GET_BONE_MATRIX(a, b, w) mat2x4(TEX(a), TEX(b)) * w
+
+ uvec4 bones = in_bone_attrib * uvec4(2u);
+ uvec4 bones_a = bones + uvec4(1u);
+
+ highp mat2x4 m = GET_BONE_MATRIX(bones.x, bones_a.x, in_weight_attrib.x);
+ m += GET_BONE_MATRIX(bones.y, bones_a.y, in_weight_attrib.y);
+ m += GET_BONE_MATRIX(bones.z, bones_a.z, in_weight_attrib.z);
+ m += GET_BONE_MATRIX(bones.w, bones_a.w, in_weight_attrib.w);
+
+ mat4 bone_matrix = mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
+
+ //reverse order because its transposed
+ out_vertex = (vec4(out_vertex, 0.0, 1.0) * bone_matrix).xy;
+#endif // USE_SKELETON
+
+#else // MODE_2D
+
+#ifdef USE_BLEND_SHAPES
+#ifdef MODE_BLEND_PASS
+ out_vertex = in_vertex + blend_vertex * blend_weight;
+
+#ifdef USE_NORMAL
+ vec3 normal = vec2_to_vec4(in_normal).xyz * blend_shape_count;
+ vec3 normal_blend = oct_to_vec3(blend_normal) * blend_weight;
+#ifdef FINAL_PASS
+ out_normal = vec3_to_oct(normalize(normal + normal_blend));
+#else
+ out_normal = vec4_to_vec2(vec4(normal + normal_blend, 0.0) / blend_shape_count);
+#endif
+#endif // USE_NORMAL
+
+#ifdef USE_TANGENT
+ vec4 tangent = vec2_to_vec4(in_tangent) * blend_shape_count;
+ vec4 tangent_blend = oct_to_tang(blend_tangent) * blend_weight;
+#ifdef FINAL_PASS
+ out_tangent = tang_to_oct(vec4(normalize(tangent.xyz + tangent_blend.xyz), tangent.w));
+#else
+ out_tangent = vec4_to_vec2(vec4((tangent.xyz + tangent_blend.xyz) / blend_shape_count, tangent.w));
+#endif
+#endif // USE_TANGENT
+
+#else // MODE_BLEND_PASS
+ out_vertex = in_vertex * blend_weight;
+
+#ifdef USE_NORMAL
+ vec3 normal = oct_to_vec3(in_normal);
+ out_normal = vec4_to_vec2(vec4(normal * blend_weight / blend_shape_count, 0.0));
+#endif
+#ifdef USE_TANGENT
+ vec4 tangent = oct_to_tang(in_tangent);
+ out_tangent = vec4_to_vec2(vec4(tangent.rgb * blend_weight / blend_shape_count, tangent.w));
+#endif
+#endif // MODE_BLEND_PASS
+#else // USE_BLEND_SHAPES
+
+ // Make attributes available to the skeleton shader if not written by blend shapes.
+ out_vertex = in_vertex;
+#ifdef USE_NORMAL
+ out_normal = in_normal;
+#endif
+#ifdef USE_TANGENT
+ out_tangent = in_tangent;
+#endif
+#endif // USE_BLEND_SHAPES
+
+#ifdef USE_SKELETON
+
+#define TEX(m) texelFetch(skeleton_texture, ivec2(m % 256u, m / 256u), 0)
+#define GET_BONE_MATRIX(a, b, c, w) mat4(TEX(a), TEX(b), TEX(c), vec4(0.0, 0.0, 0.0, 1.0)) * w
+
+ uvec4 bones = in_bone_attrib * uvec4(3);
+ uvec4 bones_a = bones + uvec4(1);
+ uvec4 bones_b = bones + uvec4(2);
+
+ highp mat4 m;
+ m = GET_BONE_MATRIX(bones.x, bones_a.x, bones_b.x, in_weight_attrib.x);
+ m += GET_BONE_MATRIX(bones.y, bones_a.y, bones_b.y, in_weight_attrib.y);
+ m += GET_BONE_MATRIX(bones.z, bones_a.z, bones_b.z, in_weight_attrib.z);
+ m += GET_BONE_MATRIX(bones.w, bones_a.w, bones_b.w, in_weight_attrib.w);
+
+#ifdef USE_EIGHT_WEIGHTS
+ bones = in_bone_attrib2 * uvec4(3);
+ bones_a = bones + uvec4(1);
+ bones_b = bones + uvec4(2);
+
+ m += GET_BONE_MATRIX(bones.x, bones_a.x, bones_b.x, in_weight_attrib2.x);
+ m += GET_BONE_MATRIX(bones.y, bones_a.y, bones_b.y, in_weight_attrib2.y);
+ m += GET_BONE_MATRIX(bones.z, bones_a.z, bones_b.z, in_weight_attrib2.z);
+ m += GET_BONE_MATRIX(bones.w, bones_a.w, bones_b.w, in_weight_attrib2.w);
+#endif
+
+ // Reverse order because its transposed.
+ out_vertex = (vec4(out_vertex, 1.0) * m).xyz;
+#ifdef USE_NORMAL
+ vec3 vertex_normal = oct_to_vec3(out_normal);
+ out_normal = vec3_to_oct(normalize((vec4(vertex_normal, 0.0) * m).xyz));
+#endif // USE_NORMAL
+#ifdef USE_TANGENT
+ vec4 vertex_tangent = oct_to_tang(out_tangent);
+ out_tangent = tang_to_oct(vec4(normalize((vec4(vertex_tangent.xyz, 0.0) * m).xyz), vertex_tangent.w));
+#endif // USE_TANGENT
+#endif // USE_SKELETON
+#endif // MODE_2D
+}
+
+/* clang-format off */
+#[fragment]
+
+void main() {
+
+}
+/* clang-format on */
diff --git a/drivers/gles3/shaders/stdlib_inc.glsl b/drivers/gles3/shaders/stdlib_inc.glsl
index d5051760d7..8d4a24cc1f 100644
--- a/drivers/gles3/shaders/stdlib_inc.glsl
+++ b/drivers/gles3/shaders/stdlib_inc.glsl
@@ -38,23 +38,33 @@ vec2 unpackSnorm2x16(uint p) {
vec2 v = vec2(float(p & uint(0xffff)), float(p >> uint(16)));
return clamp((v - 32767.0) * vec2(0.00003051851), vec2(-1.0), vec2(1.0));
}
+
#endif
-uint packUnorm4x8(vec4 v) {
+// Compatibility renames. These are exposed with the "godot_" prefix
+// to work around an Adreno bug which was exposing these ES310 functions
+// in ES300 shaders. Internally, we must use the "godot_" prefix, but user shaders
+// will be mapped automatically.
+uint godot_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));
}
-vec4 unpackUnorm4x8(uint p) {
+vec4 godot_unpackUnorm4x8(uint p) {
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) {
+uint godot_packSnorm4x8(vec4 v) {
uvec4 uv = uvec4(round(clamp(v, vec4(-1.0), vec4(1.0)) * 127.0) + 127.0);
return uv.x | uv.y << uint(8) | uv.z << uint(16) | uv.w << uint(24);
}
-vec4 unpackSnorm4x8(uint p) {
+vec4 godot_unpackSnorm4x8(uint p) {
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));
}
+
+#define packUnorm4x8 godot_packUnorm4x8
+#define unpackUnorm4x8 godot_unpackUnorm4x8
+#define packSnorm4x8 godot_packSnorm4x8
+#define unpackSnorm4x8 godot_unpackSnorm4x8