EEVEE: Use half float in some part of the pipeline #5

Closed
Clément Foucault wants to merge 1 commits from eevee-half-opti into eevee-small-type-opti

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
23 changed files with 160 additions and 120 deletions
Showing only changes of commit 98500521d4 - Show all commits

View File

@ -55,7 +55,7 @@ LightProbeRay bxdf_diffuse_lightprobe(vec3 N)
ClosureLight bxdf_diffuse_light(ClosureUndetermined cl) ClosureLight bxdf_diffuse_light(ClosureUndetermined cl)
{ {
ClosureLight light; ClosureLight light;
light.ltc_mat = vec4(1.0, 0.0, 0.0, 1.0); /* No transform, just plain cosine distribution. */ light.ltc_mat = half4(1.0, 0.0, 0.0, 1.0); /* No transform, just plain cosine distribution. */
light.N = cl.N; light.N = cl.N;
light.type = LIGHT_DIFFUSE; light.type = LIGHT_DIFFUSE;
return light; return light;
@ -144,7 +144,7 @@ ClosureLight bxdf_translucent_light(ClosureUndetermined cl, vec3 V, float thickn
* only focusing the light a tiny bit. Using the flipped normal is good enough approximation. * only focusing the light a tiny bit. Using the flipped normal is good enough approximation.
*/ */
ClosureLight light; ClosureLight light;
light.ltc_mat = vec4(1.0, 0.0, 0.0, 1.0); /* No transform, just plain cosine distribution. */ light.ltc_mat = half4(1.0, 0.0, 0.0, 1.0); /* No transform, just plain cosine distribution. */
light.N = -cl.N; light.N = -cl.N;
light.type = (thickness > 0.0) ? LIGHT_TRANSLUCENT_WITH_THICKNESS : LIGHT_DIFFUSE; light.type = (thickness > 0.0) ? LIGHT_TRANSLUCENT_WITH_THICKNESS : LIGHT_DIFFUSE;
return light; return light;

View File

@ -13,7 +13,7 @@
#include "gpu_shader_utildefines_lib.glsl" #include "gpu_shader_utildefines_lib.glsl"
struct BsdfSample { struct BsdfSample {
packed_float3 direction; float3 direction;
float pdf; float pdf;
}; };
@ -26,14 +26,14 @@ struct BsdfEval {
struct ClosureLight { struct ClosureLight {
/* LTC matrix. */ /* LTC matrix. */
packed_float4 ltc_mat; half4 ltc_mat;
/* Shading normal. */ /* Shading normal. */
packed_float3 N; packed_float3 N;
/* Enum used as index to fetch which light intensity to use [0..3]. */ /* Enum used as index to fetch which light intensity to use [0..3]. */
LightingType type; LightingType type;
/* Output both shadowed and unshadowed for shadow denoising. */ /* Output both shadowed and unshadowed for shadow denoising. */
packed_float3 light_shadowed; half3 light_shadowed;
packed_float3 light_unshadowed; half3 light_unshadowed;
}; };
/* Represent an approximation of a bunch of rays from a BSDF. */ /* Represent an approximation of a bunch of rays from a BSDF. */
@ -49,9 +49,9 @@ struct LightProbeRay {
/* General purpose 3D ray. */ /* General purpose 3D ray. */
struct Ray { struct Ray {
packed_float3 direction;
float max_time;
packed_float3 origin; packed_float3 origin;
float max_time;
float3 direction;
}; };
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */

View File

@ -396,7 +396,8 @@ ClosureLight bxdf_ggx_light_reflection(ClosureReflection cl, vec3 V)
{ {
float cos_theta = dot(cl.N, V); float cos_theta = dot(cl.N, V);
ClosureLight light; ClosureLight light;
light.ltc_mat = utility_tx_sample_lut(utility_tx, cos_theta, cl.roughness, UTIL_LTC_MAT_LAYER); light.ltc_mat = half4(
utility_tx_sample_lut(utility_tx, cos_theta, cl.roughness, UTIL_LTC_MAT_LAYER));
light.N = cl.N; light.N = cl.N;
light.type = LIGHT_SPECULAR; light.type = LIGHT_SPECULAR;
return light; return light;
@ -417,8 +418,8 @@ ClosureLight bxdf_ggx_light_transmission(ClosureRefraction cl, vec3 V, float thi
float cos_theta = dot(-cl.N, R); float cos_theta = dot(-cl.N, R);
ClosureLight light; ClosureLight light;
light.ltc_mat = utility_tx_sample_lut( light.ltc_mat = half4(
utility_tx, cos_theta, perceptual_roughness, UTIL_LTC_MAT_LAYER); utility_tx_sample_lut(utility_tx, cos_theta, perceptual_roughness, UTIL_LTC_MAT_LAYER));
light.N = -cl.N; light.N = -cl.N;
light.type = LIGHT_TRANSMISSION; light.type = LIGHT_TRANSMISSION;
return light; return light;

View File

@ -118,8 +118,8 @@ ClosureLight closure_light_new_ex(ClosureUndetermined cl,
break; break;
} }
} }
cl_light.light_shadowed = vec3(0.0); cl_light.light_shadowed = half3(0.0);
cl_light.light_unshadowed = vec3(0.0); cl_light.light_unshadowed = half3(0.0);
return cl_light; return cl_light;
} }

View File

@ -64,20 +64,21 @@ void main()
uchar receiver_light_set = gbuffer_light_link_receiver_unpack(gbuf.header); uchar receiver_light_set = gbuffer_light_link_receiver_unpack(gbuf.header);
light_eval_reflection(stack, P, Ng, V, vPz, receiver_light_set); light_eval_reflection(stack, P, Ng, V, vPz, receiver_light_set);
vec3 radiance_front = stack.cl[0].light_shadowed; half3 radiance_front = stack.cl[0].light_shadowed;
stack.cl[0] = closure_light_new(cl_transmit, V, gbuf.thickness); stack.cl[0] = closure_light_new(cl_transmit, V, gbuf.thickness);
light_eval_transmission(stack, P, Ng, V, vPz, gbuf.thickness, receiver_light_set); light_eval_transmission(stack, P, Ng, V, vPz, gbuf.thickness, receiver_light_set);
vec3 radiance_back = stack.cl[0].light_shadowed; half3 radiance_back = stack.cl[0].light_shadowed;
/* Indirect light. */ /* Indirect light. */
/* Can only load irradiance to avoid dependency loop with the reflection probe. */ /* Can only load irradiance to avoid dependency loop with the reflection probe. */
SphericalHarmonicL1 sh = lightprobe_volume_sample(P, V, Ng); SphericalHarmonicL1 sh = lightprobe_volume_sample(P, V, Ng);
radiance_front += spherical_harmonics_evaluate_lambert(Ng, sh); radiance_front += half3(spherical_harmonics_evaluate_lambert(Ng, sh));
/* TODO(fclem): Correct transmission eval. */ /* TODO(fclem): Correct transmission eval. */
radiance_back += spherical_harmonics_evaluate_lambert(-Ng, sh); radiance_back += half3(spherical_harmonics_evaluate_lambert(-Ng, sh));
out_radiance = vec4(radiance_front * albedo_front + radiance_back * albedo_back, 0.0); out_radiance = vec4(
vec3(radiance_front * half3(albedo_front) + radiance_back * half3(albedo_back)), 0.0);
} }

View File

@ -76,7 +76,7 @@ void main()
if (use_transmission) { if (use_transmission) {
ClosureUndetermined cl_transmit = gbuffer_closure_get(gbuf, 0); ClosureUndetermined cl_transmit = gbuffer_closure_get(gbuf, 0);
#if 1 /* TODO Limit to SSS. */ #if 1 /* TODO Limit to SSS. */
vec3 sss_reflect_shadowed, sss_reflect_unshadowed; half3 sss_reflect_shadowed, sss_reflect_unshadowed;
if (cl_transmit.type == CLOSURE_BSSRDF_BURLEY_ID) { if (cl_transmit.type == CLOSURE_BSSRDF_BURLEY_ID) {
sss_reflect_shadowed = stack.cl[0].light_shadowed; sss_reflect_shadowed = stack.cl[0].light_shadowed;
sss_reflect_unshadowed = stack.cl[0].light_unshadowed; sss_reflect_unshadowed = stack.cl[0].light_unshadowed;
@ -91,8 +91,8 @@ void main()
#if 1 /* TODO Limit to SSS. */ #if 1 /* TODO Limit to SSS. */
if (cl_transmit.type == CLOSURE_BSSRDF_BURLEY_ID) { if (cl_transmit.type == CLOSURE_BSSRDF_BURLEY_ID) {
/* Apply transmission profile onto transmitted light and sum with reflected light. */ /* Apply transmission profile onto transmitted light and sum with reflected light. */
vec3 sss_profile = subsurface_transmission(to_closure_subsurface(cl_transmit).sss_radius, half3 sss_profile = subsurface_transmission(to_closure_subsurface(cl_transmit).sss_radius,
abs(gbuf.thickness)); abs(gbuf.thickness));
stack.cl[0].light_shadowed *= sss_profile; stack.cl[0].light_shadowed *= sss_profile;
stack.cl[0].light_unshadowed *= sss_profile; stack.cl[0].light_unshadowed *= sss_profile;
stack.cl[0].light_shadowed += sss_reflect_shadowed; stack.cl[0].light_shadowed += sss_reflect_shadowed;
@ -102,13 +102,13 @@ void main()
} }
if (render_pass_shadow_id != -1) { if (render_pass_shadow_id != -1) {
vec3 radiance_shadowed = vec3(0); half3 radiance_shadowed = half3(0);
vec3 radiance_unshadowed = vec3(0); half3 radiance_unshadowed = half3(0);
for (int i = 0; i < LIGHT_CLOSURE_EVAL_COUNT && i < gbuf.closure_count; i++) { for (int i = 0; i < LIGHT_CLOSURE_EVAL_COUNT && i < gbuf.closure_count; i++) {
radiance_shadowed += closure_light_get(stack, i).light_shadowed; radiance_shadowed += closure_light_get(stack, i).light_shadowed;
radiance_unshadowed += closure_light_get(stack, i).light_unshadowed; radiance_unshadowed += closure_light_get(stack, i).light_unshadowed;
} }
vec3 shadows = radiance_shadowed * safe_rcp(radiance_unshadowed); half3 shadows = radiance_shadowed * safe_rcp(radiance_unshadowed);
output_renderpass_value(render_pass_shadow_id, average(shadows)); output_renderpass_value(render_pass_shadow_id, average(shadows));
} }
@ -120,24 +120,24 @@ void main()
for (int i = 0; i < LIGHT_CLOSURE_EVAL_COUNT && i < gbuf.closure_count; i++) { for (int i = 0; i < LIGHT_CLOSURE_EVAL_COUNT && i < gbuf.closure_count; i++) {
ClosureUndetermined cl = gbuffer_closure_get(gbuf, i); ClosureUndetermined cl = gbuffer_closure_get(gbuf, i);
vec3 indirect_light = lightprobe_eval(samp, cl, P, V, gbuf.thickness); half3 indirect_light = lightprobe_eval(samp, cl, P, V, gbuf.thickness);
int layer_index = gbuffer_closure_get_bin_index(gbuf, i); int layer_index = gbuffer_closure_get_bin_index(gbuf, i);
vec3 direct_light = closure_light_get(stack, i).light_shadowed; half3 direct_light = closure_light_get(stack, i).light_shadowed;
if (use_split_indirect) { if (use_split_indirect) {
write_radiance_indirect(layer_index, texel, indirect_light); write_radiance_indirect(layer_index, texel, vec3(indirect_light));
write_radiance_direct(layer_index, texel, direct_light); write_radiance_direct(layer_index, texel, vec3(direct_light));
} }
else { else {
write_radiance_direct(layer_index, texel, direct_light + indirect_light); write_radiance_direct(layer_index, texel, vec3(direct_light + indirect_light));
} }
} }
} }
else { else {
for (int i = 0; i < LIGHT_CLOSURE_EVAL_COUNT && i < gbuf.closure_count; i++) { for (int i = 0; i < LIGHT_CLOSURE_EVAL_COUNT && i < gbuf.closure_count; i++) {
int layer_index = gbuffer_closure_get_bin_index(gbuf, i); int layer_index = gbuffer_closure_get_bin_index(gbuf, i);
vec3 direct_light = closure_light_get(stack, i).light_shadowed; half3 direct_light = closure_light_get(stack, i).light_shadowed;
write_radiance_direct(layer_index, texel, direct_light); write_radiance_direct(layer_index, texel, vec3(direct_light));
} }
} }
} }

View File

@ -19,8 +19,8 @@ void main()
GBufferReader gbuf = gbuffer_read(gbuf_header_tx, gbuf_closure_tx, gbuf_normal_tx, texel); GBufferReader gbuf = gbuffer_read(gbuf_header_tx, gbuf_closure_tx, gbuf_normal_tx, texel);
vec3 albedo_front = vec3(0.0); half3 albedo_front = half3(0.0);
vec3 albedo_back = vec3(0.0); half3 albedo_back = half3(0.0);
for (int i = 0; i < GBUFFER_LAYER_MAX && i < gbuf.closure_count; i++) { for (int i = 0; i < GBUFFER_LAYER_MAX && i < gbuf.closure_count; i++) {
ClosureUndetermined cl = gbuffer_closure_get(gbuf, i); ClosureUndetermined cl = gbuffer_closure_get(gbuf, i);
@ -28,11 +28,11 @@ void main()
case CLOSURE_BSSRDF_BURLEY_ID: case CLOSURE_BSSRDF_BURLEY_ID:
case CLOSURE_BSDF_DIFFUSE_ID: case CLOSURE_BSDF_DIFFUSE_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFLECTION_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFLECTION_ID:
albedo_front += cl.color; albedo_front += half3(cl.color);
break; break;
case CLOSURE_BSDF_TRANSLUCENT_ID: case CLOSURE_BSDF_TRANSLUCENT_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
albedo_back += (gbuf.thickness != 0.0) ? square(cl.color) : cl.color; albedo_back += half3((gbuf.thickness != 0.0) ? square(cl.color) : cl.color);
break; break;
case CLOSURE_NONE_ID: case CLOSURE_NONE_ID:
/* TODO(fclem): Assert. */ /* TODO(fclem): Assert. */
@ -59,18 +59,18 @@ void main()
uchar receiver_light_set = gbuffer_light_link_receiver_unpack(gbuf.header); uchar receiver_light_set = gbuffer_light_link_receiver_unpack(gbuf.header);
light_eval_reflection(stack, P, Ng, V, vPz, receiver_light_set); light_eval_reflection(stack, P, Ng, V, vPz, receiver_light_set);
vec3 radiance_front = stack.cl[0].light_shadowed; half3 radiance_front = stack.cl[0].light_shadowed;
stack.cl[0] = closure_light_new(cl_transmit, V, gbuf.thickness); stack.cl[0] = closure_light_new(cl_transmit, V, gbuf.thickness);
light_eval_transmission(stack, P, Ng, V, vPz, gbuf.thickness, receiver_light_set); light_eval_transmission(stack, P, Ng, V, vPz, gbuf.thickness, receiver_light_set);
vec3 radiance_back = stack.cl[0].light_shadowed; half3 radiance_back = stack.cl[0].light_shadowed;
/* Indirect light. */ /* Indirect light. */
SphericalHarmonicL1 sh = lightprobe_volume_sample(P, V, Ng); SphericalHarmonicL1 sh = lightprobe_volume_sample(P, V, Ng);
radiance_front += spherical_harmonics_evaluate_lambert(Ng, sh); radiance_front += half3(spherical_harmonics_evaluate_lambert(Ng, sh));
radiance_back += spherical_harmonics_evaluate_lambert(-Ng, sh); radiance_back += half3(spherical_harmonics_evaluate_lambert(-Ng, sh));
out_radiance = vec4(radiance_front * albedo_front + radiance_back * albedo_back, 0.0); out_radiance = vec4(vec3(radiance_front * albedo_front + radiance_back * albedo_back), 0.0);
} }

View File

@ -16,7 +16,7 @@ void main()
vec3 R = -reflect(V, probe_normal); vec3 R = -reflect(V, probe_normal);
SphereProbeUvArea world_atlas_coord = reinterpret_as_atlas_coord(world_coord_packed); SphereProbeUvArea world_atlas_coord = reinterpret_as_atlas_coord(world_coord_packed);
out_color = lightprobe_spheres_sample(R, 0.0, world_atlas_coord); out_color = vec4(lightprobe_spheres_sample(R, 0.0, world_atlas_coord));
} }
else { else {
out_color = texture(planar_radiance_tx, vec3(uv, probe_index)); out_color = texture(planar_radiance_tx, vec3(uv, probe_index));

View File

@ -20,6 +20,7 @@ void main()
vec3 V = drw_world_incident_vector(P); vec3 V = drw_world_incident_vector(P);
vec3 L = reflect(-V, N); vec3 L = reflect(-V, N);
out_color = lightprobe_spheres_sample(L, 0, lightprobe_sphere_buf[probe_index].atlas_coord); out_color = vec4(
lightprobe_spheres_sample(L, 0, lightprobe_sphere_buf[probe_index].atlas_coord));
out_color.a = 0.0; out_color.a = 0.0;
} }

View File

@ -81,11 +81,11 @@ struct GBufferReader {
/* Additional object information if any closure needs it. */ /* Additional object information if any closure needs it. */
float thickness; float thickness;
/* Number of valid closure encoded in the gbuffer. */ /* Number of valid closure encoded in the gbuffer. */
int closure_count; uchar closure_count;
/* Only used for book-keeping when reading. */ /* Only used for book-keeping when reading. */
int data_len; uchar data_len;
/* Only used for debugging and testing. */ /* Only used for debugging and testing. */
int normal_len; uchar normal_len;
}; };
ClosureType gbuffer_mode_to_closure_type(uint mode) ClosureType gbuffer_mode_to_closure_type(uint mode)
@ -126,7 +126,7 @@ uint fetchGBuffer(usampler2D tx, ivec2 texel)
{ {
return texelFetch(tx, texel, 0).r; return texelFetch(tx, texel, 0).r;
} }
vec4 fetchGBuffer(sampler2DArray tx, ivec2 texel, int layer) vec4 fetchGBuffer(sampler2DArray tx, ivec2 texel, uchar layer)
{ {
return texelFetch(tx, ivec3(texel, layer), 0); return texelFetch(tx, ivec3(texel, layer), 0);
} }
@ -142,11 +142,11 @@ uint fetchGBuffer(samplerGBufferHeader tx, ivec2 texel)
{ {
return uint(0); return uint(0);
} }
vec4 fetchGBuffer(samplerGBufferClosure tx, ivec2 texel, int layer) vec4 fetchGBuffer(samplerGBufferClosure tx, ivec2 texel, uchar layer)
{ {
return vec4(0.0); return vec4(0.0);
} }
vec4 fetchGBuffer(samplerGBufferNormal tx, ivec2 texel, int layer) vec4 fetchGBuffer(samplerGBufferNormal tx, ivec2 texel, uchar layer)
{ {
return vec4(0.0); return vec4(0.0);
} }
@ -159,11 +159,11 @@ uint fetchGBuffer(samplerGBufferHeader tx, ivec2 texel)
{ {
return g_data_packed.header; return g_data_packed.header;
} }
vec4 fetchGBuffer(samplerGBufferClosure tx, ivec2 texel, int layer) vec4 fetchGBuffer(samplerGBufferClosure tx, ivec2 texel, uchar layer)
{ {
return g_data_packed.data[layer]; return g_data_packed.data[layer];
} }
vec4 fetchGBuffer(samplerGBufferNormal tx, ivec2 texel, int layer) vec4 fetchGBuffer(samplerGBufferNormal tx, ivec2 texel, uchar layer)
{ {
return g_data_packed.N[layer].xyyy; return g_data_packed.N[layer].xyyy;
} }
@ -557,8 +557,8 @@ void gbuffer_closure_diffuse_skip(inout GBufferReader gbuf)
gbuffer_skip_normal(gbuf); gbuffer_skip_normal(gbuf);
} }
void gbuffer_closure_diffuse_load(inout GBufferReader gbuf, void gbuffer_closure_diffuse_load(inout GBufferReader gbuf,
int layer, uchar layer,
int bin_index, uchar bin_index,
samplerGBufferClosure closure_tx, samplerGBufferClosure closure_tx,
samplerGBufferNormal normal_tx) samplerGBufferNormal normal_tx)
{ {
@ -584,8 +584,8 @@ void gbuffer_closure_translucent_skip(inout GBufferReader gbuf)
gbuffer_skip_normal(gbuf); gbuffer_skip_normal(gbuf);
} }
void gbuffer_closure_translucent_load(inout GBufferReader gbuf, void gbuffer_closure_translucent_load(inout GBufferReader gbuf,
int layer, uchar layer,
int bin_index, uchar bin_index,
samplerGBufferClosure closure_tx, samplerGBufferClosure closure_tx,
samplerGBufferNormal normal_tx) samplerGBufferNormal normal_tx)
{ {
@ -613,8 +613,8 @@ void gbuffer_closure_subsurface_skip(inout GBufferReader gbuf)
gbuffer_skip_normal(gbuf); gbuffer_skip_normal(gbuf);
} }
void gbuffer_closure_subsurface_load(inout GBufferReader gbuf, void gbuffer_closure_subsurface_load(inout GBufferReader gbuf,
int layer, uchar layer,
int bin_index, uchar bin_index,
samplerGBufferClosure closure_tx, samplerGBufferClosure closure_tx,
samplerGBufferNormal normal_tx) samplerGBufferNormal normal_tx)
{ {
@ -644,8 +644,8 @@ void gbuffer_closure_reflection_skip(inout GBufferReader gbuf)
gbuffer_skip_normal(gbuf); gbuffer_skip_normal(gbuf);
} }
void gbuffer_closure_reflection_load(inout GBufferReader gbuf, void gbuffer_closure_reflection_load(inout GBufferReader gbuf,
int layer, uchar layer,
int bin_index, uchar bin_index,
samplerGBufferClosure closure_tx, samplerGBufferClosure closure_tx,
samplerGBufferNormal normal_tx) samplerGBufferNormal normal_tx)
{ {
@ -675,8 +675,8 @@ void gbuffer_closure_refraction_skip(inout GBufferReader gbuf)
gbuffer_skip_normal(gbuf); gbuffer_skip_normal(gbuf);
} }
void gbuffer_closure_refraction_load(inout GBufferReader gbuf, void gbuffer_closure_refraction_load(inout GBufferReader gbuf,
int layer, uchar layer,
int bin_index, uchar bin_index,
samplerGBufferClosure closure_tx, samplerGBufferClosure closure_tx,
samplerGBufferNormal normal_tx) samplerGBufferNormal normal_tx)
{ {
@ -714,8 +714,8 @@ void gbuffer_closure_reflection_colorless_skip(inout GBufferReader gbuf)
gbuffer_skip_normal(gbuf); gbuffer_skip_normal(gbuf);
} }
void gbuffer_closure_reflection_colorless_load(inout GBufferReader gbuf, void gbuffer_closure_reflection_colorless_load(inout GBufferReader gbuf,
int layer, uchar layer,
int bin_index, uchar bin_index,
samplerGBufferClosure closure_tx, samplerGBufferClosure closure_tx,
samplerGBufferNormal normal_tx) samplerGBufferNormal normal_tx)
{ {
@ -744,8 +744,8 @@ void gbuffer_closure_refraction_colorless_skip(inout GBufferReader gbuf)
gbuffer_skip_normal(gbuf); gbuffer_skip_normal(gbuf);
} }
void gbuffer_closure_refraction_colorless_load(inout GBufferReader gbuf, void gbuffer_closure_refraction_colorless_load(inout GBufferReader gbuf,
int layer, uchar layer,
int bin_index, uchar bin_index,
samplerGBufferClosure closure_tx, samplerGBufferClosure closure_tx,
samplerGBufferNormal normal_tx) samplerGBufferNormal normal_tx)
{ {
@ -931,7 +931,7 @@ ClosureType gbuffer_closure_type_get_by_bin(uint header, int bin_index)
int gbuffer_closure_get_bin_index(GBufferReader gbuf, int layer_index) int gbuffer_closure_get_bin_index(GBufferReader gbuf, int layer_index)
{ {
int layer = 0; int layer = 0;
for (int bin = 0; bin < GBUFFER_LAYER_MAX; bin++) { for (uchar bin = 0; bin < GBUFFER_LAYER_MAX; bin++) {
GBufferMode mode = gbuffer_header_unpack(gbuf.header, bin); GBufferMode mode = gbuffer_header_unpack(gbuf.header, bin);
/* Gbuffer header can have holes. Skip GBUF_NONE. */ /* Gbuffer header can have holes. Skip GBUF_NONE. */
if (mode != GBUF_NONE) { if (mode != GBUF_NONE) {
@ -948,7 +948,7 @@ int gbuffer_closure_get_bin_index(GBufferReader gbuf, int layer_index)
ClosureUndetermined gbuffer_closure_get_by_bin(GBufferReader gbuf, int bin_index) ClosureUndetermined gbuffer_closure_get_by_bin(GBufferReader gbuf, int bin_index)
{ {
int layer_index = 0; int layer_index = 0;
for (int bin = 0; bin < GBUFFER_LAYER_MAX; bin++) { for (uchar bin = 0; bin < GBUFFER_LAYER_MAX; bin++) {
GBufferMode mode = gbuffer_header_unpack(gbuf.header, bin); GBufferMode mode = gbuffer_header_unpack(gbuf.header, bin);
if (bin == bin_index) { if (bin == bin_index) {
return gbuffer_closure_get(gbuf, layer_index); return gbuffer_closure_get(gbuf, layer_index);
@ -977,7 +977,7 @@ GBufferReader gbuffer_read(samplerGBufferHeader header_tx,
gbuf.data_len = 0; gbuf.data_len = 0;
gbuf.normal_len = 0; gbuf.normal_len = 0;
gbuf.surface_N = vec3(0.0); gbuf.surface_N = vec3(0.0);
for (int bin = 0; bin < GBUFFER_LAYER_MAX; bin++) { for (uchar bin = 0; bin < GBUFFER_LAYER_MAX; bin++) {
gbuffer_register_closure(gbuf, closure_new(CLOSURE_NONE_ID), bin); gbuffer_register_closure(gbuf, closure_new(CLOSURE_NONE_ID), bin);
} }
@ -991,7 +991,7 @@ GBufferReader gbuffer_read(samplerGBufferHeader header_tx,
gbuf.surface_N = gbuffer_normal_unpack(fetchGBuffer(normal_tx, texel, 0).xy); gbuf.surface_N = gbuffer_normal_unpack(fetchGBuffer(normal_tx, texel, 0).xy);
bool has_additional_data = false; bool has_additional_data = false;
for (int bin = 0; bin < GBUFFER_LAYER_MAX; bin++) { for (uchar bin = 0; bin < GBUFFER_LAYER_MAX; bin++) {
GBufferMode mode = gbuffer_header_unpack(gbuf.header, bin); GBufferMode mode = gbuffer_header_unpack(gbuf.header, bin);
switch (mode) { switch (mode) {
default: default:
@ -1060,7 +1060,7 @@ ClosureUndetermined gbuffer_read_bin(uint header,
} }
GBufferMode mode; GBufferMode mode;
for (int bin = 0; bin < GBUFFER_LAYER_MAX; bin++) { for (uchar bin = 0; bin < GBUFFER_LAYER_MAX; bin++) {
mode = gbuffer_header_unpack(gbuf.header, bin); mode = gbuffer_header_unpack(gbuf.header, bin);
if (bin >= bin_index) { if (bin >= bin_index) {

View File

@ -97,17 +97,17 @@ void light_eval_single_closure(LightData light,
LightVector lv, LightVector lv,
inout ClosureLight cl, inout ClosureLight cl,
vec3 V, vec3 V,
float attenuation, half attenuation,
float shadow, half shadow,
const bool is_transmission) const bool is_transmission)
{ {
attenuation *= light_power_get(light, cl.type); attenuation *= light_power_get(light, cl.type);
if (attenuation < 1e-30) { if (attenuation < 1e-30) {
return; return;
} }
float ltc_result = light_ltc(utility_tx, light, cl.N, V, lv, cl.ltc_mat); float ltc_result = light_ltc(utility_tx, light, cl.N, V, lv, vec4(cl.ltc_mat));
vec3 out_radiance = light.color * ltc_result; half3 out_radiance = half3(light.color * ltc_result);
float visibility = shadow * attenuation; half visibility = shadow * attenuation;
cl.light_shadowed += visibility * out_radiance; cl.light_shadowed += visibility * out_radiance;
cl.light_unshadowed += attenuation * out_radiance; cl.light_unshadowed += attenuation * out_radiance;
} }
@ -148,7 +148,7 @@ void light_eval_single(uint l_idx,
return; return;
} }
float shadow = 1.0; half shadow = 1.0;
if (light.tilemap_index != LIGHT_NO_SHADOW) { if (light.tilemap_index != LIGHT_NO_SHADOW) {
shadow = shadow_eval(light, shadow = shadow_eval(light,
is_directional, is_directional,

View File

@ -67,10 +67,10 @@ vec3 lightprobe_sphere_parallax(SphereProbeData probe, vec3 P, vec3 L)
* Return spherical sample normalized by irradiance at sample position. * Return spherical sample normalized by irradiance at sample position.
* This avoid most of light leaking and reduce the need for many local probes. * This avoid most of light leaking and reduce the need for many local probes.
*/ */
vec3 lightprobe_spherical_sample_normalized_with_parallax(LightProbeSample samp, half3 lightprobe_spherical_sample_normalized_with_parallax(LightProbeSample samp,
vec3 P, vec3 P,
vec3 L, vec3 L,
float lod) float lod)
{ {
SphereProbeData probe = lightprobe_sphere_buf[samp.spherical_id]; SphereProbeData probe = lightprobe_sphere_buf[samp.spherical_id];
ReflectionProbeLowFreqLight shading_sh = lightprobe_spheres_extract_low_freq( ReflectionProbeLowFreqLight shading_sh = lightprobe_spheres_extract_low_freq(
@ -87,36 +87,35 @@ float pdf_to_lod(float inv_pdf)
return blur_pdf * 2.0; return blur_pdf * 2.0;
} }
vec3 lightprobe_eval_direction(LightProbeSample samp, vec3 P, vec3 L, float inv_pdf) half3 lightprobe_eval_direction(LightProbeSample samp, vec3 P, vec3 L, float inv_pdf)
{ {
vec3 radiance_sh = lightprobe_spherical_sample_normalized_with_parallax( return lightprobe_spherical_sample_normalized_with_parallax(samp, P, L, pdf_to_lod(inv_pdf));
samp, P, L, pdf_to_lod(inv_pdf));
return radiance_sh;
} }
# ifdef EEVEE_UTILITY_TX # ifdef EEVEE_UTILITY_TX
/* TODO: Port that inside a BSSDF file. */ /* TODO: Port that inside a BSSDF file. */
vec3 lightprobe_eval(LightProbeSample samp, ClosureSubsurface cl, vec3 P, vec3 V, float thickness) half3 lightprobe_eval(LightProbeSample samp, ClosureSubsurface cl, vec3 P, vec3 V, float thickness)
{ {
vec3 sss_profile = subsurface_transmission(cl.sss_radius, abs(thickness)); half3 sss_profile = subsurface_transmission(cl.sss_radius, abs(thickness));
vec3 radiance_sh = spherical_harmonics_evaluate_lambert(cl.N, samp.volume_irradiance); half3 radiance_sh = half3(spherical_harmonics_evaluate_lambert(cl.N, samp.volume_irradiance));
radiance_sh += spherical_harmonics_evaluate_lambert(-cl.N, samp.volume_irradiance) * sss_profile; radiance_sh += half3(spherical_harmonics_evaluate_lambert(-cl.N, samp.volume_irradiance)) *
sss_profile;
return radiance_sh; return radiance_sh;
} }
vec3 lightprobe_eval( half3 lightprobe_eval(
LightProbeSample samp, ClosureUndetermined cl, vec3 P, vec3 V, float thickness) LightProbeSample samp, ClosureUndetermined cl, vec3 P, vec3 V, float thickness)
{ {
LightProbeRay ray = bxdf_lightprobe_ray(cl, P, V, thickness); LightProbeRay ray = bxdf_lightprobe_ray(cl, P, V, thickness);
float lod = sphere_probe_roughness_to_lod(ray.perceptual_roughness); float lod = sphere_probe_roughness_to_lod(ray.perceptual_roughness);
float fac = sphere_probe_roughness_to_mix_fac(ray.perceptual_roughness); half fac = sphere_probe_roughness_to_mix_fac(ray.perceptual_roughness);
vec3 radiance_cube = lightprobe_spherical_sample_normalized_with_parallax( half3 radiance_cube = lightprobe_spherical_sample_normalized_with_parallax(
samp, P, ray.dominant_direction, lod); samp, P, ray.dominant_direction, lod);
vec3 radiance_sh = spherical_harmonics_evaluate_lambert(ray.dominant_direction, half3 radiance_sh = half3(
samp.volume_irradiance); spherical_harmonics_evaluate_lambert(ray.dominant_direction, samp.volume_irradiance));
return mix(radiance_cube, radiance_sh, fac); return mix(radiance_cube, radiance_sh, fac);
} }
# endif # endif

View File

@ -10,17 +10,18 @@
#include "gpu_shader_math_vector_lib.glsl" #include "gpu_shader_math_vector_lib.glsl"
#ifdef SPHERE_PROBE #ifdef SPHERE_PROBE
vec4 lightprobe_spheres_sample(vec3 L, float lod, SphereProbeUvArea uv_area) half4 lightprobe_spheres_sample(vec3 L, float lod, SphereProbeUvArea uv_area)
{ {
float lod_min = floor(lod); float lod_min = floor(lod);
float lod_max = ceil(lod); float lod_max = ceil(lod);
float mix_fac = lod - lod_min; half mix_fac = half(lod - lod_min);
vec2 altas_uv_min, altas_uv_max; vec2 altas_uv_min, altas_uv_max;
sphere_probe_direction_to_uv(L, lod_min, lod_max, uv_area, altas_uv_min, altas_uv_max); sphere_probe_direction_to_uv(L, lod_min, lod_max, uv_area, altas_uv_min, altas_uv_max);
vec4 color_min = textureLod(lightprobe_spheres_tx, vec3(altas_uv_min, uv_area.layer), lod_min); half4 color_min, color_max;
vec4 color_max = textureLod(lightprobe_spheres_tx, vec3(altas_uv_max, uv_area.layer), lod_max); color_min = half4(textureLod(lightprobe_spheres_tx, vec3(altas_uv_min, uv_area.layer), lod_min));
color_max = half4(textureLod(lightprobe_spheres_tx, vec3(altas_uv_max, uv_area.layer), lod_max));
return mix(color_min, color_max, mix_fac); return mix(color_min, color_max, mix_fac);
} }
#endif #endif

View File

@ -68,7 +68,7 @@ void irradiance_capture_world(vec3 L, inout SphericalHarmonicL1 sh)
if (capture_info_buf.capture_world_direct) { if (capture_info_buf.capture_world_direct) {
SphereProbeUvArea atlas_coord = capture_info_buf.world_atlas_coord; SphereProbeUvArea atlas_coord = capture_info_buf.world_atlas_coord;
radiance = lightprobe_spheres_sample(L, 0.0, atlas_coord).rgb; radiance = vec3(lightprobe_spheres_sample(L, 0.0, atlas_coord).rgb);
/* Clamped brightness. */ /* Clamped brightness. */
float luma = max(1e-8, reduce_max(radiance)); float luma = max(1e-8, reduce_max(radiance));

View File

@ -70,7 +70,7 @@ void main()
float clamp_indirect = uniform_buf.clamp.surface_indirect; float clamp_indirect = uniform_buf.clamp.surface_indirect;
samp.volume_irradiance = spherical_harmonics_clamp(samp.volume_irradiance, clamp_indirect); samp.volume_irradiance = spherical_harmonics_clamp(samp.volume_irradiance, clamp_indirect);
vec3 radiance = lightprobe_eval_direction(samp, ray.origin, ray.direction, ray_pdf_inv); vec3 radiance = vec3(lightprobe_eval_direction(samp, ray.origin, ray.direction, ray_pdf_inv));
/* Set point really far for correct reprojection of background. */ /* Set point really far for correct reprojection of background. */
float hit_time = 1000.0; float hit_time = 1000.0;

View File

@ -101,7 +101,7 @@ void main()
vec3 Ng = ray.direction; vec3 Ng = ray.direction;
/* Fallback to nearest light-probe. */ /* Fallback to nearest light-probe. */
LightProbeSample samp = lightprobe_load(P, Ng, V); LightProbeSample samp = lightprobe_load(P, Ng, V);
radiance = lightprobe_eval_direction(samp, P, ray.direction, ray_pdf_inv); radiance = vec3(lightprobe_eval_direction(samp, P, ray.direction, ray_pdf_inv));
/* Set point really far for correct reprojection of background. */ /* Set point really far for correct reprojection of background. */
hit.time = 10000.0; hit.time = 10000.0;
} }

View File

@ -141,7 +141,7 @@ void main()
float clamp_indirect = uniform_buf.clamp.surface_indirect; float clamp_indirect = uniform_buf.clamp.surface_indirect;
samp.volume_irradiance = spherical_harmonics_clamp(samp.volume_irradiance, clamp_indirect); samp.volume_irradiance = spherical_harmonics_clamp(samp.volume_irradiance, clamp_indirect);
radiance = lightprobe_eval_direction(samp, ray.origin, ray.direction, ray_pdf_inv); radiance = vec3(lightprobe_eval_direction(samp, ray.origin, ray.direction, ray_pdf_inv));
/* Set point really far for correct reprojection of background. */ /* Set point really far for correct reprojection of background. */
hit.time = 10000.0; hit.time = 10000.0;
} }

View File

@ -409,15 +409,15 @@ float shadow_normal_offset(vec3 Ng, vec3 L)
* Evaluate shadowing by casting rays toward the light direction. * Evaluate shadowing by casting rays toward the light direction.
* Returns light visibility. * Returns light visibility.
*/ */
float shadow_eval(LightData light, half shadow_eval(LightData light,
const bool is_directional, const bool is_directional,
const bool is_transmission, const bool is_transmission,
bool is_translucent_with_thickness, bool is_translucent_with_thickness,
float thickness, /* Only used if is_transmission is true. */ float thickness, /* Only used if is_transmission is true. */
vec3 P, vec3 P,
vec3 Ng, vec3 Ng,
int ray_count, int ray_count,
int ray_step_count) int ray_step_count)
{ {
#if defined(EEVEE_SAMPLING_DATA) && defined(EEVEE_UTILITY_TX) #if defined(EEVEE_SAMPLING_DATA) && defined(EEVEE_UTILITY_TX)
# ifdef GPU_FRAGMENT_SHADER # ifdef GPU_FRAGMENT_SHADER
@ -474,7 +474,7 @@ float shadow_eval(LightData light,
/* Don't do a any horizon clipping in this case as the closure is lit from both sides. */ /* Don't do a any horizon clipping in this case as the closure is lit from both sides. */
lNg = (is_transmission && is_translucent_with_thickness) ? vec3(0.0) : lNg; lNg = (is_transmission && is_translucent_with_thickness) ? vec3(0.0) : lNg;
float surface_hit = 0.0; half surface_hit = 0.0;
for (int ray_index = 0; ray_index < ray_count && ray_index < SHADOW_MAX_RAY; ray_index++) { for (int ray_index = 0; ray_index < ray_count && ray_index < SHADOW_MAX_RAY; ray_index++) {
vec2 random_ray_2d = fract(hammersley_2d(ray_index, ray_count) + random_shadow_3d.xy); vec2 random_ray_2d = fract(hammersley_2d(ray_index, ray_count) + random_shadow_3d.xy);
@ -489,10 +489,10 @@ float shadow_eval(LightData light,
has_hit = shadow_map_trace(clip_ray, ray_step_count, random_shadow_3d.z); has_hit = shadow_map_trace(clip_ray, ray_step_count, random_shadow_3d.z);
} }
surface_hit += float(has_hit); surface_hit += half(has_hit);
} }
/* Average samples. */ /* Average samples. */
return saturate(1.0 - surface_hit / float(ray_count)); return saturate(1.0 - surface_hit / half(ray_count));
} }
/** \} */ /** \} */

View File

@ -15,20 +15,20 @@
#ifdef EEVEE_UTILITY_TX #ifdef EEVEE_UTILITY_TX
float subsurface_transmittance_profile(float u) half subsurface_transmittance_profile(float u)
{ {
return utility_tx_sample(utility_tx, vec2(u, 0.0), UTIL_SSS_TRANSMITTANCE_PROFILE_LAYER).r; return half(utility_tx_sample(utility_tx, vec2(u, 0.0), UTIL_SSS_TRANSMITTANCE_PROFILE_LAYER).r);
} }
/** /**
* Returns the amount of light that can travels through a uniform medium and exit at the backface. * Returns the amount of light that can travels through a uniform medium and exit at the backface.
*/ */
vec3 subsurface_transmission(vec3 sss_radii, float thickness) half3 subsurface_transmission(vec3 sss_radii, float thickness)
{ {
sss_radii *= SSS_TRANSMIT_LUT_RADIUS; sss_radii *= SSS_TRANSMIT_LUT_RADIUS;
vec3 channels_co = saturate(thickness / sss_radii) * SSS_TRANSMIT_LUT_SCALE + vec3 channels_co = saturate(thickness / sss_radii) * SSS_TRANSMIT_LUT_SCALE +
SSS_TRANSMIT_LUT_BIAS; SSS_TRANSMIT_LUT_BIAS;
vec3 translucency; half3 translucency;
translucency.x = (sss_radii.x > 0.0) ? subsurface_transmittance_profile(channels_co.x) : 0.0; translucency.x = (sss_radii.x > 0.0) ? subsurface_transmittance_profile(channels_co.x) : 0.0;
translucency.y = (sss_radii.y > 0.0) ? subsurface_transmittance_profile(channels_co.y) : 0.0; translucency.y = (sss_radii.y > 0.0) ? subsurface_transmittance_profile(channels_co.y) : 0.0;
translucency.z = (sss_radii.z > 0.0) ? subsurface_transmittance_profile(channels_co.z) : 0.0; translucency.z = (sss_radii.z > 0.0) ? subsurface_transmittance_profile(channels_co.z) : 0.0;

View File

@ -46,7 +46,7 @@ void main()
float lod = max(1.0, base_lod); float lod = max(1.0, base_lod);
float mix_factor = min(1.0, base_lod); float mix_factor = min(1.0, base_lod);
SphereProbeUvArea world_atlas_coord = reinterpret_as_atlas_coord(world_coord_packed); SphereProbeUvArea world_atlas_coord = reinterpret_as_atlas_coord(world_coord_packed);
vec4 probe_color = lightprobe_spheres_sample(-g_data.N, lod, world_atlas_coord); vec4 probe_color = vec4(lightprobe_spheres_sample(-g_data.N, lod, world_atlas_coord));
out_background.rgb = mix(out_background.rgb, probe_color.rgb, mix_factor); out_background.rgb = mix(out_background.rgb, probe_color.rgb, mix_factor);
SphericalHarmonicL1 volume_irradiance = lightprobe_volume_sample( SphericalHarmonicL1 volume_irradiance = lightprobe_volume_sample(

View File

@ -35,7 +35,7 @@ void main()
light_eval_reflection(stack, P, Ng, V, 0.0, surfel.receiver_light_set); light_eval_reflection(stack, P, Ng, V, 0.0, surfel.receiver_light_set);
if (capture_info_buf.capture_indirect) { if (capture_info_buf.capture_indirect) {
surfel_buf[index].radiance_direct.front.rgb += stack.cl[0].light_shadowed * surfel_buf[index].radiance_direct.front.rgb += vec3(stack.cl[0].light_shadowed) *
surfel.albedo_front; surfel.albedo_front;
} }
@ -46,6 +46,7 @@ void main()
light_eval_reflection(stack, P, -Ng, -V, 0.0, surfel.receiver_light_set); light_eval_reflection(stack, P, -Ng, -V, 0.0, surfel.receiver_light_set);
if (capture_info_buf.capture_indirect) { if (capture_info_buf.capture_indirect) {
surfel_buf[index].radiance_direct.back.rgb += stack.cl[0].light_shadowed * surfel.albedo_back; surfel_buf[index].radiance_direct.back.rgb += vec3(stack.cl[0].light_shadowed) *
surfel.albedo_back;
} }
} }

View File

@ -89,7 +89,7 @@ void radiance_transfer_world(inout Surfel receiver, vec3 L)
if (capture_info_buf.capture_world_indirect) { if (capture_info_buf.capture_world_indirect) {
SphereProbeUvArea atlas_coord = capture_info_buf.world_atlas_coord; SphereProbeUvArea atlas_coord = capture_info_buf.world_atlas_coord;
radiance = lightprobe_spheres_sample(L, 0.0, atlas_coord).rgb; radiance = vec3(lightprobe_spheres_sample(L, 0.0, atlas_coord).rgb);
} }
if (capture_info_buf.capture_visibility_indirect) { if (capture_info_buf.capture_visibility_indirect) {

View File

@ -576,6 +576,18 @@ vec4 safe_rcp(vec4 a)
{ {
return select(vec4(0.0), (1.0 / a), notEqual(a, vec4(0.0))); return select(vec4(0.0), (1.0 / a), notEqual(a, vec4(0.0)));
} }
half2 safe_rcp(half2 a)
{
return select(half2(0.0), (1.0 / a), notEqual(a, half2(0.0)));
}
half3 safe_rcp(half3 a)
{
return select(half3(0.0), (1.0 / a), notEqual(a, half3(0.0)));
}
half4 safe_rcp(half4 a)
{
return select(half4(0.0), (1.0 / a), notEqual(a, half4(0.0)));
}
vec2 interpolate(vec2 a, vec2 b, float t) vec2 interpolate(vec2 a, vec2 b, float t)
{ {
@ -706,6 +718,18 @@ float reduce_add(vec4 a)
{ {
return a.x + a.y + a.z + a.w; return a.x + a.y + a.z + a.w;
} }
half reduce_add(half2 a)
{
return a.x + a.y;
}
half reduce_add(half3 a)
{
return a.x + a.y + a.z;
}
half reduce_add(half4 a)
{
return a.x + a.y + a.z + a.w;
}
int reduce_add(ivec2 a) int reduce_add(ivec2 a)
{ {
return a.x + a.y; return a.x + a.y;
@ -756,6 +780,18 @@ float average(vec4 a)
{ {
return reduce_add(a) * (1.0 / 4.0); return reduce_add(a) * (1.0 / 4.0);
} }
float average(half2 a)
{
return reduce_add(a) * (1.0 / 2.0);
}
float average(half3 a)
{
return reduce_add(a) * (1.0 / 3.0);
}
float average(half4 a)
{
return reduce_add(a) * (1.0 / 4.0);
}
# define ASSERT_UNIT_EPSILON 0.0002 # define ASSERT_UNIT_EPSILON 0.0002