Files
ud18010andClaude Opus 4.8 ea93b3b217 XShader: 运行时环境光仅在全局开启后覆盖 bakedGI,编辑器保留场景 SH
修复编辑器预览中 XPbr/XTex/XTerrain 比 URP Lit 亮的问题:
旧写法无条件把 bakedGI 覆盖成 SampleXRuntimeAmbient,未运行 Game.cs 时
退回硬编码的高强度三色环境光(sky≈1.45),远亮于场景真实环境光探针。
现改为 _XRuntimeAmbientEnabled 开启后才覆盖,运行时行为不变。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 20:27:08 +08:00

146 lines
5.0 KiB
HLSL
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifndef XPBR_LIT_BASE
#define XPBR_LIT_BASE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
half4 _BaseColor;
half _Cutoff;
half _Metallic;
half _Roughness;
half _AO;
CBUFFER_END
half _XRuntimeAmbientEnabled;
half4 _XRuntimeAmbientSky;
half4 _XRuntimeAmbientEquator;
half4 _XRuntimeAmbientGround;
TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
TEXTURE2D(_MixTex); SAMPLER(sampler_MixTex);
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float4 tangentOS : TANGENT;
float2 texcoord : TEXCOORD0;
float2 staticLightmapUV : TEXCOORD1;
#ifdef DYNAMICLIGHTMAP_ON
float2 dynamicLightmapUV : TEXCOORD2;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float2 uv : TEXCOORD0;
DECLARE_LIGHTMAP_OR_SH(staticLightmapUV, vertexSH, 1);
float3 positionWS : TEXCOORD2;
half4 normalWS : TEXCOORD3; // xyz: normal, w: viewDir.x
half4 tangentWS : TEXCOORD4; // xyz: tangent, w: viewDir.y
half4 bitangentWS : TEXCOORD5; // xyz: bitangent, w: viewDir.z
#ifdef _ADDITIONAL_LIGHTS_VERTEX
half4 fogFactorAndVertexLight : TEXCOORD6; // x: fogFactor, yzw: vertex light
#else
half fogFactor : TEXCOORD6;
#endif
#ifdef DYNAMICLIGHTMAP_ON
float2 dynamicLightmapUV : TEXCOORD7;
#endif
float4 positionCS : SV_POSITION;
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
float4 shadowCoord : TEXCOORD8;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
//解码 RG 两通道球面映射压缩法线(有符号,ModelTranslator 工具编码:enc = n.xy/sqrt(2*(1+n.z)) * 0.5 + 0.5
float3 DecodeSphereMap(float2 encoded)
{
encoded = encoded * 2.0 - 1.0; //rg 无符号存储,重映射回有符号
float4 nn = float4(encoded, 1, -1);
float l = dot(nn.xyz, -nn.xyw);
nn.z = l;
nn.xy *= sqrt(l);
return nn.xyz * 2 + float3(0, 0, -1);
}
half3 SampleXRuntimeAmbient(half3 normalWS)
{
half y = normalize(normalWS).y;
half useGlobal = step(0.5h, _XRuntimeAmbientEnabled);
half3 sky = lerp(half3(1.353h, 1.452h, 1.568h), _XRuntimeAmbientSky.rgb, useGlobal);
half3 equator = lerp(half3(1.023h, 1.122h, 1.254h), _XRuntimeAmbientEquator.rgb, useGlobal);
half3 ground = lerp(half3(0.561h, 0.528h, 0.462h), _XRuntimeAmbientGround.rgb, useGlobal);
half3 upper = lerp(equator, sky, saturate(y));
half3 lower = lerp(equator, ground, saturate(-y));
return lerp(lower, upper, step(0.0h, y));
}
void InitializeInputData(Varyings input, half3 normalTS, out InputData inputData)
{
inputData = (InputData)0;
inputData.positionWS = input.positionWS;
half3 viewDirWS = GetWorldSpaceNormalizeViewDir(input.positionWS);
// 法线已在 frag 中经 TBN 转换到世界空间后写回 input.normalWS
inputData.normalWS = input.normalWS.xyz;
inputData.normalWS = NormalizeNormalPerPixel(inputData.normalWS);
inputData.viewDirectionWS = viewDirWS;
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
inputData.shadowCoord = input.shadowCoord;
#elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
inputData.shadowCoord = TransformWorldToShadowCoord(inputData.positionWS);
#else
inputData.shadowCoord = float4(0, 0, 0, 0);
#endif
#ifdef _ADDITIONAL_LIGHTS_VERTEX
inputData.fogCoord = InitializeInputDataFog(float4(input.positionWS, 1.0), input.fogFactorAndVertexLight.x);
inputData.vertexLighting = input.fogFactorAndVertexLight.yzw;
#else
inputData.fogCoord = InitializeInputDataFog(float4(input.positionWS, 1.0), input.fogFactor);
#endif
#if defined(DYNAMICLIGHTMAP_ON)
inputData.bakedGI = SAMPLE_GI(input.staticLightmapUV, input.dynamicLightmapUV, input.vertexSH, inputData.normalWS);
#elif defined(LIGHTMAP_ON)
inputData.bakedGI = SAMPLE_GI(input.staticLightmapUV, input.vertexSH, inputData.normalWS);
#else
inputData.bakedGI = SampleSH(inputData.normalWS);
#endif
// 仅在运行时全局环境光开启后才覆盖(Game.cs 设置);否则保留场景自身 SH/光照贴图,
// 避免编辑器预览比 URP Lit 亮(旧写法无条件覆盖成硬编码的高强度三色环境光)
if (_XRuntimeAmbientEnabled > 0.5h)
inputData.bakedGI = SampleXRuntimeAmbient(inputData.normalWS);
inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(input.positionCS);
inputData.shadowMask = SAMPLE_SHADOWMASK(input.staticLightmapUV);
#if defined(DEBUG_DISPLAY)
#if defined(DYNAMICLIGHTMAP_ON)
inputData.dynamicLightmapUV = input.dynamicLightmapUV;
#endif
#if defined(LIGHTMAP_ON)
inputData.staticLightmapUV = input.staticLightmapUV;
#else
inputData.vertexSH = input.vertexSH;
#endif
#endif
}
#endif