mirror of
https://github.com/godotengine/godot.git
synced 2025-01-23 02:52:28 -05:00
Merge pull request #99136 from DarioSamo/light-compute-attenuation-skip
Improve performance of shader lighting code in Forward renderers.
This commit is contained in:
commit
f5d82af1fd
3 changed files with 215 additions and 273 deletions
|
@ -2369,11 +2369,7 @@ void fragment_shader(in SceneData scene_data) {
|
||||||
continue; // Statically baked light and object uses lightmap, skip
|
continue; // Statically baked light and object uses lightmap, skip
|
||||||
}
|
}
|
||||||
|
|
||||||
float shadow = light_process_omni_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
|
light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, scene_data.taa_frame_count, albedo, alpha, screen_uv,
|
||||||
|
|
||||||
shadow = blur_shadow(shadow);
|
|
||||||
|
|
||||||
light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, screen_uv,
|
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
backlight,
|
backlight,
|
||||||
#endif
|
#endif
|
||||||
|
@ -2441,11 +2437,7 @@ void fragment_shader(in SceneData scene_data) {
|
||||||
continue; // Statically baked light and object uses lightmap, skip
|
continue; // Statically baked light and object uses lightmap, skip
|
||||||
}
|
}
|
||||||
|
|
||||||
float shadow = light_process_spot_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
|
light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, scene_data.taa_frame_count, albedo, alpha, screen_uv,
|
||||||
|
|
||||||
shadow = blur_shadow(shadow);
|
|
||||||
|
|
||||||
light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, screen_uv,
|
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
backlight,
|
backlight,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1624,13 +1624,7 @@ void main() {
|
||||||
uvec2 omni_indices = instances.data[draw_call.instance_index].omni_lights;
|
uvec2 omni_indices = instances.data[draw_call.instance_index].omni_lights;
|
||||||
for (uint i = 0; i < sc_omni_lights(); i++) {
|
for (uint i = 0; i < sc_omni_lights(); i++) {
|
||||||
uint light_index = (i > 3) ? ((omni_indices.y >> ((i - 4) * 8)) & 0xFF) : ((omni_indices.x >> (i * 8)) & 0xFF);
|
uint light_index = (i > 3) ? ((omni_indices.y >> ((i - 4) * 8)) & 0xFF) : ((omni_indices.x >> (i * 8)) & 0xFF);
|
||||||
|
light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, scene_data.taa_frame_count, albedo, alpha, screen_uv,
|
||||||
float shadow = light_process_omni_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
|
|
||||||
|
|
||||||
shadow = blur_shadow(shadow);
|
|
||||||
|
|
||||||
// Fragment lighting
|
|
||||||
light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, screen_uv,
|
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
backlight,
|
backlight,
|
||||||
#endif
|
#endif
|
||||||
|
@ -1658,12 +1652,7 @@ void main() {
|
||||||
uvec2 spot_indices = instances.data[draw_call.instance_index].spot_lights;
|
uvec2 spot_indices = instances.data[draw_call.instance_index].spot_lights;
|
||||||
for (uint i = 0; i < sc_spot_lights(); i++) {
|
for (uint i = 0; i < sc_spot_lights(); i++) {
|
||||||
uint light_index = (i > 3) ? ((spot_indices.y >> ((i - 4) * 8)) & 0xFF) : ((spot_indices.x >> (i * 8)) & 0xFF);
|
uint light_index = (i > 3) ? ((spot_indices.y >> ((i - 4) * 8)) & 0xFF) : ((spot_indices.x >> (i * 8)) & 0xFF);
|
||||||
|
light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, scene_data.taa_frame_count, albedo, alpha, screen_uv,
|
||||||
float shadow = light_process_spot_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
|
|
||||||
|
|
||||||
shadow = blur_shadow(shadow);
|
|
||||||
|
|
||||||
light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, screen_uv,
|
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
backlight,
|
backlight,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -59,16 +59,14 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_di
|
||||||
vec3 B, vec3 T, float anisotropy,
|
vec3 B, vec3 T, float anisotropy,
|
||||||
#endif
|
#endif
|
||||||
inout vec3 diffuse_light, inout vec3 specular_light) {
|
inout vec3 diffuse_light, inout vec3 specular_light) {
|
||||||
|
|
||||||
vec4 orms_unpacked = unpackUnorm4x8(orms);
|
vec4 orms_unpacked = unpackUnorm4x8(orms);
|
||||||
|
|
||||||
float roughness = orms_unpacked.y;
|
float roughness = orms_unpacked.y;
|
||||||
float metallic = orms_unpacked.z;
|
float metallic = orms_unpacked.z;
|
||||||
|
|
||||||
#if defined(LIGHT_CODE_USED)
|
#if defined(LIGHT_CODE_USED)
|
||||||
// light is written by the light shader
|
// Light is written by the user shader.
|
||||||
|
|
||||||
mat4 inv_view_matrix = scene_data_block.data.inv_view_matrix;
|
mat4 inv_view_matrix = scene_data_block.data.inv_view_matrix;
|
||||||
|
mat4 read_view_matrix = scene_data_block.data.view_matrix;
|
||||||
|
|
||||||
#ifdef USING_MOBILE_RENDERER
|
#ifdef USING_MOBILE_RENDERER
|
||||||
mat4 read_model_matrix = instances.data[draw_call.instance_index].transform;
|
mat4 read_model_matrix = instances.data[draw_call.instance_index].transform;
|
||||||
|
@ -76,158 +74,61 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_di
|
||||||
mat4 read_model_matrix = instances.data[instance_index_interp].transform;
|
mat4 read_model_matrix = instances.data[instance_index_interp].transform;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mat4 read_view_matrix = scene_data_block.data.view_matrix;
|
|
||||||
|
|
||||||
#undef projection_matrix
|
#undef projection_matrix
|
||||||
#define projection_matrix scene_data_block.data.projection_matrix
|
#define projection_matrix scene_data_block.data.projection_matrix
|
||||||
#undef inv_projection_matrix
|
#undef inv_projection_matrix
|
||||||
#define inv_projection_matrix scene_data_block.data.inv_projection_matrix
|
#define inv_projection_matrix scene_data_block.data.inv_projection_matrix
|
||||||
|
|
||||||
vec2 read_viewport_size = scene_data_block.data.viewport_size;
|
vec2 read_viewport_size = scene_data_block.data.viewport_size;
|
||||||
|
|
||||||
vec3 normal = N;
|
vec3 normal = N;
|
||||||
vec3 light = L;
|
vec3 light = L;
|
||||||
vec3 view = V;
|
vec3 view = V;
|
||||||
|
|
||||||
#CODE : LIGHT
|
#CODE : LIGHT
|
||||||
|
#else // !LIGHT_CODE_USED
|
||||||
#else
|
|
||||||
|
|
||||||
float NdotL = min(A + dot(N, L), 1.0);
|
float NdotL = min(A + dot(N, L), 1.0);
|
||||||
float cNdotL = max(NdotL, 0.0); // clamped NdotL
|
float cNdotV = max(dot(N, V), 1e-4);
|
||||||
float NdotV = dot(N, V);
|
|
||||||
float cNdotV = max(NdotV, 1e-4);
|
|
||||||
|
|
||||||
#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
|
|
||||||
vec3 H = normalize(V + L);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SPECULAR_SCHLICK_GGX)
|
|
||||||
float cNdotH = clamp(A + dot(N, H), 0.0, 1.0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
|
|
||||||
float cLdotH = clamp(A + dot(L, H), 0.0, 1.0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (metallic < 1.0) {
|
|
||||||
float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance
|
|
||||||
|
|
||||||
#if defined(DIFFUSE_LAMBERT_WRAP)
|
|
||||||
// Energy conserving lambert wrap shader.
|
|
||||||
// https://web.archive.org/web/20210228210901/http://blog.stevemcauley.com/2011/12/03/energy-conserving-wrapped-diffuse/
|
|
||||||
diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))) * (1.0 / M_PI);
|
|
||||||
#elif defined(DIFFUSE_TOON)
|
|
||||||
|
|
||||||
diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL) * (1.0 / M_PI);
|
|
||||||
|
|
||||||
#elif defined(DIFFUSE_BURLEY)
|
|
||||||
|
|
||||||
{
|
|
||||||
float FD90_minus_1 = 2.0 * cLdotH * cLdotH * roughness - 0.5;
|
|
||||||
float FdV = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotV);
|
|
||||||
float FdL = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotL);
|
|
||||||
diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL;
|
|
||||||
/*
|
|
||||||
float energyBias = mix(roughness, 0.0, 0.5);
|
|
||||||
float energyFactor = mix(roughness, 1.0, 1.0 / 1.51);
|
|
||||||
float fd90 = energyBias + 2.0 * VoH * VoH * roughness;
|
|
||||||
float f0 = 1.0;
|
|
||||||
float lightScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotL, 5.0);
|
|
||||||
float viewScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotV, 5.0);
|
|
||||||
|
|
||||||
diffuse_brdf_NL = lightScatter * viewScatter * energyFactor;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// lambert
|
|
||||||
diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
diffuse_light += light_color * diffuse_brdf_NL * attenuation;
|
|
||||||
|
|
||||||
#if defined(LIGHT_BACKLIGHT_USED)
|
|
||||||
diffuse_light += light_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * backlight * attenuation;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(LIGHT_RIM_USED)
|
|
||||||
// Epsilon min to prevent pow(0, 0) singularity which results in undefined behavior.
|
|
||||||
float rim_light = pow(max(1e-4, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
|
|
||||||
diffuse_light += rim_light * rim * mix(vec3(1.0), albedo, rim_tint) * light_color;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||||
|
{
|
||||||
{
|
|
||||||
#ifdef SSS_MODE_SKIN
|
#ifdef SSS_MODE_SKIN
|
||||||
float scale = 8.25 / transmittance_depth;
|
float scale = 8.25 / transmittance_depth;
|
||||||
float d = scale * abs(transmittance_z);
|
float d = scale * abs(transmittance_z);
|
||||||
float dd = -d * d;
|
float dd = -d * d;
|
||||||
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
|
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
|
||||||
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
|
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
|
||||||
vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
|
vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
|
||||||
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
|
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
|
||||||
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
|
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
|
||||||
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
|
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
|
||||||
|
|
||||||
diffuse_light += profile * transmittance_color.a * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI);
|
diffuse_light += profile * transmittance_color.a * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
float scale = 8.25 / transmittance_depth;
|
float scale = 8.25 / transmittance_depth;
|
||||||
float d = scale * abs(transmittance_z);
|
float d = scale * abs(transmittance_z);
|
||||||
float dd = -d * d;
|
float dd = -d * d;
|
||||||
diffuse_light += exp(dd) * transmittance_color.rgb * transmittance_color.a * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI);
|
diffuse_light += exp(dd) * transmittance_color.rgb * transmittance_color.a * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
#else
|
|
||||||
|
|
||||||
#endif //LIGHT_TRANSMITTANCE_USED
|
|
||||||
}
|
}
|
||||||
|
#endif //LIGHT_TRANSMITTANCE_USED
|
||||||
|
|
||||||
if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely
|
#if defined(LIGHT_RIM_USED)
|
||||||
|
// Epsilon min to prevent pow(0, 0) singularity which results in undefined behavior.
|
||||||
// D
|
float rim_light = pow(max(1e-4, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
|
||||||
|
diffuse_light += rim_light * rim * mix(vec3(1.0), albedo, rim_tint) * light_color;
|
||||||
#if defined(SPECULAR_TOON)
|
|
||||||
|
|
||||||
vec3 R = normalize(-reflect(L, N));
|
|
||||||
float RdotV = dot(R, V);
|
|
||||||
float mid = 1.0 - roughness;
|
|
||||||
mid *= mid;
|
|
||||||
float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
|
|
||||||
diffuse_light += light_color * intensity * attenuation * specular_amount; // write to diffuse_light, as in toon shading you generally want no reflection
|
|
||||||
|
|
||||||
#elif defined(SPECULAR_DISABLED)
|
|
||||||
// none..
|
|
||||||
|
|
||||||
#elif defined(SPECULAR_SCHLICK_GGX)
|
|
||||||
// shlick+ggx as default
|
|
||||||
float alpha_ggx = roughness * roughness;
|
|
||||||
#if defined(LIGHT_ANISOTROPY_USED)
|
|
||||||
|
|
||||||
float aspect = sqrt(1.0 - anisotropy * 0.9);
|
|
||||||
float ax = alpha_ggx / aspect;
|
|
||||||
float ay = alpha_ggx * aspect;
|
|
||||||
float XdotH = dot(T, H);
|
|
||||||
float YdotH = dot(B, H);
|
|
||||||
float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH);
|
|
||||||
float G = V_GGX_anisotropic(ax, ay, dot(T, V), dot(T, L), dot(B, V), dot(B, L), cNdotV, cNdotL);
|
|
||||||
#else // LIGHT_ANISOTROPY_USED
|
|
||||||
float D = D_GGX(cNdotH, alpha_ggx);
|
|
||||||
float G = V_GGX(cNdotL, cNdotV, alpha_ggx);
|
|
||||||
#endif // LIGHT_ANISOTROPY_USED
|
|
||||||
// F
|
|
||||||
float cLdotH5 = SchlickFresnel(cLdotH);
|
|
||||||
// Calculate Fresnel using specular occlusion term from Filament:
|
|
||||||
// https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion
|
|
||||||
float f90 = clamp(dot(f0, vec3(50.0 * 0.33)), metallic, 1.0);
|
|
||||||
vec3 F = f0 + (f90 - f0) * cLdotH5;
|
|
||||||
|
|
||||||
vec3 specular_brdf_NL = cNdotL * D * F * G;
|
|
||||||
|
|
||||||
specular_light += specular_brdf_NL * light_color * attenuation * specular_amount;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// We skip checking on attenuation on directional lights to avoid a branch that is not as beneficial for directional lights as the other ones.
|
||||||
|
const float EPSILON = 1e-3f;
|
||||||
|
if (is_directional || attenuation > EPSILON) {
|
||||||
|
float cNdotL = max(NdotL, 0.0);
|
||||||
|
#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
|
||||||
|
vec3 H = normalize(V + L);
|
||||||
|
#endif
|
||||||
|
#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
|
||||||
|
float cLdotH = clamp(A + dot(L, H), 0.0, 1.0);
|
||||||
|
#endif
|
||||||
#if defined(LIGHT_CLEARCOAT_USED)
|
#if defined(LIGHT_CLEARCOAT_USED)
|
||||||
// Clearcoat ignores normal_map, use vertex normal instead
|
// Clearcoat ignores normal_map, use vertex normal instead
|
||||||
float ccNdotL = max(min(A + dot(vertex_normal, L), 1.0), 0.0);
|
float ccNdotL = max(min(A + dot(vertex_normal, L), 1.0), 0.0);
|
||||||
|
@ -243,16 +144,89 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_di
|
||||||
float clearcoat_specular_brdf_NL = clearcoat * Gr * Fr * Dr * cNdotL;
|
float clearcoat_specular_brdf_NL = clearcoat * Gr * Fr * Dr * cNdotL;
|
||||||
|
|
||||||
specular_light += clearcoat_specular_brdf_NL * light_color * attenuation * specular_amount;
|
specular_light += clearcoat_specular_brdf_NL * light_color * attenuation * specular_amount;
|
||||||
|
|
||||||
// TODO: Clearcoat adds light to the scene right now (it is non-energy conserving), both diffuse and specular need to be scaled by (1.0 - FR)
|
// TODO: Clearcoat adds light to the scene right now (it is non-energy conserving), both diffuse and specular need to be scaled by (1.0 - FR)
|
||||||
// but to do so we need to rearrange this entire function
|
// but to do so we need to rearrange this entire function
|
||||||
#endif // LIGHT_CLEARCOAT_USED
|
#endif // LIGHT_CLEARCOAT_USED
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_SHADOW_TO_OPACITY
|
if (metallic < 1.0) {
|
||||||
alpha = min(alpha, clamp(1.0 - attenuation, 0.0, 1.0));
|
float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance
|
||||||
|
|
||||||
|
#if defined(DIFFUSE_LAMBERT_WRAP)
|
||||||
|
// Energy conserving lambert wrap shader.
|
||||||
|
// https://web.archive.org/web/20210228210901/http://blog.stevemcauley.com/2011/12/03/energy-conserving-wrapped-diffuse/
|
||||||
|
diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))) * (1.0 / M_PI);
|
||||||
|
#elif defined(DIFFUSE_TOON)
|
||||||
|
|
||||||
|
diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL) * (1.0 / M_PI);
|
||||||
|
|
||||||
|
#elif defined(DIFFUSE_BURLEY)
|
||||||
|
{
|
||||||
|
float FD90_minus_1 = 2.0 * cLdotH * cLdotH * roughness - 0.5;
|
||||||
|
float FdV = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotV);
|
||||||
|
float FdL = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotL);
|
||||||
|
diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// lambert
|
||||||
|
diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif //defined(LIGHT_CODE_USED)
|
diffuse_light += light_color * diffuse_brdf_NL * attenuation;
|
||||||
|
|
||||||
|
#if defined(LIGHT_BACKLIGHT_USED)
|
||||||
|
diffuse_light += light_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * backlight * attenuation;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roughness > 0.0) {
|
||||||
|
#if defined(SPECULAR_SCHLICK_GGX)
|
||||||
|
float cNdotH = clamp(A + dot(N, H), 0.0, 1.0);
|
||||||
|
#endif
|
||||||
|
// Apply specular light.
|
||||||
|
// FIXME: roughness == 0 should not disable specular light entirely
|
||||||
|
#if defined(SPECULAR_TOON)
|
||||||
|
vec3 R = normalize(-reflect(L, N));
|
||||||
|
float RdotV = dot(R, V);
|
||||||
|
float mid = 1.0 - roughness;
|
||||||
|
mid *= mid;
|
||||||
|
float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
|
||||||
|
diffuse_light += light_color * intensity * attenuation * specular_amount; // write to diffuse_light, as in toon shading you generally want no reflection
|
||||||
|
|
||||||
|
#elif defined(SPECULAR_DISABLED)
|
||||||
|
// Do nothing.
|
||||||
|
|
||||||
|
#elif defined(SPECULAR_SCHLICK_GGX)
|
||||||
|
// shlick+ggx as default
|
||||||
|
float alpha_ggx = roughness * roughness;
|
||||||
|
#if defined(LIGHT_ANISOTROPY_USED)
|
||||||
|
float aspect = sqrt(1.0 - anisotropy * 0.9);
|
||||||
|
float ax = alpha_ggx / aspect;
|
||||||
|
float ay = alpha_ggx * aspect;
|
||||||
|
float XdotH = dot(T, H);
|
||||||
|
float YdotH = dot(B, H);
|
||||||
|
float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH);
|
||||||
|
float G = V_GGX_anisotropic(ax, ay, dot(T, V), dot(T, L), dot(B, V), dot(B, L), cNdotV, cNdotL);
|
||||||
|
#else // LIGHT_ANISOTROPY_USED
|
||||||
|
float D = D_GGX(cNdotH, alpha_ggx);
|
||||||
|
float G = V_GGX(cNdotL, cNdotV, alpha_ggx);
|
||||||
|
#endif // LIGHT_ANISOTROPY_USED
|
||||||
|
// F
|
||||||
|
float cLdotH5 = SchlickFresnel(cLdotH);
|
||||||
|
// Calculate Fresnel using specular occlusion term from Filament:
|
||||||
|
// https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion
|
||||||
|
float f90 = clamp(dot(f0, vec3(50.0 * 0.33)), metallic, 1.0);
|
||||||
|
vec3 F = f0 + (f90 - f0) * cLdotH5;
|
||||||
|
vec3 specular_brdf_NL = cNdotL * D * F * G;
|
||||||
|
specular_light += specular_brdf_NL * light_color * attenuation * specular_amount;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_SHADOW_TO_OPACITY
|
||||||
|
alpha = min(alpha, clamp(1.0 - attenuation, 0.0, 1.0));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif // LIGHT_CODE_USED
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SHADOWS_DISABLED
|
#ifndef SHADOWS_DISABLED
|
||||||
|
@ -412,9 +386,43 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {
|
||||||
return nd * pow(max(distance, 0.0001), -decay);
|
return nd * pow(max(distance, 0.0001), -decay);
|
||||||
}
|
}
|
||||||
|
|
||||||
float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal, float taa_frame_count) {
|
void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float taa_frame_count, vec3 albedo, inout float alpha, vec2 screen_uv,
|
||||||
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
|
vec3 backlight,
|
||||||
|
#endif
|
||||||
|
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||||
|
vec4 transmittance_color,
|
||||||
|
float transmittance_depth,
|
||||||
|
float transmittance_boost,
|
||||||
|
#endif
|
||||||
|
#ifdef LIGHT_RIM_USED
|
||||||
|
float rim, float rim_tint,
|
||||||
|
#endif
|
||||||
|
#ifdef LIGHT_CLEARCOAT_USED
|
||||||
|
float clearcoat, float clearcoat_roughness, vec3 vertex_normal,
|
||||||
|
#endif
|
||||||
|
#ifdef LIGHT_ANISOTROPY_USED
|
||||||
|
vec3 binormal, vec3 tangent, float anisotropy,
|
||||||
|
#endif
|
||||||
|
inout vec3 diffuse_light, inout vec3 specular_light) {
|
||||||
|
const float EPSILON = 1e-3f;
|
||||||
|
|
||||||
|
// Omni light attenuation.
|
||||||
|
vec3 light_rel_vec = omni_lights.data[idx].position - vertex;
|
||||||
|
float light_length = length(light_rel_vec);
|
||||||
|
float omni_attenuation = get_omni_attenuation(light_length, omni_lights.data[idx].inv_radius, omni_lights.data[idx].attenuation);
|
||||||
|
|
||||||
|
// Compute size.
|
||||||
|
float size = 0.0;
|
||||||
|
if (sc_use_light_soft_shadows() && omni_lights.data[idx].size > 0.0) {
|
||||||
|
float t = omni_lights.data[idx].size / max(0.001, light_length);
|
||||||
|
size = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
|
||||||
|
}
|
||||||
|
|
||||||
|
float shadow = 1.0;
|
||||||
#ifndef SHADOWS_DISABLED
|
#ifndef SHADOWS_DISABLED
|
||||||
if (omni_lights.data[idx].shadow_opacity > 0.001) {
|
// Omni light shadow.
|
||||||
|
if (omni_attenuation > EPSILON && omni_lights.data[idx].shadow_opacity > 0.001) {
|
||||||
// there is a shadowmap
|
// there is a shadowmap
|
||||||
vec2 texel_size = scene_data_block.data.shadow_atlas_pixel_size;
|
vec2 texel_size = scene_data_block.data.shadow_atlas_pixel_size;
|
||||||
vec4 base_uv_rect = omni_lights.data[idx].atlas_rect;
|
vec4 base_uv_rect = omni_lights.data[idx].atlas_rect;
|
||||||
|
@ -432,8 +440,6 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal, float taa_fr
|
||||||
vec3 local_normal = normalize(mat3(omni_lights.data[idx].shadow_matrix) * normal);
|
vec3 local_normal = normalize(mat3(omni_lights.data[idx].shadow_matrix) * normal);
|
||||||
vec3 normal_bias = local_normal * omni_lights.data[idx].shadow_normal_bias * (1.0 - abs(dot(local_normal, shadow_dir)));
|
vec3 normal_bias = local_normal * omni_lights.data[idx].shadow_normal_bias * (1.0 - abs(dot(local_normal, shadow_dir)));
|
||||||
|
|
||||||
float shadow;
|
|
||||||
|
|
||||||
if (sc_use_light_soft_shadows() && omni_lights.data[idx].soft_shadow_size > 0.0) {
|
if (sc_use_light_soft_shadows() && omni_lights.data[idx].soft_shadow_size > 0.0) {
|
||||||
//soft shadow
|
//soft shadow
|
||||||
|
|
||||||
|
@ -539,49 +545,14 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal, float taa_fr
|
||||||
depth = 1.0 - depth;
|
depth = 1.0 - depth;
|
||||||
shadow = mix(1.0, sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth, taa_frame_count), omni_lights.data[idx].shadow_opacity);
|
shadow = mix(1.0, sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth, taa_frame_count), omni_lights.data[idx].shadow_opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return shadow;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha, vec2 screen_uv,
|
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
|
||||||
vec3 backlight,
|
|
||||||
#endif
|
|
||||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
|
||||||
vec4 transmittance_color,
|
|
||||||
float transmittance_depth,
|
|
||||||
float transmittance_boost,
|
|
||||||
#endif
|
|
||||||
#ifdef LIGHT_RIM_USED
|
|
||||||
float rim, float rim_tint,
|
|
||||||
#endif
|
|
||||||
#ifdef LIGHT_CLEARCOAT_USED
|
|
||||||
float clearcoat, float clearcoat_roughness, vec3 vertex_normal,
|
|
||||||
#endif
|
|
||||||
#ifdef LIGHT_ANISOTROPY_USED
|
|
||||||
vec3 binormal, vec3 tangent, float anisotropy,
|
|
||||||
#endif
|
|
||||||
inout vec3 diffuse_light, inout vec3 specular_light) {
|
|
||||||
vec3 light_rel_vec = omni_lights.data[idx].position - vertex;
|
|
||||||
float light_length = length(light_rel_vec);
|
|
||||||
float omni_attenuation = get_omni_attenuation(light_length, omni_lights.data[idx].inv_radius, omni_lights.data[idx].attenuation);
|
|
||||||
float light_attenuation = omni_attenuation;
|
|
||||||
vec3 color = omni_lights.data[idx].color;
|
vec3 color = omni_lights.data[idx].color;
|
||||||
|
|
||||||
float size_A = 0.0;
|
|
||||||
|
|
||||||
if (sc_use_light_soft_shadows() && omni_lights.data[idx].size > 0.0) {
|
|
||||||
float t = omni_lights.data[idx].size / max(0.001, light_length);
|
|
||||||
size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||||
float transmittance_z = transmittance_depth; //no transmittance by default
|
float transmittance_z = transmittance_depth; //no transmittance by default
|
||||||
transmittance_color.a *= light_attenuation;
|
transmittance_color.a *= omni_attenuation;
|
||||||
#ifndef SHADOWS_DISABLED
|
#ifndef SHADOWS_DISABLED
|
||||||
if (omni_lights.data[idx].shadow_opacity > 0.001) {
|
if (omni_lights.data[idx].shadow_opacity > 0.001) {
|
||||||
// Redo shadowmapping, but shrink the model a bit to avoid artifacts.
|
// Redo shadowmapping, but shrink the model a bit to avoid artifacts.
|
||||||
|
@ -673,9 +644,8 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
light_attenuation *= shadow;
|
vec3 light_rel_vec_norm = light_rel_vec / light_length;
|
||||||
|
light_compute(normal, light_rel_vec_norm, eye_vec, size, color, false, omni_attenuation * shadow, f0, orms, omni_lights.data[idx].specular_amount, albedo, alpha, screen_uv,
|
||||||
light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, false, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount, albedo, alpha, screen_uv,
|
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
backlight,
|
backlight,
|
||||||
#endif
|
#endif
|
||||||
|
@ -698,15 +668,66 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
||||||
specular_light);
|
specular_light);
|
||||||
}
|
}
|
||||||
|
|
||||||
float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal, float taa_frame_count) {
|
vec2 normal_to_panorama(vec3 n) {
|
||||||
#ifndef SHADOWS_DISABLED
|
n = normalize(n);
|
||||||
if (spot_lights.data[idx].shadow_opacity > 0.001) {
|
vec2 panorama_coords = vec2(atan(n.x, n.z), acos(-n.y));
|
||||||
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
|
|
||||||
float light_length = length(light_rel_vec);
|
|
||||||
vec3 spot_dir = spot_lights.data[idx].direction;
|
|
||||||
|
|
||||||
vec3 shadow_dir = light_rel_vec / light_length;
|
if (panorama_coords.x < 0.0) {
|
||||||
vec3 normal_bias = normal * light_length * spot_lights.data[idx].shadow_normal_bias * (1.0 - abs(dot(normal, shadow_dir)));
|
panorama_coords.x += M_PI * 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
panorama_coords /= vec2(M_PI * 2.0, M_PI);
|
||||||
|
return panorama_coords;
|
||||||
|
}
|
||||||
|
|
||||||
|
void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float taa_frame_count, vec3 albedo, inout float alpha, vec2 screen_uv,
|
||||||
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
|
vec3 backlight,
|
||||||
|
#endif
|
||||||
|
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||||
|
vec4 transmittance_color,
|
||||||
|
float transmittance_depth,
|
||||||
|
float transmittance_boost,
|
||||||
|
#endif
|
||||||
|
#ifdef LIGHT_RIM_USED
|
||||||
|
float rim, float rim_tint,
|
||||||
|
#endif
|
||||||
|
#ifdef LIGHT_CLEARCOAT_USED
|
||||||
|
float clearcoat, float clearcoat_roughness, vec3 vertex_normal,
|
||||||
|
#endif
|
||||||
|
#ifdef LIGHT_ANISOTROPY_USED
|
||||||
|
vec3 binormal, vec3 tangent, float anisotropy,
|
||||||
|
#endif
|
||||||
|
inout vec3 diffuse_light,
|
||||||
|
inout vec3 specular_light) {
|
||||||
|
const float EPSILON = 1e-3f;
|
||||||
|
|
||||||
|
// Spot light attenuation.
|
||||||
|
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
|
||||||
|
float light_length = length(light_rel_vec);
|
||||||
|
vec3 light_rel_vec_norm = light_rel_vec / light_length;
|
||||||
|
float spot_attenuation = get_omni_attenuation(light_length, spot_lights.data[idx].inv_radius, spot_lights.data[idx].attenuation);
|
||||||
|
vec3 spot_dir = spot_lights.data[idx].direction;
|
||||||
|
|
||||||
|
// This conversion to a highp float is crucial to prevent light leaking
|
||||||
|
// due to precision errors in the following calculations (cone angle is mediump).
|
||||||
|
highp float cone_angle = spot_lights.data[idx].cone_angle;
|
||||||
|
float scos = max(dot(-light_rel_vec_norm, spot_dir), cone_angle);
|
||||||
|
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cone_angle));
|
||||||
|
spot_attenuation *= 1.0 - pow(spot_rim, spot_lights.data[idx].cone_attenuation);
|
||||||
|
|
||||||
|
// Compute size.
|
||||||
|
float size = 0.0;
|
||||||
|
if (sc_use_light_soft_shadows() && spot_lights.data[idx].size > 0.0) {
|
||||||
|
float t = spot_lights.data[idx].size / max(0.001, light_length);
|
||||||
|
size = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
|
||||||
|
}
|
||||||
|
|
||||||
|
float shadow = 1.0;
|
||||||
|
#ifndef SHADOWS_DISABLED
|
||||||
|
// Spot light shadow.
|
||||||
|
if (spot_attenuation > EPSILON && spot_lights.data[idx].shadow_opacity > 0.001) {
|
||||||
|
vec3 normal_bias = normal * light_length * spot_lights.data[idx].shadow_normal_bias * (1.0 - abs(dot(normal, light_rel_vec_norm)));
|
||||||
|
|
||||||
//there is a shadowmap
|
//there is a shadowmap
|
||||||
vec4 v = vec4(vertex + normal_bias, 1.0);
|
vec4 v = vec4(vertex + normal_bias, 1.0);
|
||||||
|
@ -715,7 +736,6 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal, float taa_fr
|
||||||
splane.z += spot_lights.data[idx].shadow_bias / (light_length * spot_lights.data[idx].inv_radius);
|
splane.z += spot_lights.data[idx].shadow_bias / (light_length * spot_lights.data[idx].inv_radius);
|
||||||
splane /= splane.w;
|
splane /= splane.w;
|
||||||
|
|
||||||
float shadow;
|
|
||||||
if (sc_use_light_soft_shadows() && spot_lights.data[idx].soft_shadow_size > 0.0) {
|
if (sc_use_light_soft_shadows() && spot_lights.data[idx].soft_shadow_size > 0.0) {
|
||||||
//soft shadow
|
//soft shadow
|
||||||
|
|
||||||
|
@ -772,73 +792,15 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal, float taa_fr
|
||||||
vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z);
|
vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z);
|
||||||
shadow = mix(1.0, sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv, taa_frame_count), spot_lights.data[idx].shadow_opacity);
|
shadow = mix(1.0, sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv, taa_frame_count), spot_lights.data[idx].shadow_opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return shadow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SHADOWS_DISABLED
|
#endif // SHADOWS_DISABLED
|
||||||
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 normal_to_panorama(vec3 n) {
|
|
||||||
n = normalize(n);
|
|
||||||
vec2 panorama_coords = vec2(atan(n.x, n.z), acos(-n.y));
|
|
||||||
|
|
||||||
if (panorama_coords.x < 0.0) {
|
|
||||||
panorama_coords.x += M_PI * 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
panorama_coords /= vec2(M_PI * 2.0, M_PI);
|
|
||||||
return panorama_coords;
|
|
||||||
}
|
|
||||||
|
|
||||||
void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha, vec2 screen_uv,
|
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
|
||||||
vec3 backlight,
|
|
||||||
#endif
|
|
||||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
|
||||||
vec4 transmittance_color,
|
|
||||||
float transmittance_depth,
|
|
||||||
float transmittance_boost,
|
|
||||||
#endif
|
|
||||||
#ifdef LIGHT_RIM_USED
|
|
||||||
float rim, float rim_tint,
|
|
||||||
#endif
|
|
||||||
#ifdef LIGHT_CLEARCOAT_USED
|
|
||||||
float clearcoat, float clearcoat_roughness, vec3 vertex_normal,
|
|
||||||
#endif
|
|
||||||
#ifdef LIGHT_ANISOTROPY_USED
|
|
||||||
vec3 binormal, vec3 tangent, float anisotropy,
|
|
||||||
#endif
|
|
||||||
inout vec3 diffuse_light,
|
|
||||||
inout vec3 specular_light) {
|
|
||||||
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
|
|
||||||
float light_length = length(light_rel_vec);
|
|
||||||
float spot_attenuation = get_omni_attenuation(light_length, spot_lights.data[idx].inv_radius, spot_lights.data[idx].attenuation);
|
|
||||||
vec3 spot_dir = spot_lights.data[idx].direction;
|
|
||||||
|
|
||||||
// This conversion to a highp float is crucial to prevent light leaking
|
|
||||||
// due to precision errors in the following calculations (cone angle is mediump).
|
|
||||||
highp float cone_angle = spot_lights.data[idx].cone_angle;
|
|
||||||
float scos = max(dot(-normalize(light_rel_vec), spot_dir), cone_angle);
|
|
||||||
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cone_angle));
|
|
||||||
|
|
||||||
spot_attenuation *= 1.0 - pow(spot_rim, spot_lights.data[idx].cone_attenuation);
|
|
||||||
float light_attenuation = spot_attenuation;
|
|
||||||
vec3 color = spot_lights.data[idx].color;
|
vec3 color = spot_lights.data[idx].color;
|
||||||
float specular_amount = spot_lights.data[idx].specular_amount;
|
float specular_amount = spot_lights.data[idx].specular_amount;
|
||||||
|
|
||||||
float size_A = 0.0;
|
|
||||||
|
|
||||||
if (sc_use_light_soft_shadows() && spot_lights.data[idx].size > 0.0) {
|
|
||||||
float t = spot_lights.data[idx].size / max(0.001, light_length);
|
|
||||||
size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||||
float transmittance_z = transmittance_depth;
|
float transmittance_z = transmittance_depth;
|
||||||
transmittance_color.a *= light_attenuation;
|
transmittance_color.a *= spot_attenuation;
|
||||||
#ifndef SHADOWS_DISABLED
|
#ifndef SHADOWS_DISABLED
|
||||||
if (spot_lights.data[idx].shadow_opacity > 0.001) {
|
if (spot_lights.data[idx].shadow_opacity > 0.001) {
|
||||||
vec4 splane = (spot_lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal) * spot_lights.data[idx].transmittance_bias, 1.0));
|
vec4 splane = (spot_lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal) * spot_lights.data[idx].transmittance_bias, 1.0));
|
||||||
|
@ -882,9 +844,8 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
||||||
color *= proj.rgb * proj.a;
|
color *= proj.rgb * proj.a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
light_attenuation *= shadow;
|
|
||||||
|
|
||||||
light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, false, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount, albedo, alpha, screen_uv,
|
light_compute(normal, light_rel_vec_norm, eye_vec, size, color, false, spot_attenuation * shadow, f0, orms, spot_lights.data[idx].specular_amount, albedo, alpha, screen_uv,
|
||||||
#ifdef LIGHT_BACKLIGHT_USED
|
#ifdef LIGHT_BACKLIGHT_USED
|
||||||
backlight,
|
backlight,
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue