initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
34
drivers/gles3/shaders/SCsub
Normal file
34
drivers/gles3/shaders/SCsub
Normal file
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
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 + ["#gles3_builders.py"])
|
||||
|
||||
# compile shaders
|
||||
|
||||
# as we have a few, not yet, converted files we name the ones we want to include:
|
||||
env.GLES3_GLSL("canvas.glsl")
|
||||
env.GLES3_GLSL("feed.glsl")
|
||||
env.GLES3_GLSL("scene.glsl")
|
||||
env.GLES3_GLSL("sky.glsl")
|
||||
env.GLES3_GLSL("canvas_occlusion.glsl")
|
||||
env.GLES3_GLSL("canvas_sdf.glsl")
|
||||
env.GLES3_GLSL("particles.glsl")
|
||||
env.GLES3_GLSL("particles_copy.glsl")
|
||||
env.GLES3_GLSL("skeleton.glsl")
|
||||
|
||||
# once we finish conversion we can introduce this to cover all files:
|
||||
# for glsl_file in glsl_files:
|
||||
# env.GLES3_GLSL(glsl_file)
|
||||
|
||||
|
||||
SConscript("effects/SCsub")
|
870
drivers/gles3/shaders/canvas.glsl
Normal file
870
drivers/gles3/shaders/canvas.glsl
Normal file
@@ -0,0 +1,870 @@
|
||||
/* clang-format off */
|
||||
#[modes]
|
||||
|
||||
mode_default =
|
||||
|
||||
#[specializations]
|
||||
|
||||
DISABLE_LIGHTING = true
|
||||
USE_RGBA_SHADOWS = false
|
||||
USE_NINEPATCH = false
|
||||
USE_PRIMITIVE = false
|
||||
USE_ATTRIBUTES = false
|
||||
USE_INSTANCING = false
|
||||
|
||||
#[vertex]
|
||||
|
||||
#ifdef USE_ATTRIBUTES
|
||||
layout(location = 0) in vec2 vertex_attrib;
|
||||
layout(location = 3) in vec4 color_attrib;
|
||||
layout(location = 4) in vec2 uv_attrib;
|
||||
|
||||
#ifdef USE_INSTANCING
|
||||
|
||||
layout(location = 1) in highp vec4 instance_xform0;
|
||||
layout(location = 2) in highp vec4 instance_xform1;
|
||||
layout(location = 5) in highp uvec4 instance_color_custom_data; // Color packed into xy, custom_data packed into zw for compatibility with 3D
|
||||
|
||||
#endif // USE_INSTANCING
|
||||
|
||||
#endif // USE_ATTRIBUTES
|
||||
|
||||
#include "stdlib_inc.glsl"
|
||||
|
||||
#if defined(CUSTOM0_USED)
|
||||
layout(location = 6) in highp vec4 custom0_attrib;
|
||||
#endif
|
||||
|
||||
#if defined(CUSTOM1_USED)
|
||||
layout(location = 7) in highp vec4 custom1_attrib;
|
||||
#endif
|
||||
|
||||
layout(location = 8) in highp vec4 attrib_A;
|
||||
layout(location = 9) in highp vec4 attrib_B;
|
||||
layout(location = 10) in highp vec4 attrib_C;
|
||||
layout(location = 11) in highp vec4 attrib_D;
|
||||
layout(location = 12) in highp vec4 attrib_E;
|
||||
#ifdef USE_PRIMITIVE
|
||||
layout(location = 13) in highp uvec4 attrib_F;
|
||||
#else
|
||||
layout(location = 13) in highp vec4 attrib_F;
|
||||
#endif
|
||||
layout(location = 14) in highp uvec4 attrib_G;
|
||||
layout(location = 15) in highp uvec4 attrib_H;
|
||||
|
||||
#define read_draw_data_world_x attrib_A.xy
|
||||
#define read_draw_data_world_y attrib_A.zw
|
||||
#define read_draw_data_world_ofs attrib_B.xy
|
||||
#define read_draw_data_color_texture_pixel_size attrib_B.zw
|
||||
|
||||
#ifdef USE_PRIMITIVE
|
||||
|
||||
#define read_draw_data_point_a attrib_C.xy
|
||||
#define read_draw_data_point_b attrib_C.zw
|
||||
#define read_draw_data_point_c attrib_D.xy
|
||||
#define read_draw_data_uv_a attrib_D.zw
|
||||
#define read_draw_data_uv_b attrib_E.xy
|
||||
#define read_draw_data_uv_c attrib_E.zw
|
||||
|
||||
#define read_draw_data_color_a_rg attrib_F.x
|
||||
#define read_draw_data_color_a_ba attrib_F.y
|
||||
#define read_draw_data_color_b_rg attrib_F.z
|
||||
#define read_draw_data_color_b_ba attrib_F.w
|
||||
#define read_draw_data_color_c_rg attrib_G.x
|
||||
#define read_draw_data_color_c_ba attrib_G.y
|
||||
|
||||
#else
|
||||
|
||||
#define read_draw_data_modulation attrib_C
|
||||
#define read_draw_data_ninepatch_margins attrib_D
|
||||
#define read_draw_data_dst_rect attrib_E
|
||||
#define read_draw_data_src_rect attrib_F
|
||||
|
||||
#endif
|
||||
|
||||
#define read_draw_data_flags attrib_G.z
|
||||
#define read_draw_data_instance_offset attrib_G.w
|
||||
#define read_draw_data_lights attrib_H
|
||||
|
||||
// Varyings so the per-instance info can be used in the fragment shader
|
||||
flat out vec4 varying_A;
|
||||
flat out vec2 varying_B;
|
||||
#ifndef USE_PRIMITIVE
|
||||
flat out vec4 varying_C;
|
||||
#ifndef USE_ATTRIBUTES
|
||||
#ifdef USE_NINEPATCH
|
||||
|
||||
flat out vec2 varying_D;
|
||||
#endif
|
||||
flat out vec4 varying_E;
|
||||
#endif
|
||||
#endif
|
||||
flat out uvec2 varying_F;
|
||||
flat out uvec4 varying_G;
|
||||
|
||||
// This needs to be outside clang-format so the ubo comment is in the right place
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(std140) uniform MaterialUniforms{ //ubo:4
|
||||
|
||||
#MATERIAL_UNIFORMS
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
uniform mediump uint batch_flags;
|
||||
|
||||
/* clang-format on */
|
||||
#include "canvas_uniforms_inc.glsl"
|
||||
|
||||
out vec2 uv_interp;
|
||||
out vec4 color_interp;
|
||||
out vec2 vertex_interp;
|
||||
|
||||
#ifdef USE_NINEPATCH
|
||||
|
||||
out vec2 pixel_size_interp;
|
||||
|
||||
#endif
|
||||
|
||||
#GLOBALS
|
||||
|
||||
void main() {
|
||||
varying_A = vec4(read_draw_data_world_x, read_draw_data_world_y);
|
||||
varying_B = read_draw_data_color_texture_pixel_size;
|
||||
#ifndef USE_PRIMITIVE
|
||||
varying_C = read_draw_data_ninepatch_margins;
|
||||
|
||||
#ifndef USE_ATTRIBUTES
|
||||
#ifdef USE_NINEPATCH
|
||||
varying_D = vec2(read_draw_data_dst_rect.z, read_draw_data_dst_rect.w);
|
||||
#endif // USE_NINEPATCH
|
||||
varying_E = read_draw_data_src_rect;
|
||||
#endif // !USE_ATTRIBUTES
|
||||
#endif // USE_PRIMITIVE
|
||||
|
||||
varying_F = uvec2(read_draw_data_flags, read_draw_data_instance_offset);
|
||||
varying_G = read_draw_data_lights;
|
||||
|
||||
vec4 instance_custom = vec4(0.0);
|
||||
|
||||
#if defined(CUSTOM0_USED)
|
||||
vec4 custom0 = vec4(0.0);
|
||||
#endif
|
||||
#if defined(CUSTOM1_USED)
|
||||
vec4 custom1 = vec4(0.0);
|
||||
#endif
|
||||
|
||||
#ifdef USE_PRIMITIVE
|
||||
vec2 vertex;
|
||||
vec2 uv;
|
||||
vec4 color;
|
||||
|
||||
if (gl_VertexID % 3 == 0) {
|
||||
vertex = read_draw_data_point_a;
|
||||
uv = read_draw_data_uv_a;
|
||||
color.xy = unpackHalf2x16(read_draw_data_color_a_rg);
|
||||
color.zw = unpackHalf2x16(read_draw_data_color_a_ba);
|
||||
} else if (gl_VertexID % 3 == 1) {
|
||||
vertex = read_draw_data_point_b;
|
||||
uv = read_draw_data_uv_b;
|
||||
color.xy = unpackHalf2x16(read_draw_data_color_b_rg);
|
||||
color.zw = unpackHalf2x16(read_draw_data_color_b_ba);
|
||||
} else {
|
||||
vertex = read_draw_data_point_c;
|
||||
uv = read_draw_data_uv_c;
|
||||
color.xy = unpackHalf2x16(read_draw_data_color_c_rg);
|
||||
color.zw = unpackHalf2x16(read_draw_data_color_c_ba);
|
||||
}
|
||||
|
||||
#elif defined(USE_ATTRIBUTES)
|
||||
vec2 vertex = vertex_attrib;
|
||||
vec4 color = color_attrib * read_draw_data_modulation;
|
||||
vec2 uv = uv_attrib;
|
||||
|
||||
#ifdef USE_INSTANCING
|
||||
if (bool(batch_flags & BATCH_FLAGS_INSTANCING_HAS_COLORS)) {
|
||||
vec4 instance_color;
|
||||
instance_color.xy = unpackHalf2x16(uint(instance_color_custom_data.x));
|
||||
instance_color.zw = unpackHalf2x16(uint(instance_color_custom_data.y));
|
||||
color *= instance_color;
|
||||
}
|
||||
if (bool(batch_flags & BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA)) {
|
||||
instance_custom.xy = unpackHalf2x16(instance_color_custom_data.z);
|
||||
instance_custom.zw = unpackHalf2x16(instance_color_custom_data.w);
|
||||
}
|
||||
#endif // !USE_INSTANCING
|
||||
|
||||
#else // !USE_ATTRIBUTES
|
||||
|
||||
// crash on Adreno 320/330
|
||||
//vec2 vertex_base_arr[6] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0), vec2(1.0, 1.0));
|
||||
//vec2 vertex_base = vertex_base_arr[gl_VertexID % 6];
|
||||
//-----------------------------------------
|
||||
// ID | 0 | 1 | 2 | 3 | 4 | 5 |
|
||||
//-----------------------------------------
|
||||
// X | 0.0 | 0.0 | 1.0 | 1.0 | 0.0 | 1.0 |
|
||||
// Y | 0.0 | 1.0 | 1.0 | 0.0 | 0.0 | 1.0 |
|
||||
//-----------------------------------------
|
||||
// no crash or freeze on all Adreno 3xx with 'if / else if' and slightly faster!
|
||||
int vertex_id = gl_VertexID % 6;
|
||||
vec2 vertex_base;
|
||||
if (vertex_id == 0) {
|
||||
vertex_base = vec2(0.0, 0.0);
|
||||
} else if (vertex_id == 1) {
|
||||
vertex_base = vec2(0.0, 1.0);
|
||||
} else if (vertex_id == 2) {
|
||||
vertex_base = vec2(1.0, 1.0);
|
||||
} else if (vertex_id == 3) {
|
||||
vertex_base = vec2(1.0, 0.0);
|
||||
} else if (vertex_id == 4) {
|
||||
vertex_base = vec2(0.0, 0.0);
|
||||
} else if (vertex_id == 5) {
|
||||
vertex_base = vec2(1.0, 1.0);
|
||||
}
|
||||
|
||||
vec2 uv = read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw) * ((read_draw_data_flags & INSTANCE_FLAGS_TRANSPOSE_RECT) != uint(0) ? vertex_base.yx : vertex_base.xy);
|
||||
vec4 color = read_draw_data_modulation;
|
||||
vec2 vertex = read_draw_data_dst_rect.xy + abs(read_draw_data_dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(read_draw_data_src_rect.zw, vec2(0.0, 0.0)));
|
||||
|
||||
#endif // USE_ATTRIBUTES
|
||||
|
||||
#if defined(CUSTOM0_USED)
|
||||
custom0 = custom0_attrib;
|
||||
#endif
|
||||
|
||||
#if defined(CUSTOM1_USED)
|
||||
custom1 = custom1_attrib;
|
||||
#endif
|
||||
|
||||
mat4 model_matrix = mat4(vec4(read_draw_data_world_x, 0.0, 0.0), vec4(read_draw_data_world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(read_draw_data_world_ofs, 0.0, 1.0));
|
||||
|
||||
#ifdef USE_INSTANCING
|
||||
model_matrix = model_matrix * transpose(mat4(instance_xform0, instance_xform1, vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)));
|
||||
#endif // USE_INSTANCING
|
||||
|
||||
vec2 color_texture_pixel_size = read_draw_data_color_texture_pixel_size;
|
||||
|
||||
#ifdef USE_POINT_SIZE
|
||||
float point_size = 1.0;
|
||||
#endif
|
||||
|
||||
#ifdef USE_WORLD_VERTEX_COORDS
|
||||
vertex = (model_matrix * vec4(vertex, 0.0, 1.0)).xy;
|
||||
#endif
|
||||
{
|
||||
#CODE : VERTEX
|
||||
}
|
||||
|
||||
#ifdef USE_NINEPATCH
|
||||
pixel_size_interp = abs(read_draw_data_dst_rect.zw) * vertex_base;
|
||||
#endif
|
||||
|
||||
#if !defined(SKIP_TRANSFORM_USED) && !defined(USE_WORLD_VERTEX_COORDS)
|
||||
vertex = (model_matrix * vec4(vertex, 0.0, 1.0)).xy;
|
||||
#endif
|
||||
|
||||
color_interp = color;
|
||||
|
||||
vertex = (canvas_transform * vec4(vertex, 0.0, 1.0)).xy;
|
||||
|
||||
if (use_pixel_snap) {
|
||||
vertex = floor(vertex + 0.5);
|
||||
// precision issue on some hardware creates artifacts within texture
|
||||
// offset uv by a small amount to avoid
|
||||
uv += 1e-5;
|
||||
}
|
||||
|
||||
vertex_interp = vertex;
|
||||
uv_interp = uv;
|
||||
|
||||
gl_Position = screen_transform * vec4(vertex, 0.0, 1.0);
|
||||
|
||||
#ifdef USE_POINT_SIZE
|
||||
gl_PointSize = point_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
#[fragment]
|
||||
|
||||
#include "canvas_uniforms_inc.glsl"
|
||||
#include "stdlib_inc.glsl"
|
||||
|
||||
in vec2 uv_interp;
|
||||
in vec2 vertex_interp;
|
||||
in vec4 color_interp;
|
||||
|
||||
#ifdef USE_NINEPATCH
|
||||
|
||||
in vec2 pixel_size_interp;
|
||||
|
||||
#endif
|
||||
|
||||
// Can all be flat as they are the same for the whole batched instance
|
||||
flat in vec4 varying_A;
|
||||
flat in vec2 varying_B;
|
||||
#define read_draw_data_world_x varying_A.xy
|
||||
#define read_draw_data_world_y varying_A.zw
|
||||
#define read_draw_data_color_texture_pixel_size varying_B
|
||||
|
||||
#ifndef USE_PRIMITIVE
|
||||
flat in vec4 varying_C;
|
||||
#define read_draw_data_ninepatch_margins varying_C
|
||||
|
||||
#ifndef USE_ATTRIBUTES
|
||||
#ifdef USE_NINEPATCH
|
||||
|
||||
flat in vec2 varying_D;
|
||||
#define read_draw_data_dst_rect_z varying_D.x
|
||||
#define read_draw_data_dst_rect_w varying_D.y
|
||||
#endif
|
||||
|
||||
flat in vec4 varying_E;
|
||||
#define read_draw_data_src_rect varying_E
|
||||
#endif // USE_ATTRIBUTES
|
||||
#endif // USE_PRIMITIVE
|
||||
|
||||
flat in uvec2 varying_F;
|
||||
flat in uvec4 varying_G;
|
||||
#define read_draw_data_flags varying_F.x
|
||||
#define read_draw_data_instance_offset varying_F.y
|
||||
#define read_draw_data_lights varying_G
|
||||
|
||||
#ifndef DISABLE_LIGHTING
|
||||
uniform sampler2D atlas_texture; //texunit:-2
|
||||
uniform sampler2D shadow_atlas_texture; //texunit:-3
|
||||
#endif // DISABLE_LIGHTING
|
||||
uniform sampler2D color_buffer; //texunit:-4
|
||||
uniform sampler2D sdf_texture; //texunit:-5
|
||||
uniform sampler2D normal_texture; //texunit:-6
|
||||
uniform sampler2D specular_texture; //texunit:-7
|
||||
|
||||
uniform sampler2D color_texture; //texunit:0
|
||||
|
||||
uniform mediump uint batch_flags;
|
||||
uniform highp uint specular_shininess_in;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
/* clang-format off */
|
||||
// This needs to be outside clang-format so the ubo comment is in the right place
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(std140) uniform MaterialUniforms{ //ubo:4
|
||||
|
||||
#MATERIAL_UNIFORMS
|
||||
|
||||
};
|
||||
#endif
|
||||
/* clang-format on */
|
||||
|
||||
#GLOBALS
|
||||
|
||||
float vec4_to_float(vec4 p_vec) {
|
||||
return dot(p_vec, vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0)) * 2.0 - 1.0;
|
||||
}
|
||||
|
||||
vec2 screen_uv_to_sdf(vec2 p_uv) {
|
||||
return screen_to_sdf * p_uv;
|
||||
}
|
||||
|
||||
float texture_sdf(vec2 p_sdf) {
|
||||
vec2 uv = p_sdf * sdf_to_tex.xy + sdf_to_tex.zw;
|
||||
float d = vec4_to_float(texture(sdf_texture, uv));
|
||||
d *= SDF_MAX_LENGTH;
|
||||
return d * tex_to_sdf;
|
||||
}
|
||||
|
||||
vec2 texture_sdf_normal(vec2 p_sdf) {
|
||||
vec2 uv = p_sdf * sdf_to_tex.xy + sdf_to_tex.zw;
|
||||
|
||||
const float EPSILON = 0.001;
|
||||
return normalize(vec2(
|
||||
vec4_to_float(texture(sdf_texture, uv + vec2(EPSILON, 0.0))) - vec4_to_float(texture(sdf_texture, uv - vec2(EPSILON, 0.0))),
|
||||
vec4_to_float(texture(sdf_texture, uv + vec2(0.0, EPSILON))) - vec4_to_float(texture(sdf_texture, uv - vec2(0.0, EPSILON)))));
|
||||
}
|
||||
|
||||
vec2 sdf_to_screen_uv(vec2 p_sdf) {
|
||||
return p_sdf * sdf_to_screen;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_LIGHTING
|
||||
#ifdef LIGHT_CODE_USED
|
||||
|
||||
vec4 light_compute(
|
||||
vec3 light_vertex,
|
||||
vec3 light_position,
|
||||
vec3 normal,
|
||||
vec4 light_color,
|
||||
float light_energy,
|
||||
vec4 specular_shininess,
|
||||
inout vec4 shadow_modulate,
|
||||
vec2 screen_uv,
|
||||
vec2 uv,
|
||||
vec4 color, bool is_directional) {
|
||||
vec4 light = vec4(0.0);
|
||||
vec3 light_direction = vec3(0.0);
|
||||
|
||||
if (is_directional) {
|
||||
light_direction = normalize(mix(vec3(light_position.xy, 0.0), vec3(0, 0, 1), light_position.z));
|
||||
light_position = vec3(0.0);
|
||||
} else {
|
||||
light_direction = normalize(light_position - light_vertex);
|
||||
}
|
||||
|
||||
#CODE : LIGHT
|
||||
|
||||
return light;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
vec3 light_normal_compute(vec3 light_vec, vec3 normal, vec3 base_color, vec3 light_color, vec4 specular_shininess, bool specular_shininess_used) {
|
||||
float cNdotL = max(0.0, dot(normal, light_vec));
|
||||
|
||||
if (specular_shininess_used) {
|
||||
//blinn
|
||||
vec3 view = vec3(0.0, 0.0, 1.0); // not great but good enough
|
||||
vec3 half_vec = normalize(view + light_vec);
|
||||
|
||||
float cNdotV = max(dot(normal, view), 0.0);
|
||||
float cNdotH = max(dot(normal, half_vec), 0.0);
|
||||
float cVdotH = max(dot(view, half_vec), 0.0);
|
||||
float cLdotH = max(dot(light_vec, half_vec), 0.0);
|
||||
float shininess = exp2(15.0 * specular_shininess.a + 1.0) * 0.25;
|
||||
float blinn = pow(cNdotH, shininess);
|
||||
blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
|
||||
float s = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75);
|
||||
|
||||
return specular_shininess.rgb * light_color * s + light_color * base_color * cNdotL;
|
||||
} else {
|
||||
return light_color * base_color * cNdotL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_RGBA_SHADOWS
|
||||
|
||||
#define SHADOW_DEPTH(m_uv) (dot(textureLod(shadow_atlas_texture, (m_uv), 0.0), vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0)) * 2.0 - 1.0)
|
||||
|
||||
#else
|
||||
|
||||
#define SHADOW_DEPTH(m_uv) (textureLod(shadow_atlas_texture, (m_uv), 0.0).r)
|
||||
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
#ifdef LIGHT_CODE_USED
|
||||
,
|
||||
vec3 shadow_modulate
|
||||
#endif
|
||||
) {
|
||||
float shadow = 0.0;
|
||||
uint shadow_mode = light_array[light_base].flags & LIGHT_FLAGS_FILTER_MASK;
|
||||
|
||||
if (shadow_mode == LIGHT_FLAGS_SHADOW_NEAREST) {
|
||||
SHADOW_TEST(shadow_uv.xy);
|
||||
} else if (shadow_mode == LIGHT_FLAGS_SHADOW_PCF5) {
|
||||
vec2 shadow_pixel_size = vec2(light_array[light_base].shadow_pixel_size, 0.0);
|
||||
SHADOW_TEST(shadow_uv.xy - shadow_pixel_size * 2.0);
|
||||
SHADOW_TEST(shadow_uv.xy - shadow_pixel_size);
|
||||
SHADOW_TEST(shadow_uv.xy);
|
||||
SHADOW_TEST(shadow_uv.xy + shadow_pixel_size);
|
||||
SHADOW_TEST(shadow_uv.xy + shadow_pixel_size * 2.0);
|
||||
shadow /= 5.0;
|
||||
} else { //PCF13
|
||||
vec2 shadow_pixel_size = vec2(light_array[light_base].shadow_pixel_size, 0.0);
|
||||
SHADOW_TEST(shadow_uv.xy - shadow_pixel_size * 6.0);
|
||||
SHADOW_TEST(shadow_uv.xy - shadow_pixel_size * 5.0);
|
||||
SHADOW_TEST(shadow_uv.xy - shadow_pixel_size * 4.0);
|
||||
SHADOW_TEST(shadow_uv.xy - shadow_pixel_size * 3.0);
|
||||
SHADOW_TEST(shadow_uv.xy - shadow_pixel_size * 2.0);
|
||||
SHADOW_TEST(shadow_uv.xy - shadow_pixel_size);
|
||||
SHADOW_TEST(shadow_uv.xy);
|
||||
SHADOW_TEST(shadow_uv.xy + shadow_pixel_size);
|
||||
SHADOW_TEST(shadow_uv.xy + shadow_pixel_size * 2.0);
|
||||
SHADOW_TEST(shadow_uv.xy + shadow_pixel_size * 3.0);
|
||||
SHADOW_TEST(shadow_uv.xy + shadow_pixel_size * 4.0);
|
||||
SHADOW_TEST(shadow_uv.xy + shadow_pixel_size * 5.0);
|
||||
SHADOW_TEST(shadow_uv.xy + shadow_pixel_size * 6.0);
|
||||
shadow /= 13.0;
|
||||
}
|
||||
|
||||
vec4 shadow_color = godot_unpackUnorm4x8(light_array[light_base].shadow_color);
|
||||
#ifdef LIGHT_CODE_USED
|
||||
shadow_color.rgb *= shadow_modulate;
|
||||
#endif
|
||||
|
||||
shadow_color.a *= light_color.a; //respect light alpha
|
||||
|
||||
return mix(light_color, shadow_color, shadow);
|
||||
}
|
||||
|
||||
void light_blend_compute(uint light_base, vec4 light_color, inout vec3 color) {
|
||||
uint blend_mode = light_array[light_base].flags & LIGHT_FLAGS_BLEND_MASK;
|
||||
|
||||
if (blend_mode == LIGHT_FLAGS_BLEND_MODE_ADD) {
|
||||
color.rgb += light_color.rgb * light_color.a;
|
||||
} else if (blend_mode == LIGHT_FLAGS_BLEND_MODE_SUB) {
|
||||
color.rgb -= light_color.rgb * light_color.a;
|
||||
} else if (blend_mode == LIGHT_FLAGS_BLEND_MODE_MIX) {
|
||||
color.rgb = mix(color.rgb, light_color.rgb, light_color.a);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_NINEPATCH
|
||||
|
||||
float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, int np_repeat, inout int draw_center) {
|
||||
float tex_size = 1.0 / tex_pixel_size;
|
||||
|
||||
if (pixel < margin_begin) {
|
||||
return pixel * tex_pixel_size;
|
||||
} else if (pixel >= draw_size - margin_end) {
|
||||
return (tex_size - (draw_size - pixel)) * tex_pixel_size;
|
||||
} else {
|
||||
if (!bool(read_draw_data_flags & INSTANCE_FLAGS_NINEPATCH_DRAW_CENTER)) {
|
||||
draw_center--;
|
||||
}
|
||||
|
||||
// np_repeat is passed as uniform using NinePatchRect::AxisStretchMode enum.
|
||||
if (np_repeat == 0) { // Stretch.
|
||||
// Convert to ratio.
|
||||
float ratio = (pixel - margin_begin) / (draw_size - margin_begin - margin_end);
|
||||
// Scale to source texture.
|
||||
return (margin_begin + ratio * (tex_size - margin_begin - margin_end)) * tex_pixel_size;
|
||||
} else if (np_repeat == 1) { // Tile.
|
||||
// Convert to offset.
|
||||
float ofs = mod((pixel - margin_begin), tex_size - margin_begin - margin_end);
|
||||
// Scale to source texture.
|
||||
return (margin_begin + ofs) * tex_pixel_size;
|
||||
} else if (np_repeat == 2) { // Tile Fit.
|
||||
// Calculate scale.
|
||||
float src_area = draw_size - margin_begin - margin_end;
|
||||
float dst_area = tex_size - margin_begin - margin_end;
|
||||
float scale = max(1.0, floor(src_area / max(dst_area, 0.0000001) + 0.5));
|
||||
// Convert to ratio.
|
||||
float ratio = (pixel - margin_begin) / src_area;
|
||||
ratio = mod(ratio * scale, 1.0);
|
||||
// Scale to source texture.
|
||||
return (margin_begin + ratio * dst_area) * tex_pixel_size;
|
||||
} else { // Shouldn't happen, but silences compiler warning.
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
float msdf_median(float r, float g, float b) {
|
||||
return max(min(r, g), min(max(r, g), b));
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 color = color_interp;
|
||||
vec2 uv = uv_interp;
|
||||
vec2 vertex = vertex_interp;
|
||||
|
||||
#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE)
|
||||
vec4 region_rect = read_draw_data_src_rect;
|
||||
#else
|
||||
vec4 region_rect = vec4(0.0, 0.0, 1.0 / read_draw_data_color_texture_pixel_size);
|
||||
#endif
|
||||
|
||||
#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE)
|
||||
|
||||
#ifdef USE_NINEPATCH
|
||||
|
||||
int draw_center = 2;
|
||||
uv = vec2(
|
||||
map_ninepatch_axis(pixel_size_interp.x, abs(read_draw_data_dst_rect_z), read_draw_data_color_texture_pixel_size.x, read_draw_data_ninepatch_margins.x, read_draw_data_ninepatch_margins.z, int(read_draw_data_flags >> INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT) & 0x3, draw_center),
|
||||
map_ninepatch_axis(pixel_size_interp.y, abs(read_draw_data_dst_rect_w), read_draw_data_color_texture_pixel_size.y, read_draw_data_ninepatch_margins.y, read_draw_data_ninepatch_margins.w, int(read_draw_data_flags >> INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT) & 0x3, draw_center));
|
||||
|
||||
if (draw_center == 0) {
|
||||
color.a = 0.0;
|
||||
}
|
||||
|
||||
uv = uv * read_draw_data_src_rect.zw + read_draw_data_src_rect.xy; //apply region if needed
|
||||
|
||||
#endif
|
||||
if (bool(read_draw_data_flags & INSTANCE_FLAGS_CLIP_RECT_UV)) {
|
||||
vec2 half_texpixel = read_draw_data_color_texture_pixel_size * 0.5;
|
||||
uv = clamp(uv, read_draw_data_src_rect.xy + half_texpixel, read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw) - half_texpixel);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef USE_PRIMITIVE
|
||||
if (bool(read_draw_data_flags & INSTANCE_FLAGS_USE_MSDF)) {
|
||||
float px_range = read_draw_data_ninepatch_margins.x;
|
||||
float outline_thickness = read_draw_data_ninepatch_margins.y;
|
||||
|
||||
vec4 msdf_sample = texture(color_texture, uv);
|
||||
vec2 msdf_size = vec2(textureSize(color_texture, 0));
|
||||
vec2 dest_size = vec2(1.0) / fwidth(uv);
|
||||
float px_size = max(0.5 * dot((vec2(px_range) / msdf_size), dest_size), 1.0);
|
||||
float d = msdf_median(msdf_sample.r, msdf_sample.g, msdf_sample.b);
|
||||
|
||||
if (outline_thickness > 0.0) {
|
||||
float cr = clamp(outline_thickness, 0.0, (px_range / 2.0) - 1.0) / px_range;
|
||||
d = min(d, msdf_sample.a);
|
||||
float a = clamp((d - 0.5 + cr) * px_size, 0.0, 1.0);
|
||||
color.a = a * color.a;
|
||||
} else {
|
||||
float a = clamp((d - 0.5) * px_size + 0.5, 0.0, 1.0);
|
||||
color.a = a * color.a;
|
||||
}
|
||||
} else if (bool(read_draw_data_flags & INSTANCE_FLAGS_USE_LCD)) {
|
||||
vec4 lcd_sample = texture(color_texture, uv);
|
||||
if (lcd_sample.a == 1.0) {
|
||||
color.rgb = lcd_sample.rgb * color.a;
|
||||
} else {
|
||||
color = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
color *= texture(color_texture, uv);
|
||||
}
|
||||
|
||||
uint light_count = read_draw_data_flags & uint(0xF); // Max 16 lights.
|
||||
bool using_light = light_count > 0u || directional_light_count > 0u;
|
||||
|
||||
vec3 normal;
|
||||
|
||||
#if defined(NORMAL_USED)
|
||||
bool normal_used = true;
|
||||
#else
|
||||
bool normal_used = false;
|
||||
#endif
|
||||
|
||||
if (normal_used || (using_light && bool(batch_flags & BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED))) {
|
||||
normal.xy = texture(normal_texture, uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0);
|
||||
|
||||
#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE)
|
||||
if (bool(read_draw_data_flags & INSTANCE_FLAGS_TRANSPOSE_RECT)) {
|
||||
normal.xy = normal.yx;
|
||||
}
|
||||
normal.xy *= sign(read_draw_data_src_rect.zw);
|
||||
#endif
|
||||
|
||||
normal.z = sqrt(max(0.0, 1.0 - dot(normal.xy, normal.xy)));
|
||||
normal_used = true;
|
||||
} else {
|
||||
normal = vec3(0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec4 specular_shininess;
|
||||
|
||||
#if defined(SPECULAR_SHININESS_USED)
|
||||
|
||||
bool specular_shininess_used = true;
|
||||
#else
|
||||
bool specular_shininess_used = false;
|
||||
#endif
|
||||
|
||||
if (specular_shininess_used || (using_light && normal_used && bool(batch_flags & BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED))) {
|
||||
specular_shininess = texture(specular_texture, uv);
|
||||
specular_shininess *= godot_unpackUnorm4x8(specular_shininess_in);
|
||||
specular_shininess_used = true;
|
||||
} else {
|
||||
specular_shininess = vec4(1.0);
|
||||
}
|
||||
|
||||
#if defined(SCREEN_UV_USED)
|
||||
vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size;
|
||||
#else
|
||||
vec2 screen_uv = vec2(0.0);
|
||||
#endif
|
||||
|
||||
vec2 color_texture_pixel_size = read_draw_data_color_texture_pixel_size.xy;
|
||||
|
||||
vec3 light_vertex = vec3(vertex, 0.0);
|
||||
vec2 shadow_vertex = vertex;
|
||||
|
||||
{
|
||||
float normal_map_depth = 1.0;
|
||||
|
||||
#if defined(NORMAL_MAP_USED)
|
||||
vec3 normal_map = vec3(0.0, 0.0, 1.0);
|
||||
normal_used = true;
|
||||
#endif
|
||||
|
||||
#CODE : FRAGMENT
|
||||
|
||||
#if defined(NORMAL_MAP_USED)
|
||||
normal = mix(vec3(0.0, 0.0, 1.0), normal_map * vec3(2.0, -2.0, 1.0) - vec3(1.0, -1.0, 0.0), normal_map_depth);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (normal_used) {
|
||||
//convert by item transform
|
||||
normal.xy = mat2(normalize(read_draw_data_world_x), normalize(read_draw_data_world_y)) * normal.xy;
|
||||
//convert by canvas transform
|
||||
normal = normalize((canvas_normal_transform * vec4(normal, 0.0)).xyz);
|
||||
}
|
||||
|
||||
vec4 base_color = color;
|
||||
|
||||
#ifdef MODE_LIGHT_ONLY
|
||||
float light_only_alpha = 0.0;
|
||||
#elif !defined(MODE_UNSHADED)
|
||||
color *= canvas_modulation;
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_LIGHTING) && !defined(MODE_UNSHADED)
|
||||
|
||||
// Directional Lights
|
||||
|
||||
for (uint i = 0u; i < directional_light_count; i++) {
|
||||
uint light_base = i;
|
||||
|
||||
vec2 direction = light_array[light_base].position;
|
||||
vec4 light_color = light_array[light_base].color;
|
||||
|
||||
#ifdef LIGHT_CODE_USED
|
||||
|
||||
vec4 shadow_modulate = vec4(1.0);
|
||||
light_color = light_compute(light_vertex, vec3(direction, light_array[light_base].height), normal, light_color, light_color.a, specular_shininess, shadow_modulate, screen_uv, uv, base_color, true);
|
||||
#else
|
||||
|
||||
if (normal_used) {
|
||||
vec3 light_vec = normalize(mix(vec3(direction, 0.0), vec3(0, 0, 1), light_array[light_base].height));
|
||||
light_color.rgb = light_normal_compute(light_vec, normal, base_color.rgb, light_color.rgb, specular_shininess, specular_shininess_used);
|
||||
} else {
|
||||
light_color.rgb *= base_color.rgb;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bool(light_array[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) {
|
||||
vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array[light_base].shadow_matrix[0], light_array[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
|
||||
|
||||
vec4 shadow_uv = vec4(shadow_pos.x, light_array[light_base].shadow_y_ofs, shadow_pos.y * light_array[light_base].shadow_zfar_inv, 1.0);
|
||||
|
||||
light_color = light_shadow_compute(light_base, light_color, shadow_uv
|
||||
#ifdef LIGHT_CODE_USED
|
||||
,
|
||||
shadow_modulate.rgb
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
light_blend_compute(light_base, light_color, color.rgb);
|
||||
#ifdef MODE_LIGHT_ONLY
|
||||
light_only_alpha += light_color.a;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Positional Lights
|
||||
|
||||
for (uint i = 0u; i < MAX_LIGHTS_PER_ITEM; i++) {
|
||||
if (i >= light_count) {
|
||||
break;
|
||||
}
|
||||
uint light_base;
|
||||
if (i < 8u) {
|
||||
if (i < 4u) {
|
||||
light_base = read_draw_data_lights[0];
|
||||
} else {
|
||||
light_base = read_draw_data_lights[1];
|
||||
}
|
||||
} else {
|
||||
if (i < 12u) {
|
||||
light_base = read_draw_data_lights[2];
|
||||
} else {
|
||||
light_base = read_draw_data_lights[3];
|
||||
}
|
||||
}
|
||||
light_base >>= (i & 3u) * 8u;
|
||||
light_base &= uint(0xFF);
|
||||
|
||||
vec2 tex_uv = (vec4(vertex, 0.0, 1.0) * mat4(light_array[light_base].texture_matrix[0], light_array[light_base].texture_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
|
||||
vec2 tex_uv_atlas = tex_uv * light_array[light_base].atlas_rect.zw + light_array[light_base].atlas_rect.xy;
|
||||
|
||||
if (any(lessThan(tex_uv, vec2(0.0, 0.0))) || any(greaterThanEqual(tex_uv, vec2(1.0, 1.0)))) {
|
||||
//if outside the light texture, light color is zero
|
||||
continue;
|
||||
}
|
||||
|
||||
vec4 light_color = textureLod(atlas_texture, tex_uv_atlas, 0.0);
|
||||
vec4 light_base_color = light_array[light_base].color;
|
||||
|
||||
#ifdef LIGHT_CODE_USED
|
||||
|
||||
vec4 shadow_modulate = vec4(1.0);
|
||||
vec3 light_position = vec3(light_array[light_base].position, light_array[light_base].height);
|
||||
|
||||
light_color.rgb *= light_base_color.rgb;
|
||||
light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, uv, base_color, false);
|
||||
#else
|
||||
|
||||
light_color.rgb *= light_base_color.rgb * light_base_color.a;
|
||||
|
||||
if (normal_used) {
|
||||
vec3 light_pos = vec3(light_array[light_base].position, light_array[light_base].height);
|
||||
vec3 pos = light_vertex;
|
||||
vec3 light_vec = normalize(light_pos - pos);
|
||||
|
||||
light_color.rgb = light_normal_compute(light_vec, normal, base_color.rgb, light_color.rgb, specular_shininess, specular_shininess_used);
|
||||
} else {
|
||||
light_color.rgb *= base_color.rgb;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bool(light_array[light_base].flags & LIGHT_FLAGS_HAS_SHADOW) && bool(read_draw_data_flags & uint(INSTANCE_FLAGS_SHADOW_MASKED << i))) {
|
||||
vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array[light_base].shadow_matrix[0], light_array[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
|
||||
|
||||
vec2 pos_norm = normalize(shadow_pos);
|
||||
vec2 pos_abs = abs(pos_norm);
|
||||
vec2 pos_box = pos_norm / max(pos_abs.x, pos_abs.y);
|
||||
vec2 pos_rot = pos_norm * mat2(vec2(0.7071067811865476, -0.7071067811865476), vec2(0.7071067811865476, 0.7071067811865476)); //is there a faster way to 45 degrees rot?
|
||||
float tex_ofs;
|
||||
float dist;
|
||||
if (pos_rot.y > 0.0) {
|
||||
if (pos_rot.x > 0.0) {
|
||||
tex_ofs = pos_box.y * 0.125 + 0.125;
|
||||
dist = shadow_pos.x;
|
||||
} else {
|
||||
tex_ofs = pos_box.x * -0.125 + (0.25 + 0.125);
|
||||
dist = shadow_pos.y;
|
||||
}
|
||||
} else {
|
||||
if (pos_rot.x < 0.0) {
|
||||
tex_ofs = pos_box.y * -0.125 + (0.5 + 0.125);
|
||||
dist = -shadow_pos.x;
|
||||
} else {
|
||||
tex_ofs = pos_box.x * 0.125 + (0.75 + 0.125);
|
||||
dist = -shadow_pos.y;
|
||||
}
|
||||
}
|
||||
|
||||
dist *= light_array[light_base].shadow_zfar_inv;
|
||||
|
||||
//float distance = length(shadow_pos);
|
||||
vec4 shadow_uv = vec4(tex_ofs, light_array[light_base].shadow_y_ofs, dist, 1.0);
|
||||
|
||||
light_color = light_shadow_compute(light_base, light_color, shadow_uv
|
||||
#ifdef LIGHT_CODE_USED
|
||||
,
|
||||
shadow_modulate.rgb
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
light_blend_compute(light_base, light_color, color.rgb);
|
||||
#ifdef MODE_LIGHT_ONLY
|
||||
light_only_alpha += light_color.a;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MODE_LIGHT_ONLY
|
||||
color.a *= light_only_alpha;
|
||||
#endif
|
||||
|
||||
frag_color = color;
|
||||
}
|
68
drivers/gles3/shaders/canvas_occlusion.glsl
Normal file
68
drivers/gles3/shaders/canvas_occlusion.glsl
Normal file
@@ -0,0 +1,68 @@
|
||||
/* clang-format off */
|
||||
#[modes]
|
||||
|
||||
mode_sdf =
|
||||
mode_shadow = #define MODE_SHADOW
|
||||
mode_shadow_RGBA = #define MODE_SHADOW \n#define USE_RGBA_SHADOWS
|
||||
|
||||
#[specializations]
|
||||
|
||||
#[vertex]
|
||||
|
||||
layout(location = 0) in vec3 vertex;
|
||||
|
||||
uniform highp mat4 projection;
|
||||
uniform highp vec4 modelview1;
|
||||
uniform highp vec4 modelview2;
|
||||
uniform highp vec2 direction;
|
||||
uniform highp float z_far;
|
||||
|
||||
#ifdef MODE_SHADOW
|
||||
out float depth;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
highp vec4 vtx = vec4(vertex, 1.0) * mat4(modelview1, modelview2, vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
|
||||
|
||||
#ifdef MODE_SHADOW
|
||||
depth = dot(direction, vtx.xy);
|
||||
#endif
|
||||
gl_Position = projection * vtx;
|
||||
}
|
||||
|
||||
#[fragment]
|
||||
|
||||
|
||||
uniform highp mat4 projection;
|
||||
uniform highp vec4 modelview1;
|
||||
uniform highp vec4 modelview2;
|
||||
uniform highp vec2 direction;
|
||||
uniform highp float z_far;
|
||||
|
||||
#ifdef MODE_SHADOW
|
||||
in highp float depth;
|
||||
#endif
|
||||
|
||||
#ifdef USE_RGBA_SHADOWS
|
||||
layout(location = 0) out lowp vec4 out_buf;
|
||||
#else
|
||||
layout(location = 0) out highp float out_buf;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
float out_depth = 1.0;
|
||||
|
||||
#ifdef MODE_SHADOW
|
||||
out_depth = depth / z_far;
|
||||
#endif
|
||||
|
||||
#ifdef USE_RGBA_SHADOWS
|
||||
out_depth = clamp(out_depth, -1.0, 1.0);
|
||||
out_depth = out_depth * 0.5 + 0.5;
|
||||
highp vec4 comp = fract(out_depth * vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0));
|
||||
comp -= comp.xxyz * vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);
|
||||
out_buf = comp;
|
||||
#else
|
||||
out_buf = out_depth;
|
||||
#endif
|
||||
}
|
205
drivers/gles3/shaders/canvas_sdf.glsl
Normal file
205
drivers/gles3/shaders/canvas_sdf.glsl
Normal file
@@ -0,0 +1,205 @@
|
||||
/* clang-format off */
|
||||
#[modes]
|
||||
|
||||
mode_load = #define MODE_LOAD
|
||||
mode_load_shrink = #define MODE_LOAD_SHRINK
|
||||
mode_process = #define MODE_PROCESS
|
||||
mode_store = #define MODE_STORE
|
||||
mode_store_shrink = #define MODE_STORE_SHRINK
|
||||
|
||||
#[specializations]
|
||||
|
||||
#[vertex]
|
||||
|
||||
layout(location = 0) in vec2 vertex_attrib;
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
uniform ivec2 size;
|
||||
uniform int stride;
|
||||
uniform int shift;
|
||||
uniform ivec2 base_size;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(vertex_attrib, 1.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#[fragment]
|
||||
|
||||
#define SDF_MAX_LENGTH 16384.0
|
||||
|
||||
#if defined(MODE_LOAD) || defined(MODE_LOAD_SHRINK)
|
||||
uniform lowp sampler2D src_pixels;//texunit:0
|
||||
#else
|
||||
uniform highp isampler2D src_process;//texunit:0
|
||||
#endif
|
||||
|
||||
uniform ivec2 size;
|
||||
uniform int stride;
|
||||
uniform int shift;
|
||||
uniform ivec2 base_size;
|
||||
|
||||
#if defined(MODE_LOAD) || defined(MODE_LOAD_SHRINK) || defined(MODE_PROCESS)
|
||||
layout(location = 0) out ivec4 distance_field;
|
||||
#else
|
||||
layout(location = 0) out vec4 distance_field;
|
||||
#endif
|
||||
|
||||
vec4 float_to_vec4(float p_float) {
|
||||
highp vec4 comp = fract(p_float * vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0));
|
||||
comp -= comp.xxyz * vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);
|
||||
return comp;
|
||||
}
|
||||
|
||||
void main() {
|
||||
ivec2 pos = ivec2(gl_FragCoord.xy);
|
||||
|
||||
#ifdef MODE_LOAD
|
||||
|
||||
bool solid = texelFetch(src_pixels, pos, 0).r > 0.5;
|
||||
distance_field = solid ? ivec4(ivec2(-32767), 0, 0) : ivec4(ivec2(32767), 0, 0);
|
||||
#endif
|
||||
|
||||
#ifdef MODE_LOAD_SHRINK
|
||||
|
||||
int s = 1 << shift;
|
||||
ivec2 base = pos << shift;
|
||||
ivec2 center = base + ivec2(shift);
|
||||
|
||||
ivec2 rel = ivec2(32767);
|
||||
float d = 1e20;
|
||||
int found = 0;
|
||||
int solid_found = 0;
|
||||
for (int i = 0; i < s; i++) {
|
||||
for (int j = 0; j < s; j++) {
|
||||
ivec2 src_pos = base + ivec2(i, j);
|
||||
if (any(greaterThanEqual(src_pos, base_size))) {
|
||||
continue;
|
||||
}
|
||||
bool solid = texelFetch(src_pixels, src_pos, 0).r > 0.5;
|
||||
if (solid) {
|
||||
float dist = length(vec2(src_pos - center));
|
||||
if (dist < d) {
|
||||
d = dist;
|
||||
rel = src_pos;
|
||||
}
|
||||
solid_found++;
|
||||
}
|
||||
found++;
|
||||
}
|
||||
}
|
||||
|
||||
if (solid_found == found) {
|
||||
//mark solid only if all are solid
|
||||
rel = ivec2(-32767);
|
||||
}
|
||||
|
||||
distance_field = ivec4(rel, 0, 0);
|
||||
#endif
|
||||
|
||||
#ifdef MODE_PROCESS
|
||||
|
||||
ivec2 base = pos << shift;
|
||||
ivec2 center = base + ivec2(shift);
|
||||
|
||||
ivec2 rel = texelFetch(src_process, pos, 0).xy;
|
||||
|
||||
bool solid = rel.x < 0;
|
||||
|
||||
if (solid) {
|
||||
rel = -rel - ivec2(1);
|
||||
}
|
||||
|
||||
if (center != rel) {
|
||||
//only process if it does not point to itself
|
||||
const int ofs_table_size = 8;
|
||||
const ivec2 ofs_table[ofs_table_size] = ivec2[](
|
||||
ivec2(-1, -1),
|
||||
ivec2(0, -1),
|
||||
ivec2(+1, -1),
|
||||
|
||||
ivec2(-1, 0),
|
||||
ivec2(+1, 0),
|
||||
|
||||
ivec2(-1, +1),
|
||||
ivec2(0, +1),
|
||||
ivec2(+1, +1));
|
||||
|
||||
float dist = length(vec2(rel - center));
|
||||
for (int i = 0; i < ofs_table_size; i++) {
|
||||
ivec2 src_pos = pos + ofs_table[i] * stride;
|
||||
if (any(lessThan(src_pos, ivec2(0))) || any(greaterThanEqual(src_pos, size))) {
|
||||
continue;
|
||||
}
|
||||
ivec2 src_rel = texelFetch(src_process, src_pos, 0).xy;
|
||||
bool src_solid = src_rel.x < 0;
|
||||
if (src_solid) {
|
||||
src_rel = -src_rel - ivec2(1);
|
||||
}
|
||||
|
||||
if (src_solid != solid) {
|
||||
src_rel = ivec2(src_pos << shift); //point to itself if of different type
|
||||
}
|
||||
|
||||
float src_dist = length(vec2(src_rel - center));
|
||||
if (src_dist < dist) {
|
||||
dist = src_dist;
|
||||
rel = src_rel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (solid) {
|
||||
rel = -rel - ivec2(1);
|
||||
}
|
||||
|
||||
distance_field = ivec4(rel, 0, 0);
|
||||
#endif
|
||||
|
||||
#ifdef MODE_STORE
|
||||
|
||||
ivec2 rel = texelFetch(src_process, pos, 0).xy;
|
||||
|
||||
bool solid = rel.x < 0;
|
||||
|
||||
if (solid) {
|
||||
rel = -rel - ivec2(1);
|
||||
}
|
||||
|
||||
float d = length(vec2(rel - pos));
|
||||
|
||||
if (solid) {
|
||||
d = -d;
|
||||
}
|
||||
|
||||
d /= SDF_MAX_LENGTH;
|
||||
d = clamp(d, -1.0, 1.0);
|
||||
distance_field = float_to_vec4(d*0.5+0.5);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_STORE_SHRINK
|
||||
|
||||
ivec2 base = pos << shift;
|
||||
ivec2 center = base + ivec2(shift);
|
||||
|
||||
ivec2 rel = texelFetch(src_process, pos, 0).xy;
|
||||
|
||||
bool solid = rel.x < 0;
|
||||
|
||||
if (solid) {
|
||||
rel = -rel - ivec2(1);
|
||||
}
|
||||
|
||||
float d = length(vec2(rel - center));
|
||||
|
||||
if (solid) {
|
||||
d = -d;
|
||||
}
|
||||
d /= SDF_MAX_LENGTH;
|
||||
d = clamp(d, -1.0, 1.0);
|
||||
distance_field = float_to_vec4(d*0.5+0.5);
|
||||
|
||||
#endif
|
||||
}
|
87
drivers/gles3/shaders/canvas_uniforms_inc.glsl
Normal file
87
drivers/gles3/shaders/canvas_uniforms_inc.glsl
Normal file
@@ -0,0 +1,87 @@
|
||||
#define MAX_LIGHTS_PER_ITEM uint(16)
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
#define SDF_MAX_LENGTH 16384.0
|
||||
|
||||
#define INSTANCE_FLAGS_LIGHT_COUNT_SHIFT 0 // 4 bits.
|
||||
|
||||
#define INSTANCE_FLAGS_CLIP_RECT_UV uint(1 << 4)
|
||||
#define INSTANCE_FLAGS_TRANSPOSE_RECT uint(1 << 5)
|
||||
#define INSTANCE_FLAGS_USE_MSDF uint(1 << 6)
|
||||
#define INSTANCE_FLAGS_USE_LCD uint(1 << 7)
|
||||
|
||||
#define INSTANCE_FLAGS_NINEPATCH_DRAW_CENTER uint(1 << 8)
|
||||
#define INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT 9
|
||||
#define INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT 11
|
||||
|
||||
#define INSTANCE_FLAGS_SHADOW_MASKED_SHIFT 13u // 16 bits.
|
||||
#define INSTANCE_FLAGS_SHADOW_MASKED uint(1 << INSTANCE_FLAGS_SHADOW_MASKED_SHIFT)
|
||||
|
||||
// 1 means enabled, 2+ means trails in use
|
||||
#define BATCH_FLAGS_INSTANCING_MASK uint(0x7F)
|
||||
#define BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT 7
|
||||
#define BATCH_FLAGS_INSTANCING_HAS_COLORS uint(1 << BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT)
|
||||
#define BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT 8
|
||||
#define BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA uint(1 << BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT)
|
||||
|
||||
#define BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED uint(1 << 9)
|
||||
#define BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED uint(1 << 10)
|
||||
|
||||
layout(std140) uniform GlobalShaderUniformData { //ubo:1
|
||||
vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
|
||||
};
|
||||
|
||||
layout(std140) uniform CanvasData { //ubo:0
|
||||
mat4 canvas_transform;
|
||||
mat4 screen_transform;
|
||||
mat4 canvas_normal_transform;
|
||||
vec4 canvas_modulation;
|
||||
vec2 screen_pixel_size;
|
||||
float time;
|
||||
bool use_pixel_snap;
|
||||
|
||||
vec4 sdf_to_tex;
|
||||
vec2 screen_to_sdf;
|
||||
vec2 sdf_to_screen;
|
||||
|
||||
uint directional_light_count;
|
||||
float tex_to_sdf;
|
||||
uint pad1;
|
||||
uint pad2;
|
||||
};
|
||||
|
||||
#ifndef DISABLE_LIGHTING
|
||||
#define LIGHT_FLAGS_BLEND_MASK uint(3 << 16)
|
||||
#define LIGHT_FLAGS_BLEND_MODE_ADD uint(0 << 16)
|
||||
#define LIGHT_FLAGS_BLEND_MODE_SUB uint(1 << 16)
|
||||
#define LIGHT_FLAGS_BLEND_MODE_MIX uint(2 << 16)
|
||||
#define LIGHT_FLAGS_BLEND_MODE_MASK uint(3 << 16)
|
||||
#define LIGHT_FLAGS_HAS_SHADOW uint(1 << 20)
|
||||
#define LIGHT_FLAGS_FILTER_SHIFT 22
|
||||
#define LIGHT_FLAGS_FILTER_MASK uint(3 << 22)
|
||||
#define LIGHT_FLAGS_SHADOW_NEAREST uint(0 << 22)
|
||||
#define LIGHT_FLAGS_SHADOW_PCF5 uint(1 << 22)
|
||||
#define LIGHT_FLAGS_SHADOW_PCF13 uint(2 << 22)
|
||||
|
||||
struct Light {
|
||||
mat2x4 texture_matrix; //light to texture coordinate matrix (transposed)
|
||||
mat2x4 shadow_matrix; //light to shadow coordinate matrix (transposed)
|
||||
vec4 color;
|
||||
|
||||
uint shadow_color; // packed
|
||||
uint flags; //index to light texture
|
||||
float shadow_pixel_size;
|
||||
float height;
|
||||
|
||||
vec2 position;
|
||||
float shadow_zfar_inv;
|
||||
float shadow_y_ofs;
|
||||
|
||||
vec4 atlas_rect;
|
||||
};
|
||||
|
||||
layout(std140) uniform LightData { //ubo:2
|
||||
Light light_array[MAX_LIGHTS];
|
||||
};
|
||||
#endif // DISABLE_LIGHTING
|
100
drivers/gles3/shaders/cube_to_dp.glsl
Normal file
100
drivers/gles3/shaders/cube_to_dp.glsl
Normal file
@@ -0,0 +1,100 @@
|
||||
/* clang-format off */
|
||||
[vertex]
|
||||
|
||||
#ifdef USE_GLES_OVER_GL
|
||||
#define lowp
|
||||
#define mediump
|
||||
#define highp
|
||||
#else
|
||||
precision mediump float;
|
||||
precision mediump int;
|
||||
#endif
|
||||
|
||||
layout(location = 0) in highp vec4 vertex_attrib;
|
||||
/* clang-format on */
|
||||
layout(location = 4) in vec2 uv_in;
|
||||
|
||||
out vec2 uv_interp;
|
||||
|
||||
void main() {
|
||||
uv_interp = uv_in;
|
||||
gl_Position = vertex_attrib;
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
[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
|
||||
|
||||
uniform highp samplerCube source_cube; //texunit:0
|
||||
/* clang-format on */
|
||||
in vec2 uv_interp;
|
||||
|
||||
uniform bool z_flip;
|
||||
uniform highp float z_far;
|
||||
uniform highp float z_near;
|
||||
uniform highp float bias;
|
||||
|
||||
void main() {
|
||||
highp vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0);
|
||||
/*
|
||||
if (z_flip) {
|
||||
normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
|
||||
} else {
|
||||
normal.z = -0.5 + 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
|
||||
}
|
||||
*/
|
||||
|
||||
//normal.z = sqrt(1.0 - dot(normal.xy, normal.xy));
|
||||
//normal.xy *= 1.0 + normal.z;
|
||||
|
||||
normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
|
||||
normal = normalize(normal);
|
||||
/*
|
||||
normal.z = 0.5;
|
||||
normal = normalize(normal);
|
||||
*/
|
||||
|
||||
if (!z_flip) {
|
||||
normal.z = -normal.z;
|
||||
}
|
||||
|
||||
//normal = normalize(vec3( uv_interp * 2.0 - 1.0, 1.0 ));
|
||||
float depth = textureCube(source_cube, normal).r;
|
||||
|
||||
// absolute values for direction cosines, bigger value equals closer to basis axis
|
||||
vec3 unorm = abs(normal);
|
||||
|
||||
if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
|
||||
// x code
|
||||
unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
|
||||
} else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
|
||||
// y code
|
||||
unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
|
||||
} else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
|
||||
// z code
|
||||
unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
|
||||
} else {
|
||||
// oh-no we messed up code
|
||||
// has to be
|
||||
unorm = vec3(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
float depth_fix = 1.0 / dot(normal, unorm);
|
||||
|
||||
depth = 2.0 * depth - 1.0;
|
||||
float linear_depth = 2.0 * z_near * z_far / (z_far + z_near + depth * (z_far - z_near));
|
||||
gl_FragDepth = (z_far - (linear_depth * depth_fix + bias)) / z_far;
|
||||
}
|
291
drivers/gles3/shaders/effect_blur.glsl
Normal file
291
drivers/gles3/shaders/effect_blur.glsl
Normal file
@@ -0,0 +1,291 @@
|
||||
/* clang-format off */
|
||||
[vertex]
|
||||
|
||||
#ifdef USE_GLES_OVER_GL
|
||||
#define lowp
|
||||
#define mediump
|
||||
#define highp
|
||||
#else
|
||||
precision highp float;
|
||||
precision highp int;
|
||||
#endif
|
||||
|
||||
layout(location = 0) in vec2 vertex_attrib;
|
||||
/* clang-format on */
|
||||
layout(location = 4) in vec2 uv_in;
|
||||
|
||||
out vec2 uv_interp;
|
||||
|
||||
#ifdef USE_BLUR_SECTION
|
||||
|
||||
uniform vec4 blur_section;
|
||||
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
uv_interp = uv_in;
|
||||
gl_Position = vec4(vertex_attrib, 0.0, 1.0);
|
||||
#ifdef USE_BLUR_SECTION
|
||||
|
||||
uv_interp = blur_section.xy + uv_interp * blur_section.zw;
|
||||
gl_Position.xy = (blur_section.xy + (gl_Position.xy * 0.5 + 0.5) * blur_section.zw) * 2.0 - 1.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
[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
|
||||
|
||||
in vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
uniform sampler2D source_color; //texunit:0
|
||||
|
||||
uniform float lod;
|
||||
uniform vec2 pixel_size;
|
||||
|
||||
#if defined(GLOW_GAUSSIAN_HORIZONTAL) || defined(GLOW_GAUSSIAN_VERTICAL)
|
||||
|
||||
uniform float glow_strength;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(DOF_FAR_BLUR) || defined(DOF_NEAR_BLUR)
|
||||
|
||||
#ifdef USE_GLES_OVER_GL
|
||||
#ifdef DOF_QUALITY_LOW
|
||||
const int dof_kernel_size = 5;
|
||||
const int dof_kernel_from = 2;
|
||||
const float dof_kernel[5] = float[](0.153388, 0.221461, 0.250301, 0.221461, 0.153388);
|
||||
#endif
|
||||
|
||||
#ifdef DOF_QUALITY_MEDIUM
|
||||
const int dof_kernel_size = 11;
|
||||
const int dof_kernel_from = 5;
|
||||
const float dof_kernel[11] = float[](0.055037, 0.072806, 0.090506, 0.105726, 0.116061, 0.119726, 0.116061, 0.105726, 0.090506, 0.072806, 0.055037);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef DOF_QUALITY_HIGH
|
||||
const int dof_kernel_size = 21;
|
||||
const int dof_kernel_from = 10;
|
||||
const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.046421, 0.050582, 0.054261, 0.057307, 0.059587, 0.060998, 0.061476, 0.060998, 0.059587, 0.057307, 0.054261, 0.050582, 0.046421, 0.041944, 0.037311, 0.032676, 0.028174);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uniform sampler2D dof_source_depth; //texunit:1
|
||||
uniform float dof_begin;
|
||||
uniform float dof_end;
|
||||
uniform vec2 dof_dir;
|
||||
uniform float dof_radius;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef GLOW_FIRST_PASS
|
||||
|
||||
uniform highp float luminance_cap;
|
||||
|
||||
uniform float glow_bloom;
|
||||
uniform float glow_hdr_threshold;
|
||||
uniform float glow_hdr_scale;
|
||||
|
||||
#endif
|
||||
|
||||
uniform float camera_z_far;
|
||||
uniform float camera_z_near;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
void main() {
|
||||
#ifdef GLOW_GAUSSIAN_HORIZONTAL
|
||||
vec2 pix_size = pixel_size;
|
||||
pix_size *= 0.5; //reading from larger buffer, so use more samples
|
||||
vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pix_size, lod) * 0.174938;
|
||||
color += textureLod(source_color, uv_interp + vec2(1.0, 0.0) * pix_size, lod) * 0.165569;
|
||||
color += textureLod(source_color, uv_interp + vec2(2.0, 0.0) * pix_size, lod) * 0.140367;
|
||||
color += textureLod(source_color, uv_interp + vec2(3.0, 0.0) * pix_size, lod) * 0.106595;
|
||||
color += textureLod(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size, lod) * 0.165569;
|
||||
color += textureLod(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size, lod) * 0.140367;
|
||||
color += textureLod(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size, lod) * 0.106595;
|
||||
color *= glow_strength;
|
||||
frag_color = color;
|
||||
#endif
|
||||
|
||||
#ifdef GLOW_GAUSSIAN_VERTICAL
|
||||
vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pixel_size, lod) * 0.288713;
|
||||
color += textureLod(source_color, uv_interp + vec2(0.0, 1.0) * pixel_size, lod) * 0.233062;
|
||||
color += textureLod(source_color, uv_interp + vec2(0.0, 2.0) * pixel_size, lod) * 0.122581;
|
||||
color += textureLod(source_color, uv_interp + vec2(0.0, -1.0) * pixel_size, lod) * 0.233062;
|
||||
color += textureLod(source_color, uv_interp + vec2(0.0, -2.0) * pixel_size, lod) * 0.122581;
|
||||
color *= glow_strength;
|
||||
frag_color = color;
|
||||
#endif
|
||||
|
||||
#ifndef USE_GLES_OVER_GL
|
||||
#if defined(DOF_FAR_BLUR) || defined(DOF_NEAR_BLUR)
|
||||
|
||||
#ifdef DOF_QUALITY_LOW
|
||||
const int dof_kernel_size = 5;
|
||||
const int dof_kernel_from = 2;
|
||||
float dof_kernel[5];
|
||||
dof_kernel[0] = 0.153388;
|
||||
dof_kernel[1] = 0.221461;
|
||||
dof_kernel[2] = 0.250301;
|
||||
dof_kernel[3] = 0.221461;
|
||||
dof_kernel[4] = 0.153388;
|
||||
#endif
|
||||
|
||||
#ifdef DOF_QUALITY_MEDIUM
|
||||
const int dof_kernel_size = 11;
|
||||
const int dof_kernel_from = 5;
|
||||
float dof_kernel[11];
|
||||
dof_kernel[0] = 0.055037;
|
||||
dof_kernel[1] = 0.072806;
|
||||
dof_kernel[2] = 0.090506;
|
||||
dof_kernel[3] = 0.105726;
|
||||
dof_kernel[4] = 0.116061;
|
||||
dof_kernel[5] = 0.119726;
|
||||
dof_kernel[6] = 0.116061;
|
||||
dof_kernel[7] = 0.105726;
|
||||
dof_kernel[8] = 0.090506;
|
||||
dof_kernel[9] = 0.072806;
|
||||
dof_kernel[10] = 0.055037;
|
||||
#endif
|
||||
|
||||
#ifdef DOF_QUALITY_HIGH
|
||||
const int dof_kernel_size = 21;
|
||||
const int dof_kernel_from = 10;
|
||||
float dof_kernel[21];
|
||||
dof_kernel[0] = 0.028174;
|
||||
dof_kernel[1] = 0.032676;
|
||||
dof_kernel[2] = 0.037311;
|
||||
dof_kernel[3] = 0.041944;
|
||||
dof_kernel[4] = 0.046421;
|
||||
dof_kernel[5] = 0.050582;
|
||||
dof_kernel[6] = 0.054261;
|
||||
dof_kernel[7] = 0.057307;
|
||||
dof_kernel[8] = 0.059587;
|
||||
dof_kernel[9] = 0.060998;
|
||||
dof_kernel[10] = 0.061476;
|
||||
dof_kernel[11] = 0.060998;
|
||||
dof_kernel[12] = 0.059587;
|
||||
dof_kernel[13] = 0.057307;
|
||||
dof_kernel[14] = 0.054261;
|
||||
dof_kernel[15] = 0.050582;
|
||||
dof_kernel[16] = 0.046421;
|
||||
dof_kernel[17] = 0.041944;
|
||||
dof_kernel[18] = 0.037311;
|
||||
dof_kernel[19] = 0.032676;
|
||||
dof_kernel[20] = 0.028174;
|
||||
#endif
|
||||
#endif
|
||||
#endif //!USE_GLES_OVER_GL
|
||||
|
||||
#ifdef DOF_FAR_BLUR
|
||||
|
||||
vec4 color_accum = vec4(0.0);
|
||||
|
||||
float depth = textureLod(dof_source_depth, uv_interp, 0.0).r;
|
||||
depth = depth * 2.0 - 1.0;
|
||||
#ifdef USE_ORTHOGONAL_PROJECTION
|
||||
depth = ((depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
|
||||
#else
|
||||
depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
|
||||
#endif
|
||||
|
||||
float amount = smoothstep(dof_begin, dof_end, depth);
|
||||
float k_accum = 0.0;
|
||||
|
||||
for (int i = 0; i < dof_kernel_size; i++) {
|
||||
int int_ofs = i - dof_kernel_from;
|
||||
vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * amount * dof_radius;
|
||||
|
||||
float tap_k = dof_kernel[i];
|
||||
|
||||
float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
|
||||
tap_depth = tap_depth * 2.0 - 1.0;
|
||||
#ifdef USE_ORTHOGONAL_PROJECTION
|
||||
tap_depth = ((tap_depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
|
||||
#else
|
||||
tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
|
||||
#endif
|
||||
float tap_amount = int_ofs == 0 ? 1.0 : smoothstep(dof_begin, dof_end, tap_depth);
|
||||
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
|
||||
|
||||
vec4 tap_color = textureLod(source_color, tap_uv, 0.0) * tap_k;
|
||||
|
||||
k_accum += tap_k * tap_amount;
|
||||
color_accum += tap_color * tap_amount;
|
||||
}
|
||||
|
||||
if (k_accum > 0.0) {
|
||||
color_accum /= k_accum;
|
||||
}
|
||||
|
||||
frag_color = color_accum; ///k_accum;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef DOF_NEAR_BLUR
|
||||
|
||||
vec4 color_accum = vec4(0.0);
|
||||
|
||||
float max_accum = 0.0;
|
||||
|
||||
for (int i = 0; i < dof_kernel_size; i++) {
|
||||
int int_ofs = i - dof_kernel_from;
|
||||
vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * dof_radius;
|
||||
float ofs_influence = max(0.0, 1.0 - abs(float(int_ofs)) / float(dof_kernel_from));
|
||||
|
||||
float tap_k = dof_kernel[i];
|
||||
|
||||
vec4 tap_color = textureLod(source_color, tap_uv, 0.0);
|
||||
|
||||
float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
|
||||
tap_depth = tap_depth * 2.0 - 1.0;
|
||||
#ifdef USE_ORTHOGONAL_PROJECTION
|
||||
tap_depth = ((tap_depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
|
||||
#else
|
||||
tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
|
||||
#endif
|
||||
float tap_amount = 1.0 - smoothstep(dof_end, dof_begin, tap_depth);
|
||||
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
|
||||
|
||||
#ifdef DOF_NEAR_FIRST_TAP
|
||||
|
||||
tap_color.a = 1.0 - smoothstep(dof_end, dof_begin, tap_depth);
|
||||
|
||||
#endif
|
||||
|
||||
max_accum = max(max_accum, tap_amount * ofs_influence);
|
||||
|
||||
color_accum += tap_color * tap_k;
|
||||
}
|
||||
|
||||
color_accum.a = max(color_accum.a, sqrt(max_accum));
|
||||
|
||||
frag_color = color_accum;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef GLOW_FIRST_PASS
|
||||
|
||||
float luminance = max(frag_color.r, max(frag_color.g, frag_color.b));
|
||||
float feedback = max(smoothstep(glow_hdr_threshold, glow_hdr_threshold + glow_hdr_scale, luminance), glow_bloom);
|
||||
|
||||
frag_color = min(frag_color * feedback, vec4(luminance_cap));
|
||||
|
||||
#endif
|
||||
}
|
18
drivers/gles3/shaders/effects/SCsub
Normal file
18
drivers/gles3/shaders/effects/SCsub
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
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 + ["#gles3_builders.py"])
|
||||
|
||||
# compile shaders
|
||||
for glsl_file in glsl_files:
|
||||
env.GLES3_GLSL(glsl_file)
|
234
drivers/gles3/shaders/effects/copy.glsl
Normal file
234
drivers/gles3/shaders/effects/copy.glsl
Normal file
@@ -0,0 +1,234 @@
|
||||
/* clang-format off */
|
||||
#[modes]
|
||||
|
||||
mode_default = #define MODE_SIMPLE_COPY
|
||||
mode_copy_section = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY
|
||||
mode_copy_section_source = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY \n#define MODE_COPY_FROM
|
||||
mode_copy_section_3d = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY \n#define USE_TEXTURE_3D
|
||||
mode_copy_section_2d_array = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY \n#define USE_TEXTURE_2D_ARRAY
|
||||
mode_lens_distortion = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY \n#define USE_TEXTURE_2D_ARRAY \n#define APPLY_LENS_DISTORTION
|
||||
mode_screen = #define MODE_SIMPLE_COPY \n#define MODE_MULTIPLY
|
||||
mode_gaussian_blur = #define MODE_GAUSSIAN_BLUR
|
||||
mode_mipmap = #define MODE_MIPMAP
|
||||
mode_simple_color = #define MODE_SIMPLE_COLOR \n#define USE_COPY_SECTION
|
||||
mode_cube_to_octahedral = #define CUBE_TO_OCTAHEDRAL \n#define USE_COPY_SECTION
|
||||
mode_cube_to_panorama = #define CUBE_TO_PANORAMA
|
||||
|
||||
#[specializations]
|
||||
|
||||
CONVERT_LINEAR_TO_SRGB = false
|
||||
|
||||
#[vertex]
|
||||
|
||||
layout(location = 0) in vec2 vertex_attrib;
|
||||
|
||||
out vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
#if defined(USE_COPY_SECTION) || defined(MODE_GAUSSIAN_BLUR)
|
||||
// Defined in 0-1 coords.
|
||||
uniform highp vec4 copy_section;
|
||||
#endif
|
||||
#if defined(MODE_GAUSSIAN_BLUR) || defined(MODE_COPY_FROM)
|
||||
uniform highp vec4 source_section;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
uv_interp = vertex_attrib * 0.5 + 0.5;
|
||||
gl_Position = vec4(vertex_attrib, 1.0, 1.0);
|
||||
|
||||
#if defined(USE_COPY_SECTION) || defined(MODE_GAUSSIAN_BLUR)
|
||||
gl_Position.xy = (copy_section.xy + uv_interp.xy * copy_section.zw) * 2.0 - 1.0;
|
||||
#endif
|
||||
#if defined(MODE_GAUSSIAN_BLUR) || defined(MODE_COPY_FROM)
|
||||
uv_interp = source_section.xy + uv_interp * source_section.zw;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#[fragment]
|
||||
|
||||
in vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
#if defined(USE_TEXTURE_3D) || defined(USE_TEXTURE_2D_ARRAY)
|
||||
uniform float layer;
|
||||
uniform float lod;
|
||||
#endif
|
||||
|
||||
#ifdef MODE_SIMPLE_COLOR
|
||||
uniform vec4 color_in;
|
||||
#endif
|
||||
|
||||
#ifdef MODE_MULTIPLY
|
||||
uniform float multiply;
|
||||
#endif
|
||||
|
||||
#ifdef MODE_GAUSSIAN_BLUR
|
||||
// Defined in 0-1 coords.
|
||||
uniform highp vec2 pixel_size;
|
||||
#endif
|
||||
|
||||
#ifdef CUBE_TO_OCTAHEDRAL
|
||||
vec3 oct_to_vec3(vec2 e) {
|
||||
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
|
||||
float t = max(-v.z, 0.0);
|
||||
v.xy += t * -sign(v.xy);
|
||||
return normalize(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CUBE_TO_PANORAMA
|
||||
uniform lowp float mip_level;
|
||||
#endif
|
||||
|
||||
#if defined(CUBE_TO_OCTAHEDRAL) || defined(CUBE_TO_PANORAMA)
|
||||
uniform samplerCube source_cube; // texunit:0
|
||||
|
||||
#else // ~(defined(CUBE_TO_OCTAHEDRAL) || defined(CUBE_TO_PANORAMA))
|
||||
|
||||
#if defined(USE_TEXTURE_3D)
|
||||
uniform sampler3D source_3d; // texunit:0
|
||||
#elif defined(USE_TEXTURE_2D_ARRAY)
|
||||
uniform sampler2DArray source_2d_array; // texunit:0
|
||||
#else
|
||||
uniform sampler2D source; // texunit:0
|
||||
#endif
|
||||
|
||||
#endif // !(defined(CUBE_TO_OCTAHEDRAL) || defined(CUBE_TO_PANORAMA))
|
||||
|
||||
#ifdef APPLY_LENS_DISTORTION
|
||||
uniform vec2 eye_center;
|
||||
uniform float k1;
|
||||
uniform float k2;
|
||||
uniform float upscale;
|
||||
uniform float aspect_ratio;
|
||||
#endif // APPLY_LENS_DISTORTION
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// This expects 0-1 range input.
|
||||
vec3 linear_to_srgb(vec3 color) {
|
||||
// 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));
|
||||
}
|
||||
|
||||
void main() {
|
||||
#ifdef MODE_SIMPLE_COPY
|
||||
|
||||
vec2 uv = uv_interp;
|
||||
|
||||
#ifdef APPLY_LENS_DISTORTION
|
||||
uv = uv * 2.0 - 1.0;
|
||||
vec2 offset = uv - eye_center;
|
||||
|
||||
// take aspect ratio into account
|
||||
offset.y /= aspect_ratio;
|
||||
|
||||
// distort
|
||||
vec2 offset_sq = offset * offset;
|
||||
float radius_sq = offset_sq.x + offset_sq.y;
|
||||
float radius_s4 = radius_sq * radius_sq;
|
||||
float distortion_scale = 1.0 + (k1 * radius_sq) + (k2 * radius_s4);
|
||||
offset *= distortion_scale;
|
||||
|
||||
// reapply aspect ratio
|
||||
offset.y *= aspect_ratio;
|
||||
|
||||
// add our eye center back in
|
||||
uv = offset + eye_center;
|
||||
uv /= upscale;
|
||||
|
||||
// and check our color
|
||||
if (uv.x < -1.0 || uv.y < -1.0 || uv.x > 1.0 || uv.y > 1.0) {
|
||||
frag_color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
} else {
|
||||
uv = uv * 0.5 + 0.5;
|
||||
#endif // APPLY_LENS_DISTORTION
|
||||
|
||||
#ifdef USE_TEXTURE_3D
|
||||
vec4 color = textureLod(source_3d, vec3(uv, layer), lod);
|
||||
#elif defined(USE_TEXTURE_2D_ARRAY)
|
||||
vec4 color = textureLod(source_2d_array, vec3(uv, layer), lod);
|
||||
#else
|
||||
vec4 color = texture(source, uv);
|
||||
#endif // USE_TEXTURE_3D
|
||||
|
||||
#ifdef CONVERT_LINEAR_TO_SRGB
|
||||
// Reading from a *_SRGB texture source will have converted data to linear,
|
||||
// but we should output in sRGB!
|
||||
color.rgb = linear_to_srgb(color.rgb);
|
||||
#endif
|
||||
|
||||
#ifdef MODE_MULTIPLY
|
||||
color *= multiply;
|
||||
#endif // MODE_MULTIPLY
|
||||
|
||||
frag_color = color;
|
||||
|
||||
#ifdef APPLY_LENS_DISTORTION
|
||||
}
|
||||
#endif // APPLY_LENS_DISTORTION
|
||||
|
||||
#endif // MODE_SIMPLE_COPY
|
||||
|
||||
#ifdef MODE_SIMPLE_COLOR
|
||||
frag_color = color_in;
|
||||
#endif
|
||||
|
||||
// Efficient box filter from Jimenez: http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
|
||||
// Approximates a Gaussian in a single pass.
|
||||
#ifdef MODE_GAUSSIAN_BLUR
|
||||
vec4 A = textureLod(source, uv_interp + pixel_size * vec2(-1.0, -1.0), 0.0);
|
||||
vec4 B = textureLod(source, uv_interp + pixel_size * vec2(0.0, -1.0), 0.0);
|
||||
vec4 C = textureLod(source, uv_interp + pixel_size * vec2(1.0, -1.0), 0.0);
|
||||
vec4 D = textureLod(source, uv_interp + pixel_size * vec2(-0.5, -0.5), 0.0);
|
||||
vec4 E = textureLod(source, uv_interp + pixel_size * vec2(0.5, -0.5), 0.0);
|
||||
vec4 F = textureLod(source, uv_interp + pixel_size * vec2(-1.0, 0.0), 0.0);
|
||||
vec4 G = textureLod(source, uv_interp, 0.0);
|
||||
vec4 H = textureLod(source, uv_interp + pixel_size * vec2(1.0, 0.0), 0.0);
|
||||
vec4 I = textureLod(source, uv_interp + pixel_size * vec2(-0.5, 0.5), 0.0);
|
||||
vec4 J = textureLod(source, uv_interp + pixel_size * vec2(0.5, 0.5), 0.0);
|
||||
vec4 K = textureLod(source, uv_interp + pixel_size * vec2(-1.0, 1.0), 0.0);
|
||||
vec4 L = textureLod(source, uv_interp + pixel_size * vec2(0.0, 1.0), 0.0);
|
||||
vec4 M = textureLod(source, uv_interp + pixel_size * vec2(1.0, 1.0), 0.0);
|
||||
|
||||
float weight = 0.5 / 4.0;
|
||||
float lesser_weight = 0.125 / 4.0;
|
||||
|
||||
frag_color = (D + E + I + J) * weight;
|
||||
frag_color += (A + B + G + F) * lesser_weight;
|
||||
frag_color += (B + C + H + G) * lesser_weight;
|
||||
frag_color += (F + G + L + K) * lesser_weight;
|
||||
frag_color += (G + H + M + L) * lesser_weight;
|
||||
#endif
|
||||
|
||||
#ifdef CUBE_TO_OCTAHEDRAL
|
||||
// Treat the UV coordinates as 0-1 encoded octahedral coordinates.
|
||||
vec3 dir = oct_to_vec3(uv_interp * 2.0 - 1.0);
|
||||
frag_color = texture(source_cube, dir);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CUBE_TO_PANORAMA
|
||||
|
||||
const float PI = 3.14159265359;
|
||||
|
||||
float phi = uv_interp.x * 2.0 * PI;
|
||||
float theta = uv_interp.y * PI;
|
||||
|
||||
vec3 normal;
|
||||
normal.x = sin(phi) * sin(theta) * -1.0;
|
||||
normal.y = cos(theta);
|
||||
normal.z = cos(phi) * sin(theta) * -1.0;
|
||||
|
||||
vec3 color = srgb_to_linear(textureLod(source_cube, normal, mip_level).rgb);
|
||||
frag_color = vec4(color, 1.0);
|
||||
|
||||
#endif
|
||||
}
|
122
drivers/gles3/shaders/effects/cubemap_filter.glsl
Normal file
122
drivers/gles3/shaders/effects/cubemap_filter.glsl
Normal file
@@ -0,0 +1,122 @@
|
||||
/* clang-format off */
|
||||
#[modes]
|
||||
|
||||
mode_default =
|
||||
mode_copy = #define MODE_DIRECT_WRITE
|
||||
|
||||
#[specializations]
|
||||
|
||||
#[vertex]
|
||||
|
||||
layout(location = 0) in highp vec2 vertex_attrib;
|
||||
/* clang-format on */
|
||||
|
||||
out highp vec2 uv_interp;
|
||||
|
||||
void main() {
|
||||
uv_interp = vertex_attrib;
|
||||
gl_Position = vec4(uv_interp, 0.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#[fragment]
|
||||
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
uniform samplerCube source_cube; //texunit:0
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
uniform int face_id;
|
||||
|
||||
#ifndef MODE_DIRECT_WRITE
|
||||
uniform uint sample_count;
|
||||
uniform vec4 sample_directions_mip[MAX_SAMPLE_COUNT];
|
||||
uniform float weight;
|
||||
#endif
|
||||
|
||||
in highp vec2 uv_interp;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
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[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[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[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[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[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[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 = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
|
||||
return normalize(result);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 color = vec3(0.0);
|
||||
vec2 uv = uv_interp;
|
||||
vec3 N = texelCoordToVec(uv, face_id);
|
||||
|
||||
#ifdef MODE_DIRECT_WRITE
|
||||
frag_color = vec4(textureLod(source_cube, N, 0.0).rgb, 1.0);
|
||||
#else
|
||||
|
||||
vec4 sum = vec4(0.0);
|
||||
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 (uint sample_num = 0u; sample_num < sample_count; sample_num++) {
|
||||
vec4 sample_direction_mip = sample_directions_mip[sample_num];
|
||||
vec3 L = T * sample_direction_mip.xyz;
|
||||
vec3 val = textureLod(source_cube, L, sample_direction_mip.w).rgb;
|
||||
// Mix using linear
|
||||
val = srgb_to_linear(val);
|
||||
sum.rgb += val * sample_direction_mip.z;
|
||||
}
|
||||
|
||||
sum /= weight;
|
||||
|
||||
sum.rgb = linear_to_srgb(sum.rgb);
|
||||
frag_color = vec4(sum.rgb, 1.0);
|
||||
#endif
|
||||
}
|
113
drivers/gles3/shaders/effects/glow.glsl
Normal file
113
drivers/gles3/shaders/effects/glow.glsl
Normal file
@@ -0,0 +1,113 @@
|
||||
/* clang-format off */
|
||||
#[modes]
|
||||
|
||||
// Based on Dual filtering glow as explained in Marius Bjørge presentation at Siggraph 2015 "Bandwidth-Efficient Rendering"
|
||||
|
||||
mode_filter = #define MODE_FILTER
|
||||
mode_downsample = #define MODE_DOWNSAMPLE
|
||||
mode_upsample = #define MODE_UPSAMPLE
|
||||
|
||||
#[specializations]
|
||||
|
||||
USE_MULTIVIEW = false
|
||||
|
||||
#[vertex]
|
||||
layout(location = 0) in vec2 vertex_attrib;
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
out vec2 uv_interp;
|
||||
|
||||
void main() {
|
||||
uv_interp = vertex_attrib * 0.5 + 0.5;
|
||||
gl_Position = vec4(vertex_attrib, 1.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#[fragment]
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef MODE_FILTER
|
||||
#ifdef USE_MULTIVIEW
|
||||
uniform sampler2DArray source_color; // texunit:0
|
||||
#else
|
||||
uniform sampler2D source_color; // texunit:0
|
||||
#endif // USE_MULTIVIEW
|
||||
uniform float view;
|
||||
uniform vec2 pixel_size;
|
||||
uniform float luminance_multiplier;
|
||||
uniform float glow_bloom;
|
||||
uniform float glow_hdr_threshold;
|
||||
uniform float glow_hdr_scale;
|
||||
uniform float glow_luminance_cap;
|
||||
#endif // MODE_FILTER
|
||||
|
||||
#ifdef MODE_DOWNSAMPLE
|
||||
uniform sampler2D source_color; // texunit:0
|
||||
uniform vec2 pixel_size;
|
||||
#endif // MODE_DOWNSAMPLE
|
||||
|
||||
#ifdef MODE_UPSAMPLE
|
||||
uniform sampler2D source_color; // texunit:0
|
||||
uniform vec2 pixel_size;
|
||||
#endif // MODE_UPSAMPLE
|
||||
|
||||
in vec2 uv_interp;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
void main() {
|
||||
#ifdef MODE_FILTER
|
||||
// Note, we read from an image with double resolution, so we average those out
|
||||
#ifdef USE_MULTIVIEW
|
||||
vec2 half_pixel = pixel_size * 0.5;
|
||||
vec3 uv = vec3(uv_interp, view);
|
||||
vec3 color = textureLod(source_color, uv, 0.0).rgb * 4.0;
|
||||
color += textureLod(source_color, uv - vec3(half_pixel, 0.0), 0.0).rgb;
|
||||
color += textureLod(source_color, uv + vec3(half_pixel, 0.0), 0.0).rgb;
|
||||
color += textureLod(source_color, uv - vec3(half_pixel.x, -half_pixel.y, 0.0), 0.0).rgb;
|
||||
color += textureLod(source_color, uv + vec3(half_pixel.x, -half_pixel.y, 0.0), 0.0).rgb;
|
||||
#else
|
||||
vec2 half_pixel = pixel_size * 0.5;
|
||||
vec2 uv = uv_interp;
|
||||
vec3 color = textureLod(source_color, uv, 0.0).rgb * 4.0;
|
||||
color += textureLod(source_color, uv - half_pixel, 0.0).rgb;
|
||||
color += textureLod(source_color, uv + half_pixel, 0.0).rgb;
|
||||
color += textureLod(source_color, uv - vec2(half_pixel.x, -half_pixel.y), 0.0).rgb;
|
||||
color += textureLod(source_color, uv + vec2(half_pixel.x, -half_pixel.y), 0.0).rgb;
|
||||
#endif // USE_MULTIVIEW
|
||||
color /= luminance_multiplier * 8.0;
|
||||
|
||||
float feedback_factor = max(color.r, max(color.g, color.b));
|
||||
float feedback = max(smoothstep(glow_hdr_threshold, glow_hdr_threshold + glow_hdr_scale, feedback_factor), glow_bloom);
|
||||
|
||||
color = min(color * feedback, vec3(glow_luminance_cap));
|
||||
|
||||
frag_color = vec4(luminance_multiplier * color, 1.0);
|
||||
#endif // MODE_FILTER
|
||||
|
||||
#ifdef MODE_DOWNSAMPLE
|
||||
vec2 half_pixel = pixel_size * 0.5;
|
||||
vec4 color = textureLod(source_color, uv_interp, 0.0) * 4.0;
|
||||
color += textureLod(source_color, uv_interp - half_pixel, 0.0);
|
||||
color += textureLod(source_color, uv_interp + half_pixel, 0.0);
|
||||
color += textureLod(source_color, uv_interp - vec2(half_pixel.x, -half_pixel.y), 0.0);
|
||||
color += textureLod(source_color, uv_interp + vec2(half_pixel.x, -half_pixel.y), 0.0);
|
||||
frag_color = color / 8.0;
|
||||
#endif // MODE_DOWNSAMPLE
|
||||
|
||||
#ifdef MODE_UPSAMPLE
|
||||
vec2 half_pixel = pixel_size * 0.5;
|
||||
|
||||
vec4 color = textureLod(source_color, uv_interp + vec2(-half_pixel.x * 2.0, 0.0), 0.0);
|
||||
color += textureLod(source_color, uv_interp + vec2(-half_pixel.x, half_pixel.y), 0.0) * 2.0;
|
||||
color += textureLod(source_color, uv_interp + vec2(0.0, half_pixel.y * 2.0), 0.0);
|
||||
color += textureLod(source_color, uv_interp + vec2(half_pixel.x, half_pixel.y), 0.0) * 2.0;
|
||||
color += textureLod(source_color, uv_interp + vec2(half_pixel.x * 2.0, 0.0), 0.0);
|
||||
color += textureLod(source_color, uv_interp + vec2(half_pixel.x, -half_pixel.y), 0.0) * 2.0;
|
||||
color += textureLod(source_color, uv_interp + vec2(0.0, -half_pixel.y * 2.0), 0.0);
|
||||
color += textureLod(source_color, uv_interp + vec2(-half_pixel.x, -half_pixel.y), 0.0) * 2.0;
|
||||
|
||||
frag_color = color / 12.0;
|
||||
#endif // MODE_UPSAMPLE
|
||||
}
|
130
drivers/gles3/shaders/effects/post.glsl
Normal file
130
drivers/gles3/shaders/effects/post.glsl
Normal file
@@ -0,0 +1,130 @@
|
||||
/* clang-format off */
|
||||
#[modes]
|
||||
mode_default =
|
||||
|
||||
#[specializations]
|
||||
|
||||
USE_MULTIVIEW = false
|
||||
USE_GLOW = false
|
||||
USE_LUMINANCE_MULTIPLIER = false
|
||||
USE_BCS = false
|
||||
USE_COLOR_CORRECTION = false
|
||||
USE_1D_LUT = false
|
||||
|
||||
#[vertex]
|
||||
layout(location = 0) in vec2 vertex_attrib;
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
out vec2 uv_interp;
|
||||
|
||||
void main() {
|
||||
uv_interp = vertex_attrib * 0.5 + 0.5;
|
||||
gl_Position = vec4(vertex_attrib, 1.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#[fragment]
|
||||
/* clang-format on */
|
||||
|
||||
// If we reach this code, we always tonemap.
|
||||
#define APPLY_TONEMAPPING
|
||||
|
||||
#include "../tonemap_inc.glsl"
|
||||
|
||||
#ifdef USE_MULTIVIEW
|
||||
uniform sampler2DArray source_color; // texunit:0
|
||||
#else
|
||||
uniform sampler2D source_color; // texunit:0
|
||||
#endif // USE_MULTIVIEW
|
||||
|
||||
uniform float view;
|
||||
uniform float luminance_multiplier;
|
||||
|
||||
#ifdef USE_GLOW
|
||||
uniform sampler2D glow_color; // texunit:1
|
||||
uniform vec2 pixel_size;
|
||||
uniform float glow_intensity;
|
||||
|
||||
vec4 get_glow_color(vec2 uv) {
|
||||
vec2 half_pixel = pixel_size * 0.5;
|
||||
|
||||
vec4 color = textureLod(glow_color, uv + vec2(-half_pixel.x * 2.0, 0.0), 0.0);
|
||||
color += textureLod(glow_color, uv + vec2(-half_pixel.x, half_pixel.y), 0.0) * 2.0;
|
||||
color += textureLod(glow_color, uv + vec2(0.0, half_pixel.y * 2.0), 0.0);
|
||||
color += textureLod(glow_color, uv + vec2(half_pixel.x, half_pixel.y), 0.0) * 2.0;
|
||||
color += textureLod(glow_color, uv + vec2(half_pixel.x * 2.0, 0.0), 0.0);
|
||||
color += textureLod(glow_color, uv + vec2(half_pixel.x, -half_pixel.y), 0.0) * 2.0;
|
||||
color += textureLod(glow_color, uv + vec2(0.0, -half_pixel.y * 2.0), 0.0);
|
||||
color += textureLod(glow_color, uv + vec2(-half_pixel.x, -half_pixel.y), 0.0) * 2.0;
|
||||
|
||||
return color / 12.0;
|
||||
}
|
||||
#endif // USE_GLOW
|
||||
|
||||
#ifdef USE_COLOR_CORRECTION
|
||||
#ifdef USE_1D_LUT
|
||||
uniform sampler2D source_color_correction; //texunit:2
|
||||
|
||||
vec3 apply_color_correction(vec3 color) {
|
||||
color.r = texture(source_color_correction, vec2(color.r, 0.0f)).r;
|
||||
color.g = texture(source_color_correction, vec2(color.g, 0.0f)).g;
|
||||
color.b = texture(source_color_correction, vec2(color.b, 0.0f)).b;
|
||||
return color;
|
||||
}
|
||||
#else
|
||||
uniform sampler3D source_color_correction; //texunit:2
|
||||
|
||||
vec3 apply_color_correction(vec3 color) {
|
||||
return textureLod(source_color_correction, color, 0.0).rgb;
|
||||
}
|
||||
#endif // USE_1D_LUT
|
||||
#endif // USE_COLOR_CORRECTION
|
||||
|
||||
#ifdef USE_BCS
|
||||
vec3 apply_bcs(vec3 color) {
|
||||
color = mix(vec3(0.0), color, brightness);
|
||||
color = mix(vec3(0.5), color, contrast);
|
||||
color = mix(vec3(dot(vec3(1.0), color) * 0.33333), color, saturation);
|
||||
|
||||
return color;
|
||||
}
|
||||
#endif
|
||||
|
||||
in vec2 uv_interp;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
void main() {
|
||||
#ifdef USE_MULTIVIEW
|
||||
vec4 color = texture(source_color, vec3(uv_interp, view));
|
||||
#else
|
||||
vec4 color = texture(source_color, uv_interp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_GLOW
|
||||
vec4 glow = get_glow_color(uv_interp) * glow_intensity;
|
||||
|
||||
// Just use softlight...
|
||||
glow.rgb = clamp(glow.rgb, vec3(0.0f), vec3(1.0f));
|
||||
color.rgb = max((color.rgb + glow.rgb) - (color.rgb * glow.rgb), vec3(0.0));
|
||||
#endif // USE_GLOW
|
||||
|
||||
#ifdef USE_LUMINANCE_MULTIPLIER
|
||||
color = color / luminance_multiplier;
|
||||
#endif
|
||||
|
||||
color.rgb = srgb_to_linear(color.rgb);
|
||||
color.rgb = apply_tonemapping(color.rgb, white);
|
||||
color.rgb = linear_to_srgb(color.rgb);
|
||||
|
||||
#ifdef USE_BCS
|
||||
color.rgb = apply_bcs(color.rgb);
|
||||
#endif
|
||||
|
||||
#ifdef USE_COLOR_CORRECTION
|
||||
color.rgb = apply_color_correction(color.rgb);
|
||||
#endif
|
||||
|
||||
frag_color = color;
|
||||
}
|
39
drivers/gles3/shaders/feed.glsl
Normal file
39
drivers/gles3/shaders/feed.glsl
Normal file
@@ -0,0 +1,39 @@
|
||||
/* clang-format off */
|
||||
#[modes]
|
||||
|
||||
mode_default =
|
||||
|
||||
#[specializations]
|
||||
|
||||
USE_EXTERNAL_SAMPLER = false
|
||||
|
||||
#[vertex]
|
||||
|
||||
layout(location = 0) in vec2 vertex_attrib;
|
||||
|
||||
out vec2 uv_interp;
|
||||
|
||||
|
||||
void main() {
|
||||
uv_interp = vertex_attrib * 0.5 + 0.5;
|
||||
gl_Position = vec4(vertex_attrib, 1.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#[fragment]
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
in vec2 uv_interp;
|
||||
|
||||
/* clang-format on */
|
||||
#ifdef USE_EXTERNAL_SAMPLER
|
||||
uniform samplerExternalOES sourceFeed; // texunit:0
|
||||
#else
|
||||
uniform sampler2D sourceFeed; // texunit:0
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
vec4 color = texture(sourceFeed, uv_interp);
|
||||
|
||||
frag_color = color;
|
||||
}
|
86
drivers/gles3/shaders/lens_distorted.glsl
Normal file
86
drivers/gles3/shaders/lens_distorted.glsl
Normal file
@@ -0,0 +1,86 @@
|
||||
/* clang-format off */
|
||||
[vertex]
|
||||
|
||||
#ifdef USE_GLES_OVER_GL
|
||||
#define lowp
|
||||
#define mediump
|
||||
#define highp
|
||||
#else
|
||||
precision highp float;
|
||||
precision highp int;
|
||||
#endif
|
||||
|
||||
layout(location = 0) in highp vec2 vertex;
|
||||
/* clang-format on */
|
||||
|
||||
uniform vec2 offset;
|
||||
uniform vec2 scale;
|
||||
|
||||
out vec2 uv_interp;
|
||||
|
||||
void main() {
|
||||
uv_interp = vertex.xy * 2.0 - 1.0;
|
||||
|
||||
vec2 v = vertex.xy * scale + offset;
|
||||
gl_Position = vec4(v, 0.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
[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
|
||||
|
||||
uniform sampler2D source; //texunit:0
|
||||
/* clang-format on */
|
||||
|
||||
uniform vec2 eye_center;
|
||||
uniform float k1;
|
||||
uniform float k2;
|
||||
uniform float upscale;
|
||||
uniform float aspect_ratio;
|
||||
|
||||
in vec2 uv_interp;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
void main() {
|
||||
vec2 coords = uv_interp;
|
||||
vec2 offset = coords - eye_center;
|
||||
|
||||
// take aspect ratio into account
|
||||
offset.y /= aspect_ratio;
|
||||
|
||||
// distort
|
||||
vec2 offset_sq = offset * offset;
|
||||
float radius_sq = offset_sq.x + offset_sq.y;
|
||||
float radius_s4 = radius_sq * radius_sq;
|
||||
float distortion_scale = 1.0 + (k1 * radius_sq) + (k2 * radius_s4);
|
||||
offset *= distortion_scale;
|
||||
|
||||
// reapply aspect ratio
|
||||
offset.y *= aspect_ratio;
|
||||
|
||||
// add our eye center back in
|
||||
coords = offset + eye_center;
|
||||
coords /= upscale;
|
||||
|
||||
// and check our color
|
||||
if (coords.x < -1.0 || coords.y < -1.0 || coords.x > 1.0 || coords.y > 1.0) {
|
||||
frag_color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
} else {
|
||||
coords = (coords + vec2(1.0)) / vec2(2.0);
|
||||
frag_color = texture(source, coords);
|
||||
}
|
||||
}
|
512
drivers/gles3/shaders/particles.glsl
Normal file
512
drivers/gles3/shaders/particles.glsl
Normal file
@@ -0,0 +1,512 @@
|
||||
/* clang-format off */
|
||||
#[modes]
|
||||
|
||||
mode_default =
|
||||
|
||||
#[specializations]
|
||||
|
||||
MODE_3D = false
|
||||
USERDATA1_USED = false
|
||||
USERDATA2_USED = false
|
||||
USERDATA3_USED = false
|
||||
USERDATA4_USED = false
|
||||
USERDATA5_USED = false
|
||||
USERDATA6_USED = false
|
||||
|
||||
#[vertex]
|
||||
|
||||
#define SDF_MAX_LENGTH 16384.0
|
||||
|
||||
layout(std140) uniform GlobalShaderUniformData { //ubo:1
|
||||
vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
|
||||
};
|
||||
|
||||
// This needs to be outside clang-format so the ubo comment is in the right place
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(std140) uniform MaterialUniforms{ //ubo:2
|
||||
|
||||
#MATERIAL_UNIFORMS
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#define MAX_ATTRACTORS 32
|
||||
|
||||
#define ATTRACTOR_TYPE_SPHERE uint(0)
|
||||
#define ATTRACTOR_TYPE_BOX uint(1)
|
||||
#define ATTRACTOR_TYPE_VECTOR_FIELD uint(2)
|
||||
|
||||
struct Attractor {
|
||||
mat4 transform;
|
||||
vec4 extents; // Extents or radius. w-channel is padding.
|
||||
|
||||
uint type;
|
||||
float strength;
|
||||
float attenuation;
|
||||
float directionality;
|
||||
};
|
||||
|
||||
#define MAX_COLLIDERS 32
|
||||
|
||||
#define COLLIDER_TYPE_SPHERE uint(0)
|
||||
#define COLLIDER_TYPE_BOX uint(1)
|
||||
#define COLLIDER_TYPE_SDF uint(2)
|
||||
#define COLLIDER_TYPE_HEIGHT_FIELD uint(3)
|
||||
#define COLLIDER_TYPE_2D_SDF uint(4)
|
||||
|
||||
struct Collider {
|
||||
mat4 transform;
|
||||
vec4 extents; // Extents or radius. w-channel is padding.
|
||||
|
||||
uint type;
|
||||
float scale;
|
||||
float pad0;
|
||||
float pad1;
|
||||
};
|
||||
|
||||
layout(std140) uniform FrameData { //ubo:0
|
||||
bool emitting;
|
||||
uint cycle;
|
||||
float system_phase;
|
||||
float prev_system_phase;
|
||||
|
||||
float explosiveness;
|
||||
float randomness;
|
||||
float time;
|
||||
float delta;
|
||||
|
||||
float particle_size;
|
||||
float amount_ratio;
|
||||
float pad1;
|
||||
float pad2;
|
||||
|
||||
uint random_seed;
|
||||
uint attractor_count;
|
||||
uint collider_count;
|
||||
uint frame;
|
||||
|
||||
mat4 emission_transform;
|
||||
|
||||
vec3 emitter_velocity;
|
||||
float interp_to_end;
|
||||
|
||||
Attractor attractors[MAX_ATTRACTORS];
|
||||
Collider colliders[MAX_COLLIDERS];
|
||||
};
|
||||
|
||||
#define PARTICLE_FLAG_ACTIVE uint(1)
|
||||
#define PARTICLE_FLAG_STARTED uint(2)
|
||||
#define PARTICLE_FLAG_TRAILED uint(4)
|
||||
#define PARTICLE_FRAME_MASK uint(0xFFFF)
|
||||
#define PARTICLE_FRAME_SHIFT uint(16)
|
||||
|
||||
// ParticleData
|
||||
layout(location = 0) in highp vec4 color;
|
||||
layout(location = 1) in highp vec4 velocity_flags;
|
||||
layout(location = 2) in highp vec4 custom;
|
||||
layout(location = 3) in highp vec4 xform_1;
|
||||
layout(location = 4) in highp vec4 xform_2;
|
||||
#ifdef MODE_3D
|
||||
layout(location = 5) in highp vec4 xform_3;
|
||||
#endif
|
||||
#ifdef USERDATA1_USED
|
||||
in highp vec4 userdata1;
|
||||
#endif
|
||||
#ifdef USERDATA2_USED
|
||||
in highp vec4 userdata2;
|
||||
#endif
|
||||
#ifdef USERDATA3_USED
|
||||
in highp vec4 userdata3;
|
||||
#endif
|
||||
#ifdef USERDATA4_USED
|
||||
in highp vec4 userdata4;
|
||||
#endif
|
||||
#ifdef USERDATA5_USED
|
||||
in highp vec4 userdata5;
|
||||
#endif
|
||||
#ifdef USERDATA6_USED
|
||||
in highp vec4 userdata6;
|
||||
#endif
|
||||
|
||||
out highp vec4 out_color; //tfb:
|
||||
out highp vec4 out_velocity_flags; //tfb:
|
||||
out highp vec4 out_custom; //tfb:
|
||||
out highp vec4 out_xform_1; //tfb:
|
||||
out highp vec4 out_xform_2; //tfb:
|
||||
#ifdef MODE_3D
|
||||
out highp vec4 out_xform_3; //tfb:MODE_3D
|
||||
#endif
|
||||
#ifdef USERDATA1_USED
|
||||
out highp vec4 out_userdata1; //tfb:USERDATA1_USED
|
||||
#endif
|
||||
#ifdef USERDATA2_USED
|
||||
out highp vec4 out_userdata2; //tfb:USERDATA2_USED
|
||||
#endif
|
||||
#ifdef USERDATA3_USED
|
||||
out highp vec4 out_userdata3; //tfb:USERDATA3_USED
|
||||
#endif
|
||||
#ifdef USERDATA4_USED
|
||||
out highp vec4 out_userdata4; //tfb:USERDATA4_USED
|
||||
#endif
|
||||
#ifdef USERDATA5_USED
|
||||
out highp vec4 out_userdata5; //tfb:USERDATA5_USED
|
||||
#endif
|
||||
#ifdef USERDATA6_USED
|
||||
out highp vec4 out_userdata6; //tfb:USERDATA6_USED
|
||||
#endif
|
||||
|
||||
uniform sampler2D height_field_texture; //texunit:0
|
||||
|
||||
uniform float lifetime;
|
||||
uniform bool clear;
|
||||
uniform uint total_particles;
|
||||
uniform bool use_fractional_delta;
|
||||
|
||||
uint hash(uint x) {
|
||||
x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b);
|
||||
x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b);
|
||||
x = (x >> uint(16)) ^ x;
|
||||
return x;
|
||||
}
|
||||
|
||||
vec3 safe_normalize(vec3 direction) {
|
||||
const float EPSILON = 0.001;
|
||||
if (length(direction) < EPSILON) {
|
||||
return vec3(0.0);
|
||||
}
|
||||
return normalize(direction);
|
||||
}
|
||||
|
||||
// Needed whenever 2D sdf texture is read from as it is packed in RGBA8.
|
||||
float vec4_to_float(vec4 p_vec) {
|
||||
return dot(p_vec, vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0)) * 2.0 - 1.0;
|
||||
}
|
||||
|
||||
#GLOBALS
|
||||
|
||||
void main() {
|
||||
bool apply_forces = true;
|
||||
bool apply_velocity = true;
|
||||
float local_delta = delta;
|
||||
|
||||
float mass = 1.0;
|
||||
|
||||
bool restart = false;
|
||||
|
||||
bool restart_position = false;
|
||||
bool restart_rotation_scale = false;
|
||||
bool restart_velocity = false;
|
||||
bool restart_color = false;
|
||||
bool restart_custom = false;
|
||||
|
||||
mat4 xform = mat4(1.0);
|
||||
uint flags = 0u;
|
||||
|
||||
if (clear) {
|
||||
out_color = vec4(1.0);
|
||||
out_custom = vec4(0.0);
|
||||
out_velocity_flags = vec4(0.0);
|
||||
} else {
|
||||
out_color = color;
|
||||
out_velocity_flags = velocity_flags;
|
||||
out_custom = custom;
|
||||
xform[0] = xform_1;
|
||||
xform[1] = xform_2;
|
||||
#ifdef MODE_3D
|
||||
xform[2] = xform_3;
|
||||
#endif
|
||||
xform = transpose(xform);
|
||||
flags = floatBitsToUint(velocity_flags.w);
|
||||
#ifdef USERDATA1_USED
|
||||
out_userdata1 = userdata1;
|
||||
#endif
|
||||
#ifdef USERDATA2_USED
|
||||
out_userdata2 = userdata2;
|
||||
#endif
|
||||
#ifdef USERDATA3_USED
|
||||
out_userdata3 = userdata3;
|
||||
#endif
|
||||
#ifdef USERDATA4_USED
|
||||
out_userdata4 = userdata4;
|
||||
#endif
|
||||
#ifdef USERDATA5_USED
|
||||
out_userdata5 = userdata5;
|
||||
#endif
|
||||
#ifdef USERDATA6_USED
|
||||
out_userdata6 = userdata6;
|
||||
#endif
|
||||
}
|
||||
|
||||
//clear started flag if set
|
||||
flags &= ~PARTICLE_FLAG_STARTED;
|
||||
|
||||
bool collided = false;
|
||||
vec3 collision_normal = vec3(0.0);
|
||||
float collision_depth = 0.0;
|
||||
|
||||
vec3 attractor_force = vec3(0.0);
|
||||
|
||||
#if !defined(DISABLE_VELOCITY)
|
||||
|
||||
if (bool(flags & PARTICLE_FLAG_ACTIVE)) {
|
||||
xform[3].xyz += out_velocity_flags.xyz * local_delta;
|
||||
}
|
||||
#endif
|
||||
uint index = uint(gl_VertexID);
|
||||
if (emitting) {
|
||||
float restart_phase = float(index) / float(total_particles);
|
||||
|
||||
if (randomness > 0.0) {
|
||||
uint seed = cycle;
|
||||
if (restart_phase >= system_phase) {
|
||||
seed -= uint(1);
|
||||
}
|
||||
seed *= uint(total_particles);
|
||||
seed += index;
|
||||
float random = float(hash(seed) % uint(65536)) / 65536.0;
|
||||
restart_phase += randomness * random * 1.0 / float(total_particles);
|
||||
}
|
||||
|
||||
restart_phase *= (1.0 - explosiveness);
|
||||
|
||||
if (system_phase > prev_system_phase) {
|
||||
// restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed
|
||||
|
||||
if (restart_phase >= prev_system_phase && restart_phase < system_phase) {
|
||||
restart = true;
|
||||
if (use_fractional_delta) {
|
||||
local_delta = (system_phase - restart_phase) * lifetime;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (delta > 0.0) {
|
||||
if (restart_phase >= prev_system_phase) {
|
||||
restart = true;
|
||||
if (use_fractional_delta) {
|
||||
local_delta = (1.0 - restart_phase + system_phase) * lifetime;
|
||||
}
|
||||
|
||||
} else if (restart_phase < system_phase) {
|
||||
restart = true;
|
||||
if (use_fractional_delta) {
|
||||
local_delta = (system_phase - restart_phase) * lifetime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (restart) {
|
||||
flags = emitting ? (PARTICLE_FLAG_ACTIVE | PARTICLE_FLAG_STARTED | (cycle << PARTICLE_FRAME_SHIFT)) : 0u;
|
||||
restart_position = true;
|
||||
restart_rotation_scale = true;
|
||||
restart_velocity = true;
|
||||
restart_color = true;
|
||||
restart_custom = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool particle_active = bool(flags & PARTICLE_FLAG_ACTIVE);
|
||||
|
||||
uint particle_number = (flags >> PARTICLE_FRAME_SHIFT) * uint(total_particles) + index;
|
||||
|
||||
if (restart && particle_active) {
|
||||
#CODE : START
|
||||
}
|
||||
|
||||
if (particle_active) {
|
||||
for (uint i = 0u; i < attractor_count; i++) {
|
||||
vec3 dir;
|
||||
float amount;
|
||||
vec3 rel_vec = xform[3].xyz - attractors[i].transform[3].xyz;
|
||||
vec3 local_pos = rel_vec * mat3(attractors[i].transform);
|
||||
|
||||
if (attractors[i].type == ATTRACTOR_TYPE_SPHERE) {
|
||||
dir = safe_normalize(rel_vec);
|
||||
float d = length(local_pos) / attractors[i].extents.x;
|
||||
if (d > 1.0) {
|
||||
continue;
|
||||
}
|
||||
amount = max(0.0, 1.0 - d);
|
||||
} else if (attractors[i].type == ATTRACTOR_TYPE_BOX) {
|
||||
dir = safe_normalize(rel_vec);
|
||||
|
||||
vec3 abs_pos = abs(local_pos / attractors[i].extents.xyz);
|
||||
float d = max(abs_pos.x, max(abs_pos.y, abs_pos.z));
|
||||
if (d > 1.0) {
|
||||
continue;
|
||||
}
|
||||
amount = max(0.0, 1.0 - d);
|
||||
} else if (attractors[i].type == ATTRACTOR_TYPE_VECTOR_FIELD) {
|
||||
}
|
||||
mediump float attractor_attenuation = attractors[i].attenuation;
|
||||
amount = pow(amount, attractor_attenuation);
|
||||
dir = safe_normalize(mix(dir, attractors[i].transform[2].xyz, attractors[i].directionality));
|
||||
attractor_force -= mass * amount * dir * attractors[i].strength;
|
||||
}
|
||||
|
||||
float particle_size = particle_size;
|
||||
|
||||
#ifdef USE_COLLISION_SCALE
|
||||
|
||||
particle_size *= dot(vec3(length(xform[0].xyz), length(xform[1].xyz), length(xform[2].xyz)), vec3(0.33333333333));
|
||||
|
||||
#endif
|
||||
|
||||
if (collider_count == 1u && colliders[0].type == COLLIDER_TYPE_2D_SDF) {
|
||||
//2D collision
|
||||
|
||||
vec2 pos = xform[3].xy;
|
||||
vec4 to_sdf_x = colliders[0].transform[0];
|
||||
vec4 to_sdf_y = colliders[0].transform[1];
|
||||
vec2 sdf_pos = vec2(dot(vec4(pos, 0, 1), to_sdf_x), dot(vec4(pos, 0, 1), to_sdf_y));
|
||||
|
||||
vec4 sdf_to_screen = vec4(colliders[0].extents.xyz, colliders[0].scale);
|
||||
|
||||
vec2 uv_pos = sdf_pos * sdf_to_screen.xy + sdf_to_screen.zw;
|
||||
|
||||
if (all(greaterThan(uv_pos, vec2(0.0))) && all(lessThan(uv_pos, vec2(1.0)))) {
|
||||
vec2 pos2 = pos + vec2(0, particle_size);
|
||||
vec2 sdf_pos2 = vec2(dot(vec4(pos2, 0, 1), to_sdf_x), dot(vec4(pos2, 0, 1), to_sdf_y));
|
||||
float sdf_particle_size = distance(sdf_pos, sdf_pos2);
|
||||
|
||||
float d = vec4_to_float(texture(height_field_texture, uv_pos)) * SDF_MAX_LENGTH;
|
||||
|
||||
// Allowing for a small epsilon to allow particle just touching colliders to count as collided
|
||||
const float EPSILON = 0.001;
|
||||
d -= sdf_particle_size;
|
||||
if (d < EPSILON) {
|
||||
vec2 n = normalize(vec2(
|
||||
vec4_to_float(texture(height_field_texture, uv_pos + vec2(EPSILON, 0.0))) - vec4_to_float(texture(height_field_texture, uv_pos - vec2(EPSILON, 0.0))),
|
||||
vec4_to_float(texture(height_field_texture, uv_pos + vec2(0.0, EPSILON))) - vec4_to_float(texture(height_field_texture, uv_pos - vec2(0.0, EPSILON)))));
|
||||
|
||||
collided = true;
|
||||
sdf_pos2 = sdf_pos + n * d;
|
||||
pos2 = vec2(dot(vec4(sdf_pos2, 0, 1), colliders[0].transform[2]), dot(vec4(sdf_pos2, 0, 1), colliders[0].transform[3]));
|
||||
|
||||
n = pos - pos2;
|
||||
|
||||
collision_normal = normalize(vec3(n, 0.0));
|
||||
collision_depth = length(n);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for (uint i = 0u; i < collider_count; i++) {
|
||||
vec3 normal;
|
||||
float depth;
|
||||
bool col = false;
|
||||
|
||||
vec3 rel_vec = xform[3].xyz - colliders[i].transform[3].xyz;
|
||||
vec3 local_pos = rel_vec * mat3(colliders[i].transform);
|
||||
|
||||
// Allowing for a small epsilon to allow particle just touching colliders to count as collided
|
||||
const float EPSILON = 0.001;
|
||||
if (colliders[i].type == COLLIDER_TYPE_SPHERE) {
|
||||
float d = length(rel_vec) - (particle_size + colliders[i].extents.x);
|
||||
|
||||
if (d < EPSILON) {
|
||||
col = true;
|
||||
depth = -d;
|
||||
normal = normalize(rel_vec);
|
||||
}
|
||||
} else if (colliders[i].type == COLLIDER_TYPE_BOX) {
|
||||
vec3 abs_pos = abs(local_pos);
|
||||
vec3 sgn_pos = sign(local_pos);
|
||||
|
||||
if (any(greaterThan(abs_pos, colliders[i].extents.xyz))) {
|
||||
//point outside box
|
||||
|
||||
vec3 closest = min(abs_pos, colliders[i].extents.xyz);
|
||||
vec3 rel = abs_pos - closest;
|
||||
depth = length(rel) - particle_size;
|
||||
if (depth < EPSILON) {
|
||||
col = true;
|
||||
normal = mat3(colliders[i].transform) * (normalize(rel) * sgn_pos);
|
||||
depth = -depth;
|
||||
}
|
||||
} else {
|
||||
//point inside box
|
||||
vec3 axis_len = colliders[i].extents.xyz - abs_pos;
|
||||
// there has to be a faster way to do this?
|
||||
if (all(lessThan(axis_len.xx, axis_len.yz))) {
|
||||
normal = vec3(1, 0, 0);
|
||||
} else if (all(lessThan(axis_len.yy, axis_len.xz))) {
|
||||
normal = vec3(0, 1, 0);
|
||||
} else {
|
||||
normal = vec3(0, 0, 1);
|
||||
}
|
||||
|
||||
col = true;
|
||||
depth = dot(normal * axis_len, vec3(1)) + particle_size;
|
||||
normal = mat3(colliders[i].transform) * (normal * sgn_pos);
|
||||
}
|
||||
} else if (colliders[i].type == COLLIDER_TYPE_SDF) {
|
||||
} else if (colliders[i].type == COLLIDER_TYPE_HEIGHT_FIELD) {
|
||||
vec3 local_pos_bottom = local_pos;
|
||||
local_pos_bottom.y -= particle_size;
|
||||
|
||||
if (any(greaterThan(abs(local_pos_bottom), colliders[i].extents.xyz))) {
|
||||
continue;
|
||||
}
|
||||
const float DELTA = 1.0 / 8192.0;
|
||||
|
||||
vec3 uvw_pos = vec3(local_pos_bottom / colliders[i].extents.xyz) * 0.5 + 0.5;
|
||||
|
||||
float y = texture(height_field_texture, uvw_pos.xz).r;
|
||||
|
||||
if (y + EPSILON > uvw_pos.y) {
|
||||
//inside heightfield
|
||||
|
||||
vec3 pos1 = (vec3(uvw_pos.x, y, uvw_pos.z) * 2.0 - 1.0) * colliders[i].extents.xyz;
|
||||
vec3 pos2 = (vec3(uvw_pos.x + DELTA, texture(height_field_texture, uvw_pos.xz + vec2(DELTA, 0)).r, uvw_pos.z) * 2.0 - 1.0) * colliders[i].extents.xyz;
|
||||
vec3 pos3 = (vec3(uvw_pos.x, texture(height_field_texture, uvw_pos.xz + vec2(0, DELTA)).r, uvw_pos.z + DELTA) * 2.0 - 1.0) * colliders[i].extents.xyz;
|
||||
|
||||
normal = normalize(cross(pos1 - pos2, pos1 - pos3));
|
||||
float local_y = (vec3(local_pos / colliders[i].extents.xyz) * 0.5 + 0.5).y;
|
||||
|
||||
col = true;
|
||||
depth = dot(normal, pos1) - dot(normal, local_pos_bottom);
|
||||
}
|
||||
}
|
||||
|
||||
if (col) {
|
||||
if (!collided) {
|
||||
collided = true;
|
||||
collision_normal = normal;
|
||||
collision_depth = depth;
|
||||
} else {
|
||||
vec3 c = collision_normal * collision_depth;
|
||||
c += normal * max(0.0, depth - dot(normal, c));
|
||||
collision_normal = normalize(c);
|
||||
collision_depth = length(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (particle_active) {
|
||||
#CODE : PROCESS
|
||||
}
|
||||
|
||||
flags &= ~PARTICLE_FLAG_ACTIVE;
|
||||
if (particle_active) {
|
||||
flags |= PARTICLE_FLAG_ACTIVE;
|
||||
}
|
||||
|
||||
xform = transpose(xform);
|
||||
out_xform_1 = xform[0];
|
||||
out_xform_2 = xform[1];
|
||||
#ifdef MODE_3D
|
||||
out_xform_3 = xform[2];
|
||||
#endif
|
||||
out_velocity_flags.w = uintBitsToFloat(flags);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#[fragment]
|
||||
|
||||
void main() {
|
||||
}
|
||||
/* clang-format on */
|
121
drivers/gles3/shaders/particles_copy.glsl
Normal file
121
drivers/gles3/shaders/particles_copy.glsl
Normal file
@@ -0,0 +1,121 @@
|
||||
/* clang-format off */
|
||||
#[modes]
|
||||
|
||||
mode_default =
|
||||
|
||||
#[specializations]
|
||||
|
||||
MODE_3D = false
|
||||
|
||||
#[vertex]
|
||||
|
||||
#include "stdlib_inc.glsl"
|
||||
|
||||
// ParticleData
|
||||
layout(location = 0) in highp vec4 color;
|
||||
layout(location = 1) in highp vec4 velocity_flags;
|
||||
layout(location = 2) in highp vec4 custom;
|
||||
layout(location = 3) in highp vec4 xform_1;
|
||||
layout(location = 4) in highp vec4 xform_2;
|
||||
#ifdef MODE_3D
|
||||
layout(location = 5) in highp vec4 xform_3;
|
||||
#endif
|
||||
|
||||
/* clang-format on */
|
||||
out highp vec4 out_xform_1; //tfb:
|
||||
out highp vec4 out_xform_2; //tfb:
|
||||
#ifdef MODE_3D
|
||||
out highp vec4 out_xform_3; //tfb:MODE_3D
|
||||
#endif
|
||||
flat out highp uvec4 instance_color_custom_data; //tfb:
|
||||
|
||||
uniform lowp vec3 sort_direction;
|
||||
uniform highp float frame_remainder;
|
||||
|
||||
uniform highp vec3 align_up;
|
||||
uniform highp uint align_mode;
|
||||
|
||||
uniform highp mat4 inv_emission_transform;
|
||||
|
||||
#define TRANSFORM_ALIGN_DISABLED uint(0)
|
||||
#define TRANSFORM_ALIGN_Z_BILLBOARD uint(1)
|
||||
#define TRANSFORM_ALIGN_Y_TO_VELOCITY uint(2)
|
||||
#define TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY uint(3)
|
||||
|
||||
#define PARTICLE_FLAG_ACTIVE uint(1)
|
||||
|
||||
#define FLT_MAX float(3.402823466e+38)
|
||||
|
||||
void main() {
|
||||
// Set scale to zero and translate to -INF so particle will be invisible
|
||||
// even for materials that ignore rotation/scale (i.e. billboards).
|
||||
mat4 txform = mat4(vec4(0.0), vec4(0.0), vec4(0.0), vec4(-FLT_MAX, -FLT_MAX, -FLT_MAX, 0.0));
|
||||
if (bool(floatBitsToUint(velocity_flags.w) & PARTICLE_FLAG_ACTIVE)) {
|
||||
#ifdef MODE_3D
|
||||
txform = transpose(mat4(xform_1, xform_2, xform_3, vec4(0.0, 0.0, 0.0, 1.0)));
|
||||
#else
|
||||
txform = transpose(mat4(xform_1, xform_2, vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)));
|
||||
#endif
|
||||
|
||||
if (align_mode == TRANSFORM_ALIGN_DISABLED) {
|
||||
// nothing
|
||||
} else if (align_mode == TRANSFORM_ALIGN_Z_BILLBOARD) {
|
||||
mat3 local = mat3(normalize(cross(align_up, sort_direction)), align_up, sort_direction);
|
||||
local = local * mat3(txform);
|
||||
txform[0].xyz = local[0];
|
||||
txform[1].xyz = local[1];
|
||||
txform[2].xyz = local[2];
|
||||
} else if (align_mode == TRANSFORM_ALIGN_Y_TO_VELOCITY) {
|
||||
vec3 v = velocity_flags.xyz;
|
||||
float s = (length(txform[0]) + length(txform[1]) + length(txform[2])) / 3.0;
|
||||
if (length(v) > 0.0) {
|
||||
txform[1].xyz = normalize(v);
|
||||
} else {
|
||||
txform[1].xyz = normalize(txform[1].xyz);
|
||||
}
|
||||
|
||||
txform[0].xyz = normalize(cross(txform[1].xyz, txform[2].xyz));
|
||||
txform[2].xyz = vec3(0.0, 0.0, 1.0) * s;
|
||||
txform[0].xyz *= s;
|
||||
txform[1].xyz *= s;
|
||||
} else if (align_mode == TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
|
||||
vec3 sv = velocity_flags.xyz - sort_direction * dot(sort_direction, velocity_flags.xyz); //screen velocity
|
||||
|
||||
if (length(sv) == 0.0) {
|
||||
sv = align_up;
|
||||
}
|
||||
|
||||
sv = normalize(sv);
|
||||
|
||||
txform[0].xyz = normalize(cross(sv, sort_direction)) * length(txform[0]);
|
||||
txform[1].xyz = sv * length(txform[1]);
|
||||
txform[2].xyz = sort_direction * length(txform[2]);
|
||||
}
|
||||
|
||||
txform[3].xyz += velocity_flags.xyz * frame_remainder;
|
||||
|
||||
#ifndef MODE_3D
|
||||
// In global mode, bring 2D particles to local coordinates
|
||||
// as they will be drawn with the node position as origin.
|
||||
txform = inv_emission_transform * txform;
|
||||
#endif
|
||||
}
|
||||
txform = transpose(txform);
|
||||
|
||||
instance_color_custom_data.x = packHalf2x16(color.xy);
|
||||
instance_color_custom_data.y = packHalf2x16(color.zw);
|
||||
instance_color_custom_data.z = packHalf2x16(custom.xy);
|
||||
instance_color_custom_data.w = packHalf2x16(custom.zw);
|
||||
out_xform_1 = txform[0];
|
||||
out_xform_2 = txform[1];
|
||||
#ifdef MODE_3D
|
||||
out_xform_3 = txform[2];
|
||||
#endif
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#[fragment]
|
||||
|
||||
void main() {
|
||||
}
|
||||
/* clang-format on */
|
2629
drivers/gles3/shaders/scene.glsl
Normal file
2629
drivers/gles3/shaders/scene.glsl
Normal file
File diff suppressed because it is too large
Load Diff
282
drivers/gles3/shaders/skeleton.glsl
Normal file
282
drivers/gles3/shaders/skeleton.glsl
Normal file
@@ -0,0 +1,282 @@
|
||||
/* 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 highp 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
|
||||
|
||||
#ifdef USE_SKELETON
|
||||
uniform mediump vec2 skeleton_transform_x;
|
||||
uniform mediump vec2 skeleton_transform_y;
|
||||
uniform mediump vec2 skeleton_transform_offset;
|
||||
|
||||
uniform mediump vec2 inverse_transform_x;
|
||||
uniform mediump vec2 inverse_transform_y;
|
||||
uniform mediump vec2 inverse_transform_offset;
|
||||
#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 skeleton_matrix = mat4(vec4(skeleton_transform_x, 0.0, 0.0), vec4(skeleton_transform_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(skeleton_transform_offset, 0.0, 1.0));
|
||||
mat4 inverse_matrix = mat4(vec4(inverse_transform_x, 0.0, 0.0), vec4(inverse_transform_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(inverse_transform_offset, 0.0, 1.0));
|
||||
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));
|
||||
|
||||
bone_matrix = skeleton_matrix * transpose(bone_matrix) * inverse_matrix;
|
||||
|
||||
out_vertex = (bone_matrix * vec4(out_vertex, 0.0, 1.0)).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 */
|
273
drivers/gles3/shaders/sky.glsl
Normal file
273
drivers/gles3/shaders/sky.glsl
Normal file
@@ -0,0 +1,273 @@
|
||||
/* clang-format off */
|
||||
#[modes]
|
||||
|
||||
mode_background =
|
||||
mode_cubemap = #define USE_CUBEMAP_PASS
|
||||
|
||||
#[specializations]
|
||||
|
||||
USE_MULTIVIEW = false
|
||||
USE_INVERTED_Y = true
|
||||
APPLY_TONEMAPPING = true
|
||||
USE_QUARTER_RES_PASS = false
|
||||
USE_HALF_RES_PASS = false
|
||||
|
||||
#[vertex]
|
||||
|
||||
layout(location = 0) in vec2 vertex_attrib;
|
||||
|
||||
out vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
void main() {
|
||||
#ifdef USE_INVERTED_Y
|
||||
uv_interp = vertex_attrib;
|
||||
#else
|
||||
// We're doing clockwise culling so flip the order
|
||||
uv_interp = vec2(vertex_attrib.x, vertex_attrib.y * -1.0);
|
||||
#endif
|
||||
gl_Position = vec4(uv_interp, -1.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#[fragment]
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
#include "tonemap_inc.glsl"
|
||||
|
||||
in vec2 uv_interp;
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
uniform samplerCube radiance; //texunit:-1
|
||||
#ifdef USE_CUBEMAP_PASS
|
||||
uniform samplerCube half_res; //texunit:-2
|
||||
uniform samplerCube quarter_res; //texunit:-3
|
||||
#elif defined(USE_MULTIVIEW)
|
||||
uniform sampler2DArray half_res; //texunit:-2
|
||||
uniform sampler2DArray quarter_res; //texunit:-3
|
||||
#else
|
||||
uniform sampler2D half_res; //texunit:-2
|
||||
uniform sampler2D quarter_res; //texunit:-3
|
||||
#endif
|
||||
|
||||
layout(std140) uniform GlobalShaderUniformData { //ubo:1
|
||||
vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
|
||||
};
|
||||
|
||||
struct DirectionalLightData {
|
||||
vec4 direction_energy;
|
||||
vec4 color_size;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
layout(std140) uniform DirectionalLights { //ubo:4
|
||||
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
|
||||
}
|
||||
directional_lights;
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(std140) uniform MaterialUniforms{ //ubo:3
|
||||
|
||||
#MATERIAL_UNIFORMS
|
||||
|
||||
};
|
||||
#endif
|
||||
/* clang-format on */
|
||||
#GLOBALS
|
||||
|
||||
#ifdef USE_CUBEMAP_PASS
|
||||
#define AT_CUBEMAP_PASS true
|
||||
#else
|
||||
#define AT_CUBEMAP_PASS false
|
||||
#endif
|
||||
|
||||
#ifdef USE_HALF_RES_PASS
|
||||
#define AT_HALF_RES_PASS true
|
||||
#else
|
||||
#define AT_HALF_RES_PASS false
|
||||
#endif
|
||||
|
||||
#ifdef USE_QUARTER_RES_PASS
|
||||
#define AT_QUARTER_RES_PASS true
|
||||
#else
|
||||
#define AT_QUARTER_RES_PASS false
|
||||
#endif
|
||||
|
||||
// mat4 is a waste of space, but we don't have an easy way to set a mat3 uniform for now
|
||||
uniform mat4 orientation;
|
||||
uniform vec4 projection;
|
||||
uniform vec3 position;
|
||||
uniform float time;
|
||||
uniform float sky_energy_multiplier;
|
||||
uniform float luminance_multiplier;
|
||||
|
||||
uniform float fog_aerial_perspective;
|
||||
uniform vec4 fog_light_color;
|
||||
uniform float fog_sun_scatter;
|
||||
uniform bool fog_enabled;
|
||||
uniform float fog_density;
|
||||
uniform float fog_sky_affect;
|
||||
uniform uint directional_light_count;
|
||||
|
||||
#ifdef USE_MULTIVIEW
|
||||
layout(std140) uniform MultiviewData { // ubo:11
|
||||
highp mat4 projection_matrix_view[MAX_VIEWS];
|
||||
highp mat4 inv_projection_matrix_view[MAX_VIEWS];
|
||||
highp vec4 eye_offset[MAX_VIEWS];
|
||||
}
|
||||
multiview_data;
|
||||
#endif
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
#ifdef USE_DEBANDING
|
||||
// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
|
||||
vec3 interleaved_gradient_noise(vec2 pos) {
|
||||
const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f);
|
||||
float res = fract(magic.z * fract(dot(pos, magic.xy))) * 2.0 - 1.0;
|
||||
return vec3(res, -res, res) / 255.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_FOG)
|
||||
vec4 fog_process(vec3 view, vec3 sky_color) {
|
||||
vec3 fog_color = mix(fog_light_color.rgb, sky_color, fog_aerial_perspective);
|
||||
|
||||
if (fog_sun_scatter > 0.001) {
|
||||
vec4 sun_scatter = vec4(0.0);
|
||||
float sun_total = 0.0;
|
||||
for (uint i = 0u; i < directional_light_count; i++) {
|
||||
vec3 light_color = srgb_to_linear(directional_lights.data[i].color_size.xyz) * directional_lights.data[i].direction_energy.w;
|
||||
float light_amount = pow(max(dot(view, directional_lights.data[i].direction_energy.xyz), 0.0), 8.0) * M_PI;
|
||||
fog_color += light_color * light_amount * fog_sun_scatter;
|
||||
}
|
||||
}
|
||||
|
||||
return vec4(fog_color, 1.0);
|
||||
}
|
||||
#endif // !DISABLE_FOG
|
||||
|
||||
// Eberly approximations from https://seblagarde.wordpress.com/2014/12/01/inverse-trigonometric-functions-gpu-optimization-for-amd-gcn-architecture/.
|
||||
// input [-1, 1] and output [0, PI]
|
||||
float acos_approx(float p_x) {
|
||||
float x = abs(p_x);
|
||||
float res = -0.156583f * x + (M_PI / 2.0);
|
||||
res *= sqrt(1.0f - x);
|
||||
return (p_x >= 0.0) ? res : M_PI - res;
|
||||
}
|
||||
|
||||
// Based on https://math.stackexchange.com/questions/1098487/atan2-faster-approximation
|
||||
// but using the Eberly coefficients from https://seblagarde.wordpress.com/2014/12/01/inverse-trigonometric-functions-gpu-optimization-for-amd-gcn-architecture/.
|
||||
float atan2_approx(float y, float x) {
|
||||
float a = min(abs(x), abs(y)) / max(abs(x), abs(y));
|
||||
float s = a * a;
|
||||
float poly = 0.0872929f;
|
||||
poly = -0.301895f + poly * s;
|
||||
poly = 1.0f + poly * s;
|
||||
poly = poly * a;
|
||||
|
||||
float r = abs(y) > abs(x) ? (M_PI / 2.0) - poly : poly;
|
||||
r = x < 0.0 ? M_PI - r : r;
|
||||
r = y < 0.0 ? -r : r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 cube_normal;
|
||||
#ifdef USE_MULTIVIEW
|
||||
// In multiview our projection matrices will contain positional and rotational offsets that we need to properly unproject.
|
||||
vec4 unproject = vec4(uv_interp.xy, -1.0, 1.0); // unproject at the far plane
|
||||
vec4 unprojected = multiview_data.inv_projection_matrix_view[ViewIndex] * unproject;
|
||||
cube_normal = unprojected.xyz / unprojected.w;
|
||||
|
||||
// Unproject will give us the position between the eyes, need to re-offset.
|
||||
cube_normal += multiview_data.eye_offset[ViewIndex].xyz;
|
||||
#else
|
||||
cube_normal.z = -1.0;
|
||||
cube_normal.x = (uv_interp.x + projection.x) / projection.y;
|
||||
cube_normal.y = (-uv_interp.y - projection.z) / projection.w;
|
||||
#endif
|
||||
cube_normal = mat3(orientation) * cube_normal;
|
||||
cube_normal = normalize(cube_normal);
|
||||
|
||||
vec2 uv = gl_FragCoord.xy; // uv_interp * 0.5 + 0.5;
|
||||
|
||||
vec2 panorama_coords = vec2(atan2_approx(cube_normal.x, -cube_normal.z), acos_approx(cube_normal.y));
|
||||
|
||||
if (panorama_coords.x < 0.0) {
|
||||
panorama_coords.x += M_PI * 2.0;
|
||||
}
|
||||
|
||||
panorama_coords /= vec2(M_PI * 2.0, M_PI);
|
||||
|
||||
vec3 color = vec3(0.0, 0.0, 0.0);
|
||||
float alpha = 1.0; // Only available to subpasses
|
||||
vec4 half_res_color = vec4(1.0);
|
||||
vec4 quarter_res_color = vec4(1.0);
|
||||
vec4 custom_fog = vec4(0.0);
|
||||
|
||||
#ifdef USE_CUBEMAP_PASS
|
||||
#ifdef USES_HALF_RES_COLOR
|
||||
half_res_color = texture(samplerCube(half_res, SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), cube_normal);
|
||||
#endif
|
||||
#ifdef USES_QUARTER_RES_COLOR
|
||||
quarter_res_color = texture(samplerCube(quarter_res, SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), cube_normal);
|
||||
#endif
|
||||
#else
|
||||
#ifdef USES_HALF_RES_COLOR
|
||||
#ifdef USE_MULTIVIEW
|
||||
half_res_color = textureLod(sampler2DArray(half_res, SAMPLER_LINEAR_CLAMP), vec3(uv, ViewIndex), 0.0);
|
||||
#else
|
||||
half_res_color = textureLod(sampler2D(half_res, SAMPLER_LINEAR_CLAMP), uv, 0.0);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef USES_QUARTER_RES_COLOR
|
||||
#ifdef USE_MULTIVIEW
|
||||
quarter_res_color = textureLod(sampler2DArray(quarter_res, SAMPLER_LINEAR_CLAMP), vec3(uv, ViewIndex), 0.0);
|
||||
#else
|
||||
quarter_res_color = textureLod(sampler2D(quarter_res, SAMPLER_LINEAR_CLAMP), uv, 0.0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
{
|
||||
#CODE : SKY
|
||||
}
|
||||
|
||||
color *= sky_energy_multiplier;
|
||||
|
||||
// Convert to Linear for tonemapping so color matches scene shader better
|
||||
color = srgb_to_linear(color);
|
||||
|
||||
#if !defined(DISABLE_FOG) && !defined(USE_CUBEMAP_PASS)
|
||||
|
||||
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
|
||||
if (fog_enabled) {
|
||||
vec4 fog = fog_process(cube_normal, color.rgb);
|
||||
color.rgb = mix(color.rgb, fog.rgb, fog.a * fog_sky_affect);
|
||||
}
|
||||
|
||||
if (custom_fog.a > 0.0) {
|
||||
color.rgb = mix(color.rgb, custom_fog.rgb, custom_fog.a);
|
||||
}
|
||||
|
||||
#endif // DISABLE_FOG
|
||||
|
||||
color *= exposure;
|
||||
#ifdef APPLY_TONEMAPPING
|
||||
color = apply_tonemapping(color, white);
|
||||
#endif
|
||||
color = linear_to_srgb(color);
|
||||
|
||||
frag_color.rgb = color * luminance_multiplier;
|
||||
frag_color.a = alpha;
|
||||
|
||||
#ifdef USE_DEBANDING
|
||||
frag_color.rgb += interleaved_gradient_noise(gl_FragCoord.xy) * sky_energy_multiplier * luminance_multiplier;
|
||||
#endif
|
||||
}
|
89
drivers/gles3/shaders/stdlib_inc.glsl
Normal file
89
drivers/gles3/shaders/stdlib_inc.glsl
Normal file
@@ -0,0 +1,89 @@
|
||||
// Compatibility renames. These are exposed with the "godot_" prefix
|
||||
// to work around two distinct Adreno bugs:
|
||||
// 1. Some Adreno devices expose ES310 functions in ES300 shaders.
|
||||
// Internally, we must use the "godot_" prefix, but user shaders
|
||||
// will be mapped automatically.
|
||||
// 2. Adreno 3XX devices have poor implementations of the other packing
|
||||
// functions, so we just use our own there to keep it simple.
|
||||
|
||||
#ifdef USE_HALF2FLOAT
|
||||
// Floating point pack/unpack functions are part of the GLSL ES 300 specification used by web and mobile.
|
||||
// It appears to be safe to expose these on mobile, but when running through ANGLE this appears to break.
|
||||
uint float2half(uint f) {
|
||||
uint e = f & uint(0x7f800000);
|
||||
if (e <= uint(0x38000000)) {
|
||||
return uint(0);
|
||||
} else {
|
||||
return ((f >> uint(16)) & uint(0x8000)) |
|
||||
(((e - uint(0x38000000)) >> uint(13)) & uint(0x7c00)) |
|
||||
((f >> uint(13)) & uint(0x03ff));
|
||||
}
|
||||
}
|
||||
|
||||
uint half2float(uint h) {
|
||||
uint h_e = h & uint(0x7c00);
|
||||
return ((h & uint(0x8000)) << uint(16)) | uint((h_e >> uint(10)) != uint(0)) * (((h_e + uint(0x1c000)) << uint(13)) | ((h & uint(0x03ff)) << uint(13)));
|
||||
}
|
||||
|
||||
uint godot_packHalf2x16(vec2 v) {
|
||||
return float2half(floatBitsToUint(v.x)) | float2half(floatBitsToUint(v.y)) << uint(16);
|
||||
}
|
||||
|
||||
vec2 godot_unpackHalf2x16(uint v) {
|
||||
return vec2(uintBitsToFloat(half2float(v & uint(0xffff))),
|
||||
uintBitsToFloat(half2float(v >> uint(16))));
|
||||
}
|
||||
|
||||
uint godot_packUnorm2x16(vec2 v) {
|
||||
uvec2 uv = uvec2(round(clamp(v, vec2(0.0), vec2(1.0)) * 65535.0));
|
||||
return uv.x | uv.y << uint(16);
|
||||
}
|
||||
|
||||
vec2 godot_unpackUnorm2x16(uint p) {
|
||||
return vec2(float(p & uint(0xffff)), float(p >> uint(16))) * 0.000015259021; // 1.0 / 65535.0 optimization
|
||||
}
|
||||
|
||||
uint godot_packSnorm2x16(vec2 v) {
|
||||
uvec2 uv = uvec2(round(clamp(v, vec2(-1.0), vec2(1.0)) * 32767.0) + 32767.0);
|
||||
return uv.x | uv.y << uint(16);
|
||||
}
|
||||
|
||||
vec2 godot_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));
|
||||
}
|
||||
|
||||
#define packHalf2x16 godot_packHalf2x16
|
||||
#define unpackHalf2x16 godot_unpackHalf2x16
|
||||
#define packUnorm2x16 godot_packUnorm2x16
|
||||
#define unpackUnorm2x16 godot_unpackUnorm2x16
|
||||
#define packSnorm2x16 godot_packSnorm2x16
|
||||
#define unpackSnorm2x16 godot_unpackSnorm2x16
|
||||
|
||||
#endif // USE_HALF2FLOAT
|
||||
|
||||
// Always expose these as they are ES310 functions and not available in ES300 or GLSL 330.
|
||||
|
||||
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 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 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 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
|
182
drivers/gles3/shaders/tonemap_inc.glsl
Normal file
182
drivers/gles3/shaders/tonemap_inc.glsl
Normal file
@@ -0,0 +1,182 @@
|
||||
layout(std140) uniform TonemapData { //ubo:0
|
||||
float exposure;
|
||||
float white;
|
||||
int tonemapper;
|
||||
int pad;
|
||||
|
||||
int pad2;
|
||||
float brightness;
|
||||
float contrast;
|
||||
float saturation;
|
||||
};
|
||||
|
||||
// This expects 0-1 range input.
|
||||
vec3 linear_to_srgb(vec3 color) {
|
||||
//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);
|
||||
}
|
||||
|
||||
#ifdef APPLY_TONEMAPPING
|
||||
|
||||
// Based on Reinhard's extended formula, see equation 4 in https://doi.org/cjbgrt
|
||||
vec3 tonemap_reinhard(vec3 color, float p_white) {
|
||||
float white_squared = p_white * p_white;
|
||||
vec3 white_squared_color = white_squared * color;
|
||||
// Equivalent to color * (1 + color / white_squared) / (1 + color)
|
||||
return (white_squared_color + color * color) / (white_squared_color + white_squared);
|
||||
}
|
||||
|
||||
vec3 tonemap_filmic(vec3 color, float p_white) {
|
||||
// exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers
|
||||
// also useful to scale the input to the range that the tonemapper is designed for (some require very high input values)
|
||||
// has no effect on the curve's general shape or visual properties
|
||||
const float exposure_bias = 2.0f;
|
||||
const float A = 0.22f * exposure_bias * exposure_bias; // bias baked into constants for performance
|
||||
const float B = 0.30f * exposure_bias;
|
||||
const float C = 0.10f;
|
||||
const float D = 0.20f;
|
||||
const float E = 0.01f;
|
||||
const float F = 0.30f;
|
||||
|
||||
vec3 color_tonemapped = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F;
|
||||
float p_white_tonemapped = ((p_white * (A * p_white + C * B) + D * E) / (p_white * (A * p_white + B) + D * F)) - E / F;
|
||||
|
||||
return color_tonemapped / p_white_tonemapped;
|
||||
}
|
||||
|
||||
// Adapted from https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
|
||||
// (MIT License).
|
||||
vec3 tonemap_aces(vec3 color, float p_white) {
|
||||
const float exposure_bias = 1.8f;
|
||||
const float A = 0.0245786f;
|
||||
const float B = 0.000090537f;
|
||||
const float C = 0.983729f;
|
||||
const float D = 0.432951f;
|
||||
const float E = 0.238081f;
|
||||
|
||||
// Exposure bias baked into transform to save shader instructions. Equivalent to `color *= exposure_bias`
|
||||
const mat3 rgb_to_rrt = mat3(
|
||||
vec3(0.59719f * exposure_bias, 0.35458f * exposure_bias, 0.04823f * exposure_bias),
|
||||
vec3(0.07600f * exposure_bias, 0.90834f * exposure_bias, 0.01566f * exposure_bias),
|
||||
vec3(0.02840f * exposure_bias, 0.13383f * exposure_bias, 0.83777f * exposure_bias));
|
||||
|
||||
const mat3 odt_to_rgb = mat3(
|
||||
vec3(1.60475f, -0.53108f, -0.07367f),
|
||||
vec3(-0.10208f, 1.10813f, -0.00605f),
|
||||
vec3(-0.00327f, -0.07276f, 1.07602f));
|
||||
|
||||
color *= rgb_to_rrt;
|
||||
vec3 color_tonemapped = (color * (color + A) - B) / (color * (C * color + D) + E);
|
||||
color_tonemapped *= odt_to_rgb;
|
||||
|
||||
p_white *= exposure_bias;
|
||||
float p_white_tonemapped = (p_white * (p_white + A) - B) / (p_white * (C * p_white + D) + E);
|
||||
|
||||
return color_tonemapped / p_white_tonemapped;
|
||||
}
|
||||
|
||||
// Polynomial approximation of EaryChow's AgX sigmoid curve.
|
||||
// x must be within the range [0.0, 1.0]
|
||||
vec3 agx_contrast_approx(vec3 x) {
|
||||
// Generated with Excel trendline
|
||||
// Input data: Generated using python sigmoid with EaryChow's configuration and 57 steps
|
||||
// Additional padding values were added to give correct intersections at 0.0 and 1.0
|
||||
// 6th order, intercept of 0.0 to remove an operation and ensure intersection at 0.0
|
||||
vec3 x2 = x * x;
|
||||
vec3 x4 = x2 * x2;
|
||||
return 0.021 * x + 4.0111 * x2 - 25.682 * x2 * x + 70.359 * x4 - 74.778 * x4 * x + 27.069 * x4 * x2;
|
||||
}
|
||||
|
||||
// This is an approximation and simplification of EaryChow's AgX implementation that is used by Blender.
|
||||
// This code is based off of the script that generates the AgX_Base_sRGB.cube LUT that Blender uses.
|
||||
// Source: https://github.com/EaryChow/AgX_LUT_Gen/blob/main/AgXBasesRGB.py
|
||||
vec3 tonemap_agx(vec3 color) {
|
||||
// Combined linear sRGB to linear Rec 2020 and Blender AgX inset matrices:
|
||||
const mat3 srgb_to_rec2020_agx_inset_matrix = mat3(
|
||||
0.54490813676363087053, 0.14044005884001287035, 0.088827411851915368603,
|
||||
0.37377945959812267119, 0.75410959864013760045, 0.17887712465043811023,
|
||||
0.081384976686407536266, 0.10543358536857773485, 0.73224999956948382528);
|
||||
|
||||
// Combined inverse AgX outset matrix and linear Rec 2020 to linear sRGB matrices.
|
||||
const mat3 agx_outset_rec2020_to_srgb_matrix = mat3(
|
||||
1.9645509602733325934, -0.29932243390911083839, -0.16436833806080403409,
|
||||
-0.85585845117807513559, 1.3264510741502356555, -0.23822464068860595117,
|
||||
-0.10886710826831608324, -0.027084020983874825605, 1.402665347143271889);
|
||||
|
||||
// LOG2_MIN = -10.0
|
||||
// LOG2_MAX = +6.5
|
||||
// MIDDLE_GRAY = 0.18
|
||||
const float min_ev = -12.4739311883324; // log2(pow(2, LOG2_MIN) * MIDDLE_GRAY)
|
||||
const float max_ev = 4.02606881166759; // log2(pow(2, LOG2_MAX) * MIDDLE_GRAY)
|
||||
|
||||
// Large negative values in one channel and large positive values in other
|
||||
// channels can result in a colour that appears darker and more saturated than
|
||||
// desired after passing it through the inset matrix. For this reason, it is
|
||||
// best to prevent negative input values.
|
||||
// This is done before the Rec. 2020 transform to allow the Rec. 2020
|
||||
// transform to be combined with the AgX inset matrix. This results in a loss
|
||||
// of color information that could be correctly interpreted within the
|
||||
// Rec. 2020 color space as positive RGB values, but it is less common for Godot
|
||||
// to provide this function with negative sRGB values and therefore not worth
|
||||
// the performance cost of an additional matrix multiplication.
|
||||
// A value of 2e-10 intentionally introduces insignificant error to prevent
|
||||
// log2(0.0) after the inset matrix is applied; color will be >= 1e-10 after
|
||||
// the matrix transform.
|
||||
color = max(color, 2e-10);
|
||||
|
||||
// Do AGX in rec2020 to match Blender and then apply inset matrix.
|
||||
color = srgb_to_rec2020_agx_inset_matrix * color;
|
||||
|
||||
// Log2 space encoding.
|
||||
// Must be clamped because agx_contrast_approx may not work
|
||||
// well with values outside of the range [0.0, 1.0]
|
||||
color = clamp(log2(color), min_ev, max_ev);
|
||||
color = (color - min_ev) / (max_ev - min_ev);
|
||||
|
||||
// Apply sigmoid function approximation.
|
||||
color = agx_contrast_approx(color);
|
||||
|
||||
// Convert back to linear before applying outset matrix.
|
||||
color = pow(color, vec3(2.4));
|
||||
|
||||
// Apply outset to make the result more chroma-laden and then go back to linear sRGB.
|
||||
color = agx_outset_rec2020_to_srgb_matrix * color;
|
||||
|
||||
// Blender's lusRGB.compensate_low_side is too complex for this shader, so
|
||||
// simply return the color, even if it has negative components. These negative
|
||||
// components may be useful for subsequent color adjustments.
|
||||
return color;
|
||||
}
|
||||
|
||||
#define TONEMAPPER_LINEAR 0
|
||||
#define TONEMAPPER_REINHARD 1
|
||||
#define TONEMAPPER_FILMIC 2
|
||||
#define TONEMAPPER_ACES 3
|
||||
#define TONEMAPPER_AGX 4
|
||||
|
||||
vec3 apply_tonemapping(vec3 color, float p_white) { // inputs are LINEAR
|
||||
// Ensure color values passed to tonemappers are positive.
|
||||
// They can be negative in the case of negative lights, which leads to undesired behavior.
|
||||
if (tonemapper == TONEMAPPER_LINEAR) {
|
||||
return color;
|
||||
} else if (tonemapper == TONEMAPPER_REINHARD) {
|
||||
return tonemap_reinhard(max(vec3(0.0f), color), p_white);
|
||||
} else if (tonemapper == TONEMAPPER_FILMIC) {
|
||||
return tonemap_filmic(max(vec3(0.0f), color), p_white);
|
||||
} else if (tonemapper == TONEMAPPER_ACES) {
|
||||
return tonemap_aces(max(vec3(0.0f), color), p_white);
|
||||
} else { // TONEMAPPER_AGX
|
||||
return tonemap_agx(color);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // APPLY_TONEMAPPING
|
Reference in New Issue
Block a user