97 lines
No EOL
3.1 KiB
Text
97 lines
No EOL
3.1 KiB
Text
include "pipelines/common.glsl"
|
|
|
|
------------------
|
|
|
|
vertex_shader [[
|
|
layout (location = 0) out vec2 v_uv;
|
|
void main()
|
|
{
|
|
gl_Position = fullscreenQuad(gl_VertexID, v_uv);
|
|
}
|
|
]]
|
|
|
|
---------------------
|
|
|
|
fragment_shader [[
|
|
layout (location = 0) in vec2 v_uv;
|
|
layout (location = 0) out vec4 o_color;
|
|
layout (binding=0) uniform sampler2D u_gbuffer0;
|
|
layout (binding=1) uniform sampler2D u_gbuffer1;
|
|
layout (binding=2) uniform sampler2D u_gbuffer2;
|
|
layout (binding=3) uniform sampler2D u_gbuffer_depth;
|
|
layout (binding=4) uniform sampler2D u_shadowmap;
|
|
layout (binding=5) uniform sampler2D u_shadow_atlas;
|
|
|
|
void main()
|
|
{
|
|
vec4 gb0 = texture(u_gbuffer0, v_uv);
|
|
vec4 gb1 = texture(u_gbuffer1, v_uv);
|
|
vec4 gb2 = texture(u_gbuffer2, v_uv);
|
|
|
|
Surface surface;
|
|
surface.albedo = gb0.rgb;
|
|
surface.N = gb1.rgb * 2 - 1;
|
|
surface.roughness = gb0.w;
|
|
surface.metallic = gb1.w;
|
|
float emission = unpackEmission(gb2.x);
|
|
float translucency = gb2.y;
|
|
|
|
float ndc_depth;
|
|
surface.wpos = getViewPosition(u_gbuffer_depth, u_camera_inv_view_projection, v_uv, ndc_depth);
|
|
surface.V = normalize(-surface.wpos);
|
|
vec3 L = normalize(u_light_direction.xyz);
|
|
|
|
float shadow = getShadow(u_shadowmap, surface.wpos);
|
|
vec3 direct = PBR_ComputeDirectLight(surface
|
|
, L
|
|
, u_light_color.rgb * u_light_intensity * shadow);
|
|
direct += getTranslucency(surface.albedo, translucency, surface.V, L, surface.N, shadow);
|
|
direct += emission * surface.albedo;
|
|
|
|
float fog_factor = getFogFactor(u_camera_world_pos.y, u_camera_world_pos.y + surface.wpos.y, surface.wpos, u_fog_params.x, u_fog_params.y, u_fog_params.z);
|
|
o_color.rgb = mix(direct, u_fog_color.rgb, fog_factor);
|
|
|
|
ivec3 cluster;
|
|
int cluster_idx = getClusterIndex(ndc_depth, cluster);
|
|
|
|
int offset = b_clusters[cluster_idx].offset;
|
|
int end_lights = offset + b_clusters[cluster_idx].lights_count;
|
|
int end_end_probes = end_lights + b_clusters[cluster_idx].probes_count;
|
|
|
|
// point lights
|
|
o_color.rgb += pointLightLighting(offset, end_lights, surface, surface.wpos, u_shadow_atlas);
|
|
|
|
// env probes
|
|
float remaining_w = 1;
|
|
vec3 probe_light = vec3(0);
|
|
for (int i = end_lights; i < end_end_probes; ++i) {
|
|
int probe_idx = b_cluster_map[i];
|
|
vec3 lpos = b_probes[probe_idx].pos.xyz - surface.wpos.xyz;
|
|
vec4 rot = b_probes[probe_idx].rot;
|
|
vec3 outer_range = b_probes[probe_idx].outer_range.xyz;
|
|
vec3 inner_range = b_probes[probe_idx].inner_range.xyz;
|
|
|
|
lpos = rotateByQuat(rot, lpos);
|
|
lpos = max(abs(lpos) - inner_range, vec3(0));
|
|
vec3 range = max(outer_range - inner_range, vec3(1e-5));
|
|
|
|
vec3 rel = saturate(abs(lpos / range));
|
|
float w = 1 - max(max(rel.x, rel.z), rel.y);
|
|
if (w < 1e-5) continue;
|
|
|
|
w = min(remaining_w, w);
|
|
remaining_w -= w;
|
|
|
|
vec3 irradiance = evalSH(b_probes[probe_idx].sh_coefs, surface.N);
|
|
irradiance = max(vec3(0), irradiance);
|
|
vec3 indirect = PBR_ComputeIndirectDiffuse(irradiance, surface);
|
|
probe_light += (indirect * u_light_indirect_intensity) * w / M_PI;
|
|
if (remaining_w <= 0) break;
|
|
}
|
|
if (remaining_w < 1) {
|
|
o_color.rgb += probe_light / (1 - remaining_w);
|
|
}
|
|
|
|
o_color.w = 1;
|
|
}
|
|
]] |