128 lines
4.9 KiB
HLSL
128 lines
4.9 KiB
HLSL
#ifndef SG_TERRAIN_PBRGBUFFERPASS_INC
|
|
#define SG_TERRAIN_PBRGBUFFERPASS_INC
|
|
|
|
#include "TerrainVert.hlsl"
|
|
|
|
void InitializeInputData(Varyings input, SurfaceDescription surfaceDescription, out InputData inputData)
|
|
{
|
|
inputData = (InputData)0;
|
|
|
|
inputData.positionWS = input.positionWS;
|
|
|
|
half3 SH = 0.0h;
|
|
CalculateTerrainNormalWS(input, surfaceDescription, inputData);
|
|
|
|
#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
|
|
|
|
inputData.fogCoord = InitializeInputDataFog(float4(input.positionWS, 1.0), input.fogFactorAndVertexLight.x);
|
|
inputData.vertexLighting = input.fogFactorAndVertexLight.yzw;
|
|
|
|
#if defined(DYNAMICLIGHTMAP_ON)
|
|
inputData.bakedGI = SAMPLE_GI(input.staticLightmapUV, input.dynamicLightmapUV.xy, SH, inputData.normalWS);
|
|
#else
|
|
inputData.bakedGI = SAMPLE_GI(input.staticLightmapUV, SH, inputData.normalWS);
|
|
#endif
|
|
inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(input.positionCS);
|
|
inputData.shadowMask = SAMPLE_SHADOWMASK(input.staticLightmapUV);
|
|
|
|
#if defined(DEBUG_DISPLAY)
|
|
#if defined(DYNAMICLIGHTMAP_ON)
|
|
inputData.dynamicLightmapUV = input.dynamicLightmapUV.xy;
|
|
#endif
|
|
#if defined(LIGHTMAP_ON)
|
|
inputData.staticLightmapUV = input.staticLightmapUV;
|
|
#else
|
|
inputData.vertexSH = input.sh;
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
GBufferFragOutput frag(PackedVaryings packedInput)
|
|
{
|
|
Varyings unpacked = UnpackVaryings(packedInput);
|
|
UNITY_SETUP_INSTANCE_ID(unpacked);
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(unpacked);
|
|
|
|
|
|
#ifdef ENABLE_TERRAIN_PERPIXEL_NORMAL
|
|
float2 sampleCoords = (unpacked.texCoord0.xy / _TerrainHeightmapRecipSize.zw + 0.5f) * _TerrainHeightmapRecipSize.xy;
|
|
float3 normalOS = SAMPLE_TEXTURE2D(_TerrainNormalmapTexture, sampler_TerrainNormalmapTexture, sampleCoords).rgb;
|
|
normalOS = normalize(normalOS * 2.0 - 1.0);
|
|
|
|
unpacked.normalWS = TransformObjectToWorldNormal(normalOS);
|
|
|
|
#ifdef VARYINGS_NEED_TANGENT_WS
|
|
float4 tangentOS = ConstructTerrainTangent(normalOS, float3(0.0, 0.0, 1.0));
|
|
unpacked.tangentWS = float4(TransformObjectToWorldNormal(normalize(tangentOS.xyz)), tangentOS.w);
|
|
#endif
|
|
#endif
|
|
|
|
SurfaceDescription surfaceDescription = BuildSurfaceDescription(unpacked);
|
|
#ifdef _TERRAIN_SG_ALPHA_CLIP
|
|
half alpha = AlphaDiscard(surfaceDescription.Alpha, surfaceDescription.AlphaClipThreshold);
|
|
#else
|
|
half alpha = 1.0;
|
|
#endif
|
|
|
|
InputData inputData;
|
|
InitializeInputData(unpacked, surfaceDescription, inputData);
|
|
SETUP_DEBUG_TEXTURE_DATA(inputData, unpacked.texCoord0);
|
|
|
|
float3 specular = 0;
|
|
float metallic = surfaceDescription.Metallic;
|
|
|
|
half3 normalTS = half3(0, 0, 0);
|
|
#if defined(_NORMALMAP) && defined(_NORMAL_DROPOFF_TS)
|
|
normalTS = surfaceDescription.NormalTS;
|
|
#endif
|
|
|
|
SurfaceData surface;
|
|
surface.albedo = surfaceDescription.BaseColor;
|
|
surface.metallic = saturate(metallic);
|
|
surface.specular = specular;
|
|
surface.smoothness = saturate(surfaceDescription.Smoothness),
|
|
surface.occlusion = surfaceDescription.Occlusion,
|
|
surface.emission = surfaceDescription.Emission,
|
|
surface.alpha = 1.0;
|
|
surface.normalTS = normalTS;
|
|
surface.clearCoatMask = 0;
|
|
surface.clearCoatSmoothness = 1;
|
|
|
|
surface.albedo = AlphaModulate(surface.albedo, surface.alpha);
|
|
|
|
#ifdef _DBUFFER
|
|
ApplyDecalToSurfaceData(unpacked.positionCS, surface, inputData);
|
|
#endif
|
|
|
|
BRDFData brdfData;
|
|
InitializeBRDFData(surfaceDescription.BaseColor, metallic, specular, surfaceDescription.Smoothness, alpha, brdfData);
|
|
|
|
// Baked lighting.
|
|
half4 color;
|
|
Light mainLight = GetMainLight(inputData.shadowCoord, inputData.positionWS, inputData.shadowMask);
|
|
MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, inputData.shadowMask);
|
|
color.rgb = GlobalIllumination(brdfData, inputData.bakedGI, surfaceDescription.Occlusion, inputData.positionWS, inputData.normalWS, inputData.viewDirectionWS);
|
|
color.a = alpha;
|
|
SplatmapFinalColor(color, inputData.fogCoord);
|
|
|
|
// Dynamic lighting: emulate SplatmapFinalColor() by scaling gbuffer material properties. This will not give the same results
|
|
// as forward renderer because we apply blending pre-lighting instead of post-lighting.
|
|
// Blending of smoothness and normals is also not correct but close enough?
|
|
brdfData.albedo.rgb *= alpha;
|
|
brdfData.diffuse.rgb *= alpha;
|
|
brdfData.specular.rgb *= alpha;
|
|
brdfData.reflectivity *= alpha;
|
|
inputData.normalWS = inputData.normalWS * alpha;
|
|
surfaceDescription.Smoothness *= alpha;
|
|
|
|
return PackGBuffersBRDFData(brdfData, inputData, surfaceDescription.Smoothness, color.rgb, surfaceDescription.Occlusion);
|
|
}
|
|
|
|
#endif
|