您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
430 行
28 KiB
430 行
28 KiB
Pass
|
|
{
|
|
// based on HDPBRPass.template
|
|
Name "${PassName}"
|
|
Tags { "LightMode" = "${LightMode}" }
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// Render Modes (Blend, Cull, ZTest, Stencil, etc)
|
|
//-------------------------------------------------------------------------------------
|
|
${Blending}
|
|
${Culling}
|
|
${ZTest}
|
|
${ZWrite}
|
|
${Stencil}
|
|
${ColorMask}
|
|
//-------------------------------------------------------------------------------------
|
|
// End Render Modes
|
|
//-------------------------------------------------------------------------------------
|
|
|
|
HLSLPROGRAM
|
|
|
|
#pragma target 4.5
|
|
#pragma only_renderers d3d11 ps4 xboxone vulkan metal switch
|
|
//#pragma enable_d3d11_debug_symbols
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// Variant Definitions (active field translations to HDRP defines)
|
|
//-------------------------------------------------------------------------------------
|
|
$AlphaTest: #define _ALPHATEST_ON 1
|
|
$Material.SubsurfaceScattering: #define _MATERIAL_FEATURE_SUBSURFACE_SCATTERING 1
|
|
$Material.Transmission: #define _MATERIAL_FEATURE_TRANSMISSION 1
|
|
$Material.Anisotropy: #define _MATERIAL_FEATURE_ANISOTROPY 1
|
|
$Material.ClearCoat: #define _MATERIAL_FEATURE_CLEAR_COAT 1
|
|
$Material.Iridescence: #define _MATERIAL_FEATURE_IRIDESCENCE 1
|
|
$Material.SpecularColor: #define _MATERIAL_FEATURE_SPECULAR_COLOR 1
|
|
$SurfaceType.Transparent: #define _SURFACE_TYPE_TRANSPARENT 1
|
|
$BlendMode.Alpha: #define _BLENDMODE_ALPHA 1
|
|
$BlendMode.Add: #define _BLENDMODE_ADD 1
|
|
//-------------------------------------------------------------------------------------
|
|
// End Variant
|
|
//-------------------------------------------------------------------------------------
|
|
|
|
#pragma vertex Vert
|
|
#pragma fragment Frag
|
|
|
|
#define UNITY_MATERIAL_LIT // Need to be define before including Material.hlsl
|
|
|
|
// Use surface gradient normal mapping as it handle correctly triplanar normal mapping and multiple UVSet
|
|
// this modifies the normal calculation
|
|
// #define SURFACE_GRADIENT
|
|
|
|
// If we use subsurface scattering, enable output split lighting (for forward pass)
|
|
#if defined(_MATID_SSS) && !defined(_SURFACE_TYPE_TRANSPARENT)
|
|
#define OUTPUT_SPLIT_LIGHTING
|
|
#endif
|
|
|
|
#include "CoreRP/ShaderLibrary/Common.hlsl"
|
|
#include "CoreRP/ShaderLibrary/Wind.hlsl"
|
|
|
|
#include "CoreRP/ShaderLibrary/NormalSurfaceGradient.hlsl"
|
|
|
|
#include "ShaderGraphLibrary/Functions.hlsl"
|
|
|
|
// define FragInputs structure
|
|
#include "HDRP/ShaderPass/FragInputs.hlsl"
|
|
#include "HDRP/ShaderPass/ShaderPass.cs.hlsl"
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// Defines
|
|
//-------------------------------------------------------------------------------------
|
|
${Defines}
|
|
|
|
// this translates the new dependency tracker into the old preprocessor definitions for the existing HDRP shader code
|
|
$AttributesMesh.normalOS: #define ATTRIBUTES_NEED_NORMAL
|
|
$AttributesMesh.tangentOS: #define ATTRIBUTES_NEED_TANGENT
|
|
$AttributesMesh.uv0: #define ATTRIBUTES_NEED_TEXCOORD0
|
|
$AttributesMesh.uv1: #define ATTRIBUTES_NEED_TEXCOORD1
|
|
$AttributesMesh.uv2: #define ATTRIBUTES_NEED_TEXCOORD2
|
|
$AttributesMesh.uv3: #define ATTRIBUTES_NEED_TEXCOORD3
|
|
$AttributesMesh.color: #define ATTRIBUTES_NEED_COLOR
|
|
$VaryingsMeshToPS.positionWS: #define VARYINGS_NEED_POSITION_WS
|
|
$VaryingsMeshToPS.normalWS: #define VARYINGS_NEED_TANGENT_TO_WORLD
|
|
$VaryingsMeshToPS.texCoord0: #define VARYINGS_NEED_TEXCOORD0
|
|
$VaryingsMeshToPS.texCoord1: #define VARYINGS_NEED_TEXCOORD1
|
|
$VaryingsMeshToPS.texCoord2: #define VARYINGS_NEED_TEXCOORD2
|
|
$VaryingsMeshToPS.texCoord3: #define VARYINGS_NEED_TEXCOORD3
|
|
$VaryingsMeshToPS.color: #define VARYINGS_NEED_COLOR
|
|
$VaryingsMeshToPS.cullFace: #define VARYINGS_NEED_CULLFACE
|
|
$features.modifyMesh: #define HAVE_MESH_MODIFICATION
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// End Defines
|
|
//-------------------------------------------------------------------------------------
|
|
|
|
#include "ShaderGraphLibrary/Functions.hlsl"
|
|
#include "HDRP/ShaderVariables.hlsl"
|
|
#ifdef DEBUG_DISPLAY
|
|
#include "HDRP/Debug/DebugDisplay.hlsl"
|
|
#endif
|
|
|
|
#if (SHADERPASS == SHADERPASS_FORWARD)
|
|
// used for shaders that want to do lighting (and materials)
|
|
#include "HDRP/Lighting/Lighting.hlsl"
|
|
#else
|
|
// used for shaders that don't need lighting
|
|
#include "HDRP/Material/Material.hlsl"
|
|
#endif
|
|
#include "HDRP/Material/MaterialUtilities.hlsl"
|
|
|
|
// this function assumes the bitangent flip is encoded in tangentWS.w
|
|
// TODO: move this function to HDRP shared file, once we merge with HDRP repo
|
|
float3x3 BuildWorldToTangent(float4 tangentWS, float3 normalWS)
|
|
{
|
|
// tangentWS must not be normalized (mikkts requirement)
|
|
|
|
// Normalize normalWS vector but keep the renormFactor to apply it to bitangent and tangent
|
|
float3 unnormalizedNormalWS = normalWS;
|
|
float renormFactor = 1.0 / length(unnormalizedNormalWS);
|
|
|
|
// bitangent on the fly option in xnormal to reduce vertex shader outputs.
|
|
// this is the mikktspace transformation (must use unnormalized attributes)
|
|
float3x3 worldToTangent = CreateWorldToTangent(unnormalizedNormalWS, tangentWS.xyz, tangentWS.w > 0.0 ? 1.0 : -1.0);
|
|
|
|
// surface gradient based formulation requires a unit length initial normal. We can maintain compliance with mikkts
|
|
// by uniformly scaling all 3 vectors since normalization of the perturbed normal will cancel it.
|
|
worldToTangent[0] = worldToTangent[0] * renormFactor;
|
|
worldToTangent[1] = worldToTangent[1] * renormFactor;
|
|
worldToTangent[2] = worldToTangent[2] * renormFactor; // normalizes the interpolated vertex normal
|
|
return worldToTangent;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// Interpolator Packing And Struct Declarations
|
|
//-------------------------------------------------------------------------------------
|
|
${InterpolatorPacking}
|
|
//-------------------------------------------------------------------------------------
|
|
// End Interpolator Packing And Struct Declarations
|
|
//-------------------------------------------------------------------------------------
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// Graph generated code
|
|
//-------------------------------------------------------------------------------------
|
|
${Graph}
|
|
//-------------------------------------------------------------------------------------
|
|
// End graph generated code
|
|
//-------------------------------------------------------------------------------------
|
|
|
|
#ifdef HAVE_MESH_MODIFICATION
|
|
// TODO: we should share this between template files somehow
|
|
VertexDescriptionInputs AttributesMeshToVertexDescriptionInputs(AttributesMesh input)
|
|
{
|
|
VertexDescriptionInputs output;
|
|
ZERO_INITIALIZE(VertexDescriptionInputs, output);
|
|
|
|
$VertexDescriptionInputs.ObjectSpaceNormal: output.ObjectSpaceNormal = input.normalOS;
|
|
$VertexDescriptionInputs.WorldSpaceNormal: output.WorldSpaceNormal = TransformObjectToWorldNormal(input.normalOS);
|
|
$VertexDescriptionInputs.ViewSpaceNormal: output.ViewSpaceNormal = TransformWorldToViewDir(output.WorldSpaceNormal);
|
|
$VertexDescriptionInputs.TangentSpaceNormal: output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f);
|
|
|
|
$VertexDescriptionInputs.ObjectSpaceTangent: output.ObjectSpaceTangent = input.tangentOS;
|
|
$VertexDescriptionInputs.WorldSpaceTangent: output.WorldSpaceTangent = TransformObjectToWorldDir(input.tangentOS.xyz);
|
|
$VertexDescriptionInputs.ViewSpaceTangent: output.ViewSpaceTangent = TransformWorldToViewDir(output.WorldSpaceTangent);
|
|
$VertexDescriptionInputs.TangentSpaceTangent: output.TangentSpaceTangent = float3(1.0f, 0.0f, 0.0f);
|
|
|
|
$VertexDescriptionInputs.ObjectSpaceBiTangent: output.ObjectSpaceBiTangent = normalize(cross(input.normalOS, input.tangentOS) * (input.tangentOS.w > 0.0f ? 1.0f : -1.0f) * GetOddNegativeScale());
|
|
$VertexDescriptionInputs.WorldSpaceBiTangent: output.WorldSpaceBiTangent = TransformObjectToWorldDir(output.ObjectSpaceBiTangent);
|
|
$VertexDescriptionInputs.ViewSpaceBiTangent: output.ViewSpaceBiTangent = TransformWorldToViewDir(output.WorldSpaceBiTangent);
|
|
$VertexDescriptionInputs.TangentSpaceBiTangent: output.TangentSpaceBiTangent = float3(0.0f, 1.0f, 0.0f);
|
|
|
|
$VertexDescriptionInputs.ObjectSpacePosition: output.ObjectSpacePosition = input.positionOS;
|
|
$VertexDescriptionInputs.WorldSpacePosition: output.WorldSpacePosition = TransformObjectToWorld(input.positionOS);
|
|
$VertexDescriptionInputs.ViewSpacePosition: output.ViewSpacePosition = TransformWorldToView(output.WorldSpacePosition);
|
|
$VertexDescriptionInputs.TangentSpacePosition: output.TangentSpacePosition = float3(0.0f, 0.0f, 0.0f);
|
|
|
|
$VertexDescriptionInputs.WorldSpaceViewDirection: output.WorldSpaceViewDirection = GetWorldSpaceNormalizeViewDir(output.WorldSpacePosition);
|
|
$VertexDescriptionInputs.ObjectSpaceViewDirection: output.ObjectSpaceViewDirection = TransformWorldToObjectDir(output.WorldSpaceViewDirection);
|
|
$VertexDescriptionInputs.ViewSpaceViewDirection: output.ViewSpaceViewDirection = TransformWorldToViewDir(output.WorldSpaceViewDirection);
|
|
$VertexDescriptionInputs.TangentSpaceViewDirection: float3x3 tangentSpaceTransform = float3x3(output.WorldSpaceTangent,output.WorldSpaceBiTangent,output.WorldSpaceNormal);
|
|
$VertexDescriptionInputs.TangentSpaceViewDirection: output.TangentSpaceViewDirection = mul(tangentSpaceTransform, output.WorldSpaceViewDirection);
|
|
|
|
$VertexDescriptionInputs.ScreenPosition: output.ScreenPosition = ComputeScreenPos(TransformWorldToHClip(output.WorldSpacePosition), _ProjectionParams.x);
|
|
$VertexDescriptionInputs.uv0: output.uv0 = float4(input.uv0, 0.0f, 0.0f);
|
|
$VertexDescriptionInputs.uv1: output.uv1 = float4(input.uv1, 0.0f, 0.0f);
|
|
$VertexDescriptionInputs.uv2: output.uv2 = float4(input.uv2, 0.0f, 0.0f);
|
|
$VertexDescriptionInputs.uv3: output.uv3 = float4(input.uv3, 0.0f, 0.0f);
|
|
$VertexDescriptionInputs.VertexColor: output.VertexColor = input.color;
|
|
|
|
return output;
|
|
}
|
|
|
|
AttributesMesh ApplyMeshModification(AttributesMesh input)
|
|
{
|
|
// build graph inputs
|
|
VertexDescriptionInputs vertexDescriptionInputs = AttributesMeshToVertexDescriptionInputs(input);
|
|
|
|
// evaluate vertex graph
|
|
VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs);
|
|
|
|
// copy graph output to the results
|
|
$VertexDescription.Position: input.positionOS = vertexDescription.Position;
|
|
|
|
return input;
|
|
}
|
|
#endif // HAVE_MESH_MODIFICATION
|
|
|
|
// TODO: Do we want to build include functionality for sharing these preprocessed functions across templates?
|
|
FragInputs BuildFragInputs(VaryingsMeshToPS input)
|
|
{
|
|
FragInputs output;
|
|
ZERO_INITIALIZE(FragInputs, output);
|
|
|
|
// Init to some default value to make the computer quiet (else it output 'divide by zero' warning even if value is not used).
|
|
// TODO: this is a really poor workaround, but the variable is used in a bunch of places
|
|
// to compute normals which are then passed on elsewhere to compute other values...
|
|
output.worldToTangent = k_identity3x3;
|
|
output.positionSS = input.positionCS; // input.positionCS is SV_Position
|
|
|
|
$FragInputs.positionWS: output.positionWS = input.positionWS;
|
|
$FragInputs.worldToTangent: output.worldToTangent = BuildWorldToTangent(input.tangentWS, input.normalWS);
|
|
$FragInputs.texCoord0: output.texCoord0 = input.texCoord0;
|
|
$FragInputs.texCoord1: output.texCoord1 = input.texCoord1;
|
|
$FragInputs.texCoord2: output.texCoord2 = input.texCoord2;
|
|
$FragInputs.texCoord3: output.texCoord3 = input.texCoord3;
|
|
$FragInputs.color: output.color = input.color;
|
|
#if SHADER_STAGE_FRAGMENT
|
|
$FragInputs.isFrontFace: output.isFrontFace = IS_FRONT_VFACE(input.cullFace, true, false); // TODO: SHADER_STAGE_FRAGMENT only
|
|
$FragInputs.isFrontFace: // Handle handness of the view matrix (In Unity view matrix default to a determinant of -1)
|
|
$FragInputs.isFrontFace: // when we render a cubemap the view matrix handness is flipped (due to convention used for cubemap) we have a determinant of +1
|
|
$FragInputs.isFrontFace: output.isFrontFace = _DetViewMatrix < 0.0 ? output.isFrontFace : !output.isFrontFace;
|
|
#endif // SHADER_STAGE_FRAGMENT
|
|
|
|
return output;
|
|
}
|
|
|
|
SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS)
|
|
{
|
|
SurfaceDescriptionInputs output;
|
|
ZERO_INITIALIZE(SurfaceDescriptionInputs, output);
|
|
|
|
$SurfaceDescriptionInputs.WorldSpaceNormal: output.WorldSpaceNormal = normalize(input.worldToTangent[2].xyz);
|
|
$SurfaceDescriptionInputs.ObjectSpaceNormal: output.ObjectSpaceNormal = mul(output.WorldSpaceNormal, (float3x3) unity_ObjectToWorld); // transposed multiplication by inverse matrix to handle normal scale
|
|
$SurfaceDescriptionInputs.ViewSpaceNormal: output.ViewSpaceNormal = mul(output.WorldSpaceNormal, (float3x3) UNITY_MATRIX_I_V); // transposed multiplication by inverse matrix to handle normal scale
|
|
$SurfaceDescriptionInputs.TangentSpaceNormal: output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f);
|
|
|
|
$SurfaceDescriptionInputs.WorldSpaceTangent output.WorldSpaceTangent = input.worldToTangent[0].xyz;
|
|
$SurfaceDescriptionInputs.ObjectSpaceTangent: output.ObjectSpaceTangent = mul((float3x3) unity_WorldToObject, output.WorldSpaceTangent);
|
|
$SurfaceDescriptionInputs.ViewSpaceTangent: output.ViewSpaceTangent = mul((float3x3) UNITY_MATRIX_V, output.WorldSpaceTangent);
|
|
$SurfaceDescriptionInputs.TangentSpaceTangent: output.TangentSpaceTangent = float3(1.0f, 0.0f, 0.0f);
|
|
|
|
$SurfaceDescriptionInputs.WorldSpaceBiTangent: output.WorldSpaceBiTangent = input.worldToTangent[1].xyz;
|
|
$SurfaceDescriptionInputs.ObjectSpaceBiTangent: output.ObjectSpaceBiTangent = mul((float3x3) unity_WorldToObject, output.WorldSpaceBiTangent);
|
|
$SurfaceDescriptionInputs.ViewSpaceBiTangent: output.ViewSpaceBiTangent = mul((float3x3) UNITY_MATRIX_V, output.WorldSpaceBiTangent);
|
|
$SurfaceDescriptionInputs.TangentSpaceBiTangent: output.TangentSpaceBiTangent = float3(0.0f, 1.0f, 0.0f);
|
|
|
|
$SurfaceDescriptionInputs.WorldSpaceViewDirection: output.WorldSpaceViewDirection = normalize(viewWS);
|
|
$SurfaceDescriptionInputs.ObjectSpaceViewDirection: output.ObjectSpaceViewDirection = mul((float3x3) unity_WorldToObject, output.WorldSpaceViewDirection);
|
|
$SurfaceDescriptionInputs.ViewSpaceViewDirection: output.ViewSpaceViewDirection = mul((float3x3) UNITY_MATRIX_V, output.WorldSpaceViewDirection);
|
|
$SurfaceDescriptionInputs.TangentSpaceViewDirection: float3x3 tangentSpaceTransform = float3x3(output.WorldSpaceTangent,output.WorldSpaceBiTangent,output.WorldSpaceNormal);
|
|
$SurfaceDescriptionInputs.TangentSpaceViewDirection: output.TangentSpaceViewDirection = mul(tangentSpaceTransform, output.WorldSpaceViewDirection);
|
|
|
|
// TODO: FragInputs.positionWS is badly named -- it's camera relative, not in world space
|
|
// we have to fix it up here to match graph input expectations
|
|
$SurfaceDescriptionInputs.WorldSpacePosition: output.WorldSpacePosition = input.positionWS + _WorldSpaceCameraPos;
|
|
$SurfaceDescriptionInputs.ObjectSpacePosition: output.ObjectSpacePosition = mul(unity_WorldToObject, float4(input.positionWS + _WorldSpaceCameraPos, 1.0f)).xyz;
|
|
$SurfaceDescriptionInputs.ViewSpacePosition: float4 posViewSpace = mul(UNITY_MATRIX_V, float4(input.positionWS, 1.0f));
|
|
$SurfaceDescriptionInputs.ViewSpacePosition: output.ViewSpacePosition = posViewSpace.xyz / posViewSpace.w;
|
|
$SurfaceDescriptionInputs.TangentSpacePosition: output.TangentSpacePosition = float3(0.0f, 0.0f, 0.0f);
|
|
|
|
// TODO: positionSS is SV_Position, graph input expects screenPosition to be 0..1 across the active viewport (?)
|
|
$SurfaceDescriptionInputs.ScreenPosition: float4 clipPos = ComputeScreenPos(TransformWorldToHClip(input.positionWS), _ProjectionParams.x);
|
|
$SurfaceDescriptionInputs.ScreenPosition: output.ScreenPosition = clipPos; // float4(clipPos.x * _ScreenSize.x, clipPos.y * _ScreenSize.y, clipPos.zw); // wtf?
|
|
|
|
$SurfaceDescriptionInputs.uv0: output.uv0 = float4(input.texCoord0, 0.0f, 0.0f);
|
|
$SurfaceDescriptionInputs.uv1: output.uv1 = float4(input.texCoord1, 0.0f, 0.0f);
|
|
$SurfaceDescriptionInputs.uv2: output.uv2 = float4(input.texCoord2, 0.0f, 0.0f);
|
|
$SurfaceDescriptionInputs.uv3: output.uv3 = float4(input.texCoord3, 0.0f, 0.0f);
|
|
|
|
$SurfaceDescriptionInputs.VertexColor: output.VertexColor = input.color;
|
|
|
|
return output;
|
|
}
|
|
|
|
// existing HDRP code uses the combined function to go directly from packed to frag inputs
|
|
FragInputs UnpackVaryingsMeshToFragInputs(PackedVaryingsMeshToPS input)
|
|
{
|
|
VaryingsMeshToPS unpacked= UnpackVaryingsMeshToPS(input);
|
|
return BuildFragInputs(unpacked);
|
|
}
|
|
|
|
void BuildSurfaceData(FragInputs fragInputs, SurfaceDescription surfaceDescription, float3 V, out SurfaceData surfaceData)
|
|
{
|
|
// setup defaults -- these are used if the graph doesn't output a value
|
|
ZERO_INITIALIZE(SurfaceData, surfaceData);
|
|
surfaceData.ambientOcclusion = 1.0f;
|
|
surfaceData.subsurfaceMask = 1.0f;
|
|
|
|
// copy across graph values, if defined
|
|
$SurfaceDescription.Albedo: surfaceData.baseColor = surfaceDescription.Albedo;
|
|
$SurfaceDescription.Smoothness: surfaceData.perceptualSmoothness = surfaceDescription.Smoothness;
|
|
$SurfaceDescription.Occlusion: surfaceData.ambientOcclusion = surfaceDescription.Occlusion;
|
|
$SurfaceDescription.Metallic: surfaceData.metallic = surfaceDescription.Metallic;
|
|
// surfaceData.thickness = surfaceDescription.Thickness;
|
|
// surfaceData.diffusionProfile = surfaceDescription.DiffusionProfile;
|
|
// surfaceData.subsurfaceMask = surfaceDescription.SubsurfaceMask;
|
|
$SurfaceDescription.Specular: surfaceData.specularColor = surfaceDescription.Specular;
|
|
|
|
// 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_ANISOTROPY
|
|
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY;
|
|
#endif
|
|
#ifdef _MATERIAL_FEATURE_CLEAR_COAT
|
|
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT;
|
|
#endif
|
|
#ifdef _MATERIAL_FEATURE_IRIDESCENCE
|
|
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE;
|
|
#endif
|
|
#ifdef _MATERIAL_FEATURE_SPECULAR_COLOR
|
|
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR;
|
|
#endif
|
|
|
|
// tangent-space normal
|
|
float3 normalTS = float3(0.0f, 0.0f, 1.0f);
|
|
$SurfaceDescription.Normal: normalTS = surfaceDescription.Normal;
|
|
|
|
// compute world space normal
|
|
GetNormalWS(fragInputs, V, normalTS, surfaceData.normalWS);
|
|
|
|
// TODO: use surfaceDescription tangent definition for anisotropy
|
|
surfaceData.tangentWS = normalize(fragInputs.worldToTangent[0].xyz); // The tangent is not normalize in worldToTangent for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT
|
|
surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS);
|
|
|
|
// Init other parameters
|
|
surfaceData.anisotropy = 0;
|
|
surfaceData.coatMask = 0.0f;
|
|
surfaceData.iridescenceThickness = 0.0;
|
|
surfaceData.iridescenceMask = 1.0;
|
|
|
|
// Transparency parameters
|
|
// Use thickness from SSS
|
|
surfaceData.ior = 1.0;
|
|
surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0);
|
|
surfaceData.atDistance = 1000000.0;
|
|
surfaceData.transmittanceMask = 0.0;
|
|
|
|
// 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
|
|
surfaceData.specularOcclusion = 1.0;
|
|
#if defined(_BENTNORMALMAP) && defined(_ENABLESPECULAROCCLUSION)
|
|
// If we have bent normal and ambient occlusion, process a specular occlusion
|
|
surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData);
|
|
#elif defined(_MASKMAP)
|
|
surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(NdotV, surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness));
|
|
#endif
|
|
}
|
|
|
|
void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData)
|
|
{
|
|
// this applies the double sided tangent space correction -- see 'ApplyDoubleSidedFlipOrMirror()'
|
|
$DoubleSided: if (!fragInputs.isFrontFace) {
|
|
$DoubleSided.Flip: fragInputs.worldToTangent[1] = -fragInputs.worldToTangent[1]; // bitangent
|
|
$DoubleSided.Flip: fragInputs.worldToTangent[2] = -fragInputs.worldToTangent[2]; // normal
|
|
$DoubleSided.Mirror: fragInputs.worldToTangent[2] = -fragInputs.worldToTangent[2]; // normal
|
|
$DoubleSided: }
|
|
|
|
SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V);
|
|
SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs);
|
|
|
|
// Perform alpha test very early to save performance (a killed pixel will not sample textures)
|
|
// TODO: split graph evaluation to grab just alpha dependencies first? tricky..
|
|
$AlphaTest: DoAlphaTest(surfaceDescription.Alpha, surfaceDescription.AlphaClipThreshold);
|
|
|
|
BuildSurfaceData(fragInputs, surfaceDescription, V, surfaceData);
|
|
|
|
// Builtin Data -- we don't call GetBuiltinData(fragInputs, surfaceData, ...)
|
|
// that function assumes there are specific global properties defined
|
|
// for shadergraph shaders, we fill it out here instead
|
|
ZERO_INITIALIZE(BuiltinData, builtinData);
|
|
float3 bentNormalWS = surfaceData.normalWS; // TODO : make bent normals work
|
|
|
|
builtinData.opacity = surfaceDescription.Alpha;
|
|
builtinData.bakeDiffuseLighting = SampleBakedGI(fragInputs.positionWS, bentNormalWS, fragInputs.texCoord1, fragInputs.texCoord2); // see GetBuiltinData()
|
|
|
|
// It is safe to call this function here as surfaceData have been filled
|
|
// We want to know if we must enable transmission on GI for SSS material, if the material have no SSS, this code will be remove by the compiler.
|
|
BSDFData bsdfData = ConvertSurfaceDataToBSDFData(surfaceData);
|
|
if (HasFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_TRANSMISSION))
|
|
{
|
|
// For now simply recall the function with inverted normal, the compiler should be able to optimize the lightmap case to not resample the directional lightmap
|
|
// however it will not optimize the lightprobe case due to the proxy volume relying on dynamic if (we rely must get right of this dynamic if), not a problem for SH9, but a problem for proxy volume.
|
|
// TODO: optimize more this code.
|
|
// Add GI transmission contribution by resampling the GI for inverted vertex normal
|
|
builtinData.bakeDiffuseLighting += SampleBakedGI(fragInputs.positionWS, -fragInputs.worldToTangent[2], fragInputs.texCoord1, fragInputs.texCoord2) * bsdfData.transmittance;
|
|
}
|
|
|
|
$SurfaceDescription.Emission: builtinData.emissiveColor = surfaceDescription.Emission;
|
|
builtinData.velocity = float2(0.0, 0.0);
|
|
#ifdef SHADOWS_SHADOWMASK
|
|
float4 shadowMask = SampleShadowMask(fragInputs.positionWS, fragInputs.texCoord1);
|
|
builtinData.shadowMask0 = shadowMask.x;
|
|
builtinData.shadowMask1 = shadowMask.y;
|
|
builtinData.shadowMask2 = shadowMask.z;
|
|
builtinData.shadowMask3 = shadowMask.w;
|
|
#else
|
|
builtinData.shadowMask0 = 0.0;
|
|
builtinData.shadowMask1 = 0.0;
|
|
builtinData.shadowMask2 = 0.0;
|
|
builtinData.shadowMask3 = 0.0;
|
|
#endif
|
|
builtinData.distortion = float2(0.0, 0.0); // surfaceDescription.Distortion -- if distortion pass
|
|
builtinData.distortionBlur = 0.0; // surfaceDescription.DistortionBlur -- if distortion pass
|
|
builtinData.depthOffset = 0.0; // ApplyPerPixelDisplacement(input, V, layerTexCoord, blendMasks); #ifdef _DEPTHOFFSET_ON : ApplyDepthOffsetPositionInput(V, depthOffset, GetWorldToHClipMatrix(), posInput);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// Pass Includes
|
|
//-------------------------------------------------------------------------------------
|
|
${Includes}
|
|
//-------------------------------------------------------------------------------------
|
|
// End Pass Includes
|
|
//-------------------------------------------------------------------------------------
|
|
|
|
ENDHLSL
|
|
}
|