LumixEngine/data/pipelines/lighting.shd

117 lines
No EOL
3.8 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;
void main()
{
vec4 gb0 = texture(u_gbuffer0, v_uv);
vec4 gb1 = texture(u_gbuffer1, v_uv);
vec4 gb2 = texture(u_gbuffer2, v_uv);
vec3 albedo = gb0.rgb;
vec3 N = gb1.rgb * 2 - 1;
float roughness = gb0.w;
float metallic = gb1.w;
float emission = unpackEmission(gb2.x);
float translucency = gb2.y;
float ndc_depth;
vec3 wpos = getViewPosition(u_gbuffer_depth, u_camera_inv_view_projection, v_uv, ndc_depth);
vec3 V = normalize(-wpos);
vec3 L = normalize(u_light_direction.xyz);
float shadow = getShadow(u_shadowmap, wpos);
vec3 direct = PBR_ComputeDirectLight(albedo
, N
, L
, V
, u_light_color.rgb * u_light_intensity * shadow
, roughness
, metallic);
direct += getTranslucency(albedo, translucency, V, L, N, shadow);
float fog_factor = getFogFactor(u_camera_world_pos.y, u_camera_world_pos.y + wpos.y, 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
for (int i = offset; i < end_lights; ++i) {
int light_idx = b_cluster_map[i];
vec3 lpos = b_lights[light_idx].pos_radius.xyz - wpos.xyz;
float dist = length(lpos);
vec3 L = lpos / max(dist, 1e-5);
float attn = pow(max(0, 1 - dist / b_lights[light_idx].pos_radius.w), b_lights[light_idx].color_attn.w);
if (attn > 1e-5) {
vec3 direct_light = PBR_ComputeDirectLight(albedo.rgb, N, L, V, b_lights[light_idx].color_attn.rgb, roughness, metallic);
o_color.rgb += direct_light * attn;
}
}
// 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 - 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 =
b_probes[probe_idx].sh_coefs[0].rgb
+ b_probes[probe_idx].sh_coefs[1].rgb * (N.y)
+ b_probes[probe_idx].sh_coefs[2].rgb * (N.z)
+ b_probes[probe_idx].sh_coefs[3].rgb * (N.x)
+ b_probes[probe_idx].sh_coefs[4].rgb * (N.y * N.x)
+ b_probes[probe_idx].sh_coefs[5].rgb * (N.y * N.z)
+ b_probes[probe_idx].sh_coefs[6].rgb * (3.0 * N.z * N.z - 1.0)
+ b_probes[probe_idx].sh_coefs[7].rgb * (N.z * N.x)
+ b_probes[probe_idx].sh_coefs[8].rgb * (N.x * N.x - N.y * N.y);
irradiance = max(vec3(0), irradiance);
vec3 indirect = PBR_ComputeIndirectDiffuse(irradiance, albedo, metallic, N, V);
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;
}
]]