summaryrefslogtreecommitdiff
path: root/servers/visual/rasterizer_rd/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'servers/visual/rasterizer_rd/shaders')
-rw-r--r--servers/visual/rasterizer_rd/shaders/SCsub1
-rw-r--r--servers/visual/rasterizer_rd/shaders/blur.glsl4
-rw-r--r--servers/visual/rasterizer_rd/shaders/blur_inc.glsl1
-rw-r--r--servers/visual/rasterizer_rd/shaders/copy.glsl93
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward.glsl503
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl158
-rw-r--r--servers/visual/rasterizer_rd/shaders/tonemap.glsl10
7 files changed, 703 insertions, 67 deletions
diff --git a/servers/visual/rasterizer_rd/shaders/SCsub b/servers/visual/rasterizer_rd/shaders/SCsub
index 0a4bebcfbc..b1fa9cd3f4 100644
--- a/servers/visual/rasterizer_rd/shaders/SCsub
+++ b/servers/visual/rasterizer_rd/shaders/SCsub
@@ -10,4 +10,5 @@ if 'RD_GLSL' in env['BUILDERS']:
env.RD_GLSL('scene_forward.glsl');
env.RD_GLSL('sky.glsl');
env.RD_GLSL('tonemap.glsl');
+ env.RD_GLSL('copy.glsl');
diff --git a/servers/visual/rasterizer_rd/shaders/blur.glsl b/servers/visual/rasterizer_rd/shaders/blur.glsl
index 4f47595d2c..5907e911a3 100644
--- a/servers/visual/rasterizer_rd/shaders/blur.glsl
+++ b/servers/visual/rasterizer_rd/shaders/blur.glsl
@@ -23,6 +23,10 @@ void main() {
gl_Position = vec4( uv_interp *2.0 - 1.0, 0.0, 1.0);
+ if (bool(blur.flags&FLAG_FLIP_Y)) {
+ uv_interp.y = 1.0 - uv_interp.y;
+ }
+
}
/* clang-format off */
diff --git a/servers/visual/rasterizer_rd/shaders/blur_inc.glsl b/servers/visual/rasterizer_rd/shaders/blur_inc.glsl
index ea932130aa..275b547fc4 100644
--- a/servers/visual/rasterizer_rd/shaders/blur_inc.glsl
+++ b/servers/visual/rasterizer_rd/shaders/blur_inc.glsl
@@ -3,6 +3,7 @@
#define FLAG_USE_ORTHOGONAL_PROJECTION (1<<2)
#define FLAG_DOF_NEAR_FIRST_TAP (1<<3)
#define FLAG_GLOW_FIRST_PASS (1<<4)
+#define FLAG_FLIP_Y (1<<5)
layout(push_constant, binding = 1, std430) uniform Blur {
vec4 section;
diff --git a/servers/visual/rasterizer_rd/shaders/copy.glsl b/servers/visual/rasterizer_rd/shaders/copy.glsl
new file mode 100644
index 0000000000..e54b3972c0
--- /dev/null
+++ b/servers/visual/rasterizer_rd/shaders/copy.glsl
@@ -0,0 +1,93 @@
+/* clang-format off */
+[vertex]
+/* clang-format on */
+
+#version 450
+
+/* clang-format off */
+VERSION_DEFINES
+/* clang-format on */
+
+layout(location =0) out vec2 uv_interp;
+
+void main() {
+
+ vec2 base_arr[4] = vec2[](vec2(0.0,0.0),vec2(0.0,1.0),vec2(1.0,1.0),vec2(1.0,0.0));
+ uv_interp = base_arr[gl_VertexIndex];
+
+ gl_Position = vec4( uv_interp *2.0 - 1.0, 0.0, 1.0);
+
+}
+
+/* clang-format off */
+[fragment]
+/* clang-format on */
+
+#version 450
+
+/* clang-format off */
+VERSION_DEFINES
+/* clang-format on */
+
+layout(location =0) in vec2 uv_interp;
+
+#ifdef MODE_CUBE_TO_DP
+
+layout( set=0, binding=0 ) uniform samplerCube source_cube;
+
+layout(push_constant, binding = 0, std430) uniform Params {
+ float bias;
+ float z_far;
+ float z_near;
+ bool z_flip;
+
+} params;
+
+layout(location=0) out float depth_buffer;
+
+#endif
+
+
+void main() {
+
+#ifdef MODE_CUBE_TO_DP
+
+ vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0);
+
+ normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
+ normal = normalize(normal);
+
+
+ normal.y = -normal.y; //needs to be flipped to match projection matrix
+ if (!params.z_flip) {
+ normal.z = -normal.z;
+ }
+
+ float depth = texture(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 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
+ depth_buffer = (linear_depth * depth_fix + params.bias) / params.z_far;
+
+#endif
+}
diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
index df31d8c26f..3479929774 100644
--- a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
+++ b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
@@ -75,12 +75,26 @@ VERTEX_SHADER_GLOBALS
// See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316
//invariant gl_Position;
+layout(location =7) flat out uint instance_index;
+
+#ifdef MODE_DUAL_PARABOLOID
+
+layout(location =8) out float dp_clip;
+
+#endif
+
void main() {
+ instance_index = draw_call.instance_index;
+
+ /*if (draw_call.instance_increment) {
+ instance_index += gl_InstanceIndex;
+ }*/
+
vec3 vertex = vertex_attrib;
- mat4 world_matrix = instance_data.transform;
- mat3 world_normal_matrix= instance_data.normal_transform;
+ mat4 world_matrix = instances.data[instance_index].transform;
+ mat3 world_normal_matrix= mat3(instances.data[instance_index].normal_transform);
vec3 normal = normal_attrib;
@@ -131,8 +145,8 @@ void main() {
float roughness = 1.0;
- mat4 modelview = scene_data.inv_camera_matrix * instance_data.transform;
- mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * instance_data.normal_transform;
+ mat4 modelview = scene_data.inv_camera_matrix * world_matrix;
+ mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * world_normal_matrix;
{
/* clang-format off */
@@ -179,14 +193,35 @@ VERTEX_SHADER_CODE
#ifdef MODE_RENDER_DEPTH
+#ifdef MODE_DUAL_PARABOLOID
+
+ vertex_interp.z *= scene_data.dual_paraboloid_side;
+ normal_interp.z *= scene_data.dual_paraboloid_side;
+
+ dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias
+
+ //for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges
+
+ vec3 vtx = vertex_interp + normalize(vertex_interp) * scene_data.z_offset;
+ float distance = length(vtx);
+ vtx = normalize(vtx);
+ vtx.xy /= 1.0 - vtx.z;
+ vtx.z = (distance / scene_data.z_far);
+ vtx.z = vtx.z * 2.0 - 1.0;
+
+ vertex_interp = vtx;
+#else
+
float z_ofs = scene_data.z_offset;
z_ofs += (1.0 - abs(normal_interp.z)) * scene_data.z_slope_scale;
vertex_interp.z -= z_ofs;
+#endif
+
#endif //MODE_RENDER_DEPTH
#ifdef USE_OVERRIDE_POSITION
- gl_Position = position;
+ gl_Position = position;;
#else
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
#endif
@@ -227,10 +262,19 @@ layout(location = 5) in vec3 tangent_interp;
layout(location = 6) in vec3 binormal_interp;
#endif
+layout(location =7) flat in uint instance_index;
+
+#ifdef MODE_DUAL_PARABOLOID
+
+layout(location =8) in float dp_clip;
+
+#endif
+
+
//defines to keep compatibility with vertex
-#define world_matrix instance_data.transform;
-#define world_normal_matrix instance_data.normal_transform;
+#define world_matrix instances.data[instance_index].transform;
+#define world_normal_matrix instances.data[instance_index].normal_transform;
#define projection_matrix scene_data.projection_matrix;
#ifdef USE_MATERIAL_UNIFORMS
@@ -253,10 +297,14 @@ layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness
layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter)
#else
+#ifndef MODE_RENDER_DEPTH
layout(location = 0) out vec4 frag_color;
+#endif
#endif
+
+
// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V.
// We're dividing this factor off because the overall term we'll end up looks like
// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012):
@@ -329,7 +377,24 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
return mix(vec3(dielectric), albedo, vec3(metallic));
}
-void light_compute(vec3 N, vec3 L, vec3 V, vec3 B, vec3 T, vec3 light_color, vec3 attenuation, vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float metallic, float specular, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light, inout float alpha) {
+void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, vec3 attenuation, vec3 diffuse_color,float roughness, float metallic, float specular,float specular_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+ vec3 transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+ float rim, float rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ float clearcoat, float clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ vec3 B, vec3 T,float anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ inout float alpha,
+#endif
+ inout vec3 diffuse_light, inout vec3 specular_light
+ ) {
#if defined(USE_LIGHT_SHADER_CODE)
// light is written by the light shader
@@ -419,11 +484,11 @@ LIGHT_SHADER_CODE
diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
-#if defined(TRANSMISSION_USED)
+#if defined(LIGHT_TRANSMISSION_USED)
diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation;
#endif
-#if defined(RIM_LIGHT_USED)
+#if defined(LIGHT_RIM_USED)
float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color;
#endif
@@ -517,9 +582,209 @@ LIGHT_SHADER_CODE
#endif //defined(USE_LIGHT_SHADER_CODE)
}
+#ifndef USE_NO_SHADOWS
+
+float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec2 pos, float depth) {
+
+#ifdef SHADOW_MODE_PCF_13
+
+ float avg = textureProj(shadow, vec4(pos, depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0));
+ return avg * (1.0 / 13.0);
+#endif
+
+#ifdef SHADOW_MODE_PCF_5
+
+ float avg = textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos, depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
+ return avg * (1.0 / 5.0);
+
+#endif
+
+#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13)
+
+ return textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos, depth, 1.0));
+
+#endif
+}
+
+#endif //USE_NO_SHADOWS
+
+
+void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo,float roughness, float metallic, float specular,float p_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+ vec3 transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+ float rim, float rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ float clearcoat, float clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ vec3 binormal, vec3 tangent, float anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ inout float alpha,
+#endif
+ inout vec3 diffuse_light, inout vec3 specular_light) {
+
+ vec3 light_rel_vec = lights.data[idx].position - vertex;
+ float light_length = length(light_rel_vec);
+ float normalized_distance = light_length * lights.data[idx].inv_radius;
+ vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
+ float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x);
+ vec3 light_attenuation = vec3(omni_attenuation);
+ vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
+ color_specular.rgb*=attenuation_energy.y;
+
+#ifndef USE_NO_SHADOWS
+ vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
+ if (shadow_color_enabled.w > 0.5) {
+ // there is a shadowmap
+
+ vec3 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz;
+ float shadow_len = length(splane);
+ splane = normalize(splane);
+ vec4 clamp_rect = lights.data[idx].atlas_rect;
+
+ if (splane.z >= 0.0) {
+
+ splane.z += 1.0;
+
+ clamp_rect.y += clamp_rect.w;
+
+ } else {
+
+ splane.z = 1.0 - splane.z;
+
+ }
+
+ splane.xy /= splane.z;
+ splane.xy = splane.xy * 0.5 + 0.5;
+ splane.z = shadow_len * lights.data[idx].inv_radius;
+
+ splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
+ float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane.xy, splane.z);
+
+ light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+ }
+#endif //USE_NO_SHADOWS
+
+ light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular,color_specular.a * p_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+ transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+ rim * omni_attenuation, rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ clearcoat, clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ binormal, tangent, anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ alpha
+#endif
+ diffuse_light, specular_light);
+}
+
+
+
+void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo,float roughness, float metallic, float specular,float p_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+ vec3 transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+ float rim, float rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ float clearcoat, float clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ vec3 binormal, vec3 tangent, float anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ inout float alpha
+#endif
+ inout vec3 diffuse_light, inout vec3 specular_light) {
+
+ vec3 light_rel_vec = lights.data[idx].position - vertex;
+ float light_length = length(light_rel_vec);
+ float normalized_distance = light_length * lights.data[idx].inv_radius;
+ vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
+ float spot_attenuation = pow(max(1.0 - normalized_distance, 0.001), attenuation_energy.x);
+ vec3 spot_dir = lights.data[idx].direction;
+ vec2 spot_att_angle = unpackHalf2x16(lights.data[idx].cone_attenuation_angle);
+ float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y);
+ float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y));
+ spot_attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x);
+ vec3 light_attenuation = vec3(spot_attenuation);
+ vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
+ color_specular.rgb*=attenuation_energy.y;
+
+
+
+/*
+ if (lights.data[idx].atlas_rect!=vec4(0.0)) {
+ //use projector texture
+ }
+ */
+#ifndef USE_NO_SHADOWS
+ vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
+ if (shadow_color_enabled.w > 0.5) {
+ //there is a shadowmap
+ vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
+ splane.xyz /= splane.w;
+
+ float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane.xy, splane.z);
+
+ light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+ }
+
+#endif //USE_NO_SHADOWS
+
+ light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular,color_specular.a * p_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+ transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+ rim * omni_attenuation, rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ clearcoat, clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ binormal, tangent, anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ alpha,
+#endif
+ diffuse_light, specular_light);
+}
void main() {
+#ifdef MODE_DUAL_PARABOLOID
+
+ if (dp_clip > 0.0)
+ discard;
+#endif
//lay out everything, whathever is unused is optimized away anyway
vec3 vertex = vertex_interp;
@@ -701,14 +966,149 @@ FRAGMENT_SHADER_CODE
specular_blob_intensity *= specular * 2.0;
#endif
+#ifndef MODE_RENDER_DEPTH
//gi probes
//lightmap
//lightmap capture
- //process reflections
+#if 0
+ { // process reflections
+
+
+ vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
+ vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
+
+ for (uint i = 0; i < MAX_REFLECTION_PROBES; i++) {
+ if (i >= draw_data.reflection_probe_count) {
+ break;
+ }
+
+ uint ref_index;
+ if (i<4) {
+ if (i<2) {
+ ref_index=draw_data.reflection_probe_indices[0];
+ } else {
+ ref_index=draw_data.reflection_probe_indices[1];
+ }
+ } else {
+ if (i<6) {
+ ref_index=draw_data.reflection_probe_indices[2];
+ } else {
+ ref_index=draw_data.reflection_probe_indices[3];
+ }
+ }
+ ref_index>>=(i&1)*16;
+ ref_index&=0xFFFF;
+
+ vec3 box_extents = reflections.data[ref_index].box_extents.xyz;
+ vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz;
+
+ if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box
+ continue;
+ }
+
+ vec3 ref_vec = normalize(reflect(vertex, normal));
+
+ vec3 inner_pos = abs(local_pos / box_extents);
+ float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
+ //make blend more rounded
+ blend = mix(length(inner_pos), blend, blend);
+ blend *= blend;
+ blend = max(0.0, 1.0 - blend);
+
+ if (reflections.data[ref_index].params.x > 0.0) { // compute reflection
+ vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz;
+
+ if (reflections.data[ref_index].params.w > 0.5) { //box project
+
+ vec3 nrdir = normalize(local_ref_vec);
+ vec3 rbmax = (box_extents - local_pos) / nrdir;
+ vec3 rbmin = (-box_extents - local_pos) / nrdir;
+
+ vec3 rbminmax = mix(rbmin, rbmax, greaterThan(nrdir, vec3(0.0, 0.0, 0.0)));
+
+ float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
+ vec3 posonbox = local_pos + nrdir * fa;
+ local_ref_vec = posonbox - reflections.data[ref_index].box_offset.xyz;
+ }
+
+ vec4 reflection;
+
+#ifdef USE_RADIANCE_CUBEMAP_ARRAY
+
+ float lod,layer_blend;
+ layer_blend = modf(roughness * MAX_ROUGHNESS_LOD, lod);
+ reflection.rgb = texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, lod)).rgb;
+ reflection.rgb = mix(reflection.rgb,texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, lod+1)).rgb,layer_blend);
+
+#else
+ reflection.rgb = textureLod(samplerCube(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), local_ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
+
+#endif
+
+ if (reflections.data[ref_index].params.z < 0.5) {
+ reflection.rgb = mix(specular_light, reflection.rgb, blend);
+ }
+
+ reflection.rgb *= reflections.data[ref_index].params.x;
+ reflection.a = blend;
+ reflection.rgb *= reflection.a;
+
+ reflection_accum += reflection;
+ }
+
+#ifndef USE_LIGHTMAP
+ if (reflections.data[ref_index].ambient.a > 0.0) { //compute ambient using skybox
+
+ vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz;
+
+ vec4 ambient_out;
+
+#ifdef USE_RADIANCE_CUBEMAP_ARRAY
+ ambient_out.rgb = texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, MAX_ROUGHNESS_LOD)).rgb;
+#else
+ ambient_out.rgb = textureLod(samplerCube(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), local_amb_vec, MAX_ROUGHNESS_LOD).rgb;
+#endif //USE_RADIANCE_CUBEMAP_ARRAY
+
+ ambient_out.a = blend;
+ ambient_out.rgb = mix(reflections.data[ref_index].ambient.rgb, ambient_out.rgb, reflections.data[ref_index].ambient.a);
+ if (reflections.data[ref_index].params.z < 0.5) {
+ ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
+ }
+
+ ambient_out.rgb *= ambient_out.a;
+ ambient_accum += ambient_out;
+ } else {
+
+ vec4 ambient_out;
+ ambient_out.a = blend;
+ ambient_out.rgb = reflections.data[ref_index].ambient.rgb;
+ if (reflections.data[ref_index].params.z < 0.5) {
+ ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
+ }
+ ambient_out.rgb *= ambient_out.a;
+ ambient_accum += ambient_out;
+ }
+#endif //USE_LIGHTMAP
+
+ }
+
+ if (reflection_accum.a > 0.0) {
+ specular_light = reflection_accum.rgb / reflection_accum.a;
+ }
+
+#if !defined(USE_LIGHTMAP)
+ if (ambient_accum.a > 0.0) {
+ ambient_light = ambient_accum.rgb / ambient_accum.a;
+ }
+#endif
+
+
+ }
+#endif //0
{
#if defined(DIFFUSE_TOON)
@@ -734,8 +1134,86 @@ FRAGMENT_SHADER_CODE
//directional light
+ { //omni lights
+ uint omni_light_count = (instances.data[instance_index].flags >> INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT) & INSTANCE_FLAGS_FORWARD_MASK;
+ for (uint i = 0; i < omni_light_count; i++) {
+
+ uint light_index = instances.data[instance_index].omni_light_indices[i>>1];
+
+ if (bool(i&1)) {
+ light_index>>=16;
+ } else {
+ light_index&=0xFFFF;
+ }
+
+ //this is done on CPU, so no need to do it here
+ //if (!bool(lights.data[light_index].mask&instances.data[instance_index].layer_mask)) {
+ // continue; //not masked
+ //}
+
+ light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular,specular_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+ transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+ rim,
+ rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ clearcoat, clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ tangent, binormal, anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ alpha,
+#endif
+ diffuse_light, specular_light);
+ }
+
+ }
+
+ { //spot lights
+ uint spot_light_count = (instances.data[instance_index].flags >> INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT) & INSTANCE_FLAGS_FORWARD_MASK;
+ for (uint i = 0; i < spot_light_count; i++) {
- //process omni and spots
+ uint light_index = instances.data[instance_index].spot_light_indices[i>>1];
+
+ if (bool(i&1)) {
+ light_index>>=16;
+ } else {
+ light_index&=0xFFFF;
+ }
+
+ //this is done on CPU, so no need to do it here
+ //if (!bool(lights.data[light_index].mask&instances.data[instance_index].layer_mask)) {
+ // continue; //not masked
+ //}
+
+ light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular,specular_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+ transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+ rim,
+ rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ clearcoat, clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ tangent, binormal, anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ alpha,
+#endif
+ diffuse_light, specular_light);
+ }
+
+ }
+
+
+#endif //!MODE_RENDER_DEPTH
#ifdef USE_SHADOW_TO_OPACITY
alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));
@@ -757,6 +1235,7 @@ FRAGMENT_SHADER_CODE
#endif // USE_SHADOW_TO_OPACITY
+
#ifdef MODE_RENDER_DEPTH
//nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
#else
diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
index 3547cad46c..8951f89c13 100644
--- a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
+++ b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
@@ -2,6 +2,13 @@
#define M_PI 3.14159265359
#define ROUGHNESS_MAX_LOD 5
+layout(push_constant, binding = 0, std430) uniform DrawCall {
+ uint instance_index;
+ uint pad[3]; //16 bits minimum size
+} draw_call;
+
+
+
/* Set 0 Scene data, screen and sources (changes the least) */
layout(set=0,binding=1) uniform texture2D depth_buffer;
@@ -35,7 +42,9 @@ layout(set = 0, binding = 5) uniform textureCube radiance_cubemap;
layout(set = 0, binding = 6) uniform sampler material_samplers[12];
-layout(set=0,binding=7,std140) uniform SceneData {
+layout(set = 0, binding = 7) uniform sampler shadow_sampler;
+
+layout(set=0,binding=8,std140) uniform SceneData {
mat4 projection_matrix;
mat4 inv_projection_matrix;
@@ -63,6 +72,14 @@ layout(set=0,binding=7,std140) uniform SceneData {
mat3 radiance_inverse_xform;
+ vec2 shadow_atlas_pixel_size;
+ vec2 directional_shadow_pixel_size;
+
+ uint directional_light_count;
+ float dual_paraboloid_side;
+ float z_far;
+ uint pad0;
+
#if 0
vec4 ambient_light_color;
vec4 bg_color;
@@ -101,80 +118,125 @@ layout(set=0,binding=7,std140) uniform SceneData {
#endif
} scene_data;
+#define INSTANCE_FLAGS_FORWARD_MASK 3
+#define INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT 3
+#define INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT 6
+#define INSTANCE_FLAGS_FORWARD_DECAL_SHIFT 9
+
+
+struct InstanceData {
+ mat4 transform;
+ mat4 normal_transform;
+ uint flags;
+ uint instance_ofs; //instance_offset in instancing/skeleton buffer
+ uint gi_offset; //GI information when using lightmapping (VCT or lightmap)
+ uint layer_mask;
+
+ uint reflection_probe_indices[4];
+ uint omni_light_indices[4];
+ uint spot_light_indices[4];
+ uint decal_indices[4];
+};
+
+
+layout(set=0,binding=9,std430) buffer Instances {
+ InstanceData data[];
+} instances;
+
+struct ReflectionData {
+
+ vec4 box_extents;
+ vec4 box_offset;
+ vec4 params; // intensity, 0, interior , boxproject
+ vec4 ambient; // ambient color, energy
+ mat4 local_matrix; // up to here for spot and omni, rest is for directional
+ // notes: for ambientblend, use distance to edge to blend between already existing global environment
+};
+
+layout(set=0,binding=10,std140) uniform ReflectionProbeData {
+ ReflectionData data[MAX_REFLECTION_DATA_STRUCTS];
+} reflections;
+
+
+struct LightData { //this structure needs to be 128 bits
+
+ vec3 position;
+ float inv_radius;
+ vec3 direction;
+ uint attenuation_energy; //attenuation
+ uint color_specular; //rgb color, a specular (8 bit unorm)
+ uint cone_attenuation_angle; // attenuation and angle, (16bit float)
+ uint mask;
+ uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm)
+ vec4 atlas_rect; //used for shadow atlas uv on omni, and for projection atlas on spot
+ mat4 shadow_matrix;
+};
+
+layout(set=0,binding=11,std140) uniform Lights {
+ LightData data[MAX_LIGHT_DATA_STRUCTS];
+} lights;
+
+layout(set=0,binding=12) uniform texture2D shadow_atlas;
-#if 0
struct DirectionalLightData {
- vec4 light_pos_inv_radius;
- vec4 light_direction_attenuation;
- vec4 light_color_energy;
- vec4 light_params; // cone attenuation, angle, specular, shadow enabled,
- vec4 light_clamp;
- vec4 shadow_color_contact;
+ vec3 direction;
+ float energy;
+ vec3 color;
+ float specular;
+ uint mask;
+ uint pad0,pad1,pad2;
+ vec3 shadow_color;
+ bool shadow_enabled;
+ vec4 shadow_atlas_rect;
+ vec4 shadow_split_offsets;
mat4 shadow_matrix1;
mat4 shadow_matrix2;
mat4 shadow_matrix3;
mat4 shadow_matrix4;
- vec4 shadow_split_offsets;
+
};
-#endif
-/* Set 1 Skeleton Data (most objects lack it, so it changes little */
+layout(set=0,binding=13,std140) uniform DirectionalLights {
+ DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
+} directional_lights;
-#if 0
-layout(set = 1 binding = 0, std140) uniform SkeletonData {
- mat4 transform;
- bool use_skeleton;
- bool use_world_coords;
- bool pad1;
- bool pad2;
-} skeleton;
+layout(set=0,binding=14) uniform texture2D directional_shadow_atlas;
-layout(set = 1, binding = 1) uniform textureBuffer skeleton_bones;
-#endif
+/*
+layout(set=0,binding=15,std430) buffer Skeletons {
+ vec4 data[];
+} skeletons;
+*/
-/* Set 2 Custom Material Data (changess less than instance) */
+/* Set 1 Instancing (Multimesh) */
+//layout(set = 1, binding = 0) uniform textureBuffer multimesh_transforms;
-/* Set 3 Instance Data (Set on every draw call) */
+/* Set 2 Instancing (Multimesh) data */
-layout(push_constant, binding = 0, std430) uniform DrawData {
- //used in forward rendering, 16 bits indices, max 8
- uint reflection_probe_count;
- uint omni_light_count;
- uint spot_light_count;
- uint decal_count;
- uvec4 reflection_probe_indices;
- uvec4 omni_light_indices;
- uvec4 spot_light_indices;
- uvec4 decal_indices;
-} draw_data;
+#if 0
-layout(set = 3, binding = 0, std140) uniform InstanceData {
- mat4 transform;
- mat3 normal_transform;
- uint flags;
- uint pad0;
- uint pad1;
- uint pad2;
-} instance_data;
+#ifdef USE_RADIANCE_CUBEMAP_ARRAY
-layout(set = 3, binding = 1) uniform textureBuffer multimesh_transforms;
+layout(set = 3, binding = 2) uniform textureCubeArray reflection_probes[MAX_REFLECTION_PROBES];
-#ifdef USE_LIGHTMAP
+#else
-layout(set = 3, binding = 2) uniform texture2D lightmap;
+layout(set = 3, binding = 2) uniform textureCube reflection_probes[MAX_REFLECTION_PROBES];
#endif
+
#ifdef USE_VOXEL_CONE_TRACING
-layout(set = 3, binding = 3) uniform texture3D gi_probe[2];
+layout(set = 3, binding = 4) uniform texture3D gi_probe[2];
#ifdef USE_ANISOTROPIC_VOXEL_CONE_TRACING
-layout(set = 3, binding = 4) uniform texture3D gi_probe_aniso_pos[2];
-layout(set = 3, binding = 5) uniform texture3D gi_probe_aniso_neg[2];
+layout(set = 3, binding = 5) uniform texture3D gi_probe_aniso_pos[2];
+layout(set = 3, binding = 6) uniform texture3D gi_probe_aniso_neg[2];
#endif
#endif
+#endif
diff --git a/servers/visual/rasterizer_rd/shaders/tonemap.glsl b/servers/visual/rasterizer_rd/shaders/tonemap.glsl
index 284c934cf6..6797ff9f77 100644
--- a/servers/visual/rasterizer_rd/shaders/tonemap.glsl
+++ b/servers/visual/rasterizer_rd/shaders/tonemap.glsl
@@ -166,7 +166,9 @@ vec3 tonemap_reinhard(vec3 color, float white) {
return (white * color + color) / (color * white + white);
}
-vec3 linear_to_srgb(vec3 color) { // convert linear rgb to srgb, assumes clamped input in range [0;1]
+vec3 linear_to_srgb(vec3 color) {
+ //if going to srgb, clamp from 0 to 1.
+ color = clamp(color,vec3(0.0),vec3(1.0));
const vec3 a = vec3(0.055f);
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
}
@@ -233,15 +235,9 @@ vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blendi
return color + glow;
} else if (params.glow_mode==GLOW_MODE_SCREEN) {
//need color clamping
- color = clamp(color,0.0,1.0);
- glow = clamp(glow,0.0,1.0);
-
return max((color + glow) - (color * glow), vec3(0.0));
} else if ( params.glow_mode==GLOW_MODE_SOFTLIGHT) {
//need color clamping
- color = clamp(color,0.0,1.0);
- glow = clamp(glow,0.0,1.0);
-
glow = glow * vec3(0.5f) + vec3(0.5f);
color.r = (glow.r <= 0.5f) ? (color.r - (1.0f - 2.0f * glow.r) * color.r * (1.0f - color.r)) : (((glow.r > 0.5f) && (color.r <= 0.25f)) ? (color.r + (2.0f * glow.r - 1.0f) * (4.0f * color.r * (4.0f * color.r + 1.0f) * (color.r - 1.0f) + 7.0f * color.r)) : (color.r + (2.0f * glow.r - 1.0f) * (sqrt(color.r) - color.r)));