void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) { ZERO_INITIALIZE(SurfaceData, surfaceData); // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct // however specularOcclusion can come from the graph, so need to be init here so it can be override. surfaceData.specularOcclusion = 1.0; surfaceData.thickness = 0.0; $SurfaceDescription.BaseColor: surfaceData.baseColor = surfaceDescription.BaseColor; $SurfaceDescription.Smoothness: surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; $SurfaceDescription.Occlusion: surfaceData.ambientOcclusion = surfaceDescription.Occlusion; $SurfaceDescription.SpecularOcclusion: surfaceData.specularOcclusion = surfaceDescription.SpecularOcclusion; $SurfaceDescription.Metallic: surfaceData.metallic = surfaceDescription.Metallic; $SurfaceDescription.SubsurfaceMask: surfaceData.subsurfaceMask = surfaceDescription.SubsurfaceMask; $SurfaceDescription.TransmissionMask: surfaceData.transmissionMask = surfaceDescription.TransmissionMask.xxx; $SurfaceDescription.Thickness: surfaceData.thickness = surfaceDescription.Thickness; $SurfaceDescription.DiffusionProfileHash: surfaceData.diffusionProfileHash = asuint(surfaceDescription.DiffusionProfileHash); $SurfaceDescription.Specular: surfaceData.specularColor = surfaceDescription.Specular; $SurfaceDescription.CoatMask: surfaceData.coatMask = surfaceDescription.CoatMask; $SurfaceDescription.Anisotropy: surfaceData.anisotropy = surfaceDescription.Anisotropy; $SurfaceDescription.IridescenceMask: surfaceData.iridescenceMask = surfaceDescription.IridescenceMask; $SurfaceDescription.IridescenceThickness: surfaceData.iridescenceThickness = surfaceDescription.IridescenceThickness; #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) if (_EnableSSRefraction) { $SurfaceDescription.RefractionIndex: surfaceData.ior = surfaceDescription.RefractionIndex; $SurfaceDescription.RefractionColor: surfaceData.transmittanceColor = surfaceDescription.RefractionColor; $SurfaceDescription.RefractionDistance: surfaceData.atDistance = surfaceDescription.RefractionDistance; surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); surfaceDescription.Alpha = 1.0; } else { surfaceData.ior = 1.0; surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); surfaceData.atDistance = 1.0; surfaceData.transmittanceMask = 0.0; surfaceDescription.Alpha = 1.0; } #else surfaceData.ior = 1.0; surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); surfaceData.atDistance = 1.0; surfaceData.transmittanceMask = 0.0; #endif // These static material feature allow compile time optimization surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; #endif #ifdef _MATERIAL_FEATURE_TRANSMISSION surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; #endif #ifdef _MATERIAL_FEATURE_COLORED_TRANSMISSION surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_COLORED_TRANSMISSION; $SurfaceDescription.TransmissionTint: surfaceData.transmissionMask = surfaceDescription.TransmissionTint; #endif #ifdef _MATERIAL_FEATURE_ANISOTROPY surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. surfaceData.normalWS = float3(0, 1, 0); #endif #ifdef _MATERIAL_FEATURE_IRIDESCENCE surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; #endif #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; #endif #ifdef _MATERIAL_FEATURE_CLEAR_COAT surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; #endif #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) // Require to have setup baseColor // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); #endif float3 doubleSidedConstants = GetDoubleSidedConstants(); ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT $SurfaceDescription.TangentOS: surfaceData.tangentWS = TransformObjectToWorldNormal(surfaceDescription.TangentOS); $SurfaceDescription.TangentTS: surfaceData.tangentWS = TransformTangentToWorld(surfaceDescription.TangentTS, fragInputs.tangentToWorld); $SurfaceDescription.TangentWS: surfaceData.tangentWS = surfaceDescription.TangentWS; bentNormalWS = surfaceData.normalWS; $BentNormal: GetNormalWS(fragInputs, surfaceDescription.BentNormal, bentNormalWS, doubleSidedConstants); surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); #ifdef DEBUG_DISPLAY #if !defined(SHADER_STAGE_RAY_TRACING) // Mipmap mode debugging isn't supported with ray tracing as it relies on derivatives if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) { #ifdef FRAG_INPUTS_USE_TEXCOORD0 surfaceData.baseColor = GET_TEXTURE_STREAMING_DEBUG(posInput.positionSS, fragInputs.texCoord0); #else surfaceData.baseColor = GET_TEXTURE_STREAMING_DEBUG_NO_UV(posInput.positionSS); #endif surfaceData.metallic = 0; } #endif // We need to call ApplyDebugToSurfaceData after filling the surfaceData and before filling builtinData // as it can modify attribute use for static lighting ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); #endif // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. // If user provide bent normal then we process a better term #if defined(_SPECULAR_OCCLUSION_CUSTOM) // Just use the value passed through via the slot (not active otherwise) #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) // If we have bent normal and ambient occlusion, process a specular occlusion surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); #endif #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); #endif }