Merge pull request #53850 from Calinou/gles2-remove-unused-shaders
This commit is contained in:
commit
22219e2e35
|
@ -4,20 +4,11 @@ Import("env")
|
||||||
|
|
||||||
if "GLES2_GLSL" in env["BUILDERS"]:
|
if "GLES2_GLSL" in env["BUILDERS"]:
|
||||||
env.GLES2_GLSL("copy.glsl")
|
env.GLES2_GLSL("copy.glsl")
|
||||||
# env.GLES2_GLSL('resolve.glsl');
|
|
||||||
env.GLES2_GLSL("canvas.glsl")
|
env.GLES2_GLSL("canvas.glsl")
|
||||||
env.GLES2_GLSL("canvas_shadow.glsl")
|
env.GLES2_GLSL("canvas_shadow.glsl")
|
||||||
env.GLES2_GLSL("scene.glsl")
|
env.GLES2_GLSL("scene.glsl")
|
||||||
env.GLES2_GLSL("cubemap_filter.glsl")
|
env.GLES2_GLSL("cubemap_filter.glsl")
|
||||||
env.GLES2_GLSL("cube_to_dp.glsl")
|
env.GLES2_GLSL("cube_to_dp.glsl")
|
||||||
# env.GLES2_GLSL('blend_shape.glsl');
|
|
||||||
# env.GLES2_GLSL('screen_space_reflection.glsl');
|
|
||||||
env.GLES2_GLSL("effect_blur.glsl")
|
env.GLES2_GLSL("effect_blur.glsl")
|
||||||
# env.GLES2_GLSL('subsurf_scattering.glsl');
|
|
||||||
# env.GLES2_GLSL('ssao.glsl');
|
|
||||||
# env.GLES2_GLSL('ssao_minify.glsl');
|
|
||||||
# env.GLES2_GLSL('ssao_blur.glsl');
|
|
||||||
# env.GLES2_GLSL('exposure.glsl');
|
|
||||||
env.GLES2_GLSL("tonemap.glsl")
|
env.GLES2_GLSL("tonemap.glsl")
|
||||||
# env.GLES2_GLSL('particles.glsl');
|
|
||||||
env.GLES2_GLSL("lens_distorted.glsl")
|
env.GLES2_GLSL("lens_distorted.glsl")
|
||||||
|
|
|
@ -1,193 +0,0 @@
|
||||||
/* clang-format off */
|
|
||||||
[vertex]
|
|
||||||
|
|
||||||
/*
|
|
||||||
from VisualServer:
|
|
||||||
|
|
||||||
ARRAY_VERTEX=0,
|
|
||||||
ARRAY_NORMAL=1,
|
|
||||||
ARRAY_TANGENT=2,
|
|
||||||
ARRAY_COLOR=3,
|
|
||||||
ARRAY_TEX_UV=4,
|
|
||||||
ARRAY_TEX_UV2=5,
|
|
||||||
ARRAY_BONES=6,
|
|
||||||
ARRAY_WEIGHTS=7,
|
|
||||||
ARRAY_INDEX=8,
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef USE_2D_VERTEX
|
|
||||||
#define VFORMAT vec2
|
|
||||||
#else
|
|
||||||
#define VFORMAT vec3
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* INPUT ATTRIBS */
|
|
||||||
|
|
||||||
layout(location = 0) in highp VFORMAT vertex_attrib;
|
|
||||||
/* clang-format on */
|
|
||||||
layout(location = 1) in vec3 normal_attrib;
|
|
||||||
|
|
||||||
#ifdef ENABLE_TANGENT
|
|
||||||
layout(location = 2) in vec4 tangent_attrib;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_COLOR
|
|
||||||
layout(location = 3) in vec4 color_attrib;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_UV
|
|
||||||
layout(location = 4) in vec2 uv_attrib;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_UV2
|
|
||||||
layout(location = 5) in vec2 uv2_attrib;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_SKELETON
|
|
||||||
layout(location = 6) in ivec4 bone_attrib;
|
|
||||||
layout(location = 7) in vec4 weight_attrib;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* BLEND ATTRIBS */
|
|
||||||
|
|
||||||
#ifdef ENABLE_BLEND
|
|
||||||
|
|
||||||
layout(location = 8) in highp VFORMAT vertex_attrib_blend;
|
|
||||||
layout(location = 9) in vec3 normal_attrib_blend;
|
|
||||||
|
|
||||||
#ifdef ENABLE_TANGENT
|
|
||||||
layout(location = 10) in vec4 tangent_attrib_blend;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_COLOR
|
|
||||||
layout(location = 11) in vec4 color_attrib_blend;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_UV
|
|
||||||
layout(location = 12) in vec2 uv_attrib_blend;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_UV2
|
|
||||||
layout(location = 13) in vec2 uv2_attrib_blend;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_SKELETON
|
|
||||||
layout(location = 14) in ivec4 bone_attrib_blend;
|
|
||||||
layout(location = 15) in vec4 weight_attrib_blend;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* OUTPUTS */
|
|
||||||
|
|
||||||
out VFORMAT vertex_out; //tfb:
|
|
||||||
|
|
||||||
#ifdef ENABLE_NORMAL
|
|
||||||
out vec3 normal_out; //tfb:ENABLE_NORMAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_TANGENT
|
|
||||||
out vec4 tangent_out; //tfb:ENABLE_TANGENT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_COLOR
|
|
||||||
out vec4 color_out; //tfb:ENABLE_COLOR
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_UV
|
|
||||||
out vec2 uv_out; //tfb:ENABLE_UV
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_UV2
|
|
||||||
out vec2 uv2_out; //tfb:ENABLE_UV2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_SKELETON
|
|
||||||
out ivec4 bone_out; //tfb:ENABLE_SKELETON
|
|
||||||
out vec4 weight_out; //tfb:ENABLE_SKELETON
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uniform float blend_amount;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
#ifdef ENABLE_BLEND
|
|
||||||
|
|
||||||
vertex_out = vertex_attrib_blend + vertex_attrib * blend_amount;
|
|
||||||
|
|
||||||
#ifdef ENABLE_NORMAL
|
|
||||||
normal_out = normal_attrib_blend + normal_attrib * blend_amount;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_TANGENT
|
|
||||||
|
|
||||||
tangent_out.xyz = tangent_attrib_blend.xyz + tangent_attrib.xyz * blend_amount;
|
|
||||||
tangent_out.w = tangent_attrib_blend.w; //just copy, no point in blending his
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_COLOR
|
|
||||||
|
|
||||||
color_out = color_attrib_blend + color_attrib * blend_amount;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_UV
|
|
||||||
|
|
||||||
uv_out = uv_attrib_blend + uv_attrib * blend_amount;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_UV2
|
|
||||||
|
|
||||||
uv2_out = uv2_attrib_blend + uv2_attrib * blend_amount;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_SKELETON
|
|
||||||
|
|
||||||
bone_out = bone_attrib_blend;
|
|
||||||
weight_out = weight_attrib_blend + weight_attrib * blend_amount;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else //ENABLE_BLEND
|
|
||||||
|
|
||||||
vertex_out = vertex_attrib * blend_amount;
|
|
||||||
|
|
||||||
#ifdef ENABLE_NORMAL
|
|
||||||
normal_out = normal_attrib * blend_amount;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_TANGENT
|
|
||||||
|
|
||||||
tangent_out.xyz = tangent_attrib.xyz * blend_amount;
|
|
||||||
tangent_out.w = tangent_attrib.w; //just copy, no point in blending his
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_COLOR
|
|
||||||
|
|
||||||
color_out = color_attrib * blend_amount;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_UV
|
|
||||||
|
|
||||||
uv_out = uv_attrib * blend_amount;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_UV2
|
|
||||||
|
|
||||||
uv2_out = uv2_attrib * blend_amount;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_SKELETON
|
|
||||||
|
|
||||||
bone_out = bone_attrib;
|
|
||||||
weight_out = weight_attrib * blend_amount;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
gl_Position = vec4(0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clang-format off */
|
|
||||||
[fragment]
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
|
|
||||||
}
|
|
||||||
/* clang-format on */
|
|
|
@ -1,86 +0,0 @@
|
||||||
/* clang-format off */
|
|
||||||
[vertex]
|
|
||||||
|
|
||||||
layout(location = 0) in highp vec4 vertex_attrib;
|
|
||||||
/* clang-format on */
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = vertex_attrib;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clang-format off */
|
|
||||||
[fragment]
|
|
||||||
|
|
||||||
uniform highp sampler2D source_exposure; //texunit:0
|
|
||||||
/* clang-format on */
|
|
||||||
|
|
||||||
#ifdef EXPOSURE_BEGIN
|
|
||||||
|
|
||||||
uniform highp ivec2 source_render_size;
|
|
||||||
uniform highp ivec2 target_size;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef EXPOSURE_END
|
|
||||||
|
|
||||||
uniform highp sampler2D prev_exposure; //texunit:1
|
|
||||||
uniform highp float exposure_adjust;
|
|
||||||
uniform highp float min_luminance;
|
|
||||||
uniform highp float max_luminance;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
layout(location = 0) out highp float exposure;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
#ifdef EXPOSURE_BEGIN
|
|
||||||
|
|
||||||
ivec2 src_pos = ivec2(gl_FragCoord.xy) * source_render_size / target_size;
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
//more precise and expensive, but less jittery
|
|
||||||
ivec2 next_pos = ivec2(gl_FragCoord.xy + ivec2(1)) * source_render_size / target_size;
|
|
||||||
next_pos = max(next_pos, src_pos + ivec2(1)); //so it at least reads one pixel
|
|
||||||
highp vec3 source_color = vec3(0.0);
|
|
||||||
for (int i = src_pos.x; i < next_pos.x; i++) {
|
|
||||||
for (int j = src_pos.y; j < next_pos.y; j++) {
|
|
||||||
source_color += texelFetch(source_exposure, ivec2(i, j), 0).rgb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
source_color /= float((next_pos.x - src_pos.x) * (next_pos.y - src_pos.y));
|
|
||||||
#else
|
|
||||||
highp vec3 source_color = texelFetch(source_exposure, src_pos, 0).rgb;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
exposure = max(source_color.r, max(source_color.g, source_color.b));
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
ivec2 coord = ivec2(gl_FragCoord.xy);
|
|
||||||
exposure = texelFetch(source_exposure, coord * 3 + ivec2(0, 0), 0).r;
|
|
||||||
exposure += texelFetch(source_exposure, coord * 3 + ivec2(1, 0), 0).r;
|
|
||||||
exposure += texelFetch(source_exposure, coord * 3 + ivec2(2, 0), 0).r;
|
|
||||||
exposure += texelFetch(source_exposure, coord * 3 + ivec2(0, 1), 0).r;
|
|
||||||
exposure += texelFetch(source_exposure, coord * 3 + ivec2(1, 1), 0).r;
|
|
||||||
exposure += texelFetch(source_exposure, coord * 3 + ivec2(2, 1), 0).r;
|
|
||||||
exposure += texelFetch(source_exposure, coord * 3 + ivec2(0, 2), 0).r;
|
|
||||||
exposure += texelFetch(source_exposure, coord * 3 + ivec2(1, 2), 0).r;
|
|
||||||
exposure += texelFetch(source_exposure, coord * 3 + ivec2(2, 2), 0).r;
|
|
||||||
exposure *= (1.0 / 9.0);
|
|
||||||
|
|
||||||
#ifdef EXPOSURE_END
|
|
||||||
|
|
||||||
#ifdef EXPOSURE_FORCE_SET
|
|
||||||
//will stay as is
|
|
||||||
#else
|
|
||||||
highp float prev_lum = texelFetch(prev_exposure, ivec2(0, 0), 0).r; //1 pixel previous exposure
|
|
||||||
exposure = clamp(prev_lum + (exposure - prev_lum) * exposure_adjust, min_luminance, max_luminance);
|
|
||||||
|
|
||||||
#endif //EXPOSURE_FORCE_SET
|
|
||||||
|
|
||||||
#endif //EXPOSURE_END
|
|
||||||
|
|
||||||
#endif //EXPOSURE_BEGIN
|
|
||||||
}
|
|
|
@ -1,260 +0,0 @@
|
||||||
/* clang-format off */
|
|
||||||
[vertex]
|
|
||||||
|
|
||||||
layout(location = 0) in highp vec4 color;
|
|
||||||
/* clang-format on */
|
|
||||||
layout(location = 1) in highp vec4 velocity_active;
|
|
||||||
layout(location = 2) in highp vec4 custom;
|
|
||||||
layout(location = 3) in highp vec4 xform_1;
|
|
||||||
layout(location = 4) in highp vec4 xform_2;
|
|
||||||
layout(location = 5) in highp vec4 xform_3;
|
|
||||||
|
|
||||||
struct Attractor {
|
|
||||||
vec3 pos;
|
|
||||||
vec3 dir;
|
|
||||||
float radius;
|
|
||||||
float eat_radius;
|
|
||||||
float strength;
|
|
||||||
float attenuation;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAX_ATTRACTORS 64
|
|
||||||
|
|
||||||
uniform bool emitting;
|
|
||||||
uniform float system_phase;
|
|
||||||
uniform float prev_system_phase;
|
|
||||||
uniform int total_particles;
|
|
||||||
uniform float explosiveness;
|
|
||||||
uniform float randomness;
|
|
||||||
uniform float time;
|
|
||||||
uniform float delta;
|
|
||||||
|
|
||||||
uniform int attractor_count;
|
|
||||||
uniform Attractor attractors[MAX_ATTRACTORS];
|
|
||||||
uniform bool clear;
|
|
||||||
uniform uint cycle;
|
|
||||||
uniform float lifetime;
|
|
||||||
uniform mat4 emission_transform;
|
|
||||||
uniform uint random_seed;
|
|
||||||
|
|
||||||
out highp vec4 out_color; //tfb:
|
|
||||||
out highp vec4 out_velocity_active; //tfb:
|
|
||||||
out highp vec4 out_custom; //tfb:
|
|
||||||
out highp vec4 out_xform_1; //tfb:
|
|
||||||
out highp vec4 out_xform_2; //tfb:
|
|
||||||
out highp vec4 out_xform_3; //tfb:
|
|
||||||
|
|
||||||
#if defined(USE_MATERIAL)
|
|
||||||
|
|
||||||
/* clang-format off */
|
|
||||||
layout(std140) uniform UniformData { //ubo:0
|
|
||||||
|
|
||||||
MATERIAL_UNIFORMS
|
|
||||||
|
|
||||||
};
|
|
||||||
/* clang-format on */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* clang-format off */
|
|
||||||
|
|
||||||
VERTEX_SHADER_GLOBALS
|
|
||||||
|
|
||||||
/* clang-format on */
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
#ifdef PARTICLES_COPY
|
|
||||||
|
|
||||||
out_color = color;
|
|
||||||
out_velocity_active = velocity_active;
|
|
||||||
out_custom = custom;
|
|
||||||
out_xform_1 = xform_1;
|
|
||||||
out_xform_2 = xform_2;
|
|
||||||
out_xform_3 = xform_3;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
bool apply_forces = true;
|
|
||||||
bool apply_velocity = true;
|
|
||||||
float local_delta = delta;
|
|
||||||
|
|
||||||
float mass = 1.0;
|
|
||||||
|
|
||||||
float restart_phase = float(gl_VertexID) / float(total_particles);
|
|
||||||
|
|
||||||
if (randomness > 0.0) {
|
|
||||||
uint seed = cycle;
|
|
||||||
if (restart_phase >= system_phase) {
|
|
||||||
seed -= uint(1);
|
|
||||||
}
|
|
||||||
seed *= uint(total_particles);
|
|
||||||
seed += uint(gl_VertexID);
|
|
||||||
float random = float(hash(seed) % uint(65536)) / 65536.0;
|
|
||||||
restart_phase += randomness * random * 1.0 / float(total_particles);
|
|
||||||
}
|
|
||||||
|
|
||||||
restart_phase *= (1.0 - explosiveness);
|
|
||||||
bool restart = false;
|
|
||||||
bool shader_active = velocity_active.a > 0.5;
|
|
||||||
|
|
||||||
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;
|
|
||||||
#ifdef USE_FRACTIONAL_DELTA
|
|
||||||
local_delta = (system_phase - restart_phase) * lifetime;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (restart_phase >= prev_system_phase) {
|
|
||||||
restart = true;
|
|
||||||
#ifdef USE_FRACTIONAL_DELTA
|
|
||||||
local_delta = (1.0 - restart_phase + system_phase) * lifetime;
|
|
||||||
#endif
|
|
||||||
} else if (restart_phase < system_phase) {
|
|
||||||
restart = true;
|
|
||||||
#ifdef USE_FRACTIONAL_DELTA
|
|
||||||
local_delta = (system_phase - restart_phase) * lifetime;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint current_cycle = cycle;
|
|
||||||
|
|
||||||
if (system_phase < restart_phase) {
|
|
||||||
current_cycle -= uint(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint particle_number = current_cycle * uint(total_particles) + uint(gl_VertexID);
|
|
||||||
int index = int(gl_VertexID);
|
|
||||||
|
|
||||||
if (restart) {
|
|
||||||
shader_active = emitting;
|
|
||||||
}
|
|
||||||
|
|
||||||
mat4 xform;
|
|
||||||
|
|
||||||
#if defined(ENABLE_KEEP_DATA)
|
|
||||||
if (clear) {
|
|
||||||
#else
|
|
||||||
if (clear || restart) {
|
|
||||||
#endif
|
|
||||||
out_color = vec4(1.0);
|
|
||||||
out_velocity_active = vec4(0.0);
|
|
||||||
out_custom = vec4(0.0);
|
|
||||||
if (!restart)
|
|
||||||
shader_active = false;
|
|
||||||
|
|
||||||
xform = mat4(
|
|
||||||
vec4(1.0, 0.0, 0.0, 0.0),
|
|
||||||
vec4(0.0, 1.0, 0.0, 0.0),
|
|
||||||
vec4(0.0, 0.0, 1.0, 0.0),
|
|
||||||
vec4(0.0, 0.0, 0.0, 1.0));
|
|
||||||
} else {
|
|
||||||
out_color = color;
|
|
||||||
out_velocity_active = velocity_active;
|
|
||||||
out_custom = custom;
|
|
||||||
xform = transpose(mat4(xform_1, xform_2, xform_3, vec4(vec3(0.0), 1.0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shader_active) {
|
|
||||||
//execute shader
|
|
||||||
|
|
||||||
{
|
|
||||||
/* clang-format off */
|
|
||||||
|
|
||||||
VERTEX_SHADER_CODE
|
|
||||||
|
|
||||||
/* clang-format on */
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(DISABLE_FORCE)
|
|
||||||
|
|
||||||
if (false) {
|
|
||||||
vec3 force = vec3(0.0);
|
|
||||||
for (int i = 0; i < attractor_count; i++) {
|
|
||||||
vec3 rel_vec = xform[3].xyz - attractors[i].pos;
|
|
||||||
float dist = length(rel_vec);
|
|
||||||
if (attractors[i].radius < dist)
|
|
||||||
continue;
|
|
||||||
if (attractors[i].eat_radius > 0.0 && attractors[i].eat_radius > dist) {
|
|
||||||
out_velocity_active.a = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
rel_vec = normalize(rel_vec);
|
|
||||||
|
|
||||||
float attenuation = pow(dist / attractors[i].radius, attractors[i].attenuation);
|
|
||||||
|
|
||||||
if (attractors[i].dir == vec3(0.0)) {
|
|
||||||
//towards center
|
|
||||||
force += attractors[i].strength * rel_vec * attenuation * mass;
|
|
||||||
} else {
|
|
||||||
force += attractors[i].strength * attractors[i].dir * attenuation * mass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out_velocity_active.xyz += force * local_delta;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(DISABLE_VELOCITY)
|
|
||||||
|
|
||||||
if (true) {
|
|
||||||
xform[3].xyz += out_velocity_active.xyz * local_delta;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
xform = mat4(0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
xform = transpose(xform);
|
|
||||||
|
|
||||||
out_velocity_active.a = mix(0.0, 1.0, shader_active);
|
|
||||||
|
|
||||||
out_xform_1 = xform[0];
|
|
||||||
out_xform_2 = xform[1];
|
|
||||||
out_xform_3 = xform[2];
|
|
||||||
|
|
||||||
#endif //PARTICLES_COPY
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clang-format off */
|
|
||||||
[fragment]
|
|
||||||
|
|
||||||
//any code here is never executed, stuff is filled just so it works
|
|
||||||
|
|
||||||
#if defined(USE_MATERIAL)
|
|
||||||
|
|
||||||
layout(std140) uniform UniformData {
|
|
||||||
|
|
||||||
MATERIAL_UNIFORMS
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FRAGMENT_SHADER_GLOBALS
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
{
|
|
||||||
|
|
||||||
LIGHT_SHADER_CODE
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
FRAGMENT_SHADER_CODE
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* clang-format on */
|
|
|
@ -1,42 +0,0 @@
|
||||||
/* clang-format off */
|
|
||||||
[vertex]
|
|
||||||
|
|
||||||
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]
|
|
||||||
|
|
||||||
#if !defined(GLES_OVER_GL)
|
|
||||||
precision mediump float;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
in vec2 uv_interp;
|
|
||||||
/* clang-format on */
|
|
||||||
uniform sampler2D source_specular; //texunit:0
|
|
||||||
uniform sampler2D source_ssr; //texunit:1
|
|
||||||
|
|
||||||
uniform vec2 pixel_size;
|
|
||||||
|
|
||||||
in vec2 uv2_interp;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 frag_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 specular = texture(source_specular, uv_interp);
|
|
||||||
|
|
||||||
#ifdef USE_SSR
|
|
||||||
vec4 ssr = textureLod(source_ssr, uv_interp, 0.0);
|
|
||||||
specular.rgb = mix(specular.rgb, ssr.rgb * specular.a, ssr.a);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
frag_color = vec4(specular.rgb, 1.0);
|
|
||||||
}
|
|
|
@ -1,284 +0,0 @@
|
||||||
/* clang-format off */
|
|
||||||
[vertex]
|
|
||||||
|
|
||||||
layout(location = 0) in highp vec4 vertex_attrib;
|
|
||||||
/* clang-format on */
|
|
||||||
layout(location = 4) in vec2 uv_in;
|
|
||||||
|
|
||||||
out vec2 uv_interp;
|
|
||||||
out vec2 pos_interp;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
uv_interp = uv_in;
|
|
||||||
gl_Position = vertex_attrib;
|
|
||||||
pos_interp.xy = gl_Position.xy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clang-format off */
|
|
||||||
[fragment]
|
|
||||||
|
|
||||||
in vec2 uv_interp;
|
|
||||||
/* clang-format on */
|
|
||||||
in vec2 pos_interp;
|
|
||||||
|
|
||||||
uniform sampler2D source_diffuse; //texunit:0
|
|
||||||
uniform sampler2D source_normal_roughness; //texunit:1
|
|
||||||
uniform sampler2D source_depth; //texunit:2
|
|
||||||
|
|
||||||
uniform float camera_z_near;
|
|
||||||
uniform float camera_z_far;
|
|
||||||
|
|
||||||
uniform vec2 viewport_size;
|
|
||||||
uniform vec2 pixel_size;
|
|
||||||
|
|
||||||
uniform float filter_mipmap_levels;
|
|
||||||
|
|
||||||
uniform mat4 inverse_projection;
|
|
||||||
uniform mat4 projection;
|
|
||||||
|
|
||||||
uniform int num_steps;
|
|
||||||
uniform float depth_tolerance;
|
|
||||||
uniform float distance_fade;
|
|
||||||
uniform float curve_fade_in;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 frag_color;
|
|
||||||
|
|
||||||
vec2 view_to_screen(vec3 view_pos, out float w) {
|
|
||||||
vec4 projected = projection * vec4(view_pos, 1.0);
|
|
||||||
projected.xyz /= projected.w;
|
|
||||||
projected.xy = projected.xy * 0.5 + 0.5;
|
|
||||||
w = projected.w;
|
|
||||||
return projected.xy;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define M_PI 3.14159265359
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 diffuse = texture(source_diffuse, uv_interp);
|
|
||||||
vec4 normal_roughness = texture(source_normal_roughness, uv_interp);
|
|
||||||
|
|
||||||
vec3 normal;
|
|
||||||
|
|
||||||
normal = normal_roughness.xyz * 2.0 - 1.0;
|
|
||||||
|
|
||||||
float roughness = normal_roughness.w;
|
|
||||||
|
|
||||||
float depth_tex = texture(source_depth, uv_interp).r;
|
|
||||||
|
|
||||||
vec4 world_pos = inverse_projection * vec4(uv_interp * 2.0 - 1.0, depth_tex * 2.0 - 1.0, 1.0);
|
|
||||||
vec3 vertex = world_pos.xyz / world_pos.w;
|
|
||||||
|
|
||||||
vec3 view_dir = normalize(vertex);
|
|
||||||
vec3 ray_dir = normalize(reflect(view_dir, normal));
|
|
||||||
|
|
||||||
if (dot(ray_dir, normal) < 0.001) {
|
|
||||||
frag_color = vec4(0.0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//ray_dir = normalize(view_dir - normal * dot(normal,view_dir) * 2.0);
|
|
||||||
|
|
||||||
//ray_dir = normalize(vec3(1,1,-1));
|
|
||||||
|
|
||||||
////////////////
|
|
||||||
|
|
||||||
//make ray length and clip it against the near plane (don't want to trace beyond visible)
|
|
||||||
float ray_len = (vertex.z + ray_dir.z * camera_z_far) > -camera_z_near ? (-camera_z_near - vertex.z) / ray_dir.z : camera_z_far;
|
|
||||||
vec3 ray_end = vertex + ray_dir * ray_len;
|
|
||||||
|
|
||||||
float w_begin;
|
|
||||||
vec2 vp_line_begin = view_to_screen(vertex, w_begin);
|
|
||||||
float w_end;
|
|
||||||
vec2 vp_line_end = view_to_screen(ray_end, w_end);
|
|
||||||
vec2 vp_line_dir = vp_line_end - vp_line_begin;
|
|
||||||
|
|
||||||
//we need to interpolate w along the ray, to generate perspective correct reflections
|
|
||||||
|
|
||||||
w_begin = 1.0 / w_begin;
|
|
||||||
w_end = 1.0 / w_end;
|
|
||||||
|
|
||||||
float z_begin = vertex.z * w_begin;
|
|
||||||
float z_end = ray_end.z * w_end;
|
|
||||||
|
|
||||||
vec2 line_begin = vp_line_begin / pixel_size;
|
|
||||||
vec2 line_dir = vp_line_dir / pixel_size;
|
|
||||||
float z_dir = z_end - z_begin;
|
|
||||||
float w_dir = w_end - w_begin;
|
|
||||||
|
|
||||||
// clip the line to the viewport edges
|
|
||||||
|
|
||||||
float scale_max_x = min(1.0, 0.99 * (1.0 - vp_line_begin.x) / max(1e-5, vp_line_dir.x));
|
|
||||||
float scale_max_y = min(1.0, 0.99 * (1.0 - vp_line_begin.y) / max(1e-5, vp_line_dir.y));
|
|
||||||
float scale_min_x = min(1.0, 0.99 * vp_line_begin.x / max(1e-5, -vp_line_dir.x));
|
|
||||||
float scale_min_y = min(1.0, 0.99 * vp_line_begin.y / max(1e-5, -vp_line_dir.y));
|
|
||||||
float line_clip = min(scale_max_x, scale_max_y) * min(scale_min_x, scale_min_y);
|
|
||||||
line_dir *= line_clip;
|
|
||||||
z_dir *= line_clip;
|
|
||||||
w_dir *= line_clip;
|
|
||||||
|
|
||||||
//clip z and w advance to line advance
|
|
||||||
vec2 line_advance = normalize(line_dir); //down to pixel
|
|
||||||
float step_size = length(line_advance) / length(line_dir);
|
|
||||||
float z_advance = z_dir * step_size; // adapt z advance to line advance
|
|
||||||
float w_advance = w_dir * step_size; // adapt w advance to line advance
|
|
||||||
|
|
||||||
//make line advance faster if direction is closer to pixel edges (this avoids sampling the same pixel twice)
|
|
||||||
float advance_angle_adj = 1.0 / max(abs(line_advance.x), abs(line_advance.y));
|
|
||||||
line_advance *= advance_angle_adj; // adapt z advance to line advance
|
|
||||||
z_advance *= advance_angle_adj;
|
|
||||||
w_advance *= advance_angle_adj;
|
|
||||||
|
|
||||||
vec2 pos = line_begin;
|
|
||||||
float z = z_begin;
|
|
||||||
float w = w_begin;
|
|
||||||
float z_from = z / w;
|
|
||||||
float z_to = z_from;
|
|
||||||
float depth;
|
|
||||||
vec2 prev_pos = pos;
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
float steps_taken = 0.0;
|
|
||||||
|
|
||||||
for (int i = 0; i < num_steps; i++) {
|
|
||||||
pos += line_advance;
|
|
||||||
z += z_advance;
|
|
||||||
w += w_advance;
|
|
||||||
|
|
||||||
//convert to linear depth
|
|
||||||
|
|
||||||
depth = texture(source_depth, pos * pixel_size).r * 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
|
|
||||||
depth = -depth;
|
|
||||||
|
|
||||||
z_from = z_to;
|
|
||||||
z_to = z / w;
|
|
||||||
|
|
||||||
if (depth > z_to) {
|
|
||||||
//if depth was surpassed
|
|
||||||
if (depth <= max(z_to, z_from) + depth_tolerance) {
|
|
||||||
//check the depth tolerance
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
steps_taken += 1.0;
|
|
||||||
prev_pos = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
float margin_blend = 1.0;
|
|
||||||
|
|
||||||
vec2 margin = vec2((viewport_size.x + viewport_size.y) * 0.5 * 0.05); //make a uniform margin
|
|
||||||
if (any(bvec4(lessThan(pos, -margin), greaterThan(pos, viewport_size + margin)))) {
|
|
||||||
//clip outside screen + margin
|
|
||||||
frag_color = vec4(0.0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
//blend fading out towards external margin
|
|
||||||
vec2 margin_grad = mix(pos - viewport_size, -pos, lessThan(pos, vec2(0.0)));
|
|
||||||
margin_blend = 1.0 - smoothstep(0.0, margin.x, max(margin_grad.x, margin_grad.y));
|
|
||||||
//margin_blend=1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 final_pos;
|
|
||||||
float grad;
|
|
||||||
grad = steps_taken / float(num_steps);
|
|
||||||
float initial_fade = curve_fade_in == 0.0 ? 1.0 : pow(clamp(grad, 0.0, 1.0), curve_fade_in);
|
|
||||||
float fade = pow(clamp(1.0 - grad, 0.0, 1.0), distance_fade) * initial_fade;
|
|
||||||
final_pos = pos;
|
|
||||||
|
|
||||||
#ifdef REFLECT_ROUGHNESS
|
|
||||||
|
|
||||||
vec4 final_color;
|
|
||||||
//if roughness is enabled, do screen space cone tracing
|
|
||||||
if (roughness > 0.001) {
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//use a blurred version (in consecutive mipmaps) of the screen to simulate roughness
|
|
||||||
|
|
||||||
float gloss = 1.0 - roughness;
|
|
||||||
float cone_angle = roughness * M_PI * 0.5;
|
|
||||||
vec2 cone_dir = final_pos - line_begin;
|
|
||||||
float cone_len = length(cone_dir);
|
|
||||||
cone_dir = normalize(cone_dir); //will be used normalized from now on
|
|
||||||
float max_mipmap = filter_mipmap_levels - 1.0;
|
|
||||||
float gloss_mult = gloss;
|
|
||||||
|
|
||||||
float rem_alpha = 1.0;
|
|
||||||
final_color = vec4(0.0);
|
|
||||||
|
|
||||||
for (int i = 0; i < 7; i++) {
|
|
||||||
float op_len = 2.0 * tan(cone_angle) * cone_len; //opposite side of iso triangle
|
|
||||||
float radius;
|
|
||||||
{
|
|
||||||
//fit to sphere inside cone (sphere ends at end of cone), something like this:
|
|
||||||
// ___
|
|
||||||
// \O/
|
|
||||||
// V
|
|
||||||
//
|
|
||||||
// as it avoids bleeding from beyond the reflection as much as possible. As a plus
|
|
||||||
// it also makes the rough reflection more elongated.
|
|
||||||
float a = op_len;
|
|
||||||
float h = cone_len;
|
|
||||||
float a2 = a * a;
|
|
||||||
float fh2 = 4.0f * h * h;
|
|
||||||
radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h);
|
|
||||||
}
|
|
||||||
|
|
||||||
//find the place where screen must be sampled
|
|
||||||
vec2 sample_pos = (line_begin + cone_dir * (cone_len - radius)) * pixel_size;
|
|
||||||
//radius is in pixels, so it's natural that log2(radius) maps to the right mipmap for the amount of pixels
|
|
||||||
float mipmap = clamp(log2(radius), 0.0, max_mipmap);
|
|
||||||
|
|
||||||
//mipmap = max(mipmap-1.0,0.0);
|
|
||||||
//do sampling
|
|
||||||
|
|
||||||
vec4 sample_color;
|
|
||||||
{
|
|
||||||
sample_color = textureLod(source_diffuse, sample_pos, mipmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
//multiply by gloss
|
|
||||||
sample_color.rgb *= gloss_mult;
|
|
||||||
sample_color.a = gloss_mult;
|
|
||||||
|
|
||||||
rem_alpha -= sample_color.a;
|
|
||||||
if (rem_alpha < 0.0) {
|
|
||||||
sample_color.rgb *= (1.0 - abs(rem_alpha));
|
|
||||||
}
|
|
||||||
|
|
||||||
final_color += sample_color;
|
|
||||||
|
|
||||||
if (final_color.a >= 0.95) {
|
|
||||||
// This code of accumulating gloss and aborting on near one
|
|
||||||
// makes sense when you think of cone tracing.
|
|
||||||
// Think of it as if roughness was 0, then we could abort on the first
|
|
||||||
// iteration. For lesser roughness values, we need more iterations, but
|
|
||||||
// each needs to have less influence given the sphere is smaller
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cone_len -= radius * 2.0; //go to next (smaller) circle.
|
|
||||||
|
|
||||||
gloss_mult *= gloss;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final_color = textureLod(source_diffuse, final_pos * pixel_size, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
frag_color = vec4(final_color.rgb, fade * margin_blend);
|
|
||||||
|
|
||||||
#else
|
|
||||||
frag_color = vec4(textureLod(source_diffuse, final_pos * pixel_size, 0.0).rgb, fade * margin_blend);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} else {
|
|
||||||
frag_color = vec4(0.0, 0.0, 0.0, 0.0);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,283 +0,0 @@
|
||||||
/* clang-format off */
|
|
||||||
[vertex]
|
|
||||||
|
|
||||||
layout(location = 0) in highp vec4 vertex_attrib;
|
|
||||||
/* clang-format on */
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = vertex_attrib;
|
|
||||||
gl_Position.z = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clang-format off */
|
|
||||||
[fragment]
|
|
||||||
|
|
||||||
#define TWO_PI 6.283185307179586476925286766559
|
|
||||||
|
|
||||||
#ifdef SSAO_QUALITY_HIGH
|
|
||||||
|
|
||||||
#define NUM_SAMPLES (80)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SSAO_QUALITY_LOW
|
|
||||||
|
|
||||||
#define NUM_SAMPLES (15)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(SSAO_QUALITY_LOW) && !defined(SSAO_QUALITY_HIGH)
|
|
||||||
|
|
||||||
#define NUM_SAMPLES (40)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower
|
|
||||||
// miplevel to maintain reasonable spatial locality in the cache
|
|
||||||
// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing.
|
|
||||||
// If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively
|
|
||||||
#define LOG_MAX_OFFSET (3)
|
|
||||||
|
|
||||||
// This must be less than or equal to the MAX_MIP_LEVEL defined in SSAO.cpp
|
|
||||||
#define MAX_MIP_LEVEL (4)
|
|
||||||
|
|
||||||
// This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent
|
|
||||||
// taps from lining up. This particular choice was tuned for NUM_SAMPLES == 9
|
|
||||||
|
|
||||||
const int ROTATIONS[] = int[](
|
|
||||||
1, 1, 2, 3, 2, 5, 2, 3, 2,
|
|
||||||
3, 3, 5, 5, 3, 4, 7, 5, 5, 7,
|
|
||||||
9, 8, 5, 5, 7, 7, 7, 8, 5, 8,
|
|
||||||
11, 12, 7, 10, 13, 8, 11, 8, 7, 14,
|
|
||||||
11, 11, 13, 12, 13, 19, 17, 13, 11, 18,
|
|
||||||
19, 11, 11, 14, 17, 21, 15, 16, 17, 18,
|
|
||||||
13, 17, 11, 17, 19, 18, 25, 18, 19, 19,
|
|
||||||
29, 21, 19, 27, 31, 29, 21, 18, 17, 29,
|
|
||||||
31, 31, 23, 18, 25, 26, 25, 23, 19, 34,
|
|
||||||
19, 27, 21, 25, 39, 29, 17, 21, 27);
|
|
||||||
/* clang-format on */
|
|
||||||
|
|
||||||
//#define NUM_SPIRAL_TURNS (7)
|
|
||||||
const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES - 1];
|
|
||||||
|
|
||||||
uniform sampler2D source_depth; //texunit:0
|
|
||||||
uniform highp usampler2D source_depth_mipmaps; //texunit:1
|
|
||||||
uniform sampler2D source_normal; //texunit:2
|
|
||||||
|
|
||||||
uniform ivec2 screen_size;
|
|
||||||
uniform float camera_z_far;
|
|
||||||
uniform float camera_z_near;
|
|
||||||
|
|
||||||
uniform float intensity_div_r6;
|
|
||||||
uniform float radius;
|
|
||||||
|
|
||||||
#ifdef ENABLE_RADIUS2
|
|
||||||
uniform float intensity_div_r62;
|
|
||||||
uniform float radius2;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uniform float bias;
|
|
||||||
uniform float proj_scale;
|
|
||||||
|
|
||||||
layout(location = 0) out float visibility;
|
|
||||||
|
|
||||||
uniform vec4 proj_info;
|
|
||||||
|
|
||||||
vec3 reconstructCSPosition(vec2 S, float z) {
|
|
||||||
#ifdef USE_ORTHOGONAL_PROJECTION
|
|
||||||
return vec3((S.xy * proj_info.xy + proj_info.zw), z);
|
|
||||||
#else
|
|
||||||
return vec3((S.xy * proj_info.xy + proj_info.zw) * z, z);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 getPosition(ivec2 ssP) {
|
|
||||||
vec3 P;
|
|
||||||
P.z = texelFetch(source_depth, ssP, 0).r;
|
|
||||||
|
|
||||||
P.z = P.z * 2.0 - 1.0;
|
|
||||||
#ifdef USE_ORTHOGONAL_PROJECTION
|
|
||||||
P.z = ((P.z + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
|
|
||||||
#else
|
|
||||||
P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near));
|
|
||||||
#endif
|
|
||||||
P.z = -P.z;
|
|
||||||
|
|
||||||
// Offset to pixel center
|
|
||||||
P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z);
|
|
||||||
return P;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Reconstructs screen-space unit normal from screen-space position */
|
|
||||||
vec3 reconstructCSFaceNormal(vec3 C) {
|
|
||||||
return normalize(cross(dFdy(C), dFdx(C)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */
|
|
||||||
vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR) {
|
|
||||||
// Radius relative to ssR
|
|
||||||
float alpha = (float(sampleNumber) + 0.5) * (1.0 / float(NUM_SAMPLES));
|
|
||||||
float angle = alpha * (float(NUM_SPIRAL_TURNS) * 6.28) + spinAngle;
|
|
||||||
|
|
||||||
ssR = alpha;
|
|
||||||
return vec2(cos(angle), sin(angle));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR. Assumes length(unitOffset) == 1 */
|
|
||||||
vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR) {
|
|
||||||
// Derivation:
|
|
||||||
// mipLevel = floor(log(ssR / MAX_OFFSET));
|
|
||||||
int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL);
|
|
||||||
|
|
||||||
ivec2 ssP = ivec2(ssR * unitOffset) + ssC;
|
|
||||||
|
|
||||||
vec3 P;
|
|
||||||
|
|
||||||
// We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map.
|
|
||||||
// Manually clamp to the texture size because texelFetch bypasses the texture unit
|
|
||||||
ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), (screen_size >> mipLevel) - ivec2(1));
|
|
||||||
|
|
||||||
if (mipLevel < 1) {
|
|
||||||
//read from depth buffer
|
|
||||||
P.z = texelFetch(source_depth, mipP, 0).r;
|
|
||||||
P.z = P.z * 2.0 - 1.0;
|
|
||||||
#ifdef USE_ORTHOGONAL_PROJECTION
|
|
||||||
P.z = ((P.z + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
|
|
||||||
#else
|
|
||||||
P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near));
|
|
||||||
|
|
||||||
#endif
|
|
||||||
P.z = -P.z;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
//read from mipmaps
|
|
||||||
uint d = texelFetch(source_depth_mipmaps, mipP, mipLevel - 1).r;
|
|
||||||
P.z = -(float(d) / 65535.0) * camera_z_far;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Offset to pixel center
|
|
||||||
P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z);
|
|
||||||
|
|
||||||
return P;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds
|
|
||||||
to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius
|
|
||||||
|
|
||||||
Note that units of H() in the HPG12 paper are meters, not
|
|
||||||
unitless. The whole falloff/sampling function is therefore
|
|
||||||
unitless. In this implementation, we factor out (9 / radius).
|
|
||||||
|
|
||||||
Four versions of the falloff function are implemented below
|
|
||||||
*/
|
|
||||||
float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in float p_radius, in int tapIndex, in float randomPatternRotationAngle) {
|
|
||||||
// Offset on the unit disk, spun for this pixel
|
|
||||||
float ssR;
|
|
||||||
vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR);
|
|
||||||
ssR *= ssDiskRadius;
|
|
||||||
|
|
||||||
// The occluding point in camera space
|
|
||||||
vec3 Q = getOffsetPosition(ssC, unitOffset, ssR);
|
|
||||||
|
|
||||||
vec3 v = Q - C;
|
|
||||||
|
|
||||||
float vv = dot(v, v);
|
|
||||||
float vn = dot(v, n_C);
|
|
||||||
|
|
||||||
const float epsilon = 0.01;
|
|
||||||
float radius2 = p_radius * p_radius;
|
|
||||||
|
|
||||||
// A: From the HPG12 paper
|
|
||||||
// Note large epsilon to avoid overdarkening within cracks
|
|
||||||
//return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6;
|
|
||||||
|
|
||||||
// B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended]
|
|
||||||
float f = max(radius2 - vv, 0.0);
|
|
||||||
return f * f * f * max((vn - bias) / (epsilon + vv), 0.0);
|
|
||||||
|
|
||||||
// C: Medium contrast (which looks better at high radii), no division. Note that the
|
|
||||||
// contribution still falls off with radius^2, but we've adjusted the rate in a way that is
|
|
||||||
// more computationally efficient and happens to be aesthetically pleasing.
|
|
||||||
// return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0);
|
|
||||||
|
|
||||||
// D: Low contrast, no division operation
|
|
||||||
// return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
// Pixel being shaded
|
|
||||||
ivec2 ssC = ivec2(gl_FragCoord.xy);
|
|
||||||
|
|
||||||
// World space point being shaded
|
|
||||||
vec3 C = getPosition(ssC);
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (C.z <= -camera_z_far*0.999) {
|
|
||||||
// We're on the skybox
|
|
||||||
visibility=1.0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//visibility=-C.z/camera_z_far;
|
|
||||||
//return;
|
|
||||||
#if 0
|
|
||||||
vec3 n_C = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0;
|
|
||||||
#else
|
|
||||||
vec3 n_C = reconstructCSFaceNormal(C);
|
|
||||||
n_C = -n_C;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Hash function used in the HPG12 AlchemyAO paper
|
|
||||||
float randomPatternRotationAngle = mod(float((3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10), TWO_PI);
|
|
||||||
|
|
||||||
// Reconstruct normals from positions. These will lead to 1-pixel black lines
|
|
||||||
// at depth discontinuities, however the blur will wipe those out so they are not visible
|
|
||||||
// in the final image.
|
|
||||||
|
|
||||||
// Choose the screen-space sample radius
|
|
||||||
// proportional to the projected area of the sphere
|
|
||||||
#ifdef USE_ORTHOGONAL_PROJECTION
|
|
||||||
float ssDiskRadius = -proj_scale * radius;
|
|
||||||
#else
|
|
||||||
float ssDiskRadius = -proj_scale * radius / C.z;
|
|
||||||
#endif
|
|
||||||
float sum = 0.0;
|
|
||||||
for (int i = 0; i < NUM_SAMPLES; ++i) {
|
|
||||||
sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius, i, randomPatternRotationAngle);
|
|
||||||
}
|
|
||||||
|
|
||||||
float A = max(0.0, 1.0 - sum * intensity_div_r6 * (5.0 / float(NUM_SAMPLES)));
|
|
||||||
|
|
||||||
#ifdef ENABLE_RADIUS2
|
|
||||||
|
|
||||||
//go again for radius2
|
|
||||||
randomPatternRotationAngle = mod(float((5 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 11), TWO_PI);
|
|
||||||
|
|
||||||
// Reconstruct normals from positions. These will lead to 1-pixel black lines
|
|
||||||
// at depth discontinuities, however the blur will wipe those out so they are not visible
|
|
||||||
// in the final image.
|
|
||||||
|
|
||||||
// Choose the screen-space sample radius
|
|
||||||
// proportional to the projected area of the sphere
|
|
||||||
ssDiskRadius = -proj_scale * radius2 / C.z;
|
|
||||||
|
|
||||||
sum = 0.0;
|
|
||||||
for (int i = 0; i < NUM_SAMPLES; ++i) {
|
|
||||||
sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius2, i, randomPatternRotationAngle);
|
|
||||||
}
|
|
||||||
|
|
||||||
A = min(A, max(0.0, 1.0 - sum * intensity_div_r62 * (5.0 / float(NUM_SAMPLES))));
|
|
||||||
#endif
|
|
||||||
// Bilateral box-filter over a quad for free, respecting depth edges
|
|
||||||
// (the difference that this makes is subtle)
|
|
||||||
if (abs(dFdx(C.z)) < 0.02) {
|
|
||||||
A -= dFdx(A) * (float(ssC.x & 1) - 0.5);
|
|
||||||
}
|
|
||||||
if (abs(dFdy(C.z)) < 0.02) {
|
|
||||||
A -= dFdy(A) * (float(ssC.y & 1) - 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
visibility = A;
|
|
||||||
}
|
|
|
@ -1,116 +0,0 @@
|
||||||
/* clang-format off */
|
|
||||||
[vertex]
|
|
||||||
|
|
||||||
layout(location = 0) in highp vec4 vertex_attrib;
|
|
||||||
/* clang-format on */
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = vertex_attrib;
|
|
||||||
gl_Position.z = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clang-format off */
|
|
||||||
[fragment]
|
|
||||||
|
|
||||||
uniform sampler2D source_ssao; //texunit:0
|
|
||||||
/* clang-format on */
|
|
||||||
uniform sampler2D source_depth; //texunit:1
|
|
||||||
uniform sampler2D source_normal; //texunit:3
|
|
||||||
|
|
||||||
layout(location = 0) out float visibility;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Tunable Parameters:
|
|
||||||
|
|
||||||
/** Increase to make depth edges crisper. Decrease to reduce flicker. */
|
|
||||||
uniform float edge_sharpness;
|
|
||||||
|
|
||||||
/** Step in 2-pixel intervals since we already blurred against neighbors in the
|
|
||||||
first AO pass. This constant can be increased while R decreases to improve
|
|
||||||
performance at the expense of some dithering artifacts.
|
|
||||||
|
|
||||||
Morgan found that a scale of 3 left a 1-pixel checkerboard grid that was
|
|
||||||
unobjectionable after shading was applied but eliminated most temporal incoherence
|
|
||||||
from using small numbers of sample taps.
|
|
||||||
*/
|
|
||||||
|
|
||||||
uniform int filter_scale;
|
|
||||||
|
|
||||||
/** Filter radius in pixels. This will be multiplied by SCALE. */
|
|
||||||
#define R (4)
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Gaussian coefficients
|
|
||||||
const float gaussian[R + 1] =
|
|
||||||
//float[](0.356642, 0.239400, 0.072410, 0.009869);
|
|
||||||
//float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0
|
|
||||||
float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0
|
|
||||||
//float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0
|
|
||||||
|
|
||||||
/** (1, 0) or (0, 1)*/
|
|
||||||
uniform ivec2 axis;
|
|
||||||
|
|
||||||
uniform float camera_z_far;
|
|
||||||
uniform float camera_z_near;
|
|
||||||
|
|
||||||
uniform ivec2 screen_size;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
ivec2 ssC = ivec2(gl_FragCoord.xy);
|
|
||||||
|
|
||||||
float depth = texelFetch(source_depth, ssC, 0).r;
|
|
||||||
//vec3 normal = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0;
|
|
||||||
|
|
||||||
depth = depth * 2.0 - 1.0;
|
|
||||||
depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
|
|
||||||
|
|
||||||
float depth_divide = 1.0 / camera_z_far;
|
|
||||||
|
|
||||||
//depth *= depth_divide;
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (depth > camera_z_far * 0.999) {
|
|
||||||
discard; //skybox
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
float sum = texelFetch(source_ssao, ssC, 0).r;
|
|
||||||
|
|
||||||
// Base weight for depth falloff. Increase this for more blurriness,
|
|
||||||
// decrease it for better edge discrimination
|
|
||||||
float BASE = gaussian[0];
|
|
||||||
float totalWeight = BASE;
|
|
||||||
sum *= totalWeight;
|
|
||||||
|
|
||||||
ivec2 clamp_limit = screen_size - ivec2(1);
|
|
||||||
|
|
||||||
for (int r = -R; r <= R; ++r) {
|
|
||||||
// We already handled the zero case above. This loop should be unrolled and the static branch optimized out,
|
|
||||||
// so the IF statement has no runtime cost
|
|
||||||
if (r != 0) {
|
|
||||||
ivec2 ppos = ssC + axis * (r * filter_scale);
|
|
||||||
float value = texelFetch(source_ssao, clamp(ppos, ivec2(0), clamp_limit), 0).r;
|
|
||||||
ivec2 rpos = clamp(ppos, ivec2(0), clamp_limit);
|
|
||||||
float temp_depth = texelFetch(source_depth, rpos, 0).r;
|
|
||||||
//vec3 temp_normal = texelFetch(source_normal, rpos, 0).rgb * 2.0 - 1.0;
|
|
||||||
|
|
||||||
temp_depth = temp_depth * 2.0 - 1.0;
|
|
||||||
temp_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - temp_depth * (camera_z_far - camera_z_near));
|
|
||||||
// temp_depth *= depth_divide;
|
|
||||||
|
|
||||||
// spatial domain: offset gaussian tap
|
|
||||||
float weight = 0.3 + gaussian[abs(r)];
|
|
||||||
//weight *= max(0.0,dot(temp_normal,normal));
|
|
||||||
|
|
||||||
// range domain (the "bilateral" weight). As depth difference increases, decrease weight.
|
|
||||||
weight *= max(0.0, 1.0 - edge_sharpness * abs(temp_depth - depth));
|
|
||||||
|
|
||||||
sum += value * weight;
|
|
||||||
totalWeight += weight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const float epsilon = 0.0001;
|
|
||||||
visibility = sum / (totalWeight + epsilon);
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
/* clang-format off */
|
|
||||||
[vertex]
|
|
||||||
|
|
||||||
layout(location = 0) in highp vec4 vertex_attrib;
|
|
||||||
/* clang-format on */
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = vertex_attrib;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clang-format off */
|
|
||||||
[fragment]
|
|
||||||
|
|
||||||
#ifdef MINIFY_START
|
|
||||||
|
|
||||||
#define SDEPTH_TYPE highp sampler2D
|
|
||||||
uniform float camera_z_far;
|
|
||||||
uniform float camera_z_near;
|
|
||||||
/* clang-format on */
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define SDEPTH_TYPE mediump usampler2D
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uniform SDEPTH_TYPE source_depth; //texunit:0
|
|
||||||
|
|
||||||
uniform ivec2 from_size;
|
|
||||||
uniform int source_mipmap;
|
|
||||||
|
|
||||||
layout(location = 0) out mediump uint depth;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
ivec2 ssP = ivec2(gl_FragCoord.xy);
|
|
||||||
|
|
||||||
// Rotated grid subsampling to avoid XY directional bias or Z precision bias while downsampling.
|
|
||||||
// On DX9, the bit-and can be implemented with floating-point modulo
|
|
||||||
|
|
||||||
#ifdef MINIFY_START
|
|
||||||
float fdepth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r;
|
|
||||||
fdepth = fdepth * 2.0 - 1.0;
|
|
||||||
#ifdef USE_ORTHOGONAL_PROJECTION
|
|
||||||
fdepth = ((fdepth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
|
|
||||||
#else
|
|
||||||
fdepth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - fdepth * (camera_z_far - camera_z_near));
|
|
||||||
#endif
|
|
||||||
fdepth /= camera_z_far;
|
|
||||||
depth = uint(clamp(fdepth * 65535.0, 0.0, 65535.0));
|
|
||||||
|
|
||||||
#else
|
|
||||||
depth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r;
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -1,171 +0,0 @@
|
||||||
/* clang-format off */
|
|
||||||
[vertex]
|
|
||||||
|
|
||||||
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]
|
|
||||||
|
|
||||||
//#define QUALIFIER uniform // some guy on the interweb says it may be faster with this
|
|
||||||
#define QUALIFIER const
|
|
||||||
|
|
||||||
#ifdef USE_25_SAMPLES
|
|
||||||
const int kernel_size = 25;
|
|
||||||
/* clang-format on */
|
|
||||||
QUALIFIER vec2 kernel[25] = vec2[](
|
|
||||||
vec2(0.530605, 0.0),
|
|
||||||
vec2(0.000973794, -3.0),
|
|
||||||
vec2(0.00333804, -2.52083),
|
|
||||||
vec2(0.00500364, -2.08333),
|
|
||||||
vec2(0.00700976, -1.6875),
|
|
||||||
vec2(0.0094389, -1.33333),
|
|
||||||
vec2(0.0128496, -1.02083),
|
|
||||||
vec2(0.017924, -0.75),
|
|
||||||
vec2(0.0263642, -0.520833),
|
|
||||||
vec2(0.0410172, -0.333333),
|
|
||||||
vec2(0.0493588, -0.1875),
|
|
||||||
vec2(0.0402784, -0.0833333),
|
|
||||||
vec2(0.0211412, -0.0208333),
|
|
||||||
vec2(0.0211412, 0.0208333),
|
|
||||||
vec2(0.0402784, 0.0833333),
|
|
||||||
vec2(0.0493588, 0.1875),
|
|
||||||
vec2(0.0410172, 0.333333),
|
|
||||||
vec2(0.0263642, 0.520833),
|
|
||||||
vec2(0.017924, 0.75),
|
|
||||||
vec2(0.0128496, 1.02083),
|
|
||||||
vec2(0.0094389, 1.33333),
|
|
||||||
vec2(0.00700976, 1.6875),
|
|
||||||
vec2(0.00500364, 2.08333),
|
|
||||||
vec2(0.00333804, 2.52083),
|
|
||||||
vec2(0.000973794, 3.0));
|
|
||||||
#endif //USE_25_SAMPLES
|
|
||||||
|
|
||||||
#ifdef USE_17_SAMPLES
|
|
||||||
const int kernel_size = 17;
|
|
||||||
QUALIFIER vec2 kernel[17] = vec2[](
|
|
||||||
vec2(0.536343, 0.0),
|
|
||||||
vec2(0.00317394, -2.0),
|
|
||||||
vec2(0.0100386, -1.53125),
|
|
||||||
vec2(0.0144609, -1.125),
|
|
||||||
vec2(0.0216301, -0.78125),
|
|
||||||
vec2(0.0347317, -0.5),
|
|
||||||
vec2(0.0571056, -0.28125),
|
|
||||||
vec2(0.0582416, -0.125),
|
|
||||||
vec2(0.0324462, -0.03125),
|
|
||||||
vec2(0.0324462, 0.03125),
|
|
||||||
vec2(0.0582416, 0.125),
|
|
||||||
vec2(0.0571056, 0.28125),
|
|
||||||
vec2(0.0347317, 0.5),
|
|
||||||
vec2(0.0216301, 0.78125),
|
|
||||||
vec2(0.0144609, 1.125),
|
|
||||||
vec2(0.0100386, 1.53125),
|
|
||||||
vec2(0.00317394, 2.0));
|
|
||||||
#endif //USE_17_SAMPLES
|
|
||||||
|
|
||||||
#ifdef USE_11_SAMPLES
|
|
||||||
const int kernel_size = 11;
|
|
||||||
QUALIFIER vec2 kernel[11] = vec2[](
|
|
||||||
vec2(0.560479, 0.0),
|
|
||||||
vec2(0.00471691, -2.0),
|
|
||||||
vec2(0.0192831, -1.28),
|
|
||||||
vec2(0.03639, -0.72),
|
|
||||||
vec2(0.0821904, -0.32),
|
|
||||||
vec2(0.0771802, -0.08),
|
|
||||||
vec2(0.0771802, 0.08),
|
|
||||||
vec2(0.0821904, 0.32),
|
|
||||||
vec2(0.03639, 0.72),
|
|
||||||
vec2(0.0192831, 1.28),
|
|
||||||
vec2(0.00471691, 2.0));
|
|
||||||
#endif //USE_11_SAMPLES
|
|
||||||
|
|
||||||
uniform float max_radius;
|
|
||||||
uniform float camera_z_far;
|
|
||||||
uniform float camera_z_near;
|
|
||||||
uniform float unit_size;
|
|
||||||
uniform vec2 dir;
|
|
||||||
in vec2 uv_interp;
|
|
||||||
|
|
||||||
uniform sampler2D source_diffuse; //texunit:0
|
|
||||||
uniform sampler2D source_sss; //texunit:1
|
|
||||||
uniform sampler2D source_depth; //texunit:2
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 frag_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
float strength = texture(source_sss, uv_interp).r;
|
|
||||||
strength *= strength; //stored as sqrt
|
|
||||||
|
|
||||||
// Fetch color of current pixel:
|
|
||||||
vec4 base_color = texture(source_diffuse, uv_interp);
|
|
||||||
|
|
||||||
if (strength > 0.0) {
|
|
||||||
// Fetch linear depth of current pixel:
|
|
||||||
float depth = texture(source_depth, uv_interp).r * 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;
|
|
||||||
float scale = unit_size; //remember depth is negative by default in OpenGL
|
|
||||||
#else
|
|
||||||
depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
|
|
||||||
float scale = unit_size / depth; //remember depth is negative by default in OpenGL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Calculate the final step to fetch the surrounding pixels:
|
|
||||||
vec2 step = max_radius * scale * dir;
|
|
||||||
step *= strength; // Modulate it using the alpha channel.
|
|
||||||
step *= 1.0 / 3.0; // Divide by 3 as the kernels range from -3 to 3.
|
|
||||||
|
|
||||||
// Accumulate the center sample:
|
|
||||||
vec3 color_accum = base_color.rgb;
|
|
||||||
color_accum *= kernel[0].x;
|
|
||||||
#ifdef ENABLE_STRENGTH_WEIGHTING
|
|
||||||
float color_weight = kernel[0].x;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Accumulate the other samples:
|
|
||||||
for (int i = 1; i < kernel_size; i++) {
|
|
||||||
// Fetch color and depth for current sample:
|
|
||||||
vec2 offset = uv_interp + kernel[i].y * step;
|
|
||||||
vec3 color = texture(source_diffuse, offset).rgb;
|
|
||||||
|
|
||||||
#ifdef ENABLE_FOLLOW_SURFACE
|
|
||||||
// If the difference in depth is huge, we lerp color back to "colorM":
|
|
||||||
float depth_cmp = texture(source_depth, offset).r * 2.0 - 1.0;
|
|
||||||
|
|
||||||
#ifdef USE_ORTHOGONAL_PROJECTION
|
|
||||||
depth_cmp = ((depth_cmp + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
|
|
||||||
#else
|
|
||||||
depth_cmp = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth_cmp * (camera_z_far - camera_z_near));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
float s = clamp(300.0f * scale * max_radius * abs(depth - depth_cmp), 0.0, 1.0);
|
|
||||||
color = mix(color, base_color.rgb, s);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Accumulate:
|
|
||||||
color *= kernel[i].x;
|
|
||||||
|
|
||||||
#ifdef ENABLE_STRENGTH_WEIGHTING
|
|
||||||
float color_s = texture(source_sss, offset).r;
|
|
||||||
color_weight += color_s * kernel[i].x;
|
|
||||||
color *= color_s;
|
|
||||||
#endif
|
|
||||||
color_accum += color;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_STRENGTH_WEIGHTING
|
|
||||||
color_accum /= color_weight;
|
|
||||||
#endif
|
|
||||||
frag_color = vec4(color_accum, base_color.a); //keep alpha (used for SSAO)
|
|
||||||
} else {
|
|
||||||
frag_color = base_color;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue