diff options
| -rwxr-xr-x | 3ner.cginc | 13 | ||||
| -rwxr-xr-x | 3ner.shader | 2 | ||||
| -rwxr-xr-x | brdf.cginc | 12 | ||||
| -rwxr-xr-x | lighting.cginc | 78 |
4 files changed, 103 insertions, 2 deletions
@@ -324,6 +324,19 @@ float4 frag(v2f i, uint facing : SV_IsFrontFace BrdfData bd; float4 lit = brdf(i, pbr, light_data, bd); +#if defined(VERTEXLIGHT_ON) && (defined(FORWARD_BASE_PASS) || defined(OUTLINES_PASS)) + [loop] + for (uint light_index = 0; light_index < 4; ++light_index) { + [branch] + if (any(unity_LightColor[light_index].rgb > 0)) { + LightData vertex_light_data = light_data; + GetVertexLighting(i, pbr, light_index, vertex_light_data); + BrdfData vertex_bd; + lit.rgb += brdf(i, pbr, vertex_light_data, true, vertex_bd).rgb; + } + } +#endif + return apply_debug_view(i, pbr, light_data, bd, lit); } diff --git a/3ner.shader b/3ner.shader index 213eb72..dd63f1d 100755 --- a/3ner.shader +++ b/3ner.shader @@ -1439,6 +1439,7 @@ Shader "yum_food/3ner" #pragma multi_compile_fullshadows #pragma multi_compile_instancing #pragma multi_compile_fog + #pragma multi_compile_fragment _ VERTEXLIGHT_ON #pragma vertex vert //ifex _Geometry_Enabled==0 #pragma geometry geom @@ -1470,6 +1471,7 @@ Shader "yum_food/3ner" #pragma multi_compile_fullshadows #pragma multi_compile_instancing #pragma multi_compile_fog + #pragma multi_compile_fragment _ VERTEXLIGHT_ON #pragma vertex vert //ifex _Geometry_Enabled==0 #pragma geometry geom @@ -107,7 +107,7 @@ float G_Estevez(float roughness, float NoL, float NoV) { return 1.0 / ((1.0 + lambda_l + lambda_v) * 4.0 * NoL * NoV); } -float4 brdf(v2f i, Pbr pbr, LightData data, out BrdfData bd) { +float4 brdf(v2f i, Pbr pbr, LightData data, bool direct_only, out BrdfData bd) { bd = (BrdfData)0; float3 specular = 0; float3 diffuse = 0; @@ -235,6 +235,8 @@ float4 brdf(v2f i, Pbr pbr, LightData data, out BrdfData bd) { // Indirect #if !defined(FURNACE_TEST_DIRECT) && (defined(FORWARD_BASE_PASS) || defined(OUTLINES_PASS)) + [branch] + if (!direct_only) { float3 remainder = 1.0f; #if defined(_CLEARCOAT) @@ -282,6 +284,8 @@ float4 brdf(v2f i, Pbr pbr, LightData data, out BrdfData bd) { #endif #if defined(FORWARD_BASE_PASS) + [branch] + if (!direct_only) { [branch] if (_UdonLightVolumeEnabled) { @@ -306,7 +310,7 @@ float4 brdf(v2f i, Pbr pbr, LightData data, out BrdfData bd) { diffuse *= data.common.ao; #if (defined(_EMISSIONS) || defined(_LETTER_GRID)) && defined(FORWARD_BASE_PASS) - float3 emission = pbr.emission; + float3 emission = direct_only ? 0 : pbr.emission; #else float3 emission = 0; #endif @@ -315,4 +319,8 @@ float4 brdf(v2f i, Pbr pbr, LightData data, out BrdfData bd) { return float4(lit.rgb * lit.a, lit.a); } +float4 brdf(v2f i, Pbr pbr, LightData data, out BrdfData bd) { + return brdf(i, pbr, data, false, bd); +} + #endif // __BRDF_INC diff --git a/lighting.cginc b/lighting.cginc index 835613e..b3ac3fa 100755 --- a/lighting.cginc +++ b/lighting.cginc @@ -36,6 +36,84 @@ float4 getDirectLightColorIntensity() { return float4(_LightColor0.xyz, _LightColor0.w); } +#if defined(VERTEXLIGHT_ON) && (defined(FORWARD_BASE_PASS) || defined(OUTLINES_PASS)) +// Mirrors can disable pixel lights, which makes Unity expose up to four point +// lights through the vertex-light uniforms instead of drawing ForwardAdd. +// Evaluate them per fragment so they use the same normals and BRDF as pixel +// lights. Demoted spot lights are supplied by Unity as point lights here. +void GetVertexLighting(v2f i, Pbr pbr, uint light_index, inout LightData data) { + float3 light_position = float3( + unity_4LightPosX0[light_index], + unity_4LightPosY0[light_index], + unity_4LightPosZ0[light_index]); + float3 to_light = light_position - i.worldPos; + float distance_squared = max(dot(to_light, to_light), 1e-6f); + float3 light_direction = to_light * rsqrt(distance_squared); + + // Match Unity/Poiyomi's vertex-light range fade rather than allowing the + // reciprocal attenuation tail to illuminate indefinitely. + float attenuation_squared = unity_4LightAtten0[light_index]; + float attenuation = rcp(1.0f + distance_squared * attenuation_squared); + float range_fade = saturate(1.0f - distance_squared * attenuation_squared / 25.0f); + attenuation = min(attenuation, range_fade * range_fade); + + data.direct.dir = light_direction; + data.direct.H = normalize(data.common.V + light_direction); +#if defined(_WRAPPED_LIGHTING) + data.direct.NoL = max(1e-4, wrapNoL(saturate(dot(pbr.normal, light_direction)), _Wrapped_Lighting_Amount)); +#else + data.direct.NoL = max(1e-4, dot(pbr.normal, light_direction)); +#endif + data.direct.NoH = max(1e-4, dot(pbr.normal, data.direct.H)); + data.direct.LoH = max(1e-4, dot(light_direction, data.direct.H)); +#if defined(_CLEARCOAT) + data.direct.NoH_cc = max(1e-4, dot(pbr.cc_normal, data.direct.H)); + data.direct.NoL_cc = max(1e-4, dot(pbr.cc_normal, light_direction)); +#endif + float direct_LoV = dot(light_direction, data.common.V); + data.direct.LoV = max(1e-4, direct_LoV); + data.direct.double_LoV = max(1e-4, 2.0f * direct_LoV * direct_LoV - 1.0f); + data.direct.color = unity_LightColor[light_index].rgb * attenuation; + +#if defined(_BRIGHTNESS_CLAMP) + float3 direct_hsv = RGBtoHSV(data.direct.color); + direct_hsv[2] = clamp(direct_hsv[2], _Brightness_Clamp_Min, _Brightness_Clamp_Max); + data.direct.color = HSVtoRGB(direct_hsv); +#endif +#if defined(_BRIGHTNESS_MULTIPLIER) + data.direct.color *= _Brightness_Multiplier; +#endif + +#if defined(_GLITTER) + float2 glitter_uv = UV_SCOFF(i, _Glitter_Mask_ST, _Glitter_UV_Channel); + float2x2 glitter_uv_J = uv_ellipsoid(transpose(float2x2(ddx(glitter_uv), ddy(glitter_uv)))); +#if defined(_GLITTER_NORMAL_OVERRIDE) + float2 glitter_normal_uv = UV_SCOFF(i, _Glitter_Normal_Override_ST, + _Glitter_UV_Channel); + float3 glitter_normal = _Glitter_Normal_Override.Sample( + bilinear_clamp_s, glitter_normal_uv).xyz * 2 - 1; + glitter_normal = glitter_normal.xzy * float3(-1, 1, -1); + glitter_normal = UnityObjectToWorldNormal(glitter_normal); + float3x3 glitter_tbn = tbn_from_normal_tangent(glitter_normal, i.tangent); +#else + float3x3 glitter_tbn = pbr.tbn; +#endif + float3 direct_H_tangent = mul(data.direct.H, transpose(glitter_tbn)); + float3 direct_micro_normal; +#if defined(_GLITTER_BASE_ROUGHNESS_OVERRIDE) + float glitter_roughness = _Glitter_Base_Roughness_Override; +#else + float glitter_roughness = pbr.roughness; +#endif + data.glitter.direct_D = D_Kemppinen( + direct_H_tangent, glitter_roughness, _Glitter_Roughness, + _Glitter_Angular_Cells, glitter_uv, glitter_uv_J, + GLITTER_REFERENCE_N * GLITTER_POPULATION_SCALE, _Glitter_Amount, + _Glitter_Filter_Size, direct_micro_normal); +#endif +} +#endif + float3 getIndirectSpecular(v2f i, float perceptual_roughness, float3 view_dir, float3 reflect_dir, float3 indirect_diffuse) { UnityGIInput data = InitialiseUnityGIInput(i.worldPos, view_dir); float3 env_refl = UnityGI_prefilteredRadiance(data, perceptual_roughness, reflect_dir); |
