Alex Lian
7 年前
当前提交
0d975dea
共有 68 个文件被更改,包括 3224 次插入 和 347 次删除
-
539ShaderGraph/HDPipeline/HDUnlitSubShader.cs
-
1com.unity.render-pipelines.high-definition/CHANGELOG.md
-
16com.unity.render-pipelines.high-definition/HDRP/Editor/BuildPlayer/HDRPVariantStripper.cs
-
9com.unity.render-pipelines.high-definition/HDRP/Lighting/LightLoop/ShaderBase.hlsl
-
26com.unity.render-pipelines.high-definition/HDRP/Material/LayeredLit/LayeredLit.shader
-
29com.unity.render-pipelines.high-definition/HDRP/Material/LayeredLit/LayeredLitTessellation.shader
-
23com.unity.render-pipelines.high-definition/HDRP/Material/Lit/Lit.shader
-
4com.unity.render-pipelines.high-definition/HDRP/Material/Lit/LitProperties.hlsl
-
29com.unity.render-pipelines.high-definition/HDRP/Material/Lit/LitTessellation.shader
-
6com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.cs
-
38com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.cs.hlsl
-
115com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.hlsl
-
21com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLitData.hlsl
-
21com.unity.render-pipelines.high-definition/HDRP/Material/Unlit/Unlit.shader
-
4com.unity.render-pipelines.high-definition/HDRP/Material/Unlit/UnlitProperties.hlsl
-
5com.unity.render-pipelines.high-definition/HDRP/ShaderPass/ShaderPassDepthOnly.hlsl
-
4com.unity.shadergraph/Editor/Data/Graphs/ShaderGraphRequirements.cs
-
2com.unity.shadergraph/Editor/Data/Interfaces/IGeneratesFunction.cs
-
2com.unity.shadergraph/Editor/Data/Nodes/Artistic/Adjustment/ChannelMixerNode.cs
-
4com.unity.shadergraph/Editor/Data/Nodes/Artistic/Adjustment/InvertColorsNode.cs
-
2com.unity.shadergraph/Editor/Data/Nodes/Artistic/Mask/ChannelMaskNode.cs
-
2com.unity.shadergraph/Editor/Data/Nodes/Artistic/Normal/NormalCreateNode.cs
-
4com.unity.shadergraph/Editor/Data/Nodes/Channel/FlipNode.cs
-
2com.unity.shadergraph/Editor/Data/Nodes/CodeFunctionNode.cs
-
2com.unity.shadergraph/Editor/Data/Nodes/Input/Gradient/GradientNode.cs
-
2com.unity.shadergraph/Editor/Data/Nodes/Input/Scene/FogNode.cs
-
2com.unity.shadergraph/Editor/Data/Nodes/Math/Basic/MultiplyNode.cs
-
2com.unity.shadergraph/Editor/Data/Nodes/Math/Matrix/MatrixConstructionNode.cs
-
4com.unity.shadergraph/Editor/Data/Nodes/Procedural/Noise/GradientNoiseNode.cs
-
4com.unity.shadergraph/Editor/Data/Nodes/Procedural/Noise/SimpleNoiseNode.cs
-
4com.unity.shadergraph/Editor/Data/Nodes/Procedural/Noise/VoronoiNode.cs
-
2com.unity.shadergraph/Editor/Data/Nodes/UV/FlipbookNode.cs
-
6com.unity.shadergraph/Editor/Data/Nodes/Utility/SubGraphNode.cs
-
6com.unity.shadergraph/Editor/Data/SubGraph/SubGraph.cs
-
533com.unity.shadergraph/Editor/Data/Util/GraphUtil.cs
-
20com.unity.shadergraph/Editor/Data/Util/ShaderGenerator.cs
-
275com.unity.shadergraph/Editor/Templates/HDUnlitPassForward.template
-
790ShaderGraph/HDPipeline/HDPBRSubShader.cs
-
11ShaderGraph/HDPipeline/HDPBRSubShader.cs.meta
-
444ShaderGraph/HDPipeline/HDSubShaderUtilities.cs
-
11ShaderGraph/HDPipeline/HDSubShaderUtilities.cs.meta
-
8ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/AssetPostProcessors.meta
-
104ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/AssetPostProcessors/NormalMapVarianceTexturePostprocessor.cs
-
11ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/AssetPostProcessors/NormalMapVarianceTexturePostprocessor.cs.meta
-
21ShaderGraph/com.unity.shadergraph/Editor/Data/Util/GraphContext.cs
-
11ShaderGraph/com.unity.shadergraph/Editor/Data/Util/GraphContext.cs.meta
-
366ShaderGraph/com.unity.shadergraph/Editor/Templates/HDPBRPass.template
-
8ShaderGraph/com.unity.shadergraph/Editor/Templates/HDPBRPass.template.meta
-
8Tests/GraphicsTests/RenderPipeline/HDRenderPipeline/Scenes/2xxx_Lighting/2401_Light_on_Tesselation.meta
-
8Tests/Scripts/GraphicTests/HDRenderPipeline.meta
|
|||
// Unlit shader always render in forward |
|||
Name "ForwardUnlit" |
|||
// based on HDUnlitPassForward.template |
|||
Name "${PassName}" |
|||
// Material options generated by graph |
|||
${Tags} |
|||
//------------------------------------------------------------------------------------- |
|||
// Render Modes (Blend, Cull, ZTest, Stencil, etc) |
|||
//------------------------------------------------------------------------------------- |
|||
HLSLPROGRAM |
|||
${Stencil} |
|||
${ColorMask} |
|||
//------------------------------------------------------------------------------------- |
|||
// End Render Modes |
|||
//------------------------------------------------------------------------------------- |
|||
|
|||
HLSLPROGRAM |
|||
|
|||
#pragma only_renderers d3d11 ps4 vulkan metal // TEMP: until we go further in dev |
|||
#pragma only_renderers d3d11 ps4 xboxone vulkan metal switch |
|||
//------------------------------------------------------------------------------------- |
|||
// Variant Definitions |
|||
//------------------------------------------------------------------------------------- |
|||
${VariantDefines} |
|||
//------------------------------------------------------------------------------------- |
|||
// End Variant |
|||
//------------------------------------------------------------------------------------- |
|||
|
|||
// ------------------------------------- |
|||
// HD Pipeline keywords |
|||
// Defines generated by graph |
|||
${Defines} |
|||
#include "CoreRP/ShaderLibrary/common.hlsl" |
|||
#include "HDRP/ShaderVariables.hlsl" |
|||
#include "CoreRP/ShaderLibrary/Common.hlsl" |
|||
// #include "CoreRP/ShaderLibrary/Wind.hlsl" |
|||
|
|||
#include "ShaderGraphLibrary/Functions.hlsl" |
|||
|
|||
// define FragInputs structure |
|||
#include "ShaderGraphLibrary/Functions.hlsl" |
|||
#include "HDRP/Material/Material.hlsl" |
|||
// This include will define the various Attributes/Varyings structure |
|||
#include "HDRP/ShaderPass/VaryingMesh.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 |
|||
//------------------------------------------------------------------------------------- |
|||
// End Defines |
|||
//------------------------------------------------------------------------------------- |
|||
|
|||
#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 |
|||
//------------------------------------------------------------------------------------- |
|||
void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData) |
|||
//------------------------------------------------------------------------------------- |
|||
// End graph generated code |
|||
//------------------------------------------------------------------------------------- |
|||
|
|||
// 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 |
|||
$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); |
|||
|
|||
$SurfaceDescriptionInputs.screenPosition: output.screenPosition = input.positionSS; |
|||
|
|||
$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); |
|||
|
|||
// copy across graph values, if defined |
|||
$SurfaceDescription.Color: surfaceData.color = surfaceDescription.Color; |
|||
} |
|||
|
|||
void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData) |
|||
// Pixel transformations performed by graph |
|||
${PixelShader} |
|||
SurfaceDescriptionInputs surfaceInput; |
|||
|
|||
// Surface description inputs defined by graph |
|||
${PixelShaderSurfaceInputs} |
|||
SurfaceDescription surf = PopulateSurfaceData(surfaceInput); |
|||
// 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: } |
|||
float3 Color = float3(0.5, 0.5, 0.5); |
|||
float Alpha = 1; |
|||
float AlphaClipThreshold = 0; |
|||
|
|||
// Surface description remap performed by graph |
|||
${PixelShaderSurfaceRemap} |
|||
surfaceData.color = Color; |
|||
SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); |
|||
SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); |
|||
#ifdef _ALPHATEST_ON |
|||
DoAlphaTest(Alpha, AlphaClipThreshold); |
|||
#endif |
|||
// 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.. |
|||
#ifdef _ALPHATEST_ON |
|||
DoAlphaTest(surfaceDescription.Alpha, surfaceDescription.AlphaClipThreshold); |
|||
#endif |
|||
// Builtin Data |
|||
builtinData.opacity = Alpha; |
|||
builtinData.bakeDiffuseLighting = float3(0.0, 0.0, 0.0); |
|||
builtinData.emissiveIntensity = 0; |
|||
builtinData.emissiveColor = 0; |
|||
builtinData.velocity = float2(0.0, 0.0); |
|||
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); |
|||
|
|||
builtinData.opacity = surfaceDescription.Alpha; |
|||
builtinData.bakeDiffuseLighting = float3(0.0, 0.0, 0.0); |
|||
|
|||
builtinData.emissiveIntensity = 1.0f; |
|||
$SurfaceDescription.Emission: builtinData.emissiveColor = surfaceDescription.Emission; |
|||
builtinData.velocity = float2(0.0, 0.0); |
|||
builtinData.distortion = float2(0.0, 0.0); |
|||
builtinData.distortionBlur = 0.0; |
|||
builtinData.depthOffset = 0.0; |
|||
|
|||
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); |
|||
#include "HDRP/ShaderPass/${ShaderPassInclude}.hlsl" |
|||
//------------------------------------------------------------------------------------- |
|||
// Pass Includes |
|||
//------------------------------------------------------------------------------------- |
|||
${Includes} |
|||
//------------------------------------------------------------------------------------- |
|||
// End Pass Includes |
|||
//------------------------------------------------------------------------------------- |
|||
|
|||
ENDHLSL |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using System.Collections; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using UnityEditor.Graphing; |
|||
|
|||
|
|||
namespace UnityEditor.ShaderGraph |
|||
{ |
|||
public class HDPBRSubShader : IPBRSubShader |
|||
{ |
|||
Pass m_PassGBuffer = new Pass() |
|||
{ |
|||
Name = "GBuffer", |
|||
LightMode = "GBuffer", |
|||
TemplateName = "HDPBRPass.template", |
|||
ShaderPassName = "SHADERPASS_GBUFFER", |
|||
StencilOverride = new List<string>() |
|||
{ |
|||
"// Stencil setup for gbuffer", |
|||
"Stencil", |
|||
"{", |
|||
" WriteMask 7", // [_StencilWriteMask] // default: StencilMask.Lighting (fixed at compile time)
|
|||
" Ref 2", // [_StencilRef] // default: StencilLightingUsage.RegularLighting (fixed at compile time)
|
|||
" Comp Always", |
|||
" Pass Replace", |
|||
"}" |
|||
}, |
|||
ExtraDefines = new List<string>() |
|||
{ |
|||
"#pragma multi_compile _ DEBUG_DISPLAY", |
|||
"#pragma multi_compile _ LIGHTMAP_ON", |
|||
"#pragma multi_compile _ DIRLIGHTMAP_COMBINED", |
|||
"#pragma multi_compile _ DYNAMICLIGHTMAP_ON", |
|||
"#pragma multi_compile _ SHADOWS_SHADOWMASK", |
|||
}, |
|||
Includes = new List<string>() |
|||
{ |
|||
"#include \"HDRP/ShaderPass/ShaderPassGBuffer.hlsl\"", |
|||
}, |
|||
RequiredFields = new List<string>() |
|||
{ |
|||
"FragInputs.worldToTangent", |
|||
"FragInputs.positionWS", |
|||
}, |
|||
PixelShaderSlots = new List<int>() |
|||
{ |
|||
PBRMasterNode.AlbedoSlotId, |
|||
PBRMasterNode.NormalSlotId, |
|||
PBRMasterNode.MetallicSlotId, |
|||
PBRMasterNode.SpecularSlotId, |
|||
PBRMasterNode.EmissionSlotId, |
|||
PBRMasterNode.SmoothnessSlotId, |
|||
PBRMasterNode.OcclusionSlotId, |
|||
PBRMasterNode.AlphaSlotId, |
|||
PBRMasterNode.AlphaThresholdSlotId |
|||
}, |
|||
}; |
|||
|
|||
Pass m_PassGBufferWithPrepass = new Pass() |
|||
{ |
|||
Name = "GBufferWithPrepass", |
|||
LightMode = "GBufferWithPrepass", |
|||
TemplateName = "HDPBRPass.template", |
|||
ShaderPassName = "SHADERPASS_GBUFFER", |
|||
StencilOverride = new List<string>() |
|||
{ |
|||
"// Stencil setup for GBufferWithPrepass", |
|||
"Stencil", |
|||
"{", |
|||
" WriteMask 7", // _StencilWriteMask // StencilMask.Lighting (fixed at compile time)
|
|||
" Ref 2", // _StencilRef // StencilLightingUsage.RegularLighting (fixed at compile time)
|
|||
" Comp Always", |
|||
" Pass Replace", |
|||
"}" |
|||
}, |
|||
ExtraDefines = new List<string>() |
|||
{ |
|||
"#pragma multi_compile _ DEBUG_DISPLAY", |
|||
"#pragma multi_compile _ LIGHTMAP_ON", |
|||
"#pragma multi_compile _ DIRLIGHTMAP_COMBINED", |
|||
"#pragma multi_compile _ DYNAMICLIGHTMAP_ON", |
|||
"#pragma multi_compile _ SHADOWS_SHADOWMASK", |
|||
"#define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST", |
|||
}, |
|||
Includes = new List<string>() |
|||
{ |
|||
"#include \"HDRP/ShaderPass/ShaderPassGBuffer.hlsl\"", |
|||
}, |
|||
RequiredFields = new List<string>() |
|||
{ |
|||
// "FragInputs.worldToTangent",
|
|||
// "FragInputs.positionWS",
|
|||
}, |
|||
PixelShaderSlots = new List<int>() |
|||
{ |
|||
PBRMasterNode.AlbedoSlotId, |
|||
PBRMasterNode.NormalSlotId, |
|||
PBRMasterNode.MetallicSlotId, |
|||
PBRMasterNode.SpecularSlotId, |
|||
PBRMasterNode.EmissionSlotId, |
|||
PBRMasterNode.SmoothnessSlotId, |
|||
PBRMasterNode.OcclusionSlotId, |
|||
PBRMasterNode.AlphaSlotId, |
|||
PBRMasterNode.AlphaThresholdSlotId |
|||
}, |
|||
}; |
|||
|
|||
Pass m_PassMETA = new Pass() |
|||
{ |
|||
Name = "META", |
|||
LightMode = "Meta", |
|||
TemplateName = "HDPBRPass.template", |
|||
ShaderPassName = "SHADERPASS_LIGHT_TRANSPORT", |
|||
CullOverride = "Cull Off", |
|||
Includes = new List<string>() |
|||
{ |
|||
"#include \"HDRP/ShaderPass/ShaderPassLightTransport.hlsl\"", |
|||
}, |
|||
RequiredFields = new List<string>() |
|||
{ |
|||
"AttributesMesh.normalOS", |
|||
"AttributesMesh.tangentOS", // Always present as we require it also in case of anisotropic lighting
|
|||
"AttributesMesh.uv0", |
|||
"AttributesMesh.uv1", |
|||
"AttributesMesh.color", |
|||
"AttributesMesh.uv2", // SHADERPASS_LIGHT_TRANSPORT always uses uv2
|
|||
// "FragInputs.worldToTangent",
|
|||
// "FragInputs.positionWS",
|
|||
}, |
|||
PixelShaderSlots = new List<int>() |
|||
{ |
|||
PBRMasterNode.AlbedoSlotId, |
|||
PBRMasterNode.NormalSlotId, |
|||
PBRMasterNode.MetallicSlotId, |
|||
PBRMasterNode.SpecularSlotId, |
|||
PBRMasterNode.EmissionSlotId, |
|||
PBRMasterNode.SmoothnessSlotId, |
|||
PBRMasterNode.OcclusionSlotId, |
|||
PBRMasterNode.AlphaSlotId, |
|||
PBRMasterNode.AlphaThresholdSlotId |
|||
} |
|||
}; |
|||
|
|||
Pass m_PassShadowCaster = new Pass() |
|||
{ |
|||
Name = "ShadowCaster", |
|||
LightMode = "ShadowCaster", |
|||
TemplateName = "HDPBRPass.template", |
|||
ShaderPassName = "SHADERPASS_SHADOWS", |
|||
ColorMaskOverride = "ColorMask 0", |
|||
ExtraDefines = new List<string>() |
|||
{ |
|||
"#define USE_LEGACY_UNITY_MATRIX_VARIABLES", |
|||
}, |
|||
Includes = new List<string>() |
|||
{ |
|||
"#include \"HDRP/ShaderPass/ShaderPassDepthOnly.hlsl\"", |
|||
}, |
|||
RequiredFields = new List<string>() |
|||
{ |
|||
// "FragInputs.worldToTangent",
|
|||
// "FragInputs.positionWS",
|
|||
}, |
|||
PixelShaderSlots = new List<int>() |
|||
{ |
|||
PBRMasterNode.AlphaSlotId, |
|||
PBRMasterNode.AlphaThresholdSlotId |
|||
} |
|||
}; |
|||
|
|||
Pass m_PassDepthOnly = new Pass() |
|||
{ |
|||
Name = "DepthOnly", |
|||
LightMode = "DepthOnly", |
|||
TemplateName = "HDPBRPass.template", |
|||
ShaderPassName = "SHADERPASS_DEPTH_ONLY", |
|||
ColorMaskOverride = "ColorMask 0", |
|||
Includes = new List<string>() |
|||
{ |
|||
"#include \"HDRP/ShaderPass/ShaderPassDepthOnly.hlsl\"", |
|||
}, |
|||
RequiredFields = new List<string>() |
|||
{ |
|||
// "FragInputs.worldToTangent",
|
|||
// "FragInputs.positionWS",
|
|||
}, |
|||
PixelShaderSlots = new List<int>() |
|||
{ |
|||
PBRMasterNode.AlphaSlotId, |
|||
PBRMasterNode.AlphaThresholdSlotId |
|||
} |
|||
}; |
|||
|
|||
Pass m_PassMotionVectors = new Pass() |
|||
{ |
|||
Name = "Motion Vectors", |
|||
LightMode = "MotionVectors", |
|||
TemplateName = "HDPBRPass.template", |
|||
ShaderPassName = "SHADERPASS_VELOCITY", |
|||
Includes = new List<string>() |
|||
{ |
|||
"#include \"HDRP/ShaderPass/ShaderPassVelocity.hlsl\"", |
|||
}, |
|||
RequiredFields = new List<string>() |
|||
{ |
|||
"FragInputs.positionWS", |
|||
}, |
|||
PixelShaderSlots = new List<int>() |
|||
{ |
|||
PBRMasterNode.AlphaSlotId, |
|||
PBRMasterNode.AlphaThresholdSlotId |
|||
}, |
|||
StencilOverride = new List<string>() |
|||
{ |
|||
"// If velocity pass (motion vectors) is enabled we tag the stencil so it don't perform CameraMotionVelocity", |
|||
"Stencil", |
|||
"{", |
|||
" WriteMask 128", // [_StencilWriteMaskMV] (int) HDRenderPipeline.StencilBitMask.ObjectVelocity // this requires us to pull in the HD Pipeline assembly...
|
|||
" Ref 128", // [_StencilRefMV]
|
|||
" Comp Always", |
|||
" Pass Replace", |
|||
"}" |
|||
} |
|||
}; |
|||
|
|||
Pass m_PassDistortion = new Pass() |
|||
{ |
|||
Name = "Distortion", |
|||
LightMode = "DistortionVectors", |
|||
TemplateName = "HDPBRPass.template", |
|||
ShaderPassName = "SHADERPASS_DISTORTION", |
|||
BlendOverride = "Blend One One, One One", // [_DistortionSrcBlend] [_DistortionDstBlend], [_DistortionBlurSrcBlend] [_DistortionBlurDstBlend]
|
|||
BlendOpOverride = "BlendOp Add, Add", // Add, [_DistortionBlurBlendOp]
|
|||
ZTestOverride = "ZTest LEqual", // [_ZTestModeDistortion]
|
|||
ZWriteOverride = "ZWrite Off", |
|||
Includes = new List<string>() |
|||
{ |
|||
"#include \"HDRP/ShaderPass/ShaderPassDistortion.hlsl\"", |
|||
}, |
|||
RequiredFields = new List<string>() |
|||
{ |
|||
// "FragInputs.worldToTangent",
|
|||
// "FragInputs.positionWS",
|
|||
}, |
|||
PixelShaderSlots = new List<int>() |
|||
{ |
|||
PBRMasterNode.AlphaSlotId, |
|||
PBRMasterNode.AlphaThresholdSlotId |
|||
} |
|||
}; |
|||
|
|||
Pass m_PassTransparentDepthPrepass = new Pass() |
|||
{ |
|||
Name = "TransparentDepthPrepass", |
|||
LightMode = "TransparentDepthPrepass", |
|||
TemplateName = "HDPBRPass.template", |
|||
ShaderPassName = "SHADERPASS_DEPTH_ONLY", |
|||
ColorMaskOverride = "ColorMask 0", |
|||
ExtraDefines = new List<string>() |
|||
{ |
|||
"#define CUTOFF_TRANSPARENT_DEPTH_PREPASS", |
|||
}, |
|||
Includes = new List<string>() |
|||
{ |
|||
"#include \"HDRP/ShaderPass/ShaderPassDepthOnly.hlsl\"", |
|||
}, |
|||
RequiredFields = new List<string>() |
|||
{ |
|||
// "FragInputs.worldToTangent",
|
|||
// "FragInputs.positionWS",
|
|||
}, |
|||
PixelShaderSlots = new List<int>() |
|||
{ |
|||
PBRMasterNode.AlphaSlotId, |
|||
PBRMasterNode.AlphaThresholdSlotId |
|||
} |
|||
}; |
|||
|
|||
Pass m_PassTransparentBackface = new Pass() |
|||
{ |
|||
Name = "TransparentBackface", |
|||
LightMode = "TransparentBackface", |
|||
TemplateName = "HDPBRPass.template", |
|||
ShaderPassName = "SHADERPASS_FORWARD", |
|||
CullOverride = "Cull Front", |
|||
ExtraDefines = new List<string>() |
|||
{ |
|||
"#pragma multi_compile _ DEBUG_DISPLAY", |
|||
"#pragma multi_compile _ LIGHTMAP_ON", |
|||
"#pragma multi_compile _ DIRLIGHTMAP_COMBINED", |
|||
"#pragma multi_compile _ DYNAMICLIGHTMAP_ON", |
|||
"#pragma multi_compile _ SHADOWS_SHADOWMASK", |
|||
"#pragma multi_compile LIGHTLOOP_SINGLE_PASS LIGHTLOOP_TILE_PASS", |
|||
"#pragma multi_compile USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST", |
|||
}, |
|||
Includes = new List<string>() |
|||
{ |
|||
"#include \"HDRP/ShaderPass/ShaderPassForward.hlsl\"", |
|||
}, |
|||
RequiredFields = new List<string>() |
|||
{ |
|||
// "FragInputs.worldToTangent",
|
|||
// "FragInputs.positionWS",
|
|||
}, |
|||
PixelShaderSlots = new List<int>() |
|||
{ |
|||
PBRMasterNode.AlbedoSlotId, |
|||
PBRMasterNode.NormalSlotId, |
|||
PBRMasterNode.MetallicSlotId, |
|||
PBRMasterNode.SpecularSlotId, |
|||
PBRMasterNode.EmissionSlotId, |
|||
PBRMasterNode.SmoothnessSlotId, |
|||
PBRMasterNode.OcclusionSlotId, |
|||
PBRMasterNode.AlphaSlotId, |
|||
PBRMasterNode.AlphaThresholdSlotId |
|||
} |
|||
}; |
|||
|
|||
Pass m_PassForward = new Pass() |
|||
{ |
|||
Name = "Forward", |
|||
LightMode = "Forward", |
|||
TemplateName = "HDPBRPass.template", |
|||
ShaderPassName = "SHADERPASS_FORWARD", |
|||
ExtraDefines = new List<string>() |
|||
{ |
|||
"#pragma multi_compile _ DEBUG_DISPLAY", |
|||
"#pragma multi_compile _ LIGHTMAP_ON", |
|||
"#pragma multi_compile _ DIRLIGHTMAP_COMBINED", |
|||
"#pragma multi_compile _ DYNAMICLIGHTMAP_ON", |
|||
"#pragma multi_compile _ SHADOWS_SHADOWMASK", |
|||
"#pragma multi_compile LIGHTLOOP_SINGLE_PASS LIGHTLOOP_TILE_PASS", |
|||
"#pragma multi_compile USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST" |
|||
}, |
|||
StencilOverride = new List<string>() |
|||
{ |
|||
"// Stencil setup for forward", |
|||
"Stencil", |
|||
"{", |
|||
" WriteMask 7", // [_StencilWriteMask] // default: StencilMask.Lighting (fixed at compile time)
|
|||
" Ref 2", // [_StencilRef] // default: StencilLightingUsage.RegularLighting (fixed at compile time)
|
|||
" Comp Always", |
|||
" Pass Replace", |
|||
"}" |
|||
}, |
|||
Includes = new List<string>() |
|||
{ |
|||
"#include \"HDRP/ShaderPass/ShaderPassForward.hlsl\"", |
|||
}, |
|||
RequiredFields = new List<string>() |
|||
{ |
|||
"FragInputs.worldToTangent", |
|||
// "FragInputs.positionWS",
|
|||
}, |
|||
PixelShaderSlots = new List<int>() |
|||
{ |
|||
PBRMasterNode.AlbedoSlotId, |
|||
PBRMasterNode.NormalSlotId, |
|||
PBRMasterNode.MetallicSlotId, |
|||
PBRMasterNode.SpecularSlotId, |
|||
PBRMasterNode.EmissionSlotId, |
|||
PBRMasterNode.SmoothnessSlotId, |
|||
PBRMasterNode.OcclusionSlotId, |
|||
PBRMasterNode.AlphaSlotId, |
|||
PBRMasterNode.AlphaThresholdSlotId |
|||
} |
|||
}; |
|||
|
|||
Pass m_PassTransparentDepthPostpass = new Pass() |
|||
{ |
|||
Name = "TransparentDepthPostpass", |
|||
LightMode = "TransparentDepthPostpass", |
|||
TemplateName = "HDPBRPass.template", |
|||
ShaderPassName = "SHADERPASS_DEPTH_ONLY", |
|||
ColorMaskOverride = "ColorMask 0", |
|||
ExtraDefines = new List<string>() |
|||
{ |
|||
"#define CUTOFF_TRANSPARENT_DEPTH_POSTPASS", |
|||
}, |
|||
Includes = new List<string>() |
|||
{ |
|||
"#include \"HDRP/ShaderPass/ShaderPassDepthOnly.hlsl\"", |
|||
}, |
|||
RequiredFields = new List<string>() |
|||
{ |
|||
// "FragInputs.worldToTangent",
|
|||
// "FragInputs.positionWS",
|
|||
}, |
|||
PixelShaderSlots = new List<int>() |
|||
{ |
|||
PBRMasterNode.AlphaSlotId, |
|||
PBRMasterNode.AlphaThresholdSlotId |
|||
} |
|||
}; |
|||
|
|||
private static string GetVariantDefines(PBRMasterNode masterNode) |
|||
{ |
|||
ShaderGenerator defines = new ShaderGenerator(); |
|||
|
|||
// TODO:
|
|||
// _MATERIAL_FEATURE_SUBSURFACE_SCATTERING
|
|||
// _MATERIAL_FEATURE_TRANSMISSION
|
|||
// _MATERIAL_FEATURE_ANISOTROPY
|
|||
// _MATERIAL_FEATURE_CLEAR_COAT
|
|||
// _MATERIAL_FEATURE_IRIDESCENCE
|
|||
|
|||
switch (masterNode.model) |
|||
{ |
|||
case PBRMasterNode.Model.Metallic: |
|||
break; |
|||
case PBRMasterNode.Model.Specular: |
|||
defines.AddShaderChunk("#define _MATERIAL_FEATURE_SPECULAR_COLOR 1", true); |
|||
break; |
|||
default: |
|||
// TODO: error!
|
|||
break; |
|||
} |
|||
|
|||
// #pragma shader_feature _ALPHATEST_ON
|
|||
float constantAlpha = 0.0f; |
|||
if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId) || |
|||
(float.TryParse(masterNode.GetSlotValue(PBRMasterNode.AlphaThresholdSlotId, GenerationMode.ForReals), out constantAlpha) && (constantAlpha > 0.0f))) |
|||
{ |
|||
defines.AddShaderChunk("#define _ALPHATEST_ON 1", true); |
|||
} |
|||
|
|||
// if (kTesselationMode != TessellationMode.None)
|
|||
// {
|
|||
// defines.AddShaderChunk("#define _TESSELLATION_PHONG 1", true);
|
|||
// }
|
|||
|
|||
// #pragma shader_feature _ _VERTEX_DISPLACEMENT _PIXEL_DISPLACEMENT
|
|||
// switch (kDisplacementMode)
|
|||
// {
|
|||
// case DisplacementMode.None:
|
|||
// break;
|
|||
// case DisplacementMode.Vertex:
|
|||
// defines.AddShaderChunk("#define _VERTEX_DISPLACEMENT 1", true);
|
|||
// break;
|
|||
// case DisplacementMode.Pixel:
|
|||
// defines.AddShaderChunk("#define _PIXEL_DISPLACEMENT 1", true);
|
|||
// Depth offset is only enabled if per pixel displacement is
|
|||
// if (kDepthOffsetEnable)
|
|||
// {
|
|||
// // #pragma shader_feature _DEPTHOFFSET_ON
|
|||
// defines.AddShaderChunk("#define _DEPTHOFFSET_ON 1", true);
|
|||
// }
|
|||
// break;
|
|||
// case DisplacementMode.Tessellation:
|
|||
// if (kTessellationEnabled)
|
|||
// {
|
|||
// defines.AddShaderChunk("#define _TESSELLATION_DISPLACEMENT 1", true);
|
|||
// }
|
|||
// break;
|
|||
// }
|
|||
|
|||
// #pragma shader_feature _VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE
|
|||
// #pragma shader_feature _DISPLACEMENT_LOCK_TILING_SCALE
|
|||
// #pragma shader_feature _PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE
|
|||
// #pragma shader_feature _VERTEX_WIND
|
|||
// #pragma shader_feature _ _REFRACTION_PLANE _REFRACTION_SPHERE
|
|||
//
|
|||
// #pragma shader_feature _ _MAPPING_PLANAR _MAPPING_TRIPLANAR // MOVE to a node
|
|||
// #pragma shader_feature _NORMALMAP_TANGENT_SPACE
|
|||
// #pragma shader_feature _ _REQUIRE_UV2 _REQUIRE_UV3
|
|||
//
|
|||
// #pragma shader_feature _NORMALMAP
|
|||
if (masterNode.IsSlotConnected(PBRMasterNode.NormalSlotId)) |
|||
{ |
|||
defines.AddShaderChunk("#define _NORMALMAP 1", true); |
|||
} |
|||
|
|||
// #pragma shader_feature _MASKMAP
|
|||
// #pragma shader_feature _BENTNORMALMAP
|
|||
// #pragma shader_feature _EMISSIVE_COLOR_MAP
|
|||
// #pragma shader_feature _ENABLESPECULAROCCLUSION
|
|||
// #pragma shader_feature _HEIGHTMAP
|
|||
// #pragma shader_feature _TANGENTMAP
|
|||
// #pragma shader_feature _ANISOTROPYMAP
|
|||
// #pragma shader_feature _DETAIL_MAP // MOVE to a node
|
|||
// #pragma shader_feature _SUBSURFACE_RADIUS_MAP
|
|||
// #pragma shader_feature _THICKNESSMAP
|
|||
// #pragma shader_feature _SPECULARCOLORMAP
|
|||
// #pragma shader_feature _TRANSMITTANCECOLORMAP
|
|||
|
|||
// Keywords for transparent
|
|||
// #pragma shader_feature _SURFACE_TYPE_TRANSPARENT
|
|||
if (masterNode.surfaceType != SurfaceType.Opaque) |
|||
{ |
|||
// transparent-only defines
|
|||
defines.AddShaderChunk("#define _SURFACE_TYPE_TRANSPARENT 1", true); |
|||
|
|||
// #pragma shader_feature _ _BLENDMODE_ALPHA _BLENDMODE_ADD _BLENDMODE_PRE_MULTIPLY
|
|||
if (masterNode.alphaMode == AlphaMode.Alpha) |
|||
{ |
|||
defines.AddShaderChunk("#define _BLENDMODE_ALPHA 1", true); |
|||
} |
|||
else if (masterNode.alphaMode == AlphaMode.Additive) |
|||
{ |
|||
defines.AddShaderChunk("#define _BLENDMODE_ADD 1", true); |
|||
} |
|||
// else if (masterNode.alphaMode == PBRMasterNode.AlphaMode.PremultiplyAlpha) // TODO
|
|||
// {
|
|||
// defines.AddShaderChunk("#define _BLENDMODE_PRE_MULTIPLY 1", true);
|
|||
// }
|
|||
|
|||
// #pragma shader_feature _BLENDMODE_PRESERVE_SPECULAR_LIGHTING
|
|||
// if (kEnableBlendModePreserveSpecularLighting)
|
|||
// {
|
|||
// defines.AddShaderChunk("#define _BLENDMODE_PRESERVE_SPECULAR_LIGHTING 1", true);
|
|||
// }
|
|||
|
|||
// #pragma shader_feature _ENABLE_FOG_ON_TRANSPARENT
|
|||
// if (kEnableFogOnTransparent)
|
|||
// {
|
|||
// defines.AddShaderChunk("#define _ENABLE_FOG_ON_TRANSPARENT 1", true);
|
|||
// }
|
|||
} |
|||
else |
|||
{ |
|||
// opaque-only defines
|
|||
} |
|||
|
|||
// MaterialId are used as shader feature to allow compiler to optimize properly
|
|||
// Note _MATID_STANDARD is not define as there is always the default case "_". We assign default as _MATID_STANDARD, so we never test _MATID_STANDARD
|
|||
// #pragma shader_feature _ _MATID_SSS _MATID_ANISO _MATID_SPECULAR _MATID_CLEARCOAT
|
|||
|
|||
// enable dithering LOD crossfade
|
|||
// #pragma multi_compile _ LOD_FADE_CROSSFADE
|
|||
// TODO: We should have this keyword only if VelocityInGBuffer is enable, how to do that ?
|
|||
//#pragma multi_compile VELOCITYOUTPUT_OFF VELOCITYOUTPUT_ON
|
|||
|
|||
return defines.GetShaderString(2); |
|||
} |
|||
|
|||
private static bool GenerateShaderPass(PBRMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions, ShaderGenerator result) |
|||
{ |
|||
var templateLocation = ShaderGenerator.GetTemplatePath(pass.TemplateName); |
|||
if (!File.Exists(templateLocation)) |
|||
{ |
|||
// TODO: produce error here
|
|||
return false; |
|||
} |
|||
|
|||
// grab all of the active nodes
|
|||
var activeNodeList = ListPool<INode>.Get(); |
|||
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots); |
|||
|
|||
// graph requirements describe what the graph itself requires
|
|||
var graphRequirements = ShaderGraphRequirements.FromNodes(activeNodeList, ShaderStageCapability.Fragment); |
|||
|
|||
ShaderStringBuilder graphNodeFunctions = new ShaderStringBuilder(); |
|||
graphNodeFunctions.IncreaseIndent(); |
|||
var functionRegistry = new FunctionRegistry(graphNodeFunctions); |
|||
|
|||
// Build the list of active slots based on what the pass requires
|
|||
// TODO: this can be a shared function -- From here through GraphUtil.GenerateSurfaceDescription(..)
|
|||
var activeSlots = new List<MaterialSlot>(); |
|||
foreach (var id in pass.PixelShaderSlots) |
|||
{ |
|||
MaterialSlot slot = masterNode.FindSlot<MaterialSlot>(id); |
|||
if (slot != null) |
|||
{ |
|||
activeSlots.Add(slot); |
|||
} |
|||
} |
|||
|
|||
// build the graph outputs structure to hold the results of each active slots (and fill out activeFields to indicate they are active)
|
|||
string graphInputStructName = "SurfaceDescriptionInputs"; |
|||
string graphOutputStructName = "SurfaceDescription"; |
|||
string graphEvalFunctionName = "SurfaceDescriptionFunction"; |
|||
ShaderStringBuilder graphEvalFunction = new ShaderStringBuilder(); |
|||
ShaderStringBuilder graphOutputs = new ShaderStringBuilder(); |
|||
PropertyCollector graphProperties = new PropertyCollector(); |
|||
|
|||
// build the graph outputs structure, and populate activeFields with the fields of that structure
|
|||
HashSet<string> activeFields = new HashSet<string>(); |
|||
GraphUtil.GenerateSurfaceDescriptionStruct(graphOutputs, activeSlots, true); |
|||
//GraphUtil.GenerateSurfaceDescriptionStruct(graphOutputs, activeSlots, true, graphOutputStructName, activeFields);
|
|||
|
|||
// Build the graph evaluation code, to evaluate the specified slots
|
|||
GraphUtil.GenerateSurfaceDescriptionFunction( |
|||
activeNodeList, |
|||
masterNode, |
|||
masterNode.owner as AbstractMaterialGraph, |
|||
graphEvalFunction, |
|||
functionRegistry, |
|||
graphProperties, |
|||
graphRequirements, // TODO : REMOVE UNUSED
|
|||
mode, |
|||
graphEvalFunctionName, |
|||
graphOutputStructName, |
|||
null, |
|||
activeSlots, |
|||
graphInputStructName); |
|||
|
|||
var blendCode = new ShaderStringBuilder(); |
|||
var cullCode = new ShaderStringBuilder(); |
|||
var zTestCode = new ShaderStringBuilder(); |
|||
var zWriteCode = new ShaderStringBuilder(); |
|||
var stencilCode = new ShaderStringBuilder(); |
|||
var colorMaskCode = new ShaderStringBuilder(); |
|||
HDSubShaderUtilities.BuildRenderStatesFromPassAndMaterialOptions(pass, materialOptions, blendCode, cullCode, zTestCode, zWriteCode, stencilCode, colorMaskCode); |
|||
|
|||
if (masterNode.twoSided.isOn) |
|||
{ |
|||
activeFields.Add("DoubleSided"); |
|||
if (pass.ShaderPassName != "SHADERPASS_VELOCITY") // HACK to get around lack of a good interpolator dependency system
|
|||
{ // we need to be able to build interpolators using multiple input structs
|
|||
// also: should only require isFrontFace if Normals are required...
|
|||
activeFields.Add("DoubleSided.Mirror"); // TODO: change this depending on what kind of normal flip you want..
|
|||
activeFields.Add("FragInputs.isFrontFace"); // will need this for determining normal flip mode
|
|||
} |
|||
} |
|||
|
|||
if (pass.PixelShaderSlots != null) |
|||
{ |
|||
foreach (var slotId in pass.PixelShaderSlots) |
|||
{ |
|||
var slot = masterNode.FindSlot<MaterialSlot>(slotId); |
|||
if(slot != null) |
|||
{ |
|||
var rawSlotName = slot.RawDisplayName().ToString(); |
|||
var descriptionVar = string.Format("{0}.{1}", graphOutputStructName, rawSlotName); |
|||
activeFields.Add(descriptionVar); |
|||
} |
|||
} |
|||
} |
|||
|
|||
var packedInterpolatorCode = new ShaderGenerator(); |
|||
var graphInputs = new ShaderGenerator(); |
|||
HDRPShaderStructs.Generate( |
|||
packedInterpolatorCode, |
|||
graphInputs, |
|||
graphRequirements, |
|||
pass.RequiredFields, |
|||
CoordinateSpace.World, |
|||
activeFields); |
|||
|
|||
// debug output all active fields
|
|||
var interpolatorDefines = new ShaderGenerator(); |
|||
{ |
|||
interpolatorDefines.AddShaderChunk("// ACTIVE FIELDS:"); |
|||
foreach (string f in activeFields) |
|||
{ |
|||
interpolatorDefines.AddShaderChunk("// " + f); |
|||
} |
|||
} |
|||
|
|||
ShaderGenerator defines = new ShaderGenerator(); |
|||
{ |
|||
defines.AddShaderChunk(string.Format("#define SHADERPASS {0}", pass.ShaderPassName), true); |
|||
if (pass.ExtraDefines != null) |
|||
{ |
|||
foreach (var define in pass.ExtraDefines) |
|||
defines.AddShaderChunk(define); |
|||
} |
|||
defines.AddGenerator(interpolatorDefines); |
|||
} |
|||
|
|||
var shaderPassIncludes = new ShaderGenerator(); |
|||
if (pass.Includes != null) |
|||
{ |
|||
foreach (var include in pass.Includes) |
|||
shaderPassIncludes.AddShaderChunk(include); |
|||
} |
|||
|
|||
|
|||
// build graph code
|
|||
var graph = new ShaderGenerator(); |
|||
graph.AddShaderChunk("// Graph Inputs"); |
|||
graph.Indent(); |
|||
graph.AddGenerator(graphInputs); |
|||
graph.Deindent(); |
|||
graph.AddShaderChunk("// Graph Outputs"); |
|||
graph.Indent(); |
|||
graph.AddShaderChunk(graphOutputs.ToString()); |
|||
//graph.AddGenerator(graphOutputs);
|
|||
graph.Deindent(); |
|||
graph.AddShaderChunk("// Graph Properties (uniform inputs)"); |
|||
graph.AddShaderChunk(graphProperties.GetPropertiesDeclaration(1)); |
|||
graph.AddShaderChunk("// Graph Node Functions"); |
|||
graph.AddShaderChunk(graphNodeFunctions.ToString()); |
|||
graph.AddShaderChunk("// Graph Evaluation"); |
|||
graph.Indent(); |
|||
graph.AddShaderChunk(graphEvalFunction.ToString()); |
|||
//graph.AddGenerator(graphEvalFunction);
|
|||
graph.Deindent(); |
|||
|
|||
// build the hash table of all named fragments TODO: could make this Dictionary<string, ShaderGenerator / string> ?
|
|||
Dictionary<string, string> namedFragments = new Dictionary<string, string>(); |
|||
namedFragments.Add("${Defines}", defines.GetShaderString(2, false)); |
|||
namedFragments.Add("${Graph}", graph.GetShaderString(2, false)); |
|||
namedFragments.Add("${LightMode}", pass.LightMode); |
|||
namedFragments.Add("${PassName}", pass.Name); |
|||
namedFragments.Add("${Includes}", shaderPassIncludes.GetShaderString(2, false)); |
|||
namedFragments.Add("${InterpolatorPacking}", packedInterpolatorCode.GetShaderString(2, false)); |
|||
namedFragments.Add("${Blending}", blendCode.ToString()); |
|||
namedFragments.Add("${Culling}", cullCode.ToString()); |
|||
namedFragments.Add("${ZTest}", zTestCode.ToString()); |
|||
namedFragments.Add("${ZWrite}", zWriteCode.ToString()); |
|||
namedFragments.Add("${Stencil}", stencilCode.ToString()); |
|||
namedFragments.Add("${ColorMask}", colorMaskCode.ToString()); |
|||
namedFragments.Add("${LOD}", materialOptions.lod.ToString()); |
|||
namedFragments.Add("${VariantDefines}", GetVariantDefines(masterNode)); |
|||
|
|||
// process the template to generate the shader code for this pass TODO: could make this a shared function
|
|||
string[] templateLines = File.ReadAllLines(templateLocation); |
|||
System.Text.StringBuilder builder = new System.Text.StringBuilder(); |
|||
foreach (string line in templateLines) |
|||
{ |
|||
ShaderSpliceUtil.PreprocessShaderCode(line, activeFields, namedFragments, builder); |
|||
builder.AppendLine(); |
|||
} |
|||
|
|||
result.AddShaderChunk(builder.ToString(), false); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
public string GetSubshader(IMasterNode iMasterNode, GenerationMode mode) |
|||
{ |
|||
var masterNode = iMasterNode as PBRMasterNode; |
|||
var subShader = new ShaderGenerator(); |
|||
subShader.AddShaderChunk("SubShader", true); |
|||
subShader.AddShaderChunk("{", true); |
|||
subShader.Indent(); |
|||
{ |
|||
SurfaceMaterialOptions materialOptions = HDSubShaderUtilities.BuildMaterialOptions(masterNode.surfaceType, masterNode.alphaMode, masterNode.twoSided.isOn); |
|||
|
|||
// Add tags at the SubShader level
|
|||
{ |
|||
var tagsVisitor = new ShaderStringBuilder(); |
|||
materialOptions.GetTags(tagsVisitor); |
|||
subShader.AddShaderChunk(tagsVisitor.ToString(), false); |
|||
} |
|||
|
|||
// generate the necessary shader passes
|
|||
bool opaque = (masterNode.surfaceType == SurfaceType.Opaque); |
|||
bool transparent = (masterNode.surfaceType != SurfaceType.Opaque); |
|||
bool distortionActive = false; |
|||
bool transparentDepthPrepassActive = transparent && false; |
|||
bool transparentBackfaceActive = transparent && false; |
|||
bool transparentDepthPostpassActive = transparent && false; |
|||
|
|||
if (opaque) |
|||
{ |
|||
GenerateShaderPass(masterNode, m_PassGBuffer, mode, materialOptions, subShader); |
|||
GenerateShaderPass(masterNode, m_PassGBufferWithPrepass, mode, materialOptions, subShader); |
|||
} |
|||
|
|||
GenerateShaderPass(masterNode, m_PassMETA, mode, materialOptions, subShader); |
|||
GenerateShaderPass(masterNode, m_PassShadowCaster, mode, materialOptions, subShader); |
|||
|
|||
if (opaque) |
|||
{ |
|||
GenerateShaderPass(masterNode, m_PassDepthOnly, mode, materialOptions, subShader); |
|||
GenerateShaderPass(masterNode, m_PassMotionVectors, mode, materialOptions, subShader); |
|||
} |
|||
|
|||
if (distortionActive) |
|||
{ |
|||
GenerateShaderPass(masterNode, m_PassDistortion, mode, materialOptions, subShader); |
|||
} |
|||
|
|||
if (transparentDepthPrepassActive) |
|||
{ |
|||
GenerateShaderPass(masterNode, m_PassTransparentDepthPrepass, mode, materialOptions, subShader); |
|||
} |
|||
|
|||
if (transparentBackfaceActive) |
|||
{ |
|||
GenerateShaderPass(masterNode, m_PassTransparentBackface, mode, materialOptions, subShader); |
|||
} |
|||
|
|||
GenerateShaderPass(masterNode, m_PassForward, mode, materialOptions, subShader); |
|||
|
|||
if (transparentDepthPostpassActive) |
|||
{ |
|||
GenerateShaderPass(masterNode, m_PassTransparentDepthPostpass, mode, materialOptions, subShader); |
|||
} |
|||
} |
|||
subShader.Deindent(); |
|||
subShader.AddShaderChunk("}", true); |
|||
|
|||
return subShader.GetShaderString(0); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: c4e8610eb7ce19747bb637c68acc55cd |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using UnityEditor.Graphing; |
|||
using UnityEngine; // Vector3,4
|
|||
using UnityEditor.ShaderGraph; |
|||
|
|||
namespace UnityEditor.ShaderGraph |
|||
{ |
|||
public static class HDRPShaderStructs |
|||
{ |
|||
struct AttributesMesh |
|||
{ |
|||
[Semantic("POSITION")] Vector3 positionOS; |
|||
[Semantic("NORMAL")][Optional] Vector3 normalOS; |
|||
[Semantic("TANGENT")][Optional] Vector4 tangentOS; // Stores bi-tangent sign in w
|
|||
[Semantic("TEXCOORD0")][Optional] Vector2 uv0; |
|||
[Semantic("TEXCOORD1")][Optional] Vector2 uv1; |
|||
[Semantic("TEXCOORD2")][Optional] Vector2 uv2; |
|||
[Semantic("TEXCOORD3")][Optional] Vector2 uv3; |
|||
[Semantic("COLOR")][Optional] Vector4 color; |
|||
}; |
|||
|
|||
struct VaryingsMeshToPS |
|||
{ |
|||
[Semantic("SV_Position")] Vector4 positionCS; |
|||
[Optional] Vector3 positionWS; |
|||
[Optional] Vector3 normalWS; |
|||
[Optional] Vector4 tangentWS; // w contain mirror sign
|
|||
[Optional] Vector2 texCoord0; |
|||
[Optional] Vector2 texCoord1; |
|||
[Optional] Vector2 texCoord2; |
|||
[Optional] Vector2 texCoord3; |
|||
[Optional] Vector4 color; |
|||
[Optional] [Semantic("FRONT_FACE_SEMANTIC")] [OverrideType("FRONT_FACE_TYPE")] [PreprocessorIf("SHADER_STAGE_FRAGMENT")] |
|||
bool cullFace; |
|||
|
|||
public static Dependency[] tessellationDependencies = new Dependency[] |
|||
{ |
|||
new Dependency("VaryingsMeshToPS.positionWS", "VaryingsMeshToDS.positionWS"), |
|||
new Dependency("VaryingsMeshToPS.normalWS", "VaryingsMeshToDS.normalWS"), |
|||
new Dependency("VaryingsMeshToPS.tangentWS", "VaryingsMeshToDS.tangentWS"), |
|||
new Dependency("VaryingsMeshToPS.texCoord0", "VaryingsMeshToDS.texCoord0"), |
|||
new Dependency("VaryingsMeshToPS.texCoord1", "VaryingsMeshToDS.texCoord1"), |
|||
new Dependency("VaryingsMeshToPS.texCoord2", "VaryingsMeshToDS.texCoord2"), |
|||
new Dependency("VaryingsMeshToPS.texCoord3", "VaryingsMeshToDS.texCoord3"), |
|||
new Dependency("VaryingsMeshToPS.color", "VaryingsMeshToDS.color"), |
|||
}; |
|||
|
|||
public static Dependency[] standardDependencies = new Dependency[] |
|||
{ |
|||
new Dependency("VaryingsMeshToPS.positionWS", "AttributesMesh.positionOS"), |
|||
new Dependency("VaryingsMeshToPS.normalWS", "AttributesMesh.normalOS"), |
|||
new Dependency("VaryingsMeshToPS.tangentWS", "AttributesMesh.tangentOS"), |
|||
new Dependency("VaryingsMeshToPS.texCoord0", "AttributesMesh.uv0"), |
|||
new Dependency("VaryingsMeshToPS.texCoord1", "AttributesMesh.uv1"), |
|||
new Dependency("VaryingsMeshToPS.texCoord2", "AttributesMesh.uv2"), |
|||
new Dependency("VaryingsMeshToPS.texCoord3", "AttributesMesh.uv3"), |
|||
new Dependency("VaryingsMeshToPS.color", "AttributesMesh.color"), |
|||
}; |
|||
}; |
|||
|
|||
struct VaryingsMeshToDS |
|||
{ |
|||
Vector3 positionWS; |
|||
Vector3 normalWS; |
|||
[Optional] Vector4 tangentWS; |
|||
[Optional] Vector2 texCoord0; |
|||
[Optional] Vector2 texCoord1; |
|||
[Optional] Vector2 texCoord2; |
|||
[Optional] Vector2 texCoord3; |
|||
[Optional] Vector4 color; |
|||
|
|||
public static Dependency[] tessellationDependencies = new Dependency[] |
|||
{ |
|||
new Dependency("VaryingsMeshToDS.tangentWS", "VaryingsMeshToPS.tangentWS"), |
|||
new Dependency("VaryingsMeshToDS.texCoord0", "VaryingsMeshToPS.texCoord0"), |
|||
new Dependency("VaryingsMeshToDS.texCoord1", "VaryingsMeshToPS.texCoord1"), |
|||
new Dependency("VaryingsMeshToDS.texCoord2", "VaryingsMeshToPS.texCoord2"), |
|||
new Dependency("VaryingsMeshToDS.texCoord3", "VaryingsMeshToPS.texCoord3"), |
|||
new Dependency("VaryingsMeshToDS.color", "VaryingsMeshToPS.color"), |
|||
}; |
|||
}; |
|||
|
|||
struct FragInputs |
|||
{ |
|||
public static Dependency[] dependencies = new Dependency[] |
|||
{ |
|||
new Dependency("FragInputs.positionWS", "VaryingsMeshToPS.positionWS"), |
|||
new Dependency("FragInputs.worldToTangent", "VaryingsMeshToPS.tangentWS"), |
|||
new Dependency("FragInputs.worldToTangent", "VaryingsMeshToPS.normalWS"), |
|||
new Dependency("FragInputs.texCoord0", "VaryingsMeshToPS.texCoord0"), |
|||
new Dependency("FragInputs.texCoord1", "VaryingsMeshToPS.texCoord1"), |
|||
new Dependency("FragInputs.texCoord2", "VaryingsMeshToPS.texCoord2"), |
|||
new Dependency("FragInputs.texCoord3", "VaryingsMeshToPS.texCoord3"), |
|||
new Dependency("FragInputs.color", "VaryingsMeshToPS.color"), |
|||
new Dependency("FragInputs.isFrontFace", "VaryingsMeshToPS.cullFace"), |
|||
}; |
|||
}; |
|||
|
|||
struct SurfaceDescriptionInputs |
|||
{ |
|||
[Optional] Vector3 ObjectSpaceNormal; |
|||
[Optional] Vector3 ViewSpaceNormal; |
|||
[Optional] Vector3 WorldSpaceNormal; |
|||
[Optional] Vector3 TangentSpaceNormal; |
|||
|
|||
[Optional] Vector3 ObjectSpaceTangent; |
|||
[Optional] Vector3 ViewSpaceTangent; |
|||
[Optional] Vector3 WorldSpaceTangent; |
|||
[Optional] Vector3 TangentSpaceTangent; |
|||
|
|||
[Optional] Vector3 ObjectSpaceBiTangent; |
|||
[Optional] Vector3 ViewSpaceBiTangent; |
|||
[Optional] Vector3 WorldSpaceBiTangent; |
|||
[Optional] Vector3 TangentSpaceBiTangent; |
|||
|
|||
[Optional] Vector3 ObjectSpaceViewDirection; |
|||
[Optional] Vector3 ViewSpaceViewDirection; |
|||
[Optional] Vector3 WorldSpaceViewDirection; |
|||
[Optional] Vector3 TangentSpaceViewDirection; |
|||
|
|||
[Optional] Vector3 ObjectSpacePosition; |
|||
[Optional] Vector3 ViewSpacePosition; |
|||
[Optional] Vector3 WorldSpacePosition; |
|||
[Optional] Vector3 TangentSpacePosition; |
|||
|
|||
[Optional] Vector4 screenPosition; |
|||
[Optional] Vector4 uv0; |
|||
[Optional] Vector4 uv1; |
|||
[Optional] Vector4 uv2; |
|||
[Optional] Vector4 uv3; |
|||
[Optional] Vector4 vertexColor; |
|||
|
|||
public static Dependency[] dependencies = new Dependency[] |
|||
{ |
|||
new Dependency("SurfaceDescriptionInputs.WorldSpaceNormal", "FragInputs.worldToTangent"), |
|||
new Dependency("SurfaceDescriptionInputs.ObjectSpaceNormal", "SurfaceDescriptionInputs.WorldSpaceNormal"), |
|||
new Dependency("SurfaceDescriptionInputs.ViewSpaceNormal", "SurfaceDescriptionInputs.WorldSpaceNormal"), |
|||
|
|||
new Dependency("SurfaceDescriptionInputs.WorldSpaceTangent", "FragInputs.worldToTangent"), |
|||
new Dependency("SurfaceDescriptionInputs.ObjectSpaceTangent", "SurfaceDescriptionInputs.WorldSpaceTangent"), |
|||
new Dependency("SurfaceDescriptionInputs.ViewSpaceTangent", "SurfaceDescriptionInputs.WorldSpaceTangent"), |
|||
|
|||
new Dependency("SurfaceDescriptionInputs.WorldSpaceBiTangent", "FragInputs.worldToTangent"), |
|||
new Dependency("SurfaceDescriptionInputs.ObjectSpaceBiTangent", "SurfaceDescriptionInputs.WorldSpaceBiTangent"), |
|||
new Dependency("SurfaceDescriptionInputs.ViewSpaceBiTangent", "SurfaceDescriptionInputs.WorldSpaceBiTangent"), |
|||
|
|||
new Dependency("SurfaceDescriptionInputs.WorldSpacePosition", "FragInputs.positionWS"), |
|||
new Dependency("SurfaceDescriptionInputs.ObjectSpacePosition", "FragInputs.positionWS"), |
|||
new Dependency("SurfaceDescriptionInputs.ViewSpacePosition", "FragInputs.positionWS"), |
|||
|
|||
new Dependency("SurfaceDescriptionInputs.WorldSpaceViewDirection", "FragInputs.positionWS"), // we build WorldSpaceViewDirection using FragInputs.positionWS in GetWorldSpaceNormalizeViewDir()
|
|||
new Dependency("SurfaceDescriptionInputs.ObjectSpaceViewDirection", "SurfaceDescriptionInputs.WorldSpaceViewDirection"), |
|||
new Dependency("SurfaceDescriptionInputs.ViewSpaceViewDirection", "SurfaceDescriptionInputs.WorldSpaceViewDirection"), |
|||
new Dependency("SurfaceDescriptionInputs.TangentSpaceViewDirection", "SurfaceDescriptionInputs.WorldSpaceViewDirection"), |
|||
new Dependency("SurfaceDescriptionInputs.TangentSpaceViewDirection", "SurfaceDescriptionInputs.WorldSpaceTangent"), |
|||
new Dependency("SurfaceDescriptionInputs.TangentSpaceViewDirection", "SurfaceDescriptionInputs.WorldSpaceBiTangent"), |
|||
new Dependency("SurfaceDescriptionInputs.TangentSpaceViewDirection", "SurfaceDescriptionInputs.WorldSpaceNormal"), |
|||
|
|||
new Dependency("SurfaceDescriptionInputs.screenPosition", "FragInputs.positionSS"), |
|||
new Dependency("SurfaceDescriptionInputs.uv0", "FragInputs.texCoord0"), |
|||
new Dependency("SurfaceDescriptionInputs.uv1", "FragInputs.texCoord1"), |
|||
new Dependency("SurfaceDescriptionInputs.uv2", "FragInputs.texCoord2"), |
|||
new Dependency("SurfaceDescriptionInputs.uv3", "FragInputs.texCoord3"), |
|||
new Dependency("SurfaceDescriptionInputs.vertexColor", "FragInputs.color"), |
|||
}; |
|||
}; |
|||
|
|||
static void AddActiveFieldsFromGraphRequirements(HashSet<string> activeFields, ShaderGraphRequirements requirements) |
|||
{ |
|||
if (requirements.requiresScreenPosition) |
|||
{ |
|||
activeFields.Add("SurfaceDescriptionInputs.screenPosition"); |
|||
} |
|||
|
|||
if (requirements.requiresVertexColor) |
|||
{ |
|||
activeFields.Add("SurfaceDescriptionInputs.vertexColor"); |
|||
} |
|||
|
|||
if (requirements.requiresNormal != 0) |
|||
{ |
|||
if ((requirements.requiresNormal & NeededCoordinateSpace.Object) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.ObjectSpaceNormal"); |
|||
|
|||
if ((requirements.requiresNormal & NeededCoordinateSpace.View) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.ViewSpaceNormal"); |
|||
|
|||
if ((requirements.requiresNormal & NeededCoordinateSpace.World) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.WorldSpaceNormal"); |
|||
|
|||
if ((requirements.requiresNormal & NeededCoordinateSpace.Tangent) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.TangentSpaceNormal"); |
|||
} |
|||
|
|||
if (requirements.requiresTangent != 0) |
|||
{ |
|||
if ((requirements.requiresTangent & NeededCoordinateSpace.Object) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.ObjectSpaceTangent"); |
|||
|
|||
if ((requirements.requiresTangent & NeededCoordinateSpace.View) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.ViewSpaceTangent"); |
|||
|
|||
if ((requirements.requiresTangent & NeededCoordinateSpace.World) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.WorldSpaceTangent"); |
|||
|
|||
if ((requirements.requiresTangent & NeededCoordinateSpace.Tangent) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.TangentSpaceTangent"); |
|||
} |
|||
|
|||
if (requirements.requiresBitangent != 0) |
|||
{ |
|||
if ((requirements.requiresBitangent & NeededCoordinateSpace.Object) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.ObjectSpaceBiTangent"); |
|||
|
|||
if ((requirements.requiresBitangent & NeededCoordinateSpace.View) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.ViewSpaceBiTangent"); |
|||
|
|||
if ((requirements.requiresBitangent & NeededCoordinateSpace.World) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.WorldSpaceBiTangent"); |
|||
|
|||
if ((requirements.requiresBitangent & NeededCoordinateSpace.Tangent) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.TangentSpaceBiTangent"); |
|||
} |
|||
|
|||
if (requirements.requiresViewDir != 0) |
|||
{ |
|||
if ((requirements.requiresViewDir & NeededCoordinateSpace.Object) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.ObjectSpaceViewDirection"); |
|||
|
|||
if ((requirements.requiresViewDir & NeededCoordinateSpace.View) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.ViewSpaceViewDirection"); |
|||
|
|||
if ((requirements.requiresViewDir & NeededCoordinateSpace.World) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.WorldSpaceViewDirection"); |
|||
|
|||
if ((requirements.requiresViewDir & NeededCoordinateSpace.Tangent) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.TangentSpaceViewDirection"); |
|||
} |
|||
|
|||
if (requirements.requiresPosition != 0) |
|||
{ |
|||
if ((requirements.requiresPosition & NeededCoordinateSpace.Object) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.ObjectSpacePosition"); |
|||
|
|||
if ((requirements.requiresPosition & NeededCoordinateSpace.View) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.ViewSpacePosition"); |
|||
|
|||
if ((requirements.requiresPosition & NeededCoordinateSpace.World) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.WorldSpacePosition"); |
|||
|
|||
if ((requirements.requiresPosition & NeededCoordinateSpace.Tangent) > 0) |
|||
activeFields.Add("SurfaceDescriptionInputs.TangentSpacePosition"); |
|||
} |
|||
|
|||
foreach (var channel in requirements.requiresMeshUVs.Distinct()) |
|||
{ |
|||
activeFields.Add("SurfaceDescriptionInputs." + channel.GetUVName()); |
|||
} |
|||
} |
|||
|
|||
// TODO : split this function into buildActiveFields and buildHLSLTypeDeclaration functions
|
|||
public static void Generate( |
|||
ShaderGenerator codeResult, |
|||
ShaderGenerator graphInputsResult, |
|||
ShaderGraphRequirements graphRequirements, |
|||
List<string> passRequiredFields, // fields the pass requires
|
|||
CoordinateSpace preferedCoordinateSpace, |
|||
HashSet<string> activeFields) |
|||
{ |
|||
if (preferedCoordinateSpace == CoordinateSpace.Tangent) |
|||
preferedCoordinateSpace = CoordinateSpace.World; |
|||
|
|||
// build initial requirements
|
|||
AddActiveFieldsFromGraphRequirements(activeFields, graphRequirements); |
|||
if (passRequiredFields != null) |
|||
{ |
|||
foreach (var requiredField in passRequiredFields) |
|||
{ |
|||
activeFields.Add(requiredField); |
|||
} |
|||
} |
|||
|
|||
// propagate requirements using dependencies
|
|||
{ |
|||
ShaderSpliceUtil.ApplyDependencies( |
|||
activeFields, |
|||
new List<Dependency[]>() |
|||
{ |
|||
FragInputs.dependencies, |
|||
VaryingsMeshToPS.standardDependencies, |
|||
SurfaceDescriptionInputs.dependencies, |
|||
}); |
|||
} |
|||
|
|||
// generate code based on requirements
|
|||
ShaderSpliceUtil.BuildType(typeof(AttributesMesh), activeFields, codeResult); |
|||
ShaderSpliceUtil.BuildType(typeof(VaryingsMeshToPS), activeFields, codeResult); |
|||
ShaderSpliceUtil.BuildType(typeof(VaryingsMeshToDS), activeFields, codeResult); |
|||
ShaderSpliceUtil.BuildPackedType(typeof(VaryingsMeshToPS), activeFields, codeResult); |
|||
ShaderSpliceUtil.BuildPackedType(typeof(VaryingsMeshToDS), activeFields, codeResult); |
|||
ShaderSpliceUtil.BuildType(typeof(SurfaceDescriptionInputs), activeFields, graphInputsResult); |
|||
} |
|||
}; |
|||
|
|||
public struct Pass |
|||
{ |
|||
public string Name; |
|||
public string LightMode; |
|||
public string ShaderPassName; |
|||
public List<string> Includes; |
|||
public string TemplateName; |
|||
public List<string> ExtraDefines; |
|||
public List<int> VertexShaderSlots; // These control what slots are used by the pass vertex shader
|
|||
public List<int> PixelShaderSlots; // These control what slots are used by the pass pixel shader
|
|||
public string CullOverride; |
|||
public string BlendOverride; |
|||
public string BlendOpOverride; |
|||
public string ZTestOverride; |
|||
public string ZWriteOverride; |
|||
public string ColorMaskOverride; |
|||
public List<string> StencilOverride; |
|||
public List<string> RequiredFields; // feeds into the dependency analysis
|
|||
public ShaderGraphRequirements requirements; |
|||
}; |
|||
|
|||
public static class HDSubShaderUtilities |
|||
{ |
|||
public static void BuildRenderStatesFromPassAndMaterialOptions( |
|||
Pass pass, |
|||
SurfaceMaterialOptions materialOptions, |
|||
ShaderStringBuilder blendCode, |
|||
ShaderStringBuilder cullCode, |
|||
ShaderStringBuilder zTestCode, |
|||
ShaderStringBuilder zWriteCode, |
|||
ShaderStringBuilder stencilCode, |
|||
ShaderStringBuilder colorMaskCode) |
|||
{ |
|||
if (pass.BlendOverride != null) |
|||
{ |
|||
blendCode.AppendLine(pass.BlendOverride); |
|||
} |
|||
else |
|||
{ |
|||
materialOptions.GetBlend(blendCode); |
|||
} |
|||
|
|||
if (pass.BlendOpOverride != null) |
|||
{ |
|||
blendCode.AppendLine(pass.BlendOpOverride); |
|||
} |
|||
|
|||
if (pass.CullOverride != null) |
|||
{ |
|||
cullCode.AppendLine(pass.CullOverride); |
|||
} |
|||
else |
|||
{ |
|||
materialOptions.GetCull(cullCode); |
|||
} |
|||
|
|||
if (pass.ZTestOverride != null) |
|||
{ |
|||
zTestCode.AppendLine(pass.ZTestOverride); |
|||
} |
|||
else |
|||
{ |
|||
materialOptions.GetDepthTest(zTestCode); |
|||
} |
|||
|
|||
if (pass.ZWriteOverride != null) |
|||
{ |
|||
zWriteCode.AppendLine(pass.ZWriteOverride); |
|||
} |
|||
else |
|||
{ |
|||
materialOptions.GetDepthWrite(zWriteCode); |
|||
} |
|||
|
|||
if (pass.ColorMaskOverride != null) |
|||
{ |
|||
colorMaskCode.AppendLine(pass.ColorMaskOverride); |
|||
} |
|||
else |
|||
{ |
|||
// material option default is to not declare anything for color mask
|
|||
} |
|||
|
|||
if (pass.StencilOverride != null) |
|||
{ |
|||
foreach (var str in pass.StencilOverride) |
|||
{ |
|||
stencilCode.AppendLine(str); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
stencilCode.AppendLine("// Default Stencil"); |
|||
} |
|||
} |
|||
|
|||
public static SurfaceMaterialOptions BuildMaterialOptions(SurfaceType surfaceType, AlphaMode alphaMode, bool twoSided) |
|||
{ |
|||
SurfaceMaterialOptions materialOptions = new SurfaceMaterialOptions(); |
|||
if (surfaceType == SurfaceType.Opaque) |
|||
{ |
|||
materialOptions.srcBlend = SurfaceMaterialOptions.BlendMode.One; |
|||
materialOptions.dstBlend = SurfaceMaterialOptions.BlendMode.Zero; |
|||
materialOptions.zTest = SurfaceMaterialOptions.ZTest.LEqual; |
|||
materialOptions.zWrite = SurfaceMaterialOptions.ZWrite.On; |
|||
materialOptions.renderQueue = SurfaceMaterialOptions.RenderQueue.Geometry; |
|||
materialOptions.renderType = SurfaceMaterialOptions.RenderType.Opaque; |
|||
} |
|||
else |
|||
{ |
|||
switch (alphaMode) |
|||
{ |
|||
case AlphaMode.Alpha: |
|||
materialOptions.srcBlend = SurfaceMaterialOptions.BlendMode.SrcAlpha; |
|||
materialOptions.dstBlend = SurfaceMaterialOptions.BlendMode.OneMinusSrcAlpha; |
|||
materialOptions.zTest = SurfaceMaterialOptions.ZTest.LEqual; |
|||
materialOptions.zWrite = SurfaceMaterialOptions.ZWrite.Off; |
|||
materialOptions.renderQueue = SurfaceMaterialOptions.RenderQueue.Transparent; |
|||
materialOptions.renderType = SurfaceMaterialOptions.RenderType.Transparent; |
|||
break; |
|||
case AlphaMode.Additive: |
|||
materialOptions.srcBlend = SurfaceMaterialOptions.BlendMode.One; |
|||
materialOptions.dstBlend = SurfaceMaterialOptions.BlendMode.One; |
|||
materialOptions.zTest = SurfaceMaterialOptions.ZTest.LEqual; |
|||
materialOptions.zWrite = SurfaceMaterialOptions.ZWrite.Off; |
|||
materialOptions.renderQueue = SurfaceMaterialOptions.RenderQueue.Transparent; |
|||
materialOptions.renderType = SurfaceMaterialOptions.RenderType.Transparent; |
|||
break; |
|||
// TODO: other blend modes
|
|||
} |
|||
} |
|||
|
|||
materialOptions.cullMode = twoSided ? SurfaceMaterialOptions.CullMode.Off : SurfaceMaterialOptions.CullMode.Back; |
|||
|
|||
return materialOptions; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 713ced4e6eef4a44799a4dd59041484b |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 3505be0d02e25a04f8932a6c2243015b |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEditor; |
|||
using UnityEngine; |
|||
|
|||
public class NormalMapVarianceTexturePostprocessor : AssetPostprocessor |
|||
{ |
|||
void OnPreprocessTexture() |
|||
{ |
|||
if (assetPath.IndexOf("_variance", StringComparison.InvariantCultureIgnoreCase) != -1) |
|||
{ |
|||
// Make sure we don't convert as a normal map.
|
|||
TextureImporter textureImporter = (TextureImporter)assetImporter; |
|||
textureImporter.convertToNormalmap = false; |
|||
textureImporter.textureCompression = TextureImporterCompression.CompressedHQ; |
|||
|
|||
textureImporter.linearTexture = true; // Says deprecated but won't work without it.
|
|||
textureImporter.sRGBTexture = false; // But we're setting the new property just in case it changes later...
|
|||
} |
|||
} |
|||
|
|||
private static Color GetColor(Color[] source, int x, int y, int width, int height) |
|||
{ |
|||
x = (x + width) % width; |
|||
y = (y + height) % height; |
|||
|
|||
int index = y * width + x; |
|||
var c = source[index]; |
|||
|
|||
return c; |
|||
} |
|||
|
|||
private static Vector3 GetNormal(Color[] source, int x, int y, int width, int height) |
|||
{ |
|||
Vector3 n = (Vector4)GetColor(source, x, y, width, height); |
|||
n = 2.0f * n - Vector3.one; |
|||
n.Normalize(); |
|||
|
|||
return n; |
|||
} |
|||
|
|||
private static Vector3 GetAverageNormal(Color[] source, int x, int y, int width, int height, int texelFootprint) |
|||
{ |
|||
Vector3 averageNormal = new Vector3(0, 0, 0); |
|||
|
|||
// Calculate the average color over the texel footprint.
|
|||
for (int i = 0; i < texelFootprint; ++i) |
|||
{ |
|||
for (int j = 0; j < texelFootprint; ++j) |
|||
{ |
|||
averageNormal += GetNormal(source, x + i, y + j, width, height); |
|||
} |
|||
} |
|||
|
|||
averageNormal /= (texelFootprint * texelFootprint); |
|||
|
|||
return averageNormal; |
|||
} |
|||
|
|||
void OnPostprocessTexture(Texture2D texture) |
|||
{ |
|||
if (assetPath.IndexOf("_variance", StringComparison.InvariantCultureIgnoreCase) != -1) |
|||
{ |
|||
// For mip 0, set the normal length to 1.
|
|||
{ |
|||
Color[] c = texture.GetPixels(0); |
|||
for (int i = 0; i < c.Length; i++) |
|||
{ |
|||
c[i].a = 1.0f; |
|||
} |
|||
texture.SetPixels(c, 0); |
|||
} |
|||
|
|||
// Based on The Order : 1886 SIGGRAPH course notes implementation. Sample all normal map
|
|||
// texels from the base mip level that are within the footprint of the current mipmap texel.
|
|||
Color[] source = texture.GetPixels(0); |
|||
for (int m = 1; m < texture.mipmapCount; m++) |
|||
{ |
|||
Color[] c = texture.GetPixels(m); |
|||
|
|||
int mipWidth = Math.Max(1, texture.width >> m); |
|||
int mipHeight = Math.Max(1, texture.height >> m); |
|||
|
|||
for (int x = 0; x < mipWidth; ++x) |
|||
{ |
|||
for (int y = 0; y < mipHeight; ++y) |
|||
{ |
|||
int texelFootprint = 1 << m; |
|||
Vector3 averageNormal = GetAverageNormal(source, x * texelFootprint, y * texelFootprint, |
|||
texture.width, texture.height, texelFootprint); |
|||
|
|||
// Store the normal length for the average normal.
|
|||
int outputPosition = y * mipWidth + x; |
|||
//c[outputPosition].a = averageNormal.magnitude;
|
|||
|
|||
float normalLength = Math.Max(0.0f, Math.Min(1.0f, averageNormal.magnitude)); |
|||
c[outputPosition].a = normalLength; |
|||
} |
|||
} |
|||
|
|||
texture.SetPixels(c, m); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: c7467d803a5cf8c479b64fbdac53aa41 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.ShaderGraph |
|||
{ |
|||
public class GraphContext |
|||
{ |
|||
public GraphContext(string inputStructName) |
|||
{ |
|||
graphInputStructName = inputStructName; |
|||
} |
|||
|
|||
public string graphInputStructName |
|||
{ |
|||
get { return m_GraphInputStructName; } |
|||
set { m_GraphInputStructName = value; } |
|||
} |
|||
|
|||
string m_GraphInputStructName; |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 9af661b17b85d264b9549380599875a6 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
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 |
|||
//------------------------------------------------------------------------------------- |
|||
${VariantDefines} |
|||
//------------------------------------------------------------------------------------- |
|||
// 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 |
|||
|
|||
// This shader support vertex modification (or not) |
|||
// TODO - move to PBR shader control |
|||
// #define HAVE_VERTEX_MODIFICATION |
|||
|
|||
// 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 |
|||
//------------------------------------------------------------------------------------- |
|||
// End Defines |
|||
//------------------------------------------------------------------------------------- |
|||
|
|||
#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 |
|||
//------------------------------------------------------------------------------------- |
|||
|
|||
// 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: output.screenPosition = input.positionSS; |
|||
|
|||
$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.. |
|||
#ifdef _ALPHATEST_ON |
|||
DoAlphaTest(surfaceDescription.Alpha, surfaceDescription.AlphaClipThreshold); |
|||
#endif |
|||
|
|||
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; |
|||
} |
|||
|
|||
builtinData.emissiveIntensity = 1.0f; |
|||
$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 |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 165a06313a2a64e258a559021bf37077 |
|||
timeCreated: 1481194716 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: af488966b4110c44a909ab5665e4334e |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 7cd8aa1b9665ad0408015b8700c38b36 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue