|
@@ -13,69 +13,72 @@
|
|
|
#define SPEC_CONSTANT_LOOP_ANNOTATION
|
|
|
#endif
|
|
|
|
|
|
-float D_GGX(float cos_theta_m, float alpha) {
|
|
|
- float a = cos_theta_m * alpha;
|
|
|
- float k = alpha / (1.0 - cos_theta_m * cos_theta_m + a * a);
|
|
|
- return k * k * (1.0 / M_PI);
|
|
|
+half D_GGX(half NoH, half roughness, hvec3 n, hvec3 h) {
|
|
|
+ half a = NoH * roughness;
|
|
|
+#ifdef EXPLICIT_FP16
|
|
|
+ hvec3 NxH = cross(n, h);
|
|
|
+ half k = roughness / (dot(NxH, NxH) + a * a);
|
|
|
+#else
|
|
|
+ float k = roughness / (1.0 - NoH * NoH + a * a);
|
|
|
+#endif
|
|
|
+ half d = k * k * half(1.0 / M_PI);
|
|
|
+ return saturateHalf(d);
|
|
|
}
|
|
|
|
|
|
// From Earl Hammon, Jr. "PBR Diffuse Lighting for GGX+Smith Microsurfaces" https://www.gdcvault.com/play/1024478/PBR-Diffuse-Lighting-for-GGX
|
|
|
-float V_GGX(float NdotL, float NdotV, float alpha) {
|
|
|
- return 0.5 / mix(2.0 * NdotL * NdotV, NdotL + NdotV, alpha);
|
|
|
+half V_GGX(half NdotL, half NdotV, half alpha) {
|
|
|
+ half v = half(0.5) / mix(half(2.0) * NdotL * NdotV, NdotL + NdotV, alpha);
|
|
|
+ return saturateHalf(v);
|
|
|
}
|
|
|
|
|
|
-float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) {
|
|
|
- float alpha2 = alpha_x * alpha_y;
|
|
|
- highp vec3 v = vec3(alpha_y * cos_phi, alpha_x * sin_phi, alpha2 * cos_theta_m);
|
|
|
- highp float v2 = dot(v, v);
|
|
|
- float w2 = alpha2 / v2;
|
|
|
- float D = alpha2 * w2 * w2 * (1.0 / M_PI);
|
|
|
- return D;
|
|
|
+half D_GGX_anisotropic(half cos_theta_m, half alpha_x, half alpha_y, half cos_phi, half sin_phi) {
|
|
|
+ half alpha2 = alpha_x * alpha_y;
|
|
|
+ vec3 v = vec3(alpha_y * cos_phi, alpha_x * sin_phi, alpha2 * cos_theta_m);
|
|
|
+ float v2 = dot(v, v);
|
|
|
+ half w2 = half(float(alpha2) / v2);
|
|
|
+ return alpha2 * w2 * w2 * half(1.0 / M_PI);
|
|
|
}
|
|
|
|
|
|
-float V_GGX_anisotropic(float alpha_x, float alpha_y, float TdotV, float TdotL, float BdotV, float BdotL, float NdotV, float NdotL) {
|
|
|
- float Lambda_V = NdotL * length(vec3(alpha_x * TdotV, alpha_y * BdotV, NdotV));
|
|
|
- float Lambda_L = NdotV * length(vec3(alpha_x * TdotL, alpha_y * BdotL, NdotL));
|
|
|
- return 0.5 / (Lambda_V + Lambda_L);
|
|
|
+half V_GGX_anisotropic(half alpha_x, half alpha_y, half TdotV, half TdotL, half BdotV, half BdotL, half NdotV, half NdotL) {
|
|
|
+ half Lambda_V = NdotL * length(hvec3(alpha_x * TdotV, alpha_y * BdotV, NdotV));
|
|
|
+ half Lambda_L = NdotV * length(hvec3(alpha_x * TdotL, alpha_y * BdotL, NdotL));
|
|
|
+ half v = half(0.5) / (Lambda_V + Lambda_L);
|
|
|
+ return saturateHalf(v);
|
|
|
}
|
|
|
|
|
|
-float SchlickFresnel(float u) {
|
|
|
- float m = 1.0 - u;
|
|
|
- float m2 = m * m;
|
|
|
+half SchlickFresnel(half u) {
|
|
|
+ half m = half(1.0) - u;
|
|
|
+ half m2 = m * m;
|
|
|
return m2 * m2 * m; // pow(m,5)
|
|
|
}
|
|
|
|
|
|
-vec3 F0(float metallic, float specular, vec3 albedo) {
|
|
|
- float dielectric = 0.16 * specular * specular;
|
|
|
+hvec3 F0(half metallic, half specular, hvec3 albedo) {
|
|
|
+ half dielectric = half(0.16) * specular * specular;
|
|
|
// use albedo * metallic as colored specular reflectance at 0 angle for metallic materials;
|
|
|
// see https://google.github.io/filament/Filament.md.html
|
|
|
- return mix(vec3(dielectric), albedo, vec3(metallic));
|
|
|
+ return mix(hvec3(dielectric), albedo, hvec3(metallic));
|
|
|
}
|
|
|
|
|
|
-void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_directional, float attenuation, vec3 f0, uint orms, float specular_amount, vec3 albedo, inout float alpha, vec2 screen_uv, vec3 energy_compensation,
|
|
|
+void light_compute(hvec3 N, hvec3 L, hvec3 V, half A, hvec3 light_color, bool is_directional, half attenuation, hvec3 f0, half roughness, half metallic, half specular_amount, hvec3 albedo, inout half alpha, vec2 screen_uv, hvec3 energy_compensation,
|
|
|
#ifdef LIGHT_BACKLIGHT_USED
|
|
|
- vec3 backlight,
|
|
|
+ hvec3 backlight,
|
|
|
#endif
|
|
|
#ifdef LIGHT_TRANSMITTANCE_USED
|
|
|
- vec4 transmittance_color,
|
|
|
- float transmittance_depth,
|
|
|
- float transmittance_boost,
|
|
|
- float transmittance_z,
|
|
|
+ hvec4 transmittance_color,
|
|
|
+ half transmittance_depth,
|
|
|
+ half transmittance_boost,
|
|
|
+ half transmittance_z,
|
|
|
#endif
|
|
|
#ifdef LIGHT_RIM_USED
|
|
|
- float rim, float rim_tint,
|
|
|
+ half rim, half rim_tint,
|
|
|
#endif
|
|
|
#ifdef LIGHT_CLEARCOAT_USED
|
|
|
- float clearcoat, float clearcoat_roughness, vec3 vertex_normal,
|
|
|
+ half clearcoat, half clearcoat_roughness, hvec3 vertex_normal,
|
|
|
#endif
|
|
|
#ifdef LIGHT_ANISOTROPY_USED
|
|
|
- vec3 B, vec3 T, float anisotropy,
|
|
|
+ hvec3 B, hvec3 T, half anisotropy,
|
|
|
#endif
|
|
|
- inout vec3 diffuse_light, inout vec3 specular_light) {
|
|
|
- vec4 orms_unpacked = unpackUnorm4x8(orms);
|
|
|
- float roughness = orms_unpacked.y;
|
|
|
- float metallic = orms_unpacked.z;
|
|
|
-
|
|
|
+ inout hvec3 diffuse_light, inout hvec3 specular_light) {
|
|
|
#if defined(LIGHT_CODE_USED)
|
|
|
// Light is written by the user shader.
|
|
|
mat4 inv_view_matrix = scene_data_block.data.inv_view_matrix;
|
|
@@ -93,66 +96,71 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_di
|
|
|
#define inv_projection_matrix scene_data_block.data.inv_projection_matrix
|
|
|
|
|
|
vec2 read_viewport_size = scene_data_block.data.viewport_size;
|
|
|
- vec3 normal = N;
|
|
|
- vec3 light = L;
|
|
|
- vec3 view = V;
|
|
|
+ vec3 normal_highp = vec3(N);
|
|
|
+ vec3 light_highp = vec3(L);
|
|
|
+ vec3 view_highp = vec3(V);
|
|
|
+ float specular_amount_highp = float(specular_amount);
|
|
|
+ vec3 light_color_highp = vec3(light_color);
|
|
|
+ float attenuation_highp = float(attenuation);
|
|
|
+ vec3 diffuse_light_highp = vec3(diffuse_light);
|
|
|
+ vec3 specular_light_highp = vec3(specular_light);
|
|
|
|
|
|
#CODE : LIGHT
|
|
|
+
|
|
|
+ diffuse_light = hvec3(diffuse_light_highp);
|
|
|
+ specular_light = hvec3(specular_light_highp);
|
|
|
#else // !LIGHT_CODE_USED
|
|
|
- float NdotL = min(A + dot(N, L), 1.0);
|
|
|
- float cNdotV = max(dot(N, V), 1e-4);
|
|
|
+ half NdotL = min(A + dot(N, L), half(1.0));
|
|
|
+ half cNdotV = max(dot(N, V), half(1e-4));
|
|
|
|
|
|
#ifdef LIGHT_TRANSMITTANCE_USED
|
|
|
{
|
|
|
#ifdef SSS_MODE_SKIN
|
|
|
- float scale = 8.25 / transmittance_depth;
|
|
|
- float d = scale * abs(transmittance_z);
|
|
|
- float dd = -d * d;
|
|
|
- vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
|
|
|
+ half scale = half(8.25) / transmittance_depth;
|
|
|
+ half d = scale * abs(transmittance_z);
|
|
|
+ float dd = float(-d * d);
|
|
|
+ hvec3 profile = hvec3(vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
|
|
|
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
|
|
|
vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
|
|
|
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
|
|
|
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, half(0.0), half(1.0)) * half(1.0 / M_PI);
|
|
|
#else
|
|
|
|
|
|
- float scale = 8.25 / transmittance_depth;
|
|
|
- float d = scale * abs(transmittance_z);
|
|
|
- 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);
|
|
|
+ half scale = half(8.25) / transmittance_depth;
|
|
|
+ half d = scale * abs(transmittance_z);
|
|
|
+ half dd = -d * d;
|
|
|
+ diffuse_light += exp(dd) * transmittance_color.rgb * transmittance_color.a * light_color * clamp(transmittance_boost - NdotL, half(0.0), half(1.0)) * half(1.0 / M_PI);
|
|
|
#endif
|
|
|
}
|
|
|
#endif //LIGHT_TRANSMITTANCE_USED
|
|
|
|
|
|
#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;
|
|
|
+ half rim_light = pow(max(half(1e-4), half(1.0) - cNdotV), max(half(0.0), (half(1.0) - roughness) * half(16.0)));
|
|
|
+ diffuse_light += rim_light * rim * mix(hvec3(1.0), albedo, rim_tint) * light_color;
|
|
|
#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-6f;
|
|
|
- if (is_directional || attenuation > EPSILON) {
|
|
|
- float cNdotL = max(NdotL, 0.0);
|
|
|
+ if (is_directional || attenuation > HALF_FLT_MIN) {
|
|
|
+ half cNdotL = max(NdotL, half(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);
|
|
|
+ hvec3 H = normalize(V + L);
|
|
|
+ half cLdotH = clamp(A + dot(L, H), half(0.0), half(1.0));
|
|
|
#endif
|
|
|
#if defined(LIGHT_CLEARCOAT_USED)
|
|
|
// Clearcoat ignores normal_map, use vertex normal instead
|
|
|
- float ccNdotL = max(min(A + dot(vertex_normal, L), 1.0), 0.0);
|
|
|
- float ccNdotH = clamp(A + dot(vertex_normal, H), 0.0, 1.0);
|
|
|
- float ccNdotV = max(dot(vertex_normal, V), 1e-4);
|
|
|
- float cLdotH5 = SchlickFresnel(cLdotH);
|
|
|
+ half ccNdotL = clamp(A + dot(vertex_normal, L), half(0.0), half(1.0));
|
|
|
+ half ccNdotH = clamp(A + dot(vertex_normal, H), half(0.0), half(1.0));
|
|
|
+ half ccNdotV = max(dot(vertex_normal, V), half(1e-4));
|
|
|
+ half cLdotH5 = SchlickFresnel(cLdotH);
|
|
|
|
|
|
- float Dr = D_GGX(ccNdotH, mix(0.001, 0.1, clearcoat_roughness));
|
|
|
- float Gr = 0.25 / (cLdotH * cLdotH);
|
|
|
- float Fr = mix(.04, 1.0, cLdotH5);
|
|
|
- float clearcoat_specular_brdf_NL = clearcoat * Gr * Fr * Dr * cNdotL;
|
|
|
+ half Dr = D_GGX(ccNdotH, half(mix(half(0.001), half(0.1), clearcoat_roughness)), vertex_normal, H);
|
|
|
+ half Gr = half(0.25) / (cLdotH * cLdotH);
|
|
|
+ half Fr = mix(half(0.04), half(1.0), cLdotH5);
|
|
|
+ half clearcoat_specular_brdf_NL = clearcoat * Gr * Fr * Dr * cNdotL;
|
|
|
|
|
|
specular_light += clearcoat_specular_brdf_NL * light_color * attenuation * specular_amount;
|
|
|
|
|
@@ -160,48 +168,49 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_di
|
|
|
// but to do so we need to rearrange this entire function
|
|
|
#endif // LIGHT_CLEARCOAT_USED
|
|
|
|
|
|
- if (metallic < 1.0) {
|
|
|
- float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance
|
|
|
+ if (metallic < half(1.0)) {
|
|
|
+ half 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);
|
|
|
+ half op_roughness = half(1.0) + roughness;
|
|
|
+ diffuse_brdf_NL = max(half(0.0), (NdotL + roughness) / (op_roughness * op_roughness)) * half(1.0 / M_PI);
|
|
|
#elif defined(DIFFUSE_TOON)
|
|
|
|
|
|
- diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL) * (1.0 / M_PI);
|
|
|
+ diffuse_brdf_NL = smoothstep(-roughness, max(roughness, half(0.01)), NdotL) * half(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;
|
|
|
+ half FD90_minus_1 = half(2.0) * cLdotH * cLdotH * roughness - half(0.5);
|
|
|
+ half FdV = half(1.0) + FD90_minus_1 * SchlickFresnel(cNdotV);
|
|
|
+ half FdL = half(1.0) + FD90_minus_1 * SchlickFresnel(cNdotL);
|
|
|
+ diffuse_brdf_NL = half(1.0 / M_PI) * FdV * FdL * cNdotL;
|
|
|
}
|
|
|
#else
|
|
|
// lambert
|
|
|
- diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
|
|
|
+ diffuse_brdf_NL = cNdotL * half(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;
|
|
|
+ diffuse_light += light_color * (hvec3(1.0 / M_PI) - diffuse_brdf_NL) * backlight * attenuation;
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
- if (roughness > 0.0) {
|
|
|
+ if (roughness > half(0.0)) {
|
|
|
#if defined(SPECULAR_SCHLICK_GGX)
|
|
|
- float cNdotH = clamp(A + dot(N, H), 0.0, 1.0);
|
|
|
+ half cNdotH = clamp(A + dot(N, H), half(0.0), half(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;
|
|
|
+ hvec3 R = normalize(-reflect(L, N));
|
|
|
+ half RdotV = dot(R, V);
|
|
|
+ half mid = half(1.0) - roughness;
|
|
|
mid *= mid;
|
|
|
- float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
|
|
|
+ half intensity = smoothstep(mid - roughness * half(0.5), mid + roughness * half(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)
|
|
@@ -209,34 +218,34 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_di
|
|
|
|
|
|
#elif defined(SPECULAR_SCHLICK_GGX)
|
|
|
// shlick+ggx as default
|
|
|
- float alpha_ggx = roughness * roughness;
|
|
|
+ half 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);
|
|
|
+ half aspect = sqrt(half(1.0) - anisotropy * half(0.9));
|
|
|
+ half ax = alpha_ggx / aspect;
|
|
|
+ half ay = alpha_ggx * aspect;
|
|
|
+ half XdotH = dot(T, H);
|
|
|
+ half YdotH = dot(B, H);
|
|
|
+ half D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH);
|
|
|
+ half 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);
|
|
|
+ half D = D_GGX(cNdotH, alpha_ggx, N, H);
|
|
|
+ half G = V_GGX(cNdotL, cNdotV, alpha_ggx);
|
|
|
#endif // LIGHT_ANISOTROPY_USED
|
|
|
// F
|
|
|
#if !defined(LIGHT_CLEARCOAT_USED)
|
|
|
- float cLdotH5 = SchlickFresnel(cLdotH);
|
|
|
+ half cLdotH5 = SchlickFresnel(cLdotH);
|
|
|
#endif
|
|
|
// 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 = energy_compensation * (cNdotL * D * F * G);
|
|
|
+ half f90 = clamp(dot(f0, hvec3(50.0 * 0.33)), metallic, half(1.0));
|
|
|
+ hvec3 F = f0 + (f90 - f0) * cLdotH5;
|
|
|
+ hvec3 specular_brdf_NL = energy_compensation * 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));
|
|
|
+ alpha = min(alpha, clamp(half(1.0 - attenuation), half(0.0), half(1.0)));
|
|
|
#endif
|
|
|
}
|
|
|
#endif // LIGHT_CODE_USED
|
|
@@ -251,13 +260,13 @@ float quick_hash(vec2 pos) {
|
|
|
return fract(magic.z * fract(dot(pos, magic.xy)));
|
|
|
}
|
|
|
|
|
|
-float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord, float taa_frame_count) {
|
|
|
+half sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord, float taa_frame_count) {
|
|
|
vec2 pos = coord.xy;
|
|
|
float depth = coord.z;
|
|
|
|
|
|
//if only one sample is taken, take it from the center
|
|
|
if (sc_directional_soft_shadow_samples() == 0) {
|
|
|
- return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
|
|
|
+ return half(textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)));
|
|
|
}
|
|
|
|
|
|
mat2 disk_rotation;
|
|
@@ -275,16 +284,16 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve
|
|
|
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data_block.data.directional_soft_shadow_kernel[i].xy), depth, 1.0));
|
|
|
}
|
|
|
|
|
|
- return avg * (1.0 / float(sc_directional_soft_shadow_samples()));
|
|
|
+ return half(avg * (1.0 / float(sc_directional_soft_shadow_samples())));
|
|
|
}
|
|
|
|
|
|
-float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord, float taa_frame_count) {
|
|
|
+half sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord, float taa_frame_count) {
|
|
|
vec2 pos = coord.xy;
|
|
|
float depth = coord.z;
|
|
|
|
|
|
//if only one sample is taken, take it from the center
|
|
|
if (sc_soft_shadow_samples() == 0) {
|
|
|
- return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
|
|
|
+ return half(textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)));
|
|
|
}
|
|
|
|
|
|
mat2 disk_rotation;
|
|
@@ -302,15 +311,15 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord, fl
|
|
|
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data_block.data.soft_shadow_kernel[i].xy), depth, 1.0));
|
|
|
}
|
|
|
|
|
|
- return avg * (1.0 / float(sc_soft_shadow_samples()));
|
|
|
+ return half(avg * (1.0 / float(sc_soft_shadow_samples())));
|
|
|
}
|
|
|
|
|
|
-float sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec4 uv_rect, vec2 flip_offset, float depth, float taa_frame_count) {
|
|
|
+half sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec4 uv_rect, vec2 flip_offset, float depth, float taa_frame_count) {
|
|
|
//if only one sample is taken, take it from the center
|
|
|
if (sc_soft_shadow_samples() == 0) {
|
|
|
vec2 pos = coord * 0.5 + 0.5;
|
|
|
pos = uv_rect.xy + pos * uv_rect.zw;
|
|
|
- return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
|
|
|
+ return half(textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)));
|
|
|
}
|
|
|
|
|
|
mat2 disk_rotation;
|
|
@@ -346,10 +355,10 @@ float sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec
|
|
|
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(sample_coord, depth, 1.0));
|
|
|
}
|
|
|
|
|
|
- return avg * (1.0 / float(sc_soft_shadow_samples()));
|
|
|
+ return half(avg * (1.0 / float(sc_soft_shadow_samples())));
|
|
|
}
|
|
|
|
|
|
-float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale, float taa_frame_count) {
|
|
|
+half sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale, float taa_frame_count) {
|
|
|
//find blocker
|
|
|
float blocker_count = 0.0;
|
|
|
float blocker_average = 0.0;
|
|
@@ -386,62 +395,62 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
|
|
|
s += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(suv, pssm_coord.z, 1.0));
|
|
|
}
|
|
|
|
|
|
- return s / float(sc_directional_penumbra_shadow_samples());
|
|
|
+ return half(s / float(sc_directional_penumbra_shadow_samples()));
|
|
|
|
|
|
} else {
|
|
|
//no blockers found, so no shadow
|
|
|
- return 1.0;
|
|
|
+ return half(1.0);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endif // SHADOWS_DISABLED
|
|
|
|
|
|
-float get_omni_attenuation(float distance, float inv_range, float decay) {
|
|
|
+half get_omni_attenuation(float distance, float inv_range, float decay) {
|
|
|
float nd = distance * inv_range;
|
|
|
nd *= nd;
|
|
|
nd *= nd; // nd^4
|
|
|
nd = max(1.0 - nd, 0.0);
|
|
|
nd *= nd; // nd^2
|
|
|
- return nd * pow(max(distance, 0.0001), -decay);
|
|
|
+ return half(nd * pow(max(distance, 0.0001), -decay));
|
|
|
}
|
|
|
|
|
|
-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, vec3 energy_compensation,
|
|
|
+void light_process_omni(uint idx, vec3 vertex, hvec3 eye_vec, hvec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, hvec3 f0, half roughness, half metallic, float taa_frame_count, hvec3 albedo, inout half alpha, vec2 screen_uv, hvec3 energy_compensation,
|
|
|
#ifdef LIGHT_BACKLIGHT_USED
|
|
|
- vec3 backlight,
|
|
|
+ hvec3 backlight,
|
|
|
#endif
|
|
|
#ifdef LIGHT_TRANSMITTANCE_USED
|
|
|
- vec4 transmittance_color,
|
|
|
- float transmittance_depth,
|
|
|
- float transmittance_boost,
|
|
|
+ hvec4 transmittance_color,
|
|
|
+ half transmittance_depth,
|
|
|
+ half transmittance_boost,
|
|
|
#endif
|
|
|
#ifdef LIGHT_RIM_USED
|
|
|
- float rim, float rim_tint,
|
|
|
+ half rim, half rim_tint,
|
|
|
#endif
|
|
|
#ifdef LIGHT_CLEARCOAT_USED
|
|
|
- float clearcoat, float clearcoat_roughness, vec3 vertex_normal,
|
|
|
+ half clearcoat, half clearcoat_roughness, hvec3 vertex_normal,
|
|
|
#endif
|
|
|
#ifdef LIGHT_ANISOTROPY_USED
|
|
|
- vec3 binormal, vec3 tangent, float anisotropy,
|
|
|
+ hvec3 binormal, hvec3 tangent, half anisotropy,
|
|
|
#endif
|
|
|
- inout vec3 diffuse_light, inout vec3 specular_light) {
|
|
|
- const float EPSILON = 1e-6f;
|
|
|
+ inout hvec3 diffuse_light, inout hvec3 specular_light) {
|
|
|
|
|
|
// 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);
|
|
|
+ half omni_attenuation = get_omni_attenuation(light_length, omni_lights.data[idx].inv_radius, omni_lights.data[idx].attenuation);
|
|
|
|
|
|
// Compute size.
|
|
|
- float size = 0.0;
|
|
|
+ half size = half(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));
|
|
|
+ half t = half(omni_lights.data[idx].size / max(0.001, light_length));
|
|
|
+ size = half(1.0) / sqrt(half(1.0) + t * t);
|
|
|
+ size = max(half(1.0) - size, half(0.0));
|
|
|
}
|
|
|
|
|
|
- float shadow = 1.0;
|
|
|
+ half shadow = half(1.0);
|
|
|
#ifndef SHADOWS_DISABLED
|
|
|
// Omni light shadow.
|
|
|
- if (omni_attenuation > EPSILON && omni_lights.data[idx].shadow_opacity > 0.001) {
|
|
|
+ if (omni_attenuation > HALF_FLT_MIN && omni_lights.data[idx].shadow_opacity > 0.001) {
|
|
|
// there is a shadowmap
|
|
|
vec2 texel_size = scene_data_block.data.shadow_atlas_pixel_size;
|
|
|
vec4 base_uv_rect = omni_lights.data[idx].atlas_rect;
|
|
@@ -456,7 +465,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|
|
float shadow_len = length(local_vert); //need to remember shadow len from here
|
|
|
vec3 shadow_dir = normalize(local_vert);
|
|
|
|
|
|
- vec3 local_normal = normalize(mat3(omni_lights.data[idx].shadow_matrix) * normal);
|
|
|
+ vec3 local_normal = normalize(mat3(omni_lights.data[idx].shadow_matrix) * vec3(normal));
|
|
|
vec3 normal_bias = local_normal * omni_lights.data[idx].shadow_normal_bias * (1.0 - abs(dot(local_normal, shadow_dir)));
|
|
|
|
|
|
if (sc_use_light_soft_shadows() && omni_lights.data[idx].soft_shadow_size > 0.0) {
|
|
@@ -520,7 +529,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|
|
|
|
|
z_norm += omni_lights.data[idx].inv_radius * omni_lights.data[idx].shadow_bias;
|
|
|
|
|
|
- shadow = 0.0;
|
|
|
+ shadow = half(0.0);
|
|
|
|
|
|
SPEC_CONSTANT_LOOP_ANNOTATION
|
|
|
for (uint i = 0; i < sc_penumbra_shadow_samples(); i++) {
|
|
@@ -541,15 +550,15 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|
|
|
|
|
pos.xy = pos.xy * 0.5 + 0.5;
|
|
|
pos.xy = uv_rect.xy + pos.xy * uv_rect.zw;
|
|
|
- shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(pos.xy, z_norm, 1.0));
|
|
|
+ shadow += half(textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(pos.xy, z_norm, 1.0)));
|
|
|
}
|
|
|
|
|
|
- shadow /= float(sc_penumbra_shadow_samples());
|
|
|
- shadow = mix(1.0, shadow, omni_lights.data[idx].shadow_opacity);
|
|
|
+ shadow /= half(sc_penumbra_shadow_samples());
|
|
|
+ shadow = mix(half(1.0), shadow, half(omni_lights.data[idx].shadow_opacity));
|
|
|
|
|
|
} else {
|
|
|
//no blockers found, so no shadow
|
|
|
- shadow = 1.0;
|
|
|
+ shadow = half(1.0);
|
|
|
}
|
|
|
} else {
|
|
|
vec4 uv_rect = base_uv_rect;
|
|
@@ -565,7 +574,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|
|
float depth = shadow_len - omni_lights.data[idx].shadow_bias;
|
|
|
depth *= omni_lights.data[idx].inv_radius;
|
|
|
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(half(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), half(omni_lights.data[idx].shadow_opacity));
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
@@ -573,7 +582,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|
|
vec3 color = omni_lights.data[idx].color;
|
|
|
|
|
|
#ifdef LIGHT_TRANSMITTANCE_USED
|
|
|
- float transmittance_z = transmittance_depth; //no transmittance by default
|
|
|
+ half transmittance_z = transmittance_depth; //no transmittance by default
|
|
|
transmittance_color.a *= omni_attenuation;
|
|
|
#ifndef SHADOWS_DISABLED
|
|
|
if (omni_lights.data[idx].shadow_opacity > 0.001) {
|
|
@@ -586,7 +595,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|
|
// Omni lights use direction.xy to store to store the offset between the two paraboloid regions
|
|
|
vec2 flip_offset = omni_lights.data[idx].direction.xy;
|
|
|
|
|
|
- vec3 local_vert = (omni_lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal) * omni_lights.data[idx].transmittance_bias, 1.0)).xyz;
|
|
|
+ vec3 local_vert = (omni_lights.data[idx].shadow_matrix * vec4(vertex - normal * omni_lights.data[idx].transmittance_bias, 1.0)).xyz;
|
|
|
|
|
|
float shadow_len = length(local_vert); //need to remember shadow len from here
|
|
|
vec3 shadow_sample = normalize(local_vert);
|
|
@@ -604,7 +613,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|
|
pos = pos * 0.5 + 0.5;
|
|
|
pos = uv_rect.xy + pos * uv_rect.zw;
|
|
|
float shadow_z = textureLod(sampler2D(shadow_atlas, SAMPLER_LINEAR_CLAMP), pos, 0.0).r;
|
|
|
- transmittance_z = (depth - shadow_z) / omni_lights.data[idx].inv_radius;
|
|
|
+ transmittance_z = half((depth - shadow_z) / omni_lights.data[idx].inv_radius);
|
|
|
}
|
|
|
#endif // !SHADOWS_DISABLED
|
|
|
#endif // LIGHT_TRANSMITTANCE_USED
|
|
@@ -667,7 +676,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|
|
}
|
|
|
|
|
|
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, energy_compensation,
|
|
|
+ light_compute(normal, hvec3(light_rel_vec_norm), eye_vec, size, hvec3(color), false, omni_attenuation * shadow, f0, roughness, metallic, half(omni_lights.data[idx].specular_amount), albedo, alpha, screen_uv, energy_compensation,
|
|
|
#ifdef LIGHT_BACKLIGHT_USED
|
|
|
backlight,
|
|
|
#endif
|
|
@@ -702,54 +711,53 @@ vec2 normal_to_panorama(vec3 n) {
|
|
|
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, vec3 energy_compensation,
|
|
|
+void light_process_spot(uint idx, vec3 vertex, hvec3 eye_vec, hvec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, hvec3 f0, half roughness, half metallic, float taa_frame_count, hvec3 albedo, inout half alpha, vec2 screen_uv, hvec3 energy_compensation,
|
|
|
#ifdef LIGHT_BACKLIGHT_USED
|
|
|
- vec3 backlight,
|
|
|
+ hvec3 backlight,
|
|
|
#endif
|
|
|
#ifdef LIGHT_TRANSMITTANCE_USED
|
|
|
- vec4 transmittance_color,
|
|
|
- float transmittance_depth,
|
|
|
- float transmittance_boost,
|
|
|
+ hvec4 transmittance_color,
|
|
|
+ half transmittance_depth,
|
|
|
+ half transmittance_boost,
|
|
|
#endif
|
|
|
#ifdef LIGHT_RIM_USED
|
|
|
- float rim, float rim_tint,
|
|
|
+ half rim, half rim_tint,
|
|
|
#endif
|
|
|
#ifdef LIGHT_CLEARCOAT_USED
|
|
|
- float clearcoat, float clearcoat_roughness, vec3 vertex_normal,
|
|
|
+ half clearcoat, half clearcoat_roughness, hvec3 vertex_normal,
|
|
|
#endif
|
|
|
#ifdef LIGHT_ANISOTROPY_USED
|
|
|
- vec3 binormal, vec3 tangent, float anisotropy,
|
|
|
+ hvec3 binormal, hvec3 tangent, half anisotropy,
|
|
|
#endif
|
|
|
- inout vec3 diffuse_light,
|
|
|
- inout vec3 specular_light) {
|
|
|
- const float EPSILON = 1e-6f;
|
|
|
+ inout hvec3 diffuse_light,
|
|
|
+ inout hvec3 specular_light) {
|
|
|
|
|
|
// 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;
|
|
|
+ hvec3 light_rel_vec_norm = hvec3(light_rel_vec / light_length);
|
|
|
+ half spot_attenuation = get_omni_attenuation(light_length, spot_lights.data[idx].inv_radius, spot_lights.data[idx].attenuation);
|
|
|
+ hvec3 spot_dir = hvec3(spot_lights.data[idx].direction);
|
|
|
+ half cone_angle = half(spot_lights.data[idx].cone_angle);
|
|
|
+ half scos = max(dot(-light_rel_vec_norm, spot_dir), cone_angle);
|
|
|
|
|
|
- // 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);
|
|
|
+ // This conversion to a highp float is crucial to prevent light leaking due to precision errors.
|
|
|
+ float spot_rim = max(1e-4, float(half(1.0) - scos) / float(half(1.0) - cone_angle));
|
|
|
+ spot_attenuation *= half(1.0 - pow(spot_rim, spot_lights.data[idx].cone_attenuation));
|
|
|
|
|
|
// Compute size.
|
|
|
- float size = 0.0;
|
|
|
+ half size = half(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));
|
|
|
+ half t = half(spot_lights.data[idx].size / max(0.001, light_length));
|
|
|
+ size = half(1.0) / sqrt(half(1.0) + t * t);
|
|
|
+ size = max(half(1.0) - size, half(0.0));
|
|
|
}
|
|
|
|
|
|
- float shadow = 1.0;
|
|
|
+ half shadow = half(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)));
|
|
|
+ if (spot_attenuation > HALF_FLT_MIN && spot_lights.data[idx].shadow_opacity > 0.001) {
|
|
|
+ vec3 normal_bias = vec3(normal) * light_length * spot_lights.data[idx].shadow_normal_bias * (1.0 - abs(dot(normal, light_rel_vec_norm)));
|
|
|
|
|
|
//there is a shadowmap
|
|
|
vec4 v = vec4(vertex + normal_bias, 1.0);
|
|
@@ -762,7 +770,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|
|
//soft shadow
|
|
|
|
|
|
//find blocker
|
|
|
- float z_norm = dot(spot_dir, -light_rel_vec) * spot_lights.data[idx].inv_radius;
|
|
|
+ float z_norm = dot(vec3(spot_dir), -light_rel_vec) * spot_lights.data[idx].inv_radius;
|
|
|
|
|
|
vec2 shadow_uv = splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy;
|
|
|
|
|
@@ -797,39 +805,38 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|
|
float penumbra = (-z_norm + blocker_average) / (1.0 - blocker_average);
|
|
|
uv_size *= penumbra;
|
|
|
|
|
|
- shadow = 0.0;
|
|
|
+ shadow = half(0.0);
|
|
|
|
|
|
SPEC_CONSTANT_LOOP_ANNOTATION
|
|
|
for (uint i = 0; i < sc_penumbra_shadow_samples(); i++) {
|
|
|
vec2 suv = shadow_uv + (disk_rotation * scene_data_block.data.penumbra_shadow_kernel[i].xy) * uv_size;
|
|
|
suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max);
|
|
|
- shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, splane.z, 1.0));
|
|
|
+ shadow += half(textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, splane.z, 1.0)));
|
|
|
}
|
|
|
|
|
|
- shadow /= float(sc_penumbra_shadow_samples());
|
|
|
- shadow = mix(1.0, shadow, spot_lights.data[idx].shadow_opacity);
|
|
|
+ shadow /= half(sc_penumbra_shadow_samples());
|
|
|
+ shadow = mix(half(1.0), shadow, half(spot_lights.data[idx].shadow_opacity));
|
|
|
|
|
|
} else {
|
|
|
//no blockers found, so no shadow
|
|
|
- shadow = 1.0;
|
|
|
+ shadow = half(1.0);
|
|
|
}
|
|
|
} else {
|
|
|
//hard shadow
|
|
|
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(half(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), half(spot_lights.data[idx].shadow_opacity));
|
|
|
}
|
|
|
}
|
|
|
#endif // SHADOWS_DISABLED
|
|
|
|
|
|
vec3 color = spot_lights.data[idx].color;
|
|
|
- float specular_amount = spot_lights.data[idx].specular_amount;
|
|
|
|
|
|
#ifdef LIGHT_TRANSMITTANCE_USED
|
|
|
- float transmittance_z = transmittance_depth;
|
|
|
+ half transmittance_z = transmittance_depth;
|
|
|
transmittance_color.a *= spot_attenuation;
|
|
|
#ifndef SHADOWS_DISABLED
|
|
|
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 - vec3(normal) * spot_lights.data[idx].transmittance_bias, 1.0));
|
|
|
splane /= splane.w;
|
|
|
|
|
|
vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z);
|
|
@@ -841,8 +848,8 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|
|
shadow_z = 2.0 * z_near * z_far / (z_far + z_near - shadow_z * (z_far - z_near));
|
|
|
|
|
|
//distance to light plane
|
|
|
- float z = dot(spot_dir, -light_rel_vec);
|
|
|
- transmittance_z = z - shadow_z;
|
|
|
+ float z = dot(vec3(spot_dir), -light_rel_vec);
|
|
|
+ transmittance_z = half(z - shadow_z);
|
|
|
}
|
|
|
#endif // !SHADOWS_DISABLED
|
|
|
#endif // LIGHT_TRANSMITTANCE_USED
|
|
@@ -871,7 +878,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- 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, energy_compensation,
|
|
|
+ light_compute(normal, hvec3(light_rel_vec_norm), eye_vec, size, hvec3(color), false, spot_attenuation * shadow, f0, roughness, metallic, half(spot_lights.data[idx].specular_amount), albedo, alpha, screen_uv, energy_compensation,
|
|
|
#ifdef LIGHT_BACKLIGHT_USED
|
|
|
backlight,
|
|
|
#endif
|
|
@@ -893,7 +900,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|
|
diffuse_light, specular_light);
|
|
|
}
|
|
|
|
|
|
-void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) {
|
|
|
+void reflection_process(uint ref_index, vec3 vertex, hvec3 ref_vec, hvec3 normal, half roughness, hvec3 ambient_light, hvec3 specular_light, inout hvec4 ambient_accum, inout hvec4 reflection_accum) {
|
|
|
vec3 box_extents = reflections.data[ref_index].box_extents;
|
|
|
vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz;
|
|
|
|
|
@@ -901,17 +908,16 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- float blend = 1.0;
|
|
|
+ half blend = half(1.0);
|
|
|
if (reflections.data[ref_index].blend_distance != 0.0) {
|
|
|
vec3 axis_blend_distance = min(vec3(reflections.data[ref_index].blend_distance), box_extents);
|
|
|
- vec3 blend_axes = abs(local_pos) - box_extents + axis_blend_distance;
|
|
|
- blend_axes /= axis_blend_distance;
|
|
|
- blend_axes = clamp(1.0 - blend_axes, vec3(0.0), vec3(1.0));
|
|
|
-
|
|
|
- blend = pow(blend_axes.x * blend_axes.y * blend_axes.z, 2.0);
|
|
|
+ vec3 blend_axes_highp = abs(local_pos) - box_extents + axis_blend_distance;
|
|
|
+ hvec3 blend_axes = hvec3(blend_axes_highp / axis_blend_distance);
|
|
|
+ blend_axes = clamp(half(1.0) - blend_axes, hvec3(0.0), hvec3(1.0));
|
|
|
+ blend = pow(blend_axes.x * blend_axes.y * blend_axes.z, half(2.0));
|
|
|
}
|
|
|
|
|
|
- if (reflections.data[ref_index].intensity > 0.0 && reflection_accum.a < 1.0) { // compute reflection
|
|
|
+ if (reflections.data[ref_index].intensity > 0.0 && reflection_accum.a < half(1.0)) { // compute reflection
|
|
|
|
|
|
vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz;
|
|
|
|
|
@@ -928,20 +934,20 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal,
|
|
|
local_ref_vec = posonbox - reflections.data[ref_index].box_offset;
|
|
|
}
|
|
|
|
|
|
- vec4 reflection;
|
|
|
- float reflection_blend = max(0.0, blend - reflection_accum.a);
|
|
|
+ hvec4 reflection;
|
|
|
+ half reflection_blend = max(half(0.0), blend - reflection_accum.a);
|
|
|
|
|
|
- reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(local_ref_vec, reflections.data[ref_index].index), sqrt(roughness) * MAX_ROUGHNESS_LOD).rgb * sc_luminance_multiplier();
|
|
|
- reflection.rgb *= reflections.data[ref_index].exposure_normalization;
|
|
|
+ reflection.rgb = hvec3(textureLod(samplerCubeArray(reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(local_ref_vec, reflections.data[ref_index].index), sqrt(roughness) * MAX_ROUGHNESS_LOD).rgb) * sc_luminance_multiplier();
|
|
|
+ reflection.rgb *= half(reflections.data[ref_index].exposure_normalization);
|
|
|
reflection.a = reflection_blend;
|
|
|
|
|
|
- reflection.rgb *= reflections.data[ref_index].intensity;
|
|
|
+ reflection.rgb *= half(reflections.data[ref_index].intensity);
|
|
|
reflection.rgb *= reflection.a;
|
|
|
|
|
|
reflection_accum += reflection;
|
|
|
}
|
|
|
|
|
|
- if (ambient_accum.a >= 1.0) {
|
|
|
+ if (ambient_accum.a >= half(1.0)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -951,20 +957,20 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal,
|
|
|
} break;
|
|
|
case REFLECTION_AMBIENT_ENVIRONMENT: {
|
|
|
vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz;
|
|
|
- vec4 ambient_out;
|
|
|
- float ambient_blend = max(0.0, blend - ambient_accum.a);
|
|
|
+ hvec4 ambient_out;
|
|
|
+ half ambient_blend = max(half(0.0), blend - ambient_accum.a);
|
|
|
|
|
|
- ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb;
|
|
|
- ambient_out.rgb *= reflections.data[ref_index].exposure_normalization;
|
|
|
+ ambient_out.rgb = hvec3(textureLod(samplerCubeArray(reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb);
|
|
|
+ ambient_out.rgb *= half(reflections.data[ref_index].exposure_normalization);
|
|
|
ambient_out.a = ambient_blend;
|
|
|
ambient_out.rgb *= ambient_out.a;
|
|
|
ambient_accum += ambient_out;
|
|
|
} break;
|
|
|
case REFLECTION_AMBIENT_COLOR: {
|
|
|
- vec4 ambient_out;
|
|
|
- float ambient_blend = max(0.0, blend - ambient_accum.a);
|
|
|
+ hvec4 ambient_out;
|
|
|
+ half ambient_blend = max(half(0.0), blend - ambient_accum.a);
|
|
|
|
|
|
- ambient_out.rgb = reflections.data[ref_index].ambient;
|
|
|
+ ambient_out.rgb = hvec3(reflections.data[ref_index].ambient);
|
|
|
ambient_out.a = ambient_blend;
|
|
|
ambient_out.rgb *= ambient_out.a;
|
|
|
ambient_accum += ambient_out;
|
|
@@ -972,7 +978,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-float blur_shadow(float shadow) {
|
|
|
+half blur_shadow(half shadow) {
|
|
|
return shadow;
|
|
|
#if 0
|
|
|
//disabling for now, will investigate later
|