diff options
Diffstat (limited to 'servers/visual/rasterizer_rd/shaders')
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/SCsub | 1 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/blur.glsl | 4 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/blur_inc.glsl | 1 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/copy.glsl | 93 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/scene_forward.glsl | 503 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl | 158 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/tonemap.glsl | 10 |
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))); |