浏览代码

Merge remote-tracking branch 'origin/master' into sg/texture-types

/main
Matt Dean 6 年前
当前提交
36a0484f
共有 133 个文件被更改,包括 2277 次插入949 次删除
  1. 3
      ScriptableRenderPipeline/HDRenderPipeline/CHANGELOG.md
  2. 16
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/BuildPlayer/HDRPVariantStripper.cs
  3. 9
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/ShaderBase.hlsl
  4. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VBuffer.hlsl
  5. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.compute
  6. 26
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLit.shader
  7. 29
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitTessellation.shader
  8. 23
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.shader
  9. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitProperties.hlsl
  10. 29
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitTessellation.shader
  11. 6
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLit.cs
  12. 38
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLit.cs.hlsl
  13. 115
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLit.hlsl
  14. 21
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLitData.hlsl
  15. 21
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Unlit/Unlit.shader
  16. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Unlit/UnlitProperties.hlsl
  17. 5
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDepthOnly.hlsl
  18. 573
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/LightWeightPBRSubShader.cs
  19. 582
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/LightWeightUnlitSubShader.cs
  20. 208
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightPBRExtraPasses.template
  21. 94
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightPBRForwardPass.template
  22. 160
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightUnlitExtraPasses.template
  23. 83
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightUnlitPass.template
  24. 1
      ShaderGraph/CHANGELOG.md
  25. 470
      ShaderGraph/HDPipeline/HDUnlitSubShader.cs
  26. 8
      ShaderGraph/Testing/Editor/TestSlot.cs
  27. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/BitangentMaterialSlot.cs
  28. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/BooleanMaterialSlot.cs
  29. 12
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ColorMaterialSlot.cs
  30. 10
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ColorRGBMaterialSlot.cs
  31. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/CubemapInputMaterialSlot.cs
  32. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/CubemapMaterialSlot.cs
  33. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/DynamicMatrixMaterialSlot.cs
  34. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/DynamicValueMaterialSlot.cs
  35. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/DynamicVectorMaterialSlot.cs
  36. 12
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/GradientInputMaterialSlot.cs
  37. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/GradientMaterialSlot.cs
  38. 68
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/MaterialSlot.cs
  39. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Matrix2MaterialSlot.cs
  40. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Matrix3MaterialSlot.cs
  41. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Matrix4MaterialSlot.cs
  42. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/NormalMaterialSlot.cs
  43. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/PositionMaterialSlot.cs
  44. 3
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/PreviewMode.cs
  45. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/SamplerStateMaterialSlot.cs
  46. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ScreenPositionMaterialSlot.cs
  47. 30
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ShaderGraphRequirements.cs
  48. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/SpaceMaterialSlot.cs
  49. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/TangentMaterialSlot.cs
  50. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture2DArrayInputMaterialSlot.cs
  51. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture2DArrayMaterialSlot.cs
  52. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture2DInputMaterialSlot.cs
  53. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture2DMaterialSlot.cs
  54. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture3DInputMaterialSlot.cs
  55. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture3DMaterialSlot.cs
  56. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/UVMaterialSlot.cs
  57. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector1MaterialSlot.cs
  58. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector2MaterialSlot.cs
  59. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector3MaterialSlot.cs
  60. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector4MaterialSlot.cs
  61. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/VertexColorMaterialSlot.cs
  62. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ViewDirectionMaterialSlot.cs
  63. 98
      ShaderGraph/com.unity.shadergraph/Editor/Data/Implementation/NodeUtils.cs
  64. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IGeneratesFunction.cs
  65. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireBitangent.cs
  66. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireMeshUV.cs
  67. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireNormal.cs
  68. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequirePosition.cs
  69. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireScreenPosition.cs
  70. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireTangent.cs
  71. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireVertexColor.cs
  72. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireViewDirection.cs
  73. 60
      ShaderGraph/com.unity.shadergraph/Editor/Data/MasterNodes/PBRMasterNode.cs
  74. 30
      ShaderGraph/com.unity.shadergraph/Editor/Data/MasterNodes/UnlitMasterNode.cs
  75. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Artistic/Adjustment/ChannelMixerNode.cs
  76. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Artistic/Adjustment/InvertColorsNode.cs
  77. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Artistic/Mask/ChannelMaskNode.cs
  78. 12
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Artistic/Normal/NormalCreateNode.cs
  79. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Channel/FlipNode.cs
  80. 91
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/CodeFunctionNode.cs
  81. 8
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Basic/ColorNode.cs
  82. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/BitangentVectorNode.cs
  83. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/NormalVectorNode.cs
  84. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/PositionNode.cs
  85. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ScreenPositionNode.cs
  86. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/TangentVectorNode.cs
  87. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/UVNode.cs
  88. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/VertexColorNode.cs
  89. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs
  90. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Gradient/GradientNode.cs
  91. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Scene/FogNode.cs
  92. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Texture/SampleCubemapNode.cs
  93. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Texture/SampleTexture2DArrayNode.cs
  94. 12
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Texture/SampleTexture2DNode.cs
  95. 34
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/MasterNode.cs
  96. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Math/Basic/MultiplyNode.cs
  97. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Math/Matrix/MatrixConstructionNode.cs
  98. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Math/Vector/TransformNode.cs
  99. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Procedural/CheckerboardNode.cs
  100. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Procedural/Noise/GradientNoiseNode.cs

3
ScriptableRenderPipeline/HDRenderPipeline/CHANGELOG.md


# Changelog
## [2018.2 undecided]
- Fix issue with LOD transition and instancing
- Support correctly scene selection for alpha tested object
### Changed, Removals and deprecations
- Removed GlobalLightLoopSettings.maxPlanarReflectionProbes and instead use value of GlobalLightLoopSettings.planarReflectionProbeCacheSize

- Fix line lights sent to the lightmappers. The backends don't support this light type.
- Fix issue with shadow mask framesettings not correctly taken into account when shadow mask is enabled for lighting.
- Fix directional light and shadow mask transition, they are now matching making smooth transition
- Fix banding issues caused by high intensity volumetric lighting
## [2018.1.0f2]

16
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/BuildPlayer/HDRPVariantStripper.cs


m_StripperFuncs.Add("HDRenderPipeline/LitTessellation", LitShaderStripper);
m_StripperFuncs.Add("HDRenderPipeline/LayeredLit", LitShaderStripper);
m_StripperFuncs.Add("HDRenderPipeline/LayeredLitTessellation", LitShaderStripper);
m_StripperFuncs.Add("HDRenderPipeline/Unlit", UnlitShaderStripper);
m_Transparent = new ShaderKeyword("_SURFACE_TYPE_TRANSPARENT");
m_DebugDisplay = new ShaderKeyword("DEBUG_DISPLAY");

//m_FeatureSSS = new ShaderKeyword("_MATERIAL_FEATURE_SUBSURFACE_SCATTERING");
}
bool UnlitShaderStripper(Shader shader, ShaderSnippetData snippet, ShaderCompilerData inputData)
{
bool isSceneSelectionPass = snippet.passName == "SceneSelectionPass";
if (isSceneSelectionPass)
return true;
return false;
}
bool isSceneSelectionPass = snippet.passName == "SceneSelectionPass";
if (isSceneSelectionPass)
return true;
bool isGBufferPass = snippet.passName == "GBuffer";
bool isForwardPass = snippet.passName == "Forward";
bool isTransparentForwardPass = snippet.passName == "TransparentDepthPostpass" || snippet.passName == "TransparentBackface" || snippet.passName == "TransparentDepthPrepass";

9
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/ShaderBase.hlsl


#ifndef __SHADERBASE_H__
#define __SHADERBASE_H__
// can't use UNITY_REVERSED_Z since it's not enabled in compute shaders
#if !defined(SHADER_API_GLES3) && !defined(SHADER_API_GLCORE)
#define REVERSE_ZBUF
#endif
#ifdef SHADER_API_PSSL
#ifndef Texture2DMS

float FetchDepth(Texture2D depthTexture, uint2 pixCoord)
{
float zdpth = LOAD_TEXTURE2D(depthTexture, pixCoord.xy).x;
#ifdef REVERSE_ZBUF
#if UNITY_REVERSED_Z
zdpth = 1.0 - zdpth;
#endif
return zdpth;

{
float zdpth = LOAD_TEXTURE2D_MSAA(depthTexture, pixCoord.xy, sampleIdx).x;
#ifdef REVERSE_ZBUF
#if UNITY_REVERSED_Z
zdpth = 1.0 - zdpth;
#endif
return zdpth;

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VBuffer.hlsl


bool quadraticFilterXY)
{
// TODO: add some slowly animated noise to the reconstructed value.
return FastTonemapInvert(SampleVBuffer(TEXTURE3D_PARAM(VBufferLighting, clampSampler),
// TODO: re-enable tone mapping after implementing pre-exposure.
return /*FastTonemapInvert*/(SampleVBuffer(TEXTURE3D_PARAM(VBufferLighting, clampSampler),
positionNDC,
linearDepth,
VBufferResolution,

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.compute


// Note: for correct filtering, the data has to be stored in the perceptual space.
// This means storing the tone mapped radiance and transmittance instead of optical depth.
// See "A Fresh Look at Generalized Sampling", p. 51.
_VBufferLightingIntegral[voxelCoord] = float4(FastTonemap(totalRadiance), Transmittance(opticalDepth));
// TODO: re-enable tone mapping after implementing pre-exposure.
_VBufferLightingIntegral[voxelCoord] = float4(/*FastTonemap*/(totalRadiance), Transmittance(opticalDepth));
// Compute the optical depth up to the end of the interval.
opticalDepth += 0.5 * extinction * dt;

26
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLit.shader


// This tags allow to use the shader replacement features
Tags{ "RenderPipeline" = "HDRenderPipeline" "RenderType" = "HDLitShader" }
Pass
{
Name "SceneSelectionPass"
Tags{ "LightMode" = "SceneSelectionPass" }
Cull[_CullMode]
ZWrite On
ColorMask 0
HLSLPROGRAM
#define SHADERPASS SHADERPASS_DEPTH_ONLY
#define SCENESELECTIONPASS // This will drive the output of the scene selection shader
#include "../../ShaderVariables.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitDepthPass.hlsl"
#include "LayeredLitData.hlsl"
#include "../../ShaderPass/ShaderPassDepthOnly.hlsl"
ENDHLSL
}
// Caution: The outline selection in the editor use the vertex shader/hull/domain shader of the first pass declare. So it should not bethe meta pass.
Pass
{

#ifdef _ALPHATEST_ON
// When we have alpha test, we will force a depth prepass so we always bypass the clip instruction in the GBuffer
#define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST
#define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST
#endif
#define SHADERPASS SHADERPASS_GBUFFER

29
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitTessellation.shader


// This tags allow to use the shader replacement features
Tags{ "RenderPipeline" = "HDRenderPipeline" "RenderType" = "HDLitShader" }
Pass
{
Name "SceneSelectionPass"
Tags{ "LightMode" = "SceneSelectionPass" }
Cull[_CullMode]
ZWrite On
ColorMask 0
HLSLPROGRAM
#pragma hull Hull
#pragma domain Domain
#define SHADERPASS SHADERPASS_DEPTH_ONLY
#define SCENESELECTIONPASS // This will drive the output of the scene selection shader
#include "../../ShaderVariables.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitDepthPass.hlsl"
#include "LayeredLitData.hlsl"
#include "../../ShaderPass/ShaderPassDepthOnly.hlsl"
ENDHLSL
}
// Caution: The outline selection in the editor use the vertex shader/hull/domain shader of the first pass declare. So it should not bethe meta pass.
Pass
{

#ifdef _ALPHATEST_ON
// When we have alpha test, we will force a depth prepass so we always bypass the clip instruction in the GBuffer
#define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST
#define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST
#endif
#define SHADERPASS SHADERPASS_GBUFFER

23
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.shader


// This tags allow to use the shader replacement features
Tags{ "RenderPipeline"="HDRenderPipeline" "RenderType" = "HDLitShader" }
Pass
{
Name "SceneSelectionPass" // Name is not used
Tags { "LightMode" = "SceneSelectionPass" }
Cull Off
HLSLPROGRAM
// We reuse depth prepass for the scene selection, allow to handle alpha correctly as well as tessellation and vertex animation
#define SHADERPASS SHADERPASS_DEPTH_ONLY
#define SCENESELECTIONPASS // This will drive the output of the scene selection shader
#include "../../ShaderVariables.hlsl"
#include "../../Material/Material.hlsl"
#include "ShaderPass/LitDepthPass.hlsl"
#include "LitData.hlsl"
#include "../../ShaderPass/ShaderPassDepthOnly.hlsl"
ENDHLSL
}
// Caution: The outline selection in the editor use the vertex shader/hull/domain shader of the first pass declare. So it should not bethe meta pass.
Pass
{

#ifdef _ALPHATEST_ON
// When we have alpha test, we will force a depth prepass so we always bypass the clip instruction in the GBuffer
#define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST
#define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST
#endif
#define SHADERPASS SHADERPASS_GBUFFER

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitProperties.hlsl


float _TessellationTilingScale;
#endif
// Following two variables are feeded by the C++ Editor for Scene selection
int _ObjectId;
int _PassValue;
CBUFFER_END

29
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitTessellation.shader


// This tags allow to use the shader replacement features
Tags{ "RenderPipeline" = "HDRenderPipeline" "RenderType" = "HDLitShader" }
Pass
{
Name "SceneSelectionPass"
Tags{ "LightMode" = "SceneSelectionPass" }
Cull[_CullMode]
ZWrite On
ColorMask 0
HLSLPROGRAM
#pragma hull Hull
#pragma domain Domain
#define SHADERPASS SHADERPASS_DEPTH_ONLY
#define SCENESELECTIONPASS // This will drive the output of the scene selection shader
#include "../../ShaderVariables.hlsl"
#include "../../Material/Material.hlsl"
#include "ShaderPass/LitDepthPass.hlsl"
#include "LitData.hlsl"
#include "../../ShaderPass/ShaderPassDepthOnly.hlsl"
ENDHLSL
}
// Caution: The outline selection in the editor use the vertex shader/hull/domain shader of the first pass declare. So it should not bethe meta pass.
Pass
{

#ifdef _ALPHATEST_ON
// When we have alpha test, we will force a depth prepass so we always bypass the clip instruction in the GBuffer
#define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST
#define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST
#endif
#define SHADERPASS SHADERPASS_GBUFFER

6
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLit.cs


[SurfaceDataAttributes(new string[]{"Coat Normal", "Coat Normal View Space"}, true)]
public Vector3 coatNormalWS;
[SurfaceDataAttributes("Average Normal Length A")]
public float averageNormalLengthA;
[SurfaceDataAttributes("Average Normal Length B")]
public float averageNormalLengthB;
[SurfaceDataAttributes("Smoothness A")]
public float perceptualSmoothnessA;

38
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLit.cs.hlsl


#define DEBUGVIEW_STACKLIT_SURFACEDATA_GEOMETRIC_NORMAL_VIEW_SPACE (1308)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_NORMAL (1309)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_NORMAL_VIEW_SPACE (1310)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_SMOOTHNESS_A (1311)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_SMOOTHNESS_B (1312)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_LOBE_MIXING (1313)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_TANGENT (1314)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_ANISOTROPY (1315)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_IRIDESCENCE_IOR (1316)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_IRIDESCENCE_THICKNESS (1317)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_SMOOTHNESS (1318)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_IOR (1319)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_THICKNESS (1320)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_EXTINCTION_COEFFICIENT (1321)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_DIFFUSION_PROFILE (1322)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_SUBSURFACE_MASK (1323)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_THICKNESS (1324)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_AVERAGE_NORMAL_LENGTH_A (1311)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_AVERAGE_NORMAL_LENGTH_B (1312)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_SMOOTHNESS_A (1313)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_SMOOTHNESS_B (1314)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_LOBE_MIXING (1315)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_TANGENT (1316)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_ANISOTROPY (1317)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_IRIDESCENCE_IOR (1318)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_IRIDESCENCE_THICKNESS (1319)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_SMOOTHNESS (1320)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_IOR (1321)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_THICKNESS (1322)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_EXTINCTION_COEFFICIENT (1323)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_DIFFUSION_PROFILE (1324)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_SUBSURFACE_MASK (1325)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_THICKNESS (1326)
//
// UnityEngine.Experimental.Rendering.HDPipeline.StackLit+BSDFData: static fields

float3 normalWS;
float3 geomNormalWS;
float3 coatNormalWS;
float averageNormalLengthA;
float averageNormalLengthB;
float perceptualSmoothnessA;
float perceptualSmoothnessB;
float lobeMix;

break;
case DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_NORMAL_VIEW_SPACE:
result = surfacedata.coatNormalWS * 0.5 + 0.5;
break;
case DEBUGVIEW_STACKLIT_SURFACEDATA_AVERAGE_NORMAL_LENGTH_A:
result = surfacedata.averageNormalLengthA.xxx;
break;
case DEBUGVIEW_STACKLIT_SURFACEDATA_AVERAGE_NORMAL_LENGTH_B:
result = surfacedata.averageNormalLengthB.xxx;
break;
case DEBUGVIEW_STACKLIT_SURFACEDATA_SMOOTHNESS_A:
result = surfacedata.perceptualSmoothnessA.xxx;

115
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLit.hlsl


float variance = _SpecularAntiAliasingScreenSpaceVariance * (dot(deltaU, deltaU) + dot(deltaV, deltaV));
float squaredRoughness = saturate(r * r + min(2.0 * variance, _SpecularAntiAliasingThreshold));
return variance;
}
// Based on The Order : 1886 SIGGRAPH course notes implementation.
float AdjustRoughness(float avgNormalLength)
{
if (avgNormalLength < 1.0)
{
float avgNormLen2 = avgNormalLength * avgNormalLength;
float kappa = (3 * avgNormalLength - avgNormalLength * avgNormLen2) / (1 - avgNormLen2);
return 1.0 / (2.0 * kappa);
}
return sqrt(squaredRoughness);
return 0.0f;
float FilterRoughness(float r, float3 geomNormalWS, float averageNormalLength)
{
// Specular AA: NormalCurvatureToRoughness
r = lerp(r, max(NormalCurvatureToRoughness(geomNormalWS), r), _NormalCurvatureToRoughnessEnabled);
// Specular AA: Tokuyoshi Filtering + 1866 normal filtering.
float varianceGeom = FilterRoughness_TOKUYOSHI(geomNormalWS, r);
float varianceNorm = AdjustRoughness(averageNormalLength);
float filteredRoughness = sqrt(saturate(r * r + min(2.0 * (varianceGeom + varianceNorm), _SpecularAntiAliasingThreshold)));
return lerp(r, filteredRoughness, _SpecularAntiAliasingEnabled);
}
//-----------------------------------------------------------------------------
// conversion function for forward

bsdfData.perceptualRoughnessA = PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothnessA);
bsdfData.perceptualRoughnessB = PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothnessB);
// Specular AA: NormalCurvatureToRoughness
float normalCurvatureToRoughnessA = max(NormalCurvatureToRoughness(bsdfData.normalWS), bsdfData.perceptualRoughnessA);
float normalCurvatureToRoughnessB = max(NormalCurvatureToRoughness(bsdfData.normalWS), bsdfData.perceptualRoughnessB);
bsdfData.perceptualRoughnessA = lerp(bsdfData.perceptualRoughnessA, normalCurvatureToRoughnessA, _NormalCurvatureToRoughnessEnabled);
bsdfData.perceptualRoughnessB = lerp(bsdfData.perceptualRoughnessB, normalCurvatureToRoughnessB, _NormalCurvatureToRoughnessEnabled);
// Specular AA: Tokuyoshi Filtering.
float filterRoughnessA = FilterRoughness_TOKUYOSHI(bsdfData.normalWS, bsdfData.perceptualRoughnessA);
float filterRoughnessB = FilterRoughness_TOKUYOSHI(bsdfData.normalWS, bsdfData.perceptualRoughnessB);
bsdfData.perceptualRoughnessA = lerp(bsdfData.perceptualRoughnessA, filterRoughnessA, _SpecularAntiAliasingEnabled);
bsdfData.perceptualRoughnessB = lerp(bsdfData.perceptualRoughnessB, filterRoughnessB, _SpecularAntiAliasingEnabled);
// Specular AA / Filtering.
bsdfData.perceptualRoughnessA = FilterRoughness(bsdfData.perceptualRoughnessA, bsdfData.geomNormalWS, surfaceData.averageNormalLengthA);
bsdfData.perceptualRoughnessB = FilterRoughness(bsdfData.perceptualRoughnessB, bsdfData.geomNormalWS, surfaceData.averageNormalLengthB);
bsdfData.lobeMix = surfaceData.lobeMix;
// There is no metallic with SSS and specular color mode

struct PreLightData
{
float NdotV[NB_NORMALS]; // Could be negative due to normal mapping, use ClampNdotV()
//float NdotV;
float geomNdotV;
float bottomAngleFGD;
float TdotV; // Stored only when VLAYERED_RECOMPUTE_PERLIGHT
float BdotV;

// slnote dual map
float PreLightData_GetBaseNdotVForFGD(BSDFData bsdfData, PreLightData preLightData, float NdotV[NB_NORMALS])
{
float baseLayerNdotV;

return baseLayerNdotV;
}
// slnote dual map
void PreLightData_SetupNormals(BSDFData bsdfData, inout PreLightData preLightData, float3 V, out float3 N[NB_NORMALS], out float NdotV[NB_NORMALS])
{
N[BASE_NORMAL_IDX] = bsdfData.normalWS;

N[COAT_NORMAL_IDX] = bsdfData.coatNormalWS;
preLightData.NdotV[COAT_NORMAL_IDX] = dot(N[COAT_NORMAL_IDX], V);
NdotV[COAT_NORMAL_IDX] = ClampNdotV(preLightData.NdotV[COAT_NORMAL_IDX]);
preLightData.geomNdotV = dot(bsdfData.geomNormalWS, V);
}
#endif
}

IF_DEBUG( if(_DebugLobeMask.y == 0.0) DV[BASE_LOBEA_IDX] = (float3)0; )
IF_DEBUG( if(_DebugLobeMask.z == 0.0) DV[BASE_LOBEB_IDX] = (float3)0; )
specularLighting = preLightData.vLayerEnergyCoeff[BOTTOM_VLAYER_IDX]
specularLighting = max(0, NdotL[DNLV_BASE_IDX]) * preLightData.vLayerEnergyCoeff[BOTTOM_VLAYER_IDX]
specularLighting += preLightData.vLayerEnergyCoeff[TOP_VLAYER_IDX]
specularLighting += max(0, NdotL[DNLV_COAT_IDX]) * preLightData.vLayerEnergyCoeff[TOP_VLAYER_IDX]
* preLightData.energyCompensationFactor[COAT_LOBE_IDX]
* DV[COAT_LOBE_IDX];

IF_DEBUG( if(_DebugLobeMask.y == 0.0) DV[BASE_LOBEA_IDX] = (float3)0; )
IF_DEBUG( if(_DebugLobeMask.z == 0.0) DV[BASE_LOBEB_IDX] = (float3)0; )
specularLighting = F * lerp(DV[0]*preLightData.energyCompensationFactor[BASE_LOBEA_IDX],
DV[1]*preLightData.energyCompensationFactor[BASE_LOBEB_IDX],
bsdfData.lobeMix);
specularLighting = max(0, NdotL[0]) * F * lerp(DV[0]*preLightData.energyCompensationFactor[BASE_LOBEA_IDX],
DV[1]*preLightData.energyCompensationFactor[BASE_LOBEB_IDX],
bsdfData.lobeMix);
float3 diffuseTerm = Lambert();
float3 diffuseTerm = Lambert() * max(0, NdotL[DNLV_BASE_IDX]);
#ifdef VLAYERED_DIFFUSE_ENERGY_HACKED_TERM
// TODOTODO: Energy when vlayered.

void EvaluateBSDF_GetNormalUnclampedNdotV(BSDFData bsdfData, PreLightData preLightData, float3 V, out float3 N, out float unclampedNdotV)
{
//TODO: This affects transmission and SSS, choose the normal the use when we have
// both. For now, just use the base:
N = bsdfData.normalWS;
unclampedNdotV = preLightData.NdotV[BASE_NORMAL_IDX];
//TODOWIP for now just return geometric normal:
N = bsdfData.geomNormalWS;
unclampedNdotV = dot(N, V);
}
else
#ifdef _STACKLIT_DEBUG
if(_DebugLobeMask.w == 2.0)
{
N = bsdfData.coatNormalWS;
unclampedNdotV = preLightData.NdotV[COAT_NORMAL_IDX];
}
else if(_DebugLobeMask.w == 3.0)
{
N = bsdfData.geomNormalWS;
unclampedNdotV = preLightData.geomNdotV;
}
{
// TODOWIP, for now, preserve previous behavior
N = bsdfData.normalWS;
unclampedNdotV = preLightData.NdotV[BASE_NORMAL_IDX];
#endif // _MATERIAL_FEATURE_COAT_NORMALMAP
}
//-----------------------------------------------------------------------------

DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
//slnote dual map
//float3 N = bsdfData.normalWS;
//float NdotV = ClampNdotV(preLightData.NdotV);
float NdotV = ClampNdotV(unclampedNdotV);
float NdotL = dot(N, L);
float LdotV = dot(L, V);

float attenuation;
EvaluateLight_Directional(lightLoopContext, posInput, lightData, bakeLightingData, N, L, color, attenuation);
float intensity = max(0, attenuation * NdotL); // Warning: attenuation can be greater than 1 due to the inverse square attenuation (when position is close to light)
// For shadow attenuation (ie receiver bias), always use the geometric normal:
EvaluateLight_Directional(lightLoopContext, posInput, lightData, bakeLightingData, bsdfData.geomNormalWS, L, color, attenuation);
// Note: We use NdotL here to early out, but in case of coat this is not correct. But we are ok with this
float intensity = max(0, attenuation); // Warning: attenuation can be greater than 1 due to the inverse square attenuation (when position is close to light)
// Note: the NdotL term is now applied in the BSDF() eval itself to account for different normals.
UNITY_BRANCH if (intensity > 0.0)
{
BSDF(V, L, NdotL, posInput.positionWS, preLightData, bsdfData, lighting.diffuse, lighting.specular);

if (_DebugLightingMode == DEBUGLIGHTINGMODE_LUX_METER)
{
// Only lighting, not BSDF
intensity = max(0, attenuation * NdotL);
lighting.diffuse = color * intensity * lightData.diffuseScale;
}
#endif

distances.xyz = float3(dist, distSq, distRcp);
}
//slnote dual map
//float3 N = bsdfData.normalWS;
//float NdotV = ClampNdotV(preLightData.NdotV);
float NdotV = ClampNdotV(unclampedNdotV);
float NdotL = dot(N, L);
float LdotV = dot(L, V);

float3 color;
float attenuation;
EvaluateLight_Punctual(lightLoopContext, posInput, lightData, bakeLightingData, N, L,
// For shadow attenuation (ie receiver bias), always use the geometric normal:
EvaluateLight_Punctual(lightLoopContext, posInput, lightData, bakeLightingData, bsdfData.geomNormalWS, L,
float intensity = max(0, attenuation * NdotL); // Warning: attenuation can be greater than 1 due to the inverse square attenuation (when position is close to light)
float intensity = max(0, attenuation); // Warning: attenuation can be greater than 1 due to the inverse square attenuation (when position is close to light)
// Note: We use NdotL here to early out, but in case of coat this is not correct. But we are ok with this
// Note: the NdotL term is now applied in the BSDF() eval itself to account for different normals.
UNITY_BRANCH if (intensity > 0.0)
{
// Simulate a sphere light with this hack

if (_DebugLightingMode == DEBUGLIGHTINGMODE_LUX_METER)
{
// Only lighting, not BSDF
intensity = max(0, attenuation * NdotL);
lighting.diffuse = color * intensity * lightData.diffuseScale;
}
#endif

if( (i == (0 IF_FEATURE_COAT(+1))) && _DebugEnvLobeMask.y == 0.0) continue;
if( (i == (1 IF_FEATURE_COAT(+1))) && _DebugEnvLobeMask.z == 0.0) continue;
#endif
//slnote dual map
//EvaluateLight_EnvIntersection(positionWS, bsdfData.normalWS, lightData, influenceShapeType, R[i], tempWeight[i]);
EvaluateLight_EnvIntersection(positionWS, influenceNormal, lightData, influenceShapeType, R[i], tempWeight[i]);
// When we are rough, we tend to see outward shifting of the reflection when at the boundary of the projection volume

21
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLitData.hlsl


#endif
}
float3 SampleTexture2DTriplanarNormalScaleBias(TEXTURE2D_ARGS(textureName, samplerName), float textureNameUV, float textureNameUVLocal, float4 textureNameST, float textureNameObjSpace, TextureUVMapping uvMapping, float scale)
float4 SampleTexture2DTriplanarNormalScaleBias(TEXTURE2D_ARGS(textureName, samplerName), float textureNameUV, float textureNameUVLocal, float4 textureNameST, float textureNameObjSpace, TextureUVMapping uvMapping, float scale)
{
if (textureNameObjSpace)
{

// Decompress normal ourselve
float3 normalOS = SampleTexture2DTriplanarScaleBias(TEXTURE2D_PARAM(textureName, samplerName), textureNameUV, textureNameUVLocal, textureNameST, uvMapping).xyz * 2.0 - 1.0;
// no need to renormalize normalOS for SurfaceGradientFromPerturbedNormal
return SurfaceGradientFromPerturbedNormal(uvMapping.vertexNormalWS, TransformObjectToWorldDir(normalOS));
return float4(SurfaceGradientFromPerturbedNormal(uvMapping.vertexNormalWS, TransformObjectToWorldDir(normalOS)), 1.0);
}
else
{

// Assume derivXplane, derivYPlane and derivZPlane sampled using (z,y), (z,x) and (x,y) respectively.
float3 volumeGrad = float3(derivZPlane.x + derivYPlane.y, derivZPlane.y + derivXplane.y, derivXplane.x + derivYPlane.x);
return SurfaceGradientFromVolumeGradient(uvMapping.vertexNormalWS, volumeGrad);
return float4(SurfaceGradientFromVolumeGradient(uvMapping.vertexNormalWS, volumeGrad), 1.0);
}
#endif

{
return SurfaceGradientFromTBN(deriv, uvMapping.vertexTangentWS[textureNameUV], uvMapping.vertexBitangentWS[textureNameUV]);
return float4(SurfaceGradientFromTBN(deriv, uvMapping.vertexTangentWS[textureNameUV], uvMapping.vertexBitangentWS[textureNameUV]), 1.0);
}
else
{

else if (textureNameUV == TEXCOORD_INDEX_PLANAR_XY)
volumeGrad = float3(deriv.x, deriv.y, 0.0);
return SurfaceGradientFromVolumeGradient(uvMapping.vertexNormalWS, volumeGrad);
return float4(SurfaceGradientFromVolumeGradient(uvMapping.vertexNormalWS, volumeGrad), 1.0f);
}
}
}

// Standard
surfaceData.baseColor = SAMPLE_TEXTURE2D_SCALE_BIAS(_BaseColorMap).rgb * _BaseColor.rgb;
float3 gradient = SAMPLE_TEXTURE2D_NORMAL_SCALE_BIAS(_NormalMap, _NormalScale);
float4 gradient = SAMPLE_TEXTURE2D_NORMAL_SCALE_BIAS(_NormalMap, _NormalScale);
//TODO: bentNormalTS
surfaceData.perceptualSmoothnessA = dot(SAMPLE_TEXTURE2D_SCALE_BIAS(_SmoothnessAMap), _SmoothnessAMapChannelMask);

#endif
surfaceData.tangentWS = normalize(input.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
float3 coatGradient = float3(0.0, 0.0, 0.0);
float4 coatGradient = float4(0.0, 0.0, 0.0, 1.0f);
#ifdef _MATERIAL_FEATURE_COAT
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_STACK_LIT_COAT;
surfaceData.coatPerceptualSmoothness = dot(SAMPLE_TEXTURE2D_SCALE_BIAS(_CoatSmoothnessMap), _CoatSmoothnessMapChannelMask);

surfaceData.geomNormalWS = input.worldToTangent[2];
// Convert back to world space normal
surfaceData.normalWS = SurfaceGradientResolveNormal(input.worldToTangent[2], gradient);
surfaceData.coatNormalWS = SurfaceGradientResolveNormal(input.worldToTangent[2], coatGradient);
surfaceData.normalWS = SurfaceGradientResolveNormal(input.worldToTangent[2], gradient.xyz);
surfaceData.coatNormalWS = SurfaceGradientResolveNormal(input.worldToTangent[2], coatGradient.xyz);
surfaceData.averageNormalLengthA = gradient.w;
surfaceData.averageNormalLengthB = coatGradient.w;
// TODO: decal etc.

21
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Unlit/Unlit.shader


Pass
{
Name "SceneSelectionPass"
Tags{ "LightMode" = "SceneSelectionPass" }
Cull[_CullMode]
ZWrite On
HLSLPROGRAM
#define SHADERPASS SHADERPASS_DEPTH_ONLY
#define SCENESELECTIONPASS // This will drive the output of the scene selection shader
#include "../../Material/Material.hlsl"
#include "ShaderPass/UnlitDepthPass.hlsl"
#include "UnlitData.hlsl"
#include "../../ShaderPass/ShaderPassDepthOnly.hlsl"
ENDHLSL
}
Pass
{
Name "Depth prepass"
Tags{ "LightMode" = "DepthForwardOnly" }

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Unlit/UnlitProperties.hlsl


// TODO: Fix the code in legacy unity so we can customize the behavior for GI
float3 _EmissionColor;
// Following two variables are feeded by the C++ Editor for Scene selection
int _ObjectId;
int _PassValue;
CBUFFER_END

5
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDepthOnly.hlsl


#ifdef _DEPTHOFFSET_ON
outputDepth = posInput.deviceDepth;
#endif
// We use depth prepass for scene selection in the editor, this code allow to output the outline correctly
#ifdef SCENESELECTIONPASS
outColor = float4(_ObjectId, _PassValue, 1, 1);
#endif
}

573
ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/LightWeightPBRSubShader.cs


[FormerName("UnityEditor.ShaderGraph.LightWeightPBRSubShader")]
public class LightWeightPBRSubShader : IPBRSubShader
{
static NeededCoordinateSpace m_VertexCoordinateSpace = NeededCoordinateSpace.Object;
static NeededCoordinateSpace m_PixelCoordinateSpace = NeededCoordinateSpace.World;
struct Pass
{
public string Name;

PBRMasterNode.OcclusionSlotId,
PBRMasterNode.AlphaSlotId,
PBRMasterNode.AlphaThresholdSlotId
},
VertexShaderSlots = new List<int>()
{
PBRMasterNode.PositionSlotId
}
};

PBRMasterNode.OcclusionSlotId,
PBRMasterNode.AlphaSlotId,
PBRMasterNode.AlphaThresholdSlotId
},
VertexShaderSlots = new List<int>()
{
PBRMasterNode.PositionSlotId
private static string GetShaderPassFromTemplate(string template, PBRMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
public string GetSubshader(IMasterNode inMasterNode, GenerationMode mode)
var builder = new ShaderStringBuilder();
builder.IncreaseIndent();
builder.IncreaseIndent();
var vertexInputs = new ShaderGenerator();
var surfaceVertexShader = new ShaderGenerator();
var surfaceDescriptionFunction = new ShaderGenerator();
var surfaceDescriptionStruct = new ShaderGenerator();
var functionRegistry = new FunctionRegistry(builder);
var surfaceInputs = new ShaderGenerator();
var templatePath = GetTemplatePath("lightweightPBRForwardPass.template");
var extraPassesTemplatePath = GetTemplatePath("lightweightPBRExtraPasses.template");
if (!File.Exists(templatePath) || !File.Exists(extraPassesTemplatePath))
return string.Empty;
string forwardTemplate = File.ReadAllText(templatePath);
string extraTemplate = File.ReadAllText(extraPassesTemplatePath);
var masterNode = inMasterNode as PBRMasterNode;
var pass = masterNode.model == PBRMasterNode.Model.Metallic ? m_ForwardPassMetallic : m_ForwardPassSpecular;
var subShader = new ShaderStringBuilder();
subShader.AppendLine("SubShader");
using (subShader.BlockScope())
{
subShader.AppendLine("Tags{ \"RenderPipeline\" = \"LightweightPipeline\"}");
var materialOptions = ShaderGenerator.GetMaterialOptions(masterNode.surfaceType, masterNode.alphaMode, masterNode.twoSided.isOn);
var tagsBuilder = new ShaderStringBuilder(0);
materialOptions.GetTags(tagsBuilder);
subShader.AppendLines(tagsBuilder.ToString());
subShader.AppendLines(GetShaderPassFromTemplate(
forwardTemplate,
masterNode,
pass,
mode,
materialOptions));
subShader.AppendLines(GetExtraPassesFromTemplate(extraTemplate, masterNode, pass, mode, materialOptions));
}
return subShader.ToString();
}
static string GetTemplatePath(string templateName)
{
string relativeTemplatePath = Path.Combine("LWRP", Path.Combine("Editor", Path.Combine("ShaderGraph", templateName)));
foreach (var path in LightweightIncludePaths.GetPaths())
{
var templatePath = Path.Combine(path, relativeTemplatePath);
if (File.Exists(templatePath))
return templatePath;
}
throw new FileNotFoundException(string.Format(@"Cannot find a template with name ""{0}"".", templateName));
}
static string GetShaderPassFromTemplate(string template, PBRMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
{
// ----------------------------------------------------- //
// SETUP //
// ----------------------------------------------------- //
// -------------------------------------
// String builders
var functionBuilder = new ShaderStringBuilder(1);
var functionRegistry = new FunctionRegistry(functionBuilder);
surfaceInputs.AddShaderChunk("struct SurfaceInputs{", false);
surfaceInputs.Indent();
var defines = new ShaderStringBuilder(1);
var graph = new ShaderStringBuilder(0);
var activeNodeList = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);
var vertexDescriptionInputStruct = new ShaderStringBuilder(1);
var vertexDescriptionStruct = new ShaderStringBuilder(1);
var vertexDescriptionFunction = new ShaderStringBuilder(1);
var requirements = ShaderGraphRequirements.FromNodes(activeNodeList);
var surfaceDescriptionInputStruct = new ShaderStringBuilder(1);
var surfaceDescriptionStruct = new ShaderStringBuilder(1);
var surfaceDescriptionFunction = new ShaderStringBuilder(1);
var vertexInputStruct = new ShaderStringBuilder(1);
var vertexOutputStruct = new ShaderStringBuilder(2);
var vertexShader = new ShaderStringBuilder(2);
var vertexShaderDescriptionInputs = new ShaderStringBuilder(2);
var vertexShaderOutputs = new ShaderStringBuilder(2);
var pixelShader = new ShaderStringBuilder(2);
var pixelShaderSurfaceInputs = new ShaderStringBuilder(2);
var pixelShaderSurfaceRemap = new ShaderStringBuilder(2);
// -------------------------------------
// Get Slot and Node lists per stage
var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot<MaterialSlot>).ToList();
var vertexNodes = ListPool<AbstractMaterialNode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);
var pixelSlots = pass.PixelShaderSlots.Select(masterNode.FindSlot<MaterialSlot>).ToList();
var pixelNodes = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);
// -------------------------------------
// Get Requirements
var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);
var pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment);
var surfaceRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false);
modelRequiements.requiresNormal |= NeededCoordinateSpace.World;
modelRequiements.requiresTangent |= NeededCoordinateSpace.World;
modelRequiements.requiresBitangent |= NeededCoordinateSpace.World;
modelRequiements.requiresPosition |= NeededCoordinateSpace.World;
modelRequiements.requiresViewDir |= NeededCoordinateSpace.World;
modelRequiements.requiresNormal |= m_PixelCoordinateSpace;
modelRequiements.requiresTangent |= m_PixelCoordinateSpace;
modelRequiements.requiresBitangent |= m_PixelCoordinateSpace;
modelRequiements.requiresPosition |= m_PixelCoordinateSpace;
modelRequiements.requiresViewDir |= m_PixelCoordinateSpace;
GraphUtil.GenerateApplicationVertexInputs(requirements.Union(modelRequiements), vertexInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresNormal, InterpolatorType.Normal, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresTangent, InterpolatorType.Tangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresBitangent, InterpolatorType.BiTangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresPosition, InterpolatorType.Position, surfaceInputs);
// ----------------------------------------------------- //
// START SHADER GENERATION //
// ----------------------------------------------------- //
// -------------------------------------
// Calculate material options
var blendingBuilder = new ShaderStringBuilder(1);
var cullingBuilder = new ShaderStringBuilder(1);
var zTestBuilder = new ShaderStringBuilder(1);
var zWriteBuilder = new ShaderStringBuilder(1);
materialOptions.GetBlend(blendingBuilder);
materialOptions.GetCull(cullingBuilder);
materialOptions.GetDepthTest(zTestBuilder);
materialOptions.GetDepthWrite(zWriteBuilder);
if (requirements.requiresVertexColor)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.VertexColor), false);
// -------------------------------------
// Generate defines
if (masterNode.IsSlotConnected(PBRMasterNode.NormalSlotId))
defines.AppendLine("#define _NORMALMAP 1");
if (masterNode.model == PBRMasterNode.Model.Specular)
defines.AppendLine("#define _SPECULAR_SETUP 1");
if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId))
defines.AppendLine("#define _AlphaClip 1");
if(masterNode.surfaceType == SurfaceType.Transparent && masterNode.alphaMode == AlphaMode.Premultiply)
defines.AppendLine("#define _ALPHAPREMULTIPLY_ON 1");
// ----------------------------------------------------- //
// START VERTEX DESCRIPTION //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Vertex Description function
// TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces
vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs");
using (vertexDescriptionInputStruct.BlockSemicolonScope())
{
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct);
if (vertexRequirements.requiresVertexColor)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
if (vertexRequirements.requiresScreenPosition)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
}
// -------------------------------------
// Generate Output structure for Vertex Description function
GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots);
// -------------------------------------
// Generate Vertex Description function
GraphUtil.GenerateVertexDescriptionFunction(
masterNode.owner as AbstractMaterialGraph,
vertexDescriptionFunction,
functionRegistry,
shaderProperties,
mode,
vertexNodes,
vertexSlots);
// ----------------------------------------------------- //
// START SURFACE DESCRIPTION //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Surface Description function
// Surface Description Input requirements are needed to exclude intermediate translation spaces
surfaceDescriptionInputStruct.AppendLine("struct SurfaceDescriptionInputs");
using (surfaceDescriptionInputStruct.BlockSemicolonScope())
{
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct);
if (requirements.requiresScreenPosition)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.ScreenPosition), false);
if (surfaceRequirements.requiresVertexColor)
surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
foreach (var channel in requirements.requiresMeshUVs.Distinct())
surfaceInputs.AddShaderChunk(string.Format("half4 {0};", channel.GetUVName()), false);
if (surfaceRequirements.requiresScreenPosition)
surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
surfaceInputs.Deindent();
surfaceInputs.AddShaderChunk("};", false);
foreach (var channel in surfaceRequirements.requiresMeshUVs.Distinct())
surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
}
surfaceVertexShader.AddShaderChunk("GraphVertexInput PopulateVertexData(GraphVertexInput v){", false);
surfaceVertexShader.Indent();
surfaceVertexShader.AddShaderChunk("return v;", false);
surfaceVertexShader.Deindent();
surfaceVertexShader.AddShaderChunk("}", false);
// -------------------------------------
// Generate Output structure for Surface Description function
var slots = new List<MaterialSlot>();
foreach (var id in pass.PixelShaderSlots)
slots.Add(masterNode.FindSlot<MaterialSlot>(id));
GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, slots, true);
GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots, true);
var usedSlots = new List<MaterialSlot>();
foreach (var id in pass.PixelShaderSlots)
usedSlots.Add(masterNode.FindSlot<MaterialSlot>(id));
// -------------------------------------
// Generate Surface Description function
GraphUtil.GenerateSurfaceDescription(
activeNodeList,
GraphUtil.GenerateSurfaceDescriptionFunction(
pixelNodes,
requirements,
pixelRequirements,
usedSlots);
pixelSlots);
var graph = new ShaderGenerator();
graph.AddShaderChunk(shaderProperties.GetPropertiesDeclaration(2), false);
graph.AddShaderChunk(surfaceInputs.GetShaderString(2), false);
graph.AddShaderChunk(builder.ToString(), false);
graph.AddShaderChunk(vertexInputs.GetShaderString(2), false);
graph.AddShaderChunk(surfaceDescriptionStruct.GetShaderString(2), false);
graph.AddShaderChunk(surfaceVertexShader.GetShaderString(2), false);
graph.AddShaderChunk(surfaceDescriptionFunction.GetShaderString(2), false);
// ----------------------------------------------------- //
// GENERATE VERTEX > PIXEL PIPELINE //
// ----------------------------------------------------- //
var blendingVisitor = new ShaderGenerator();
var cullingVisitor = new ShaderGenerator();
var zTestVisitor = new ShaderGenerator();
var zWriteVisitor = new ShaderGenerator();
// -------------------------------------
// Generate Input structure for Vertex shader
materialOptions.GetBlend(blendingVisitor);
materialOptions.GetCull(cullingVisitor);
materialOptions.GetDepthTest(zTestVisitor);
materialOptions.GetDepthWrite(zWriteVisitor);
GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(pixelRequirements.Union(modelRequiements)), vertexInputStruct);
var interpolators = new ShaderGenerator();
var localVertexShader = new ShaderGenerator();
var localPixelShader = new ShaderGenerator();
var localSurfaceInputs = new ShaderGenerator();
var surfaceOutputRemap = new ShaderGenerator();
// -------------------------------------
// Generate standard transformations
// This method ensures all required transform data is available in vertex and pixel stages
interpolators,
localVertexShader,
localPixelShader,
localSurfaceInputs,
requirements,
vertexOutputStruct,
vertexShader,
vertexShaderDescriptionInputs,
vertexShaderOutputs,
pixelShader,
pixelShaderSurfaceInputs,
pixelRequirements,
surfaceRequirements,
vertexRequirements,
ShaderGenerator defines = new ShaderGenerator();
// -------------------------------------
// Generate pixel shader surface remap
if (masterNode.IsSlotConnected(PBRMasterNode.NormalSlotId))
defines.AddShaderChunk("#define _NORMALMAP 1", true);
foreach (var slot in pixelSlots)
{
pixelShaderSurfaceRemap.AppendLine("{0} = surf.{0};", slot.shaderOutputName);
}
if (masterNode.model == PBRMasterNode.Model.Specular)
defines.AddShaderChunk("#define _SPECULAR_SETUP 1", true);
// ----------------------------------------------------- //
// FINALIZE //
// ----------------------------------------------------- //
if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId))
defines.AddShaderChunk("#define _AlphaClip 1", true);
// -------------------------------------
// Combine Graph sections
if (masterNode.surfaceType == SurfaceType.Transparent && masterNode.alphaMode == AlphaMode.Premultiply)
defines.AddShaderChunk("#define _ALPHAPREMULTIPLY_ON 1", true);
graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1));
var templateLocation = GetTemplatePath(template);
graph.AppendLine(vertexDescriptionInputStruct.ToString());
graph.AppendLine(surfaceDescriptionInputStruct.ToString());
foreach (var slot in usedSlots)
{
surfaceOutputRemap.AddShaderChunk(string.Format("{0} = surf.{0};", slot.shaderOutputName), true);
}
graph.AppendLine(functionBuilder.ToString());
graph.AppendLine(vertexDescriptionStruct.ToString());
graph.AppendLine(vertexDescriptionFunction.ToString());
graph.AppendLine(surfaceDescriptionStruct.ToString());
graph.AppendLine(surfaceDescriptionFunction.ToString());
graph.AppendLine(vertexInputStruct.ToString());
// -------------------------------------
// Generate final subshader
var resultPass = template.Replace("${Tags}", string.Empty);
resultPass = resultPass.Replace("${Blending}", blendingBuilder.ToString());
resultPass = resultPass.Replace("${Culling}", cullingBuilder.ToString());
resultPass = resultPass.Replace("${ZTest}", zTestBuilder.ToString());
resultPass = resultPass.Replace("${ZWrite}", zWriteBuilder.ToString());
resultPass = resultPass.Replace("${Defines}", defines.ToString());
resultPass = resultPass.Replace("${Graph}", graph.ToString());
resultPass = resultPass.Replace("${VertexOutputStruct}", vertexOutputStruct.ToString());
if (!File.Exists(templateLocation))
return string.Empty;
resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString());
resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexShaderDescriptionInputs.ToString());
resultPass = resultPass.Replace("${VertexShaderOutputs}", vertexShaderOutputs.ToString());
var subShaderTemplate = File.ReadAllText(templateLocation);
var resultPass = subShaderTemplate.Replace("${Defines}", defines.GetShaderString(3));
resultPass = resultPass.Replace("${Graph}", graph.GetShaderString(3));
resultPass = resultPass.Replace("${Interpolators}", interpolators.GetShaderString(3));
resultPass = resultPass.Replace("${VertexShader}", localVertexShader.GetShaderString(3));
resultPass = resultPass.Replace("${LocalPixelShader}", localPixelShader.GetShaderString(3));
resultPass = resultPass.Replace("${SurfaceInputs}", localSurfaceInputs.GetShaderString(3));
resultPass = resultPass.Replace("${SurfaceOutputRemap}", surfaceOutputRemap.GetShaderString(3));
resultPass = resultPass.Replace("${PixelShader}", pixelShader.ToString());
resultPass = resultPass.Replace("${PixelShaderSurfaceInputs}", pixelShaderSurfaceInputs.ToString());
resultPass = resultPass.Replace("${PixelShaderSurfaceRemap}", pixelShaderSurfaceRemap.ToString());
resultPass = resultPass.Replace("${Tags}", string.Empty);
resultPass = resultPass.Replace("${Blending}", blendingVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${Culling}", cullingVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${ZTest}", zTestVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${ZWrite}", zWriteVisitor.GetShaderString(2));
static string GetTemplatePath(string templateName)
static string GetExtraPassesFromTemplate(string template, PBRMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
string relativeTemplatePath = Path.Combine("LWRP", Path.Combine("Editor", Path.Combine("ShaderGraph", templateName)));
foreach (var path in LightweightIncludePaths.GetPaths())
{
var templatePath = Path.Combine(path, relativeTemplatePath);
if (File.Exists(templatePath))
return templatePath;
}
throw new FileNotFoundException(string.Format(@"Cannot find a template with name ""{0}"".", templateName));
}
// ----------------------------------------------------- //
// SETUP //
// ----------------------------------------------------- //
// -------------------------------------
// String builders
public string GetSubshader(IMasterNode inMasterNode, GenerationMode mode)
{
var masterNode = inMasterNode as PBRMasterNode;
var subShader = new ShaderGenerator();
subShader.AddShaderChunk("SubShader", true);
subShader.AddShaderChunk("{", true);
subShader.Indent();
subShader.AddShaderChunk("Tags{ \"RenderPipeline\" = \"LightweightPipeline\"}", true);
var dummyBuilder = new ShaderStringBuilder(0);
var shaderProperties = new PropertyCollector();
var functionBuilder = new ShaderStringBuilder(1);
var functionRegistry = new FunctionRegistry(functionBuilder);
var materialOptions = ShaderGenerator.GetMaterialOptions(masterNode.surfaceType, masterNode.alphaMode, masterNode.twoSided.isOn);
var tagsVisitor = new ShaderGenerator();
materialOptions.GetTags(tagsVisitor);
subShader.AddShaderChunk(tagsVisitor.GetShaderString(0), true);
var defines = new ShaderStringBuilder(2);
var graph = new ShaderStringBuilder(0);
subShader.AddShaderChunk(
GetShaderPassFromTemplate(
"lightweightPBRForwardPass.template",
masterNode,
masterNode.model == PBRMasterNode.Model.Metallic ? m_ForwardPassMetallic : m_ForwardPassSpecular,
mode,
materialOptions),
true);
var vertexDescriptionInputStruct = new ShaderStringBuilder(1);
var vertexDescriptionStruct = new ShaderStringBuilder(1);
var vertexDescriptionFunction = new ShaderStringBuilder(1);
var extraPassesTemplateLocation = GetTemplatePath("lightweightPBRExtraPasses.template");
if (File.Exists(extraPassesTemplateLocation))
var vertexInputStruct = new ShaderStringBuilder(1);
var vertexShader = new ShaderStringBuilder(2);
var vertexDescriptionInputs = new ShaderStringBuilder(2);
// -------------------------------------
// Get Slot and Node lists per stage
var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot<MaterialSlot>).ToList();
var vertexNodes = ListPool<AbstractMaterialNode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);
// -------------------------------------
// Get requirements
var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);
var modelRequiements = ShaderGraphRequirements.none;
modelRequiements.requiresNormal |= m_VertexCoordinateSpace;
modelRequiements.requiresPosition |= m_VertexCoordinateSpace;
modelRequiements.requiresMeshUVs.Add(UVChannel.UV1);
// ----------------------------------------------------- //
// START SHADER GENERATION //
// ----------------------------------------------------- //
// -------------------------------------
// Calculate material options
var cullingBuilder = new ShaderStringBuilder(1);
materialOptions.GetCull(cullingBuilder);
// -------------------------------------
// Generate defines
if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId))
defines.AppendLine("#define _AlphaClip 1");
// ----------------------------------------------------- //
// START VERTEX DESCRIPTION //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Vertex Description function
// TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces
vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs");
using (vertexDescriptionInputStruct.BlockSemicolonScope())
var extraPassesTemplate = File.ReadAllText(extraPassesTemplateLocation);
extraPassesTemplate = extraPassesTemplate.Replace("${Culling}", materialOptions.cullMode.ToString());
subShader.AddShaderChunk(extraPassesTemplate, true);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct);
if (vertexRequirements.requiresVertexColor)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
if (vertexRequirements.requiresScreenPosition)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
subShader.Deindent();
subShader.AddShaderChunk("}", true);
// -------------------------------------
// Generate Output structure for Vertex Description function
GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots);
// -------------------------------------
// Generate Vertex Description function
GraphUtil.GenerateVertexDescriptionFunction(
masterNode.owner as AbstractMaterialGraph,
vertexDescriptionFunction,
functionRegistry,
shaderProperties,
mode,
vertexNodes,
vertexSlots);
// ----------------------------------------------------- //
// GENERATE VERTEX > PIXEL PIPELINE //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Vertex shader
GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(modelRequiements), vertexInputStruct);
// -------------------------------------
// Generate standard transformations
// This method ensures all required transform data is available in vertex and pixel stages
ShaderGenerator.GenerateStandardTransforms(
3,
10,
dummyBuilder,
vertexShader,
vertexDescriptionInputs,
dummyBuilder,
dummyBuilder,
dummyBuilder,
ShaderGraphRequirements.none,
ShaderGraphRequirements.none,
modelRequiements,
vertexRequirements,
CoordinateSpace.World);
// ----------------------------------------------------- //
// FINALIZE //
// ----------------------------------------------------- //
// -------------------------------------
// Combine Graph sections
graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1));
graph.AppendLine(vertexDescriptionInputStruct.ToString());
graph.AppendLine(functionBuilder.ToString());
graph.AppendLine(vertexDescriptionStruct.ToString());
graph.AppendLine(vertexDescriptionFunction.ToString());
graph.AppendLine(vertexInputStruct.ToString());
// -------------------------------------
// Generate final subshader
var resultPass = template.Replace("${Culling}", cullingBuilder.ToString());
resultPass = resultPass.Replace("${Defines}", defines.ToString());
resultPass = resultPass.Replace("${Graph}", graph.ToString());
resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString());
resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexDescriptionInputs.ToString());
return subShader.GetShaderString(0);
return resultPass;
}
}

582
ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/LightWeightUnlitSubShader.cs


[FormerName("UnityEditor.ShaderGraph.LightWeightUnlitSubShader")]
public class LightWeightUnlitSubShader : IUnlitSubShader
{
static NeededCoordinateSpace m_VertexCoordinateSpace = NeededCoordinateSpace.Object;
static NeededCoordinateSpace m_PixelCoordinateSpace = NeededCoordinateSpace.World;
struct Pass
{
public string Name;
public List<int> VertexShaderSlots;
public List<int> PixelShaderSlots;
}
Name = "Unlit",
Name = "Pass",
},
VertexShaderSlots = new List<int>()
{
UnlitMasterNode.PositionSlotId
struct Pass
public string GetSubshader(IMasterNode inMasterNode, GenerationMode mode)
public string Name;
public List<int> VertexShaderSlots;
public List<int> PixelShaderSlots;
var templatePath = GetTemplatePath("lightweightUnlitPass.template");
var extraPassesTemplatePath = GetTemplatePath("lightweightUnlitExtraPasses.template");
if (!File.Exists(templatePath) || !File.Exists(extraPassesTemplatePath))
return string.Empty;
string forwardTemplate = File.ReadAllText(templatePath);
string extraTemplate = File.ReadAllText(extraPassesTemplatePath);
var masterNode = inMasterNode as UnlitMasterNode;
var pass = m_UnlitPass;
var subShader = new ShaderStringBuilder();
subShader.AppendLine("SubShader");
using (subShader.BlockScope())
{
subShader.AppendLine("Tags{ \"RenderPipeline\" = \"LightweightPipeline\"}");
var materialOptions = ShaderGenerator.GetMaterialOptions(masterNode.surfaceType, masterNode.alphaMode, masterNode.twoSided.isOn);
var tagsBuilder = new ShaderStringBuilder(0);
materialOptions.GetTags(tagsBuilder);
subShader.AppendLines(tagsBuilder.ToString());
subShader.AppendLines(GetShaderPassFromTemplate(
forwardTemplate,
masterNode,
pass,
mode,
materialOptions));
subShader.AppendLines(GetExtraPassesFromTemplate(extraTemplate, masterNode, pass, mode, materialOptions));
}
return subShader.ToString();
private static string GetShaderPassFromTemplate(
string template,
UnlitMasterNode masterNode,
Pass pass,
GenerationMode mode,
SurfaceMaterialOptions materialOptions)
static string GetTemplatePath(string templateName)
var builder = new ShaderStringBuilder();
builder.IncreaseIndent();
builder.IncreaseIndent();
var vertexInputs = new ShaderGenerator();
var surfaceVertexShader = new ShaderGenerator();
var surfaceDescriptionFunction = new ShaderGenerator();
var surfaceDescriptionStruct = new ShaderGenerator();
var functionRegistry = new FunctionRegistry(builder);
var surfaceInputs = new ShaderGenerator();
string relativeTemplatePath = Path.Combine("LWRP", Path.Combine("Editor", Path.Combine("ShaderGraph", templateName)));
foreach (var path in LightweightIncludePaths.GetPaths())
{
var templatePath = Path.Combine(path, relativeTemplatePath);
if (File.Exists(templatePath))
return templatePath;
}
throw new FileNotFoundException(string.Format(@"Cannot find a template with name ""{0}"".", templateName));
}
static string GetShaderPassFromTemplate(string template, UnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
{
// ----------------------------------------------------- //
// SETUP //
// ----------------------------------------------------- //
// -------------------------------------
// String builders
var functionBuilder = new ShaderStringBuilder(1);
var functionRegistry = new FunctionRegistry(functionBuilder);
var defines = new ShaderStringBuilder(1);
var graph = new ShaderStringBuilder(0);
surfaceInputs.AddShaderChunk("struct SurfaceInputs{", false);
surfaceInputs.Indent();
var vertexDescriptionInputStruct = new ShaderStringBuilder(1);
var vertexDescriptionStruct = new ShaderStringBuilder(1);
var vertexDescriptionFunction = new ShaderStringBuilder(1);
var surfaceDescriptionInputStruct = new ShaderStringBuilder(1);
var surfaceDescriptionStruct = new ShaderStringBuilder(1);
var surfaceDescriptionFunction = new ShaderStringBuilder(1);
var vertexInputStruct = new ShaderStringBuilder(1);
var vertexOutputStruct = new ShaderStringBuilder(2);
var vertexShader = new ShaderStringBuilder(2);
var vertexShaderDescriptionInputs = new ShaderStringBuilder(2);
var vertexShaderOutputs = new ShaderStringBuilder(2);
var pixelShader = new ShaderStringBuilder(2);
var pixelShaderSurfaceInputs = new ShaderStringBuilder(2);
var pixelShaderSurfaceRemap = new ShaderStringBuilder(2);
// -------------------------------------
// Get Slot and Node lists per stage
var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot<MaterialSlot>).ToList();
var vertexNodes = ListPool<AbstractMaterialNode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);
var pixelSlots = pass.PixelShaderSlots.Select(masterNode.FindSlot<MaterialSlot>).ToList();
var pixelNodes = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);
// -------------------------------------
// Get Requirements
var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);
var pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment);
var surfaceRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false);
var modelRequiements = ShaderGraphRequirements.none;
modelRequiements.requiresNormal |= m_PixelCoordinateSpace;
modelRequiements.requiresTangent |= m_PixelCoordinateSpace;
modelRequiements.requiresBitangent |= m_PixelCoordinateSpace;
modelRequiements.requiresPosition |= m_PixelCoordinateSpace;
modelRequiements.requiresViewDir |= m_PixelCoordinateSpace;
modelRequiements.requiresMeshUVs.Add(UVChannel.UV1);
// ----------------------------------------------------- //
// START SHADER GENERATION //
// ----------------------------------------------------- //
// -------------------------------------
// Calculate material options
var blendingBuilder = new ShaderStringBuilder(1);
var cullingBuilder = new ShaderStringBuilder(1);
var zTestBuilder = new ShaderStringBuilder(1);
var zWriteBuilder = new ShaderStringBuilder(1);
materialOptions.GetBlend(blendingBuilder);
materialOptions.GetCull(cullingBuilder);
materialOptions.GetDepthTest(zTestBuilder);
materialOptions.GetDepthWrite(zWriteBuilder);
// -------------------------------------
// Generate defines
if (masterNode.IsSlotConnected(UnlitMasterNode.AlphaThresholdSlotId))
defines.AppendLine("#define _AlphaClip 1");
if(masterNode.surfaceType == SurfaceType.Transparent && masterNode.alphaMode == AlphaMode.Premultiply)
defines.AppendLine("#define _ALPHAPREMULTIPLY_ON 1");
// ----------------------------------------------------- //
// START VERTEX DESCRIPTION //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Vertex Description function
// TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces
vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs");
using (vertexDescriptionInputStruct.BlockSemicolonScope())
{
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct);
if (vertexRequirements.requiresVertexColor)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
var activeNodeList = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);
if (vertexRequirements.requiresScreenPosition)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
var requirements = ShaderGraphRequirements.FromNodes(activeNodeList);
GraphUtil.GenerateApplicationVertexInputs(requirements, vertexInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresNormal, InterpolatorType.Normal, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresTangent, InterpolatorType.Tangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresBitangent, InterpolatorType.BiTangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresPosition, InterpolatorType.Position, surfaceInputs);
foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
}
if (requirements.requiresVertexColor)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.VertexColor), false);
// -------------------------------------
// Generate Output structure for Vertex Description function
if (requirements.requiresScreenPosition)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.ScreenPosition), false);
GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots);
foreach (var channel in requirements.requiresMeshUVs.Distinct())
surfaceInputs.AddShaderChunk(string.Format("half4 {0};", channel.GetUVName()), false);
// -------------------------------------
// Generate Vertex Description function
surfaceInputs.Deindent();
surfaceInputs.AddShaderChunk("};", false);
GraphUtil.GenerateVertexDescriptionFunction(
masterNode.owner as AbstractMaterialGraph,
vertexDescriptionFunction,
functionRegistry,
shaderProperties,
mode,
vertexNodes,
vertexSlots);
surfaceVertexShader.AddShaderChunk("GraphVertexInput PopulateVertexData(GraphVertexInput v){", false);
surfaceVertexShader.Indent();
surfaceVertexShader.AddShaderChunk("return v;", false);
surfaceVertexShader.Deindent();
surfaceVertexShader.AddShaderChunk("}", false);
// ----------------------------------------------------- //
// START SURFACE DESCRIPTION //
// ----------------------------------------------------- //
var slots = new List<MaterialSlot>();
foreach (var id in pass.PixelShaderSlots)
// -------------------------------------
// Generate Input structure for Surface Description function
// Surface Description Input requirements are needed to exclude intermediate translation spaces
surfaceDescriptionInputStruct.AppendLine("struct SurfaceDescriptionInputs");
using (surfaceDescriptionInputStruct.BlockSemicolonScope())
var slot = masterNode.FindSlot<MaterialSlot>(id);
if (slot != null)
slots.Add(slot);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct);
if (surfaceRequirements.requiresVertexColor)
surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
if (surfaceRequirements.requiresScreenPosition)
surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
foreach (var channel in surfaceRequirements.requiresMeshUVs.Distinct())
surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, slots, true);
var usedSlots = new List<MaterialSlot>();
foreach (var id in pass.PixelShaderSlots)
usedSlots.Add(masterNode.FindSlot<MaterialSlot>(id));
// -------------------------------------
// Generate Output structure for Surface Description function
GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots, true);
GraphUtil.GenerateSurfaceDescription(
activeNodeList,
// -------------------------------------
// Generate Surface Description function
GraphUtil.GenerateSurfaceDescriptionFunction(
pixelNodes,
requirements,
pixelRequirements,
usedSlots);
var graph = new ShaderGenerator();
graph.AddShaderChunk(shaderProperties.GetPropertiesDeclaration(2), false);
graph.AddShaderChunk(surfaceInputs.GetShaderString(2), false);
graph.AddShaderChunk(builder.ToString(), false);
graph.AddShaderChunk(vertexInputs.GetShaderString(2), false);
graph.AddShaderChunk(surfaceDescriptionStruct.GetShaderString(2), false);
graph.AddShaderChunk(surfaceVertexShader.GetShaderString(2), false);
graph.AddShaderChunk(surfaceDescriptionFunction.GetShaderString(2), false);
pixelSlots);
var blendingVisitor = new ShaderGenerator();
var cullingVisitor = new ShaderGenerator();
var zTestVisitor = new ShaderGenerator();
var zWriteVisitor = new ShaderGenerator();
// ----------------------------------------------------- //
// GENERATE VERTEX > PIXEL PIPELINE //
// ----------------------------------------------------- //
materialOptions.GetBlend(blendingVisitor);
materialOptions.GetCull(cullingVisitor);
materialOptions.GetDepthTest(zTestVisitor);
materialOptions.GetDepthWrite(zWriteVisitor);
// -------------------------------------
// Generate Input structure for Vertex shader
var interpolators = new ShaderGenerator();
var localVertexShader = new ShaderGenerator();
var localPixelShader = new ShaderGenerator();
var localSurfaceInputs = new ShaderGenerator();
var surfaceOutputRemap = new ShaderGenerator();
GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(pixelRequirements.Union(modelRequiements)), vertexInputStruct);
var reqs = ShaderGraphRequirements.none;
// -------------------------------------
// Generate standard transformations
// This method ensures all required transform data is available in vertex and pixel stages
interpolators,
localVertexShader,
localPixelShader,
localSurfaceInputs,
requirements,
reqs,
vertexOutputStruct,
vertexShader,
vertexShaderDescriptionInputs,
vertexShaderOutputs,
pixelShader,
pixelShaderSurfaceInputs,
pixelRequirements,
surfaceRequirements,
modelRequiements,
vertexRequirements,
ShaderGenerator defines = new ShaderGenerator();
// -------------------------------------
// Generate pixel shader surface remap
if (masterNode.IsSlotConnected(UnlitMasterNode.AlphaThresholdSlotId))
defines.AddShaderChunk("#define _AlphaClip 1", true);
foreach (var slot in pixelSlots)
{
pixelShaderSurfaceRemap.AppendLine("{0} = surf.{0};", slot.shaderOutputName);
}
if (masterNode.surfaceType == SurfaceType.Transparent && masterNode.alphaMode == AlphaMode.Premultiply)
defines.AddShaderChunk("#define _ALPHAPREMULTIPLY_ON 1", true);
// ----------------------------------------------------- //
// FINALIZE //
// ----------------------------------------------------- //
var templateLocation = GetTemplatePath(template);
// -------------------------------------
// Combine Graph sections
foreach (var slot in usedSlots)
{
surfaceOutputRemap.AddShaderChunk(slot.shaderOutputName
+ " = surf."
+ slot.shaderOutputName + ";", true);
}
graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1));
if (!File.Exists(templateLocation))
return string.Empty;
graph.AppendLine(vertexDescriptionInputStruct.ToString());
graph.AppendLine(surfaceDescriptionInputStruct.ToString());
var subShaderTemplate = File.ReadAllText(templateLocation);
var resultPass = subShaderTemplate.Replace("${Defines}", defines.GetShaderString(3));
resultPass = resultPass.Replace("${Graph}", graph.GetShaderString(3));
resultPass = resultPass.Replace("${Interpolators}", interpolators.GetShaderString(3));
resultPass = resultPass.Replace("${VertexShader}", localVertexShader.GetShaderString(3));
resultPass = resultPass.Replace("${LocalPixelShader}", localPixelShader.GetShaderString(3));
resultPass = resultPass.Replace("${SurfaceInputs}", localSurfaceInputs.GetShaderString(3));
resultPass = resultPass.Replace("${SurfaceOutputRemap}", surfaceOutputRemap.GetShaderString(3));
graph.AppendLine(functionBuilder.ToString());
resultPass = resultPass.Replace("${Tags}", string.Empty);
resultPass = resultPass.Replace("${Blending}", blendingVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${Culling}", cullingVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${ZTest}", zTestVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${ZWrite}", zWriteVisitor.GetShaderString(2));
graph.AppendLine(vertexDescriptionStruct.ToString());
graph.AppendLine(vertexDescriptionFunction.ToString());
graph.AppendLine(surfaceDescriptionStruct.ToString());
graph.AppendLine(surfaceDescriptionFunction.ToString());
graph.AppendLine(vertexInputStruct.ToString());
// -------------------------------------
// Generate final subshader
var resultPass = template.Replace("${Tags}", string.Empty);
resultPass = resultPass.Replace("${Blending}", blendingBuilder.ToString());
resultPass = resultPass.Replace("${Culling}", cullingBuilder.ToString());
resultPass = resultPass.Replace("${ZTest}", zTestBuilder.ToString());
resultPass = resultPass.Replace("${ZWrite}", zWriteBuilder.ToString());
resultPass = resultPass.Replace("${Defines}", defines.ToString());
resultPass = resultPass.Replace("${Graph}", graph.ToString());
resultPass = resultPass.Replace("${VertexOutputStruct}", vertexOutputStruct.ToString());
resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString());
resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexShaderDescriptionInputs.ToString());
resultPass = resultPass.Replace("${VertexShaderOutputs}", vertexShaderOutputs.ToString());
resultPass = resultPass.Replace("${PixelShader}", pixelShader.ToString());
resultPass = resultPass.Replace("${PixelShaderSurfaceInputs}", pixelShaderSurfaceInputs.ToString());
resultPass = resultPass.Replace("${PixelShaderSurfaceRemap}", pixelShaderSurfaceRemap.ToString());
static string GetTemplatePath(string templateName)
static string GetExtraPassesFromTemplate(string template, UnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
string relativeTemplatePath = Path.Combine("LWRP", Path.Combine("Editor", Path.Combine("ShaderGraph", templateName)));
foreach (var path in LightweightIncludePaths.GetPaths())
// ----------------------------------------------------- //
// SETUP //
// ----------------------------------------------------- //
// -------------------------------------
// String builders
var dummyBuilder = new ShaderStringBuilder(0);
var shaderProperties = new PropertyCollector();
var functionBuilder = new ShaderStringBuilder(1);
var functionRegistry = new FunctionRegistry(functionBuilder);
var defines = new ShaderStringBuilder(2);
var graph = new ShaderStringBuilder(0);
var vertexDescriptionInputStruct = new ShaderStringBuilder(1);
var vertexDescriptionStruct = new ShaderStringBuilder(1);
var vertexDescriptionFunction = new ShaderStringBuilder(1);
var vertexInputStruct = new ShaderStringBuilder(1);
var vertexShader = new ShaderStringBuilder(2);
var vertexDescriptionInputs = new ShaderStringBuilder(2);
// -------------------------------------
// Get Slot and Node lists per stage
var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot<MaterialSlot>).ToList();
var vertexNodes = ListPool<AbstractMaterialNode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);
// -------------------------------------
// Get requirements
var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);
var modelRequiements = ShaderGraphRequirements.none;
modelRequiements.requiresNormal |= m_VertexCoordinateSpace;
modelRequiements.requiresPosition |= m_VertexCoordinateSpace;
modelRequiements.requiresMeshUVs.Add(UVChannel.UV1);
// ----------------------------------------------------- //
// START SHADER GENERATION //
// ----------------------------------------------------- //
// -------------------------------------
// Calculate material options
var cullingBuilder = new ShaderStringBuilder(1);
materialOptions.GetCull(cullingBuilder);
// -------------------------------------
// Generate defines
if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId))
defines.AppendLine("#define _AlphaClip 1");
// ----------------------------------------------------- //
// START VERTEX DESCRIPTION //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Vertex Description function
// TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces
vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs");
using (vertexDescriptionInputStruct.BlockSemicolonScope())
var templatePath = Path.Combine(path, relativeTemplatePath);
if (File.Exists(templatePath))
return templatePath;
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct);
if (vertexRequirements.requiresVertexColor)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
if (vertexRequirements.requiresScreenPosition)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
throw new FileNotFoundException(string.Format(@"Cannot find a template with name ""{0}"".", templateName));
}
// -------------------------------------
// Generate Output structure for Vertex Description function
GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots);
// -------------------------------------
// Generate Vertex Description function
GraphUtil.GenerateVertexDescriptionFunction(
masterNode.owner as AbstractMaterialGraph,
vertexDescriptionFunction,
functionRegistry,
shaderProperties,
mode,
vertexNodes,
vertexSlots);
// ----------------------------------------------------- //
// GENERATE VERTEX > PIXEL PIPELINE //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Vertex shader
GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(modelRequiements), vertexInputStruct);
// -------------------------------------
// Generate standard transformations
// This method ensures all required transform data is available in vertex and pixel stages
public string GetSubshader(IMasterNode inMasterNode, GenerationMode mode)
{
var masterNode = inMasterNode as UnlitMasterNode;
var subShader = new ShaderGenerator();
subShader.AddShaderChunk("SubShader", true);
subShader.AddShaderChunk("{", true);
subShader.Indent();
subShader.AddShaderChunk("Tags{ \"RenderType\" = \"Opaque\" \"RenderPipeline\" = \"LightweightPipeline\"}", true);
ShaderGenerator.GenerateStandardTransforms(
3,
10,
dummyBuilder,
vertexShader,
vertexDescriptionInputs,
dummyBuilder,
dummyBuilder,
dummyBuilder,
ShaderGraphRequirements.none,
ShaderGraphRequirements.none,
modelRequiements,
vertexRequirements,
CoordinateSpace.World);
var materialOptions = ShaderGenerator.GetMaterialOptions(masterNode.surfaceType, masterNode.alphaMode, masterNode.twoSided.isOn);
var tagsVisitor = new ShaderGenerator();
materialOptions.GetTags(tagsVisitor);
subShader.AddShaderChunk(tagsVisitor.GetShaderString(0), true);
// ----------------------------------------------------- //
// FINALIZE //
// ----------------------------------------------------- //
subShader.AddShaderChunk(
GetShaderPassFromTemplate(
"lightweightUnlitPass.template",
masterNode,
m_UnlitPass,
mode,
materialOptions),
true);
// -------------------------------------
// Combine Graph sections
var extraPassesTemplateLocation = GetTemplatePath("lightweightUnlitExtraPasses.template");
if (File.Exists(extraPassesTemplateLocation))
{
var extraPassesTemplate = File.ReadAllText(extraPassesTemplateLocation);
extraPassesTemplate = extraPassesTemplate.Replace("${Culling}", materialOptions.cullMode.ToString());
subShader.AddShaderChunk(extraPassesTemplate, true);
}
graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1));
subShader.Deindent();
subShader.AddShaderChunk("}", true);
graph.AppendLine(vertexDescriptionInputStruct.ToString());
return subShader.GetShaderString(0);
graph.AppendLine(functionBuilder.ToString());
graph.AppendLine(vertexDescriptionStruct.ToString());
graph.AppendLine(vertexDescriptionFunction.ToString());
graph.AppendLine(vertexInputStruct.ToString());
// -------------------------------------
// Generate final subshader
var resultPass = template.Replace("${Culling}", cullingBuilder.ToString());
resultPass = resultPass.Replace("${Defines}", defines.ToString());
resultPass = resultPass.Replace("${Graph}", graph.ToString());
resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString());
resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexDescriptionInputs.ToString());
return resultPass;
}
}

208
ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightPBRExtraPasses.template


Pass
{
Name "ShadowCaster"
Tags{"LightMode" = "ShadowCaster"}
Name "ShadowCaster"
Tags{"LightMode" = "ShadowCaster"}
ZWrite On
ZTest LEqual
Cull ${Culling}
ZWrite On ZTest LEqual
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
// Material options generated by graph
${Culling}
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
// -------------------------------------
// Material Keywords
#pragma shader_feature _ALPHATEST_ON
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
// Defines generated by graph
${Defines}
#include "LWRP/ShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
#include "ShaderGraphLibrary/Functions.hlsl"
#include "CoreRP/ShaderLibrary/Color.hlsl"
#include "LWRP/ShaderLibrary/InputSurfacePBR.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassShadow.hlsl"
${Graph}
struct VertexOutput
{
float2 uv : TEXCOORD0;
float4 clipPos : SV_POSITION;
};
// x: global clip space bias, y: normal world space bias
float4 _ShadowBias;
float3 _LightDirection;
ENDHLSL
VertexOutput ShadowPassVertex(GraphVertexInput v)
{
VertexOutput o;
UNITY_SETUP_INSTANCE_ID(v);
// Vertex transformations performed by graph
${VertexShader}
VertexDescriptionInputs vdi = (VertexDescriptionInputs)0;
// Vertex description inputs defined by graph
${VertexShaderDescriptionInputs}
VertexDescription vd = PopulateVertexData(vdi);
v.vertex.xyz = vd.Position;
o.uv = uv1;
float3 positionWS = TransformObjectToWorld(v.vertex.xyz);
float3 normalWS = TransformObjectToWorldDir(v.normal);
float invNdotL = 1.0 - saturate(dot(_LightDirection, normalWS));
float scale = invNdotL * _ShadowBias.y;
// normal bias is negative since we want to apply an inset normal offset
positionWS = normalWS * scale.xxx + positionWS;
float4 clipPos = TransformWorldToHClip(positionWS);
// _ShadowBias.x sign depens on if platform has reversed z buffer
clipPos.z += _ShadowBias.x;
#if UNITY_REVERSED_Z
clipPos.z = min(clipPos.z, clipPos.w * UNITY_NEAR_CLIP_VALUE);
#else
clipPos.z = max(clipPos.z, clipPos.w * UNITY_NEAR_CLIP_VALUE);
#endif
o.clipPos = clipPos;
return o;
}
half4 ShadowPassFragment() : SV_TARGET
{
return 0;
}
ENDHLSL
Name "DepthOnly"
Tags{"LightMode" = "DepthOnly"}
Name "DepthOnly"
Tags{"LightMode" = "DepthOnly"}
ZWrite On
ColorMask 0
Cull ${Culling}
ZWrite On
ColorMask 0
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma target 2.0
// Material options generated by graph
${Culling}
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
#pragma vertex DepthOnlyVertex
#pragma fragment DepthOnlyFragment
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
// -------------------------------------
// Material Keywords
#pragma shader_feature _ALPHATEST_ON
#pragma vertex vert
#pragma fragment frag
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
// Defines generated by graph
${Defines}
#include "LWRP/ShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
#include "ShaderGraphLibrary/Functions.hlsl"
#include "CoreRP/ShaderLibrary/Color.hlsl"
#include "LWRP/ShaderLibrary/InputSurfacePBR.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassDepthOnly.hlsl"
ENDHLSL
${Graph}
struct VertexOutput
{
float2 uv : TEXCOORD0;
float4 clipPos : SV_POSITION;
};
VertexOutput vert(GraphVertexInput v)
{
VertexOutput o = (VertexOutput)0;
UNITY_SETUP_INSTANCE_ID(v);
// Vertex transformations performed by graph
${VertexShader}
VertexDescriptionInputs vdi = (VertexDescriptionInputs)0;
// Vertex description inputs defined by graph
${VertexShaderDescriptionInputs}
VertexDescription vd = PopulateVertexData(vdi);
v.vertex.xyz = vd.Position;
o.uv = uv1;
o.clipPos = TransformObjectToHClip(v.vertex.xyz);
return o;
}
half4 frag() : SV_TARGET
{
return 0;
}
ENDHLSL
Name "Meta"
Tags{"LightMode" = "Meta"}
Name "Meta"
Tags{"LightMode" = "Meta"}
Cull Off
Cull Off
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
#pragma vertex LightweightVertexMeta
#pragma fragment LightweightFragmentMeta
#pragma vertex LightweightVertexMeta
#pragma fragment LightweightFragmentMeta
#pragma shader_feature _SPECULAR_SETUP
#pragma shader_feature _EMISSION
#pragma shader_feature _METALLICSPECGLOSSMAP
#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature EDITOR_VISUALIZATION
#pragma shader_feature _SPECULAR_SETUP
#pragma shader_feature _EMISSION
#pragma shader_feature _METALLICSPECGLOSSMAP
#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature EDITOR_VISUALIZATION
#pragma shader_feature _SPECGLOSSMAP
#pragma shader_feature _SPECGLOSSMAP
#include "LWRP/ShaderLibrary/InputSurfacePBR.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassMetaPBR.hlsl"
ENDHLSL
}
#include "LWRP/ShaderLibrary/InputSurfacePBR.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassMetaPBR.hlsl"
ENDHLSL
}

94
ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightPBRForwardPass.template


Pass
{
Name "StandardLit"
${Tags}
${Blending}
${Culling}
${ZTest}
${ZWrite}
// Material options generated by graph
${Tags}
${Blending}
${Culling}
${ZTest}
${ZWrite}
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
// Lightweight Pipeline keywords
#pragma multi_compile _ _ADDITIONAL_LIGHTS
#pragma multi_compile _ _VERTEX_LIGHTS
#pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
#pragma multi_compile _ _SHADOWS_ENABLED
// Lightweight Pipeline keywords
#pragma multi_compile _ _ADDITIONAL_LIGHTS
#pragma multi_compile _ _VERTEX_LIGHTS
#pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
#pragma multi_compile _ _SHADOWS_ENABLED
// Unity defined keywords
#pragma multi_compile _ DIRLIGHTMAP_COMBINED
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile_fog
// Unity defined keywords
#pragma multi_compile _ DIRLIGHTMAP_COMBINED
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile_fog
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
${Defines}
// Defines generated by graph
${Defines}
#include "LWRP/ShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
#include "CoreRP/ShaderLibrary/Color.hlsl"

${Graph}
${Graph}
struct GraphVertexOutput
{
float4 clipPos : SV_POSITION;

${Interpolators}
// Interpolators defined by graph
${VertexOutputStruct}
v = PopulateVertexData(v);
// Vertex transformations performed by graph
${VertexShader}
VertexDescriptionInputs vdi = (VertexDescriptionInputs)0;
// Vertex description inputs defined by graph
${VertexShaderDescriptionInputs}
VertexDescription vd = PopulateVertexData(vdi);
v.vertex.xyz = vd.Position;
GraphVertexOutput o = (GraphVertexOutput)0;

${VertexShader}
// Vertex shader outputs defined by graph
${VertexShaderOutputs}
float3 lwWNormal = TransformObjectToWorldNormal(v.normal);
float3 lwWorldPos = TransformObjectToWorld(v.vertex.xyz);
float4 clipPos = TransformWorldToHClip(lwWorldPos);

o.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
o.clipPos = clipPos;
#ifdef _SHADOWS_ENABLED
#if SHADOWS_SCREEN
o.shadowCoord = ComputeShadowCoord(clipPos);
#else
o.shadowCoord = TransformWorldToShadowCoord(lwWorldPos);
#endif
#endif
#ifdef _SHADOWS_ENABLED
#if SHADOWS_SCREEN
o.shadowCoord = ComputeShadowCoord(clipPos);
#else
o.shadowCoord = TransformWorldToShadowCoord(lwWorldPos);
#endif
#endif
return o;
}

${LocalPixelShader}
// Pixel transformations performed by graph
${PixelShader}
SurfaceDescriptionInputs surfaceInput = (SurfaceDescriptionInputs)0;
SurfaceInputs surfaceInput = (SurfaceInputs)0;
${SurfaceInputs}
// Surface description inputs defined by graph
${PixelShaderSurfaceInputs}
SurfaceDescription surf = PopulateSurfaceData(surfaceInput);
float3 Albedo = float3(0.5, 0.5, 0.5);

float Alpha = 1;
float AlphaClipThreshold = 0;
${SurfaceOutputRemap}
// Surface description remap performed by graph
${PixelShaderSurfaceRemap}
InputData inputData;
inputData.positionWS = WorldSpacePosition;

}
ENDHLSL
}
}

160
ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightUnlitExtraPasses.template


Pass
{
Name "ShadowCaster"
Tags{"LightMode" = "ShadowCaster"}
ZWrite On ZTest LEqual
// Material options generated by graph
${Culling}
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
// Defines generated by graph
${Defines}
#include "LWRP/ShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
#include "ShaderGraphLibrary/Functions.hlsl"
#include "CoreRP/ShaderLibrary/Color.hlsl"
${Graph}
struct VertexOutput
{
float2 uv : TEXCOORD0;
float4 clipPos : SV_POSITION;
};
// x: global clip space bias, y: normal world space bias
float4 _ShadowBias;
float3 _LightDirection;
VertexOutput ShadowPassVertex(GraphVertexInput v)
{
VertexOutput o;
UNITY_SETUP_INSTANCE_ID(v);
// Vertex transformations performed by graph
${VertexShader}
VertexDescriptionInputs vdi = (VertexDescriptionInputs)0;
// Vertex description inputs defined by graph
${VertexShaderDescriptionInputs}
VertexDescription vd = PopulateVertexData(vdi);
v.vertex.xyz = vd.Position;
o.uv = uv1;
float3 positionWS = TransformObjectToWorld(v.vertex.xyz);
float3 normalWS = TransformObjectToWorldDir(v.normal);
float invNdotL = 1.0 - saturate(dot(_LightDirection, normalWS));
float scale = invNdotL * _ShadowBias.y;
// normal bias is negative since we want to apply an inset normal offset
positionWS = normalWS * scale.xxx + positionWS;
float4 clipPos = TransformWorldToHClip(positionWS);
// _ShadowBias.x sign depens on if platform has reversed z buffer
clipPos.z += _ShadowBias.x;
#if UNITY_REVERSED_Z
clipPos.z = min(clipPos.z, clipPos.w * UNITY_NEAR_CLIP_VALUE);
#else
clipPos.z = max(clipPos.z, clipPos.w * UNITY_NEAR_CLIP_VALUE);
#endif
o.clipPos = clipPos;
return o;
}
half4 ShadowPassFragment() : SV_TARGET
{
return 0;
}
ENDHLSL
}
Tags{"LightMode" = "DepthOnly"}
Tags{"LightMode" = "DepthOnly"}
ZWrite On
Cull ${Culling}
ColorMask 0
ZWrite On
ColorMask 0
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
// Material options generated by graph
${Culling}
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
#pragma vertex DepthOnlyVertex
#pragma fragment DepthOnlyFragment
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
// -------------------------------------
// Material Keywords
#pragma shader_feature _ALPHATEST_ON
#pragma vertex vert
#pragma fragment frag
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
// Defines generated by graph
${Defines}
#include "LWRP/ShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
#include "ShaderGraphLibrary/Functions.hlsl"
#include "CoreRP/ShaderLibrary/Color.hlsl"
#include "LWRP/ShaderLibrary/InputSurfaceUnlit.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassDepthOnly.hlsl"
ENDHLSL
}
${Graph}
struct VertexOutput
{
float2 uv : TEXCOORD0;
float4 clipPos : SV_POSITION;
};
VertexOutput vert(GraphVertexInput v)
{
VertexOutput o = (VertexOutput)0;
UNITY_SETUP_INSTANCE_ID(v);
// Vertex transformations performed by graph
${VertexShader}
VertexDescriptionInputs vdi = (VertexDescriptionInputs)0;
// Vertex description inputs defined by graph
${VertexShaderDescriptionInputs}
VertexDescription vd = PopulateVertexData(vdi);
v.vertex.xyz = vd.Position;
o.uv = uv1;
o.clipPos = TransformObjectToHClip(v.vertex.xyz);
return o;
}
half4 frag() : SV_TARGET
{
return 0;
}
ENDHLSL
}

83
ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightUnlitPass.template


Pass
{
Name "StandardUnlit"
Tags{"LightMode" = "LightweightForward"}
${Tags}
${Blending}
${Culling}
${ZTest}
${ZWrite}
Tags{"LightMode" = "LightweightForward"}
// Material options generated by graph
${Tags}
${Blending}
${Culling}
${ZTest}
${ZWrite}
#pragma target 2.0
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
// -------------------------------------
// Lightweight Pipeline keywords
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON
// -------------------------------------
// Unity defined keywords
#pragma multi_compile_fog
//--------------------------------------
// GPU Instancing
#pragma vertex vert
#pragma vertex vert
// Defines generated by graph
${Defines}
// Lighting include is needed because of GI
#include "LWRP/ShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"

${Defines}
${Graph}
${Graph}
${Interpolators}
// Interpolators defined by graph
${VertexOutputStruct}
{
v = PopulateVertexData(v);
{
// Vertex transformations performed by graph
${VertexShader}
VertexDescriptionInputs vdi = (VertexDescriptionInputs)0;
// Vertex description inputs defined by graph
${VertexShaderDescriptionInputs}
VertexDescription vd = PopulateVertexData(vdi);
v.vertex.xyz = vd.Position;
GraphVertexOutput o = (GraphVertexOutput)0;
UNITY_SETUP_INSTANCE_ID(v);

${VertexShader}
// Vertex shader outputs defined by graph
${VertexShaderOutputs}
}
}
${LocalPixelShader}
SurfaceInputs surfaceInput = (SurfaceInputs)0;
${SurfaceInputs}
// Pixel transformations performed by graph
${PixelShader}
SurfaceDescriptionInputs surfaceInput = (SurfaceDescriptionInputs)0;
// Surface description inputs defined by graph
${PixelShaderSurfaceInputs}
${SurfaceOutputRemap}
#if _AlphaClip
// Surface description remap performed by graph
${PixelShaderSurfaceRemap}
#if _AlphaClip
return half4(Color, Alpha);
return half4(Color, Alpha);
}
}

1
ShaderGraph/CHANGELOG.md


- Make nodes that are copied from one graph to another spawn in the center of the current view. ([#333](https://github.com/Unity-Technologies/ShaderGraph/issues/333))
- Fixed an issue with editable sub graph paths, causing the search window to sometimes yield a null reference exception.
- Ensure that the blackboard is within view when deserialized.
- Fixed float value to string error and truncation warning for normal create node.

470
ShaderGraph/HDPipeline/HDUnlitSubShader.cs


using System.IO;
using System.Linq;
using UnityEditor.Graphing;
using UnityEngine.Experimental.UIElements;
[Serializable]
public class HDUnlitSubShader
// [Serializable] ??
public class HDUnlitSubShader : IUnlitSubShader
struct Pass
Pass m_PassDepthOnly = new Pass()
public string Name;
public string ShaderPassName;
public string ShaderPassInclude;
public List<int> VertexShaderSlots;
public List<int> PixelShaderSlots;
}
Name = "Depth prepass",
LightMode = "DepthForwardOnly",
TemplateName = "HDUnlitPassForward.template",
ShaderPassName = "SHADERPASS_DEPTH_ONLY",
ZWriteOverride = "ZWrite On",
Includes = new List<string>()
{
"#include \"HDRP/ShaderPass/ShaderPassDepthOnly.hlsl\"",
},
PixelShaderSlots = new List<int>()
{
UnlitMasterNode.AlphaSlotId,
UnlitMasterNode.AlphaThresholdSlotId
}
};
Pass m_UnlitPassForwardOnly = new Pass()
Pass m_PassForward = new Pass()
Name = "ForwardOnly",
Name = "Forward Unlit",
LightMode = "ForwardOnly",
TemplateName = "HDUnlitPassForward.template",
ShaderPassInclude = "ShaderPassForwardUnlit",
ExtraDefines = new List<string>()
{
"#pragma multi_compile _ DEBUG_DISPLAY"
},
Includes = new List<string>()
{
"#include \"HDRP/ShaderPass/ShaderPassForwardUnlit.hlsl\"",
},
UnlitMasterNode.AlphaSlotId
UnlitMasterNode.AlphaSlotId,
UnlitMasterNode.AlphaThresholdSlotId
Pass m_UnlitPassForwardDepthOnly = new Pass()
Pass m_PassMETA = new Pass()
Name = "DepthForwardOnly",
ShaderPassName = "SHADERPASS_DEPTH_ONLY",
ShaderPassInclude = "ShaderPassDepthOnly",
Name = "META",
LightMode = "Meta",
TemplateName = "HDUnlitPassForward.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
},
UnlitMasterNode.AlphaSlotId
UnlitMasterNode.AlphaSlotId,
UnlitMasterNode.AlphaThresholdSlotId
}
};
Pass m_PassDistortion = new Pass()
{
Name = "Distortion",
LightMode = "DistortionVectors",
TemplateName = "HDUnlitPassForward.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\"",
},
PixelShaderSlots = new List<int>()
{
PBRMasterNode.AlphaSlotId,
PBRMasterNode.AlphaThresholdSlotId
private static string GetShaderPassFromTemplate(UnlitMasterNode masterNode, Pass pass, GenerationMode mode)
private static string GetVariantDefines(UnlitMasterNode masterNode)
var builder = new ShaderStringBuilder();
builder.IncreaseIndent();
builder.IncreaseIndent();
ShaderGenerator defines = new ShaderGenerator();
// #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);
}
var surfaceDescriptionFunction = new ShaderGenerator();
var surfaceDescriptionStruct = new ShaderGenerator();
var surfaceInputs = new ShaderGenerator();
var functionRegistry = new FunctionRegistry(builder);
// 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;
// }
var shaderProperties = new PropertyCollector();
// #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
surfaceInputs.AddShaderChunk("struct SurfaceInputs{", false);
surfaceInputs.Indent();
// #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
var activeNodeList = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);
// 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);
var requirements = ShaderGraphRequirements.FromNodes(activeNodeList);
// #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);
// }
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresNormal, InterpolatorType.Normal, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresTangent, InterpolatorType.Tangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresBitangent, InterpolatorType.BiTangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresPosition, InterpolatorType.Position, surfaceInputs);
// #pragma shader_feature _BLENDMODE_PRESERVE_SPECULAR_LIGHTING
// if (kEnableBlendModePreserveSpecularLighting)
// {
// defines.AddShaderChunk("#define _BLENDMODE_PRESERVE_SPECULAR_LIGHTING 1", true);
// }
ShaderGenerator defines = new ShaderGenerator();
defines.AddShaderChunk(string.Format("#define SHADERPASS {0}", pass.ShaderPassName), true);
// #pragma shader_feature _ENABLE_FOG_ON_TRANSPARENT
// if (kEnableFogOnTransparent)
// {
// defines.AddShaderChunk("#define _ENABLE_FOG_ON_TRANSPARENT 1", true);
// }
}
else
{
// opaque-only defines
}
if (requirements.requiresVertexColor)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.VertexColor), false);
// 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
if (requirements.requiresScreenPosition)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.ScreenPosition), false);
return defines.GetShaderString(2);
}
foreach (var channel in requirements.requiresMeshUVs.Distinct())
private static bool GenerateShaderPass(UnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions, ShaderGenerator result)
{
var templateLocation = ShaderGenerator.GetTemplatePath(pass.TemplateName);
if (!File.Exists(templateLocation))
surfaceInputs.AddShaderChunk(string.Format("half4 {0};", channel.GetUVName()), false);
defines.AddShaderChunk(string.Format("#define ATTRIBUTES_NEED_TEXCOORD{0}", (int)channel), true);
defines.AddShaderChunk(string.Format("#define VARYINGS_NEED_TEXCOORD{0}", (int)channel), true);
// TODO: produce error here
return false;
surfaceInputs.Deindent();
surfaceInputs.AddShaderChunk("};", false);
// grab all of the active nodes
var activeNodeList = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);
var slots = new List<MaterialSlot>();
// graph requirements describe what the graph itself requires
var graphRequirements = ShaderGraphRequirements.FromNodes(activeNodeList, ShaderStageCapability.All, true, true);
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>();
var slot = masterNode.FindSlot<MaterialSlot>(id);
MaterialSlot slot = masterNode.FindSlot<MaterialSlot>(id);
slots.Add(slot);
{
activeSlots.Add(slot);
}
GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, slots, true);
// 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";
var graphEvalFunction = new ShaderStringBuilder();
var graphOutputs = new ShaderStringBuilder();
PropertyCollector graphProperties = new PropertyCollector();
var usedSlots = new List<MaterialSlot>();
foreach (var id in pass.PixelShaderSlots)
usedSlots.Add(masterNode.FindSlot<MaterialSlot>(id));
// 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.GenerateSurfaceDescription(
// Build the graph evaluation code, to evaluate the specified slots
GraphUtil.GenerateSurfaceDescriptionFunction(
surfaceDescriptionFunction,
graphEvalFunction,
shaderProperties,
requirements,
graphProperties,
graphRequirements, // TODO : REMOVE UNUSED
"PopulateSurfaceData",
"SurfaceDescription",
graphEvalFunctionName,
graphOutputStructName,
usedSlots);
activeSlots,
graphInputStructName);
var graph = new ShaderGenerator();
graph.AddShaderChunk(shaderProperties.GetPropertiesDeclaration(2), false);
graph.AddShaderChunk(surfaceInputs.GetShaderString(2), false);
graph.AddShaderChunk(builder.ToString(), false);
graph.AddShaderChunk(surfaceDescriptionStruct.GetShaderString(2), false);
graph.AddShaderChunk(surfaceDescriptionFunction.GetShaderString(2), false);
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);
var tagsVisitor = new ShaderGenerator();
var blendingVisitor = new ShaderGenerator();
var cullingVisitor = new ShaderGenerator();
var zTestVisitor = new ShaderGenerator();
var zWriteVisitor = new ShaderGenerator();
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
}
}
var materialOptions = new SurfaceMaterialOptions();
materialOptions.GetTags(tagsVisitor);
materialOptions.GetBlend(blendingVisitor);
materialOptions.GetCull(cullingVisitor);
materialOptions.GetDepthTest(zTestVisitor);
materialOptions.GetDepthWrite(zWriteVisitor);
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 localPixelShader = new ShaderGenerator();
var localSurfaceInputs = new ShaderGenerator();
var surfaceOutputRemap = new ShaderGenerator();
var packedInterpolatorCode = new ShaderGenerator();
var graphInputs = new ShaderGenerator();
HDRPShaderStructs.Generate(
packedInterpolatorCode,
graphInputs,
graphRequirements,
pass.RequiredFields,
CoordinateSpace.World,
activeFields);
foreach (var channel in requirements.requiresMeshUVs.Distinct())
localSurfaceInputs.AddShaderChunk(string.Format("surfaceInput.{0} = {1};", channel.GetUVName(), string.Format("half4(input.texCoord{0}, 0, 0)", (int)channel)), false);
// debug output all active fields
var interpolatorDefines = new ShaderGenerator();
{
interpolatorDefines.AddShaderChunk("// ACTIVE FIELDS:");
foreach (string f in activeFields)
{
interpolatorDefines.AddShaderChunk("// " + f);
}
}
var templateLocation = ShaderGenerator.GetTemplatePath("HDUnlitPassForward.template");
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);
}
foreach (var slot in usedSlots)
var shaderPassIncludes = new ShaderGenerator();
if (pass.Includes != null)
surfaceOutputRemap.AddShaderChunk(slot.shaderOutputName
+ " = surf."
+ slot.shaderOutputName + ";", true);
foreach (var include in pass.Includes)
shaderPassIncludes.AddShaderChunk(include);
if (!File.Exists(templateLocation))
return string.Empty;
// 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();
}
var subShaderTemplate = File.ReadAllText(templateLocation);
var resultPass = subShaderTemplate.Replace("${Defines}", defines.GetShaderString(3));
resultPass = resultPass.Replace("${Graph}", graph.GetShaderString(3));
resultPass = resultPass.Replace("${LocalPixelShader}", localPixelShader.GetShaderString(3));
resultPass = resultPass.Replace("${SurfaceInputs}", localSurfaceInputs.GetShaderString(3));
resultPass = resultPass.Replace("${SurfaceOutputRemap}", surfaceOutputRemap.GetShaderString(3));
resultPass = resultPass.Replace("${LightMode}", pass.Name);
resultPass = resultPass.Replace("${ShaderPassInclude}", pass.ShaderPassInclude);
result.AddShaderChunk(builder.ToString(), false);
resultPass = resultPass.Replace("${Tags}", tagsVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${Blending}", blendingVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${Culling}", cullingVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${ZTest}", zTestVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${ZWrite}", zWriteVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${LOD}", "" + materialOptions.lod);
return resultPass;
return true;
}
public string GetSubshader(IMasterNode inMasterNode, GenerationMode mode)

subShader.AddShaderChunk("SubShader", true);
subShader.AddShaderChunk("{", true);
subShader.Indent();
subShader.AddShaderChunk("Tags{ \"RenderType\" = \"Opaque\" }", true);
{
SurfaceMaterialOptions materialOptions = HDSubShaderUtilities.BuildMaterialOptions(masterNode.surfaceType, masterNode.alphaMode, masterNode.twoSided.isOn);
subShader.AddShaderChunk(
GetShaderPassFromTemplate(
masterNode,
m_UnlitPassForwardDepthOnly,
mode),
true);
// Add tags at the SubShader level
{
var tagsVisitor = new ShaderStringBuilder();
materialOptions.GetTags(tagsVisitor);
subShader.AddShaderChunk(tagsVisitor.ToString(), false);
}
subShader.AddShaderChunk(
GetShaderPassFromTemplate(
masterNode,
m_UnlitPassForwardOnly,
mode),
true);
// generate the necessary shader passes
// bool opaque = (masterNode.surfaceType == SurfaceType.Opaque);
// bool transparent = (masterNode.surfaceType != SurfaceType.Opaque);
bool distortionActive = false;
GenerateShaderPass(masterNode, m_PassDepthOnly, mode, materialOptions, subShader);
GenerateShaderPass(masterNode, m_PassForward, mode, materialOptions, subShader);
GenerateShaderPass(masterNode, m_PassMETA, mode, materialOptions, subShader);
if (distortionActive)
{
GenerateShaderPass(masterNode, m_PassDistortion, mode, materialOptions, subShader);
}
}
subShader.Deindent();
subShader.AddShaderChunk("}", true);

}
}

8
ShaderGraph/Testing/Editor/TestSlot.cs


{
public TestSlot() {}
public TestSlot(int slotId, string displayName, SlotType slotType, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, displayName, slotType, shaderStage, hidden) {}
public TestSlot(int slotId, string displayName, SlotType slotType, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, displayName, slotType, stageCapability, hidden) {}
public TestSlot(int slotId, string displayName, SlotType slotType, int priority, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, displayName, slotType, priority, shaderStage, hidden) {}
public TestSlot(int slotId, string displayName, SlotType slotType, int priority, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, displayName, slotType, priority, stageCapability, hidden) {}
public override SlotValueType valueType
{

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/BitangentMaterialSlot.cs


{}
public BitangentMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, shaderStage, hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()

return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.BiTangent));
}
public NeededCoordinateSpace RequiresBitangent()
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/BooleanMaterialSlot.cs


string shaderOutputName,
SlotType slotType,
bool value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_DefaultValue = value;
m_Value = value;

12
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ColorMaterialSlot.cs


string shaderOutputName,
SlotType slotType,
Vector4 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, value, shaderStage, hidden: hidden)
: base(slotId, displayName, shaderOutputName, slotType, value, stageCapability, hidden: hidden)
{
}

{
return string.Format("IsGammaSpace() ? {0}4({1}, {2}, {3}, {4}) : {0}4 (SRGBToLinear({0}3({1}, {2}, {3})), {4})"
, precision
, value.x
, value.y
, value.z
, value.w);
, NodeUtils.FloatToShaderValue(value.x)
, NodeUtils.FloatToShaderValue(value.y)
, NodeUtils.FloatToShaderValue(value.z)
, NodeUtils.FloatToShaderValue(value.w));
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)

10
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ColorRGBMaterialSlot.cs


string shaderOutputName,
SlotType slotType,
Color value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, (Vector4)value, shaderStage, hidden: hidden)
: base(slotId, displayName, shaderOutputName, slotType, (Vector4)value, stageCapability, hidden: hidden)
{
}

{
return string.Format("IsGammaSpace() ? {0}3({1}, {2}, {3}) : SRGBToLinear({0}3({1}, {2}, {3}))"
, precision
, value.x
, value.y
, value.z);
, NodeUtils.FloatToShaderValue(value.x)
, NodeUtils.FloatToShaderValue(value.y)
, NodeUtils.FloatToShaderValue(value.z));
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/CubemapInputMaterialSlot.cs


int slotId,
string displayName,
string shaderOutputName,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, SlotType.Input, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, SlotType.Input, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/CubemapMaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{}
public override SlotValueType valueType { get { return SlotValueType.Cubemap; } }

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/DynamicMatrixMaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/DynamicValueMaterialSlot.cs


string shaderOutputName,
SlotType slotType,
Matrix4x4 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/DynamicVectorMaterialSlot.cs


string shaderOutputName,
SlotType slotType,
Vector4 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
}

12
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/GradientInputMaterialSlot.cs


int slotId,
string displayName,
string shaderOutputName,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, SlotType.Input, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, SlotType.Input, stageCapability, hidden)
{
}

generatePropertyBlock = false
});
}
for(int i = 0; i < 8; i++)
{
properties.AddShaderProperty(new Vector4ShaderProperty()

generatePropertyBlock = false
});
}
}
}
var prop = new GradientShaderProperty();

vector4Value = i < value.colorKeys.Length ? GradientUtils.ColorKeyToVector(value.colorKeys[i]) : Vector4.zero
});
}
for(int i = 0; i < 8; i++)
{
properties.Add(new PreviewProperty(PropertyType.Vector2)

value = slot.value;
}
}
}
}

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/GradientMaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
}

{
}
}
}
}

68
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/MaterialSlot.cs


string m_ShaderOutputName;
[SerializeField]
ShaderStage m_ShaderStage;
ShaderStageCapability m_StageCapability;
protected MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
protected MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
{
m_Id = slotId;
m_DisplayName = displayName;

this.shaderStage = shaderStage;
this.stageCapability = stageCapability;
protected MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, int priority, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
protected MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, int priority, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
{
m_Id = slotId;
m_DisplayName = displayName;

m_ShaderOutputName = shaderOutputName;
this.shaderStage = shaderStage;
this.stageCapability = stageCapability;
}
public virtual VisualElement InstantiateControl()

return m_DisplayName;
}
public static MaterialSlot CreateMaterialSlot(SlotValueType type, int slotId, string displayName, string shaderOutputName, SlotType slotType, Vector4 defaultValue, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
public static MaterialSlot CreateMaterialSlot(SlotValueType type, int slotId, string displayName, string shaderOutputName, SlotType slotType, Vector4 defaultValue, ShaderStageCapability shaderStageCapability = ShaderStageCapability.All, bool hidden = false)
return new SamplerStateMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
return new SamplerStateMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
return new DynamicMatrixMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
return new DynamicMatrixMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
return new Matrix4MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
return new Matrix4MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
return new Matrix3MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
return new Matrix3MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
return new Matrix2MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
return new Matrix2MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
? new Texture2DInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStage, hidden)
: new Texture2DMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
? new Texture2DInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden)
: new Texture2DMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
? new Texture2DArrayInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStage, hidden)
: new Texture2DArrayMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
? new Texture2DArrayInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden)
: new Texture2DArrayMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
? new Texture3DInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStage, hidden)
: new Texture3DMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
? new Texture3DInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden)
: new Texture3DMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
? new CubemapInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStage, hidden)
: new CubemapMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
? new CubemapInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden)
: new CubemapMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
? new GradientInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStage, hidden)
: new GradientMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
? new GradientInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden)
: new GradientMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
return new DynamicVectorMaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden);
return new DynamicVectorMaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden);
return new Vector4MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden: hidden);
return new Vector4MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden);
return new Vector3MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden: hidden);
return new Vector3MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden);
return new Vector2MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden: hidden);
return new Vector2MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden);
return new Vector1MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue.x, shaderStage, hidden: hidden);
return new Vector1MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue.x, shaderStageCapability, hidden: hidden);
return new DynamicValueMaterialSlot(slotId, displayName, shaderOutputName, slotType, new Matrix4x4(defaultValue, Vector4.zero, Vector4.zero, Vector4.zero), shaderStage, hidden);
return new DynamicValueMaterialSlot(slotId, displayName, shaderOutputName, slotType, new Matrix4x4(defaultValue, Vector4.zero, Vector4.zero, Vector4.zero), shaderStageCapability, hidden);
return new BooleanMaterialSlot(slotId, displayName, shaderOutputName, slotType, false, shaderStage, hidden);
return new BooleanMaterialSlot(slotId, displayName, shaderOutputName, slotType, false, shaderStageCapability, hidden);
}
throw new ArgumentOutOfRangeException("type", type, null);

private set { m_ShaderOutputName = value; }
}
public ShaderStage shaderStage
public ShaderStageCapability stageCapability
get { return m_ShaderStage; }
set { m_ShaderStage = value; }
get { return m_StageCapability; }
set { m_StageCapability = value; }
}
public bool hasError

&& ((isInputSlot
? otherSlot.IsCompatibleWithInputSlotType(valueType)
: IsCompatibleWithInputSlotType(otherSlot.valueType)));
}
public bool IsCompatibleStageWith(MaterialSlot otherSlot)
{
var candidateStage = otherSlot.stageCapability;
return stageCapability == ShaderStageCapability.All || candidateStage == stageCapability;
}
public virtual string GetDefaultValue(GenerationMode generationMode)

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Matrix2MaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Matrix3MaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Matrix4MaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
}

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/NormalMaterialSlot.cs


{}
public NormalMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, shaderStage, hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()

return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Normal));
}
public NeededCoordinateSpace RequiresNormal()
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/PositionMaterialSlot.cs


{}
public PositionMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, shaderStage, hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()

return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Position));
}
public NeededCoordinateSpace RequiresPosition()
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;

3
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/PreviewMode.cs


public enum PreviewMode
{
Preview2D,
Preview3D
Preview3D,
Wireframe
}
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/SamplerStateMaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
}

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ScreenPositionMaterialSlot.cs


{}
public ScreenPositionMaterialSlot(int slotId, string displayName, string shaderOutputName, ScreenSpaceType screenSpaceType,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, shaderStage, hidden: hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, stageCapability, hidden: hidden)
{
this.screenSpaceType = screenSpaceType;
}

return m_ScreenSpaceType.ToValueAsVariable();
}
public bool RequiresScreenPosition()
public bool RequiresScreenPosition(ShaderStageCapability stageCapability)
{
return !isConnected;
}

30
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ShaderGraphRequirements.cs


return newReqs;
}
public static ShaderGraphRequirements FromNodes(List<INode> nodes)
public static ShaderGraphRequirements FromNodes<T>(List<T> nodes, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool includeIntermediateSpaces = true, bool HDRPBehavior = false)
where T : class, INode
NeededCoordinateSpace requiresNormal = nodes.OfType<IMayRequireNormal>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresNormal());
NeededCoordinateSpace requiresBitangent = nodes.OfType<IMayRequireBitangent>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresBitangent());
NeededCoordinateSpace requiresTangent = nodes.OfType<IMayRequireTangent>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresTangent());
NeededCoordinateSpace requiresViewDir = nodes.OfType<IMayRequireViewDirection>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresViewDirection());
NeededCoordinateSpace requiresPosition = nodes.OfType<IMayRequirePosition>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresPosition());
NeededCoordinateSpace requiresNormal = nodes.OfType<IMayRequireNormal>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresNormal(stageCapability));
NeededCoordinateSpace requiresBitangent = nodes.OfType<IMayRequireBitangent>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresBitangent(stageCapability));
NeededCoordinateSpace requiresTangent = nodes.OfType<IMayRequireTangent>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresTangent(stageCapability));
NeededCoordinateSpace requiresViewDir = nodes.OfType<IMayRequireViewDirection>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresViewDirection(stageCapability));
NeededCoordinateSpace requiresPosition = nodes.OfType<IMayRequirePosition>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresPosition(stageCapability));
bool requiresScreenPosition = nodes.OfType<IMayRequireScreenPosition>().Any(x => x.RequiresScreenPosition());
bool requiresVertexColor = nodes.OfType<IMayRequireVertexColor>().Any(x => x.RequiresVertexColor());

// if anything needs tangentspace we have make
// sure to have our othonormal basis!
var compoundSpaces = requiresBitangent | requiresNormal | requiresPosition
if(includeIntermediateSpaces)
{
var compoundSpaces = requiresBitangent | requiresNormal | requiresPosition
var needsTangentSpace = (compoundSpaces & NeededCoordinateSpace.Tangent) > 0;
if (needsTangentSpace)
{
requiresBitangent |= NeededCoordinateSpace.Object;
requiresNormal |= NeededCoordinateSpace.Object;
requiresTangent |= NeededCoordinateSpace.Object;
var needsTangentSpace = (compoundSpaces & NeededCoordinateSpace.Tangent) > 0;
if (needsTangentSpace && !HDRPBehavior)
{
requiresBitangent |= NeededCoordinateSpace.World;
requiresNormal |= NeededCoordinateSpace.World;
requiresTangent |= NeededCoordinateSpace.World;
}
}
var reqs = new ShaderGraphRequirements()

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/SpaceMaterialSlot.cs


{}
protected SpaceMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, shaderStage, hidden: hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, stageCapability, hidden: hidden)
{
this.space = space;
}

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/TangentMaterialSlot.cs


{}
public TangentMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, shaderStage, hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()

return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Tangent));
}
public NeededCoordinateSpace RequiresTangent()
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture2DArrayInputMaterialSlot.cs


int slotId,
string displayName,
string shaderOutputName,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability shaderStageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, SlotType.Input, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, SlotType.Input, shaderStageCapability, hidden)
{}
public override VisualElement InstantiateControl()

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture2DArrayMaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability shaderStageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden)
{}
public override SlotValueType valueType { get { return SlotValueType.Texture2DArray; } }

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture2DInputMaterialSlot.cs


int slotId,
string displayName,
string shaderOutputName,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, SlotType.Input, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, SlotType.Input, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture2DMaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{}
public override SlotValueType valueType { get { return SlotValueType.Texture2D; } }

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture3DInputMaterialSlot.cs


int slotId,
string displayName,
string shaderOutputName,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability shaderStageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, SlotType.Input, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, SlotType.Input, shaderStageCapability, hidden)
{}
public override VisualElement InstantiateControl()

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture3DMaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability shaderStageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden)
{}
public override SlotValueType valueType { get { return SlotValueType.Texture3D; } }

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/UVMaterialSlot.cs


{}
public UVMaterialSlot(int slotId, string displayName, string shaderOutputName, UVChannel channel,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector2.zero, shaderStage, hidden: hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector2.zero, stageCapability, hidden: hidden)
{
this.channel = channel;
}

return string.Format("IN.{0}.xy", channel.GetUVName());
}
public bool RequiresMeshUV(UVChannel channel)
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
{
if (isConnected)
return false;

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector1MaterialSlot.cs


string shaderOutputName,
SlotType slotType,
float value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_DefaultValue = value;
m_Value = value;

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector2MaterialSlot.cs


string shaderOutputName,
SlotType slotType,
Vector2 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
m_Labels = new[] { label1, label2 };

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector3MaterialSlot.cs


string shaderOutputName,
SlotType slotType,
Vector3 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
m_Labels = new[] { label1, label2, label3 };

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector4MaterialSlot.cs


string shaderOutputName,
SlotType slotType,
Vector4 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
m_Labels = new[] { label1, label2, label3, label4 };

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/VertexColorMaterialSlot.cs


public class VertexColorMaterialSlot : Vector4MaterialSlot, IMayRequireScreenPosition
{
public VertexColorMaterialSlot(int slotId, string displayName, string shaderOutputName,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, shaderStage, hidden: hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, stageCapability, hidden: hidden)
{}
public override VisualElement InstantiateControl()

return string.Format("IN.{0}", ShaderGeneratorNames.VertexColor);
}
public bool RequiresScreenPosition()
public bool RequiresScreenPosition(ShaderStageCapability stageCapability)
{
return !isConnected;
}

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ViewDirectionMaterialSlot.cs


{}
public ViewDirectionMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, shaderStage, hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()
{

return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.ViewDirection));
}
public NeededCoordinateSpace RequiresViewDirection()
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;

98
ShaderGraph/com.unity.shadergraph/Editor/Data/Implementation/NodeUtils.cs


Exclude
}
public static void DepthFirstCollectNodesFromNode(List<INode> nodeList, INode node, IncludeSelf includeSelf = IncludeSelf.Include, List<int> slotIds = null)
public static void DepthFirstCollectNodesFromNode<T>(List<T> nodeList, T node, IncludeSelf includeSelf = IncludeSelf.Include, List<int> slotIds = null)
where T : class, INode
{
// no where to start
if (node == null)

{
foreach (var edge in node.owner.GetEdges(node.GetSlotReference(slot)))
{
var outputNode = node.owner.GetNodeFromGuid(edge.outputSlot.nodeGuid);
var outputNode = node.owner.GetNodeFromGuid(edge.outputSlot.nodeGuid) as T;
if (outputNode != null)
DepthFirstCollectNodesFromNode(nodeList, outputNode);
}
}

nodeList.Add(node);
}
static Stack<INode> s_NodeStack = new Stack<INode>();
static Stack<MaterialSlot> s_SlotStack = new Stack<MaterialSlot>();
public static ShaderStage FindEffectiveShaderStage(INode initialNode, bool goingBackwards)
public static ShaderStage GetEffectiveShaderStage(MaterialSlot initialSlot, bool goingBackwards)
var shaderStage = ShaderStage.Dynamic;
s_NodeStack.Clear();
s_NodeStack.Push(initialNode);
while (s_NodeStack.Any() && shaderStage == ShaderStage.Dynamic)
var graph = initialSlot.owner.owner;
s_SlotStack.Clear();
s_SlotStack.Push(initialSlot);
while (s_SlotStack.Any())
var node = s_NodeStack.Pop();
foreach (var slot in goingBackwards ? node.GetInputSlots<MaterialSlot>() : node.GetOutputSlots<MaterialSlot>())
var slot = s_SlotStack.Pop();
ShaderStage stage;
if (slot.stageCapability.TryGetShaderStage(out stage))
return stage;
if (goingBackwards && slot.isInputSlot)
{
foreach (var edge in graph.GetEdges(slot.slotReference))
if (shaderStage != ShaderStage.Dynamic)
break;
if (slot.shaderStage == ShaderStage.Dynamic)
var node = graph.GetNodeFromGuid(edge.outputSlot.nodeGuid);
s_SlotStack.Push(node.FindOutputSlot<MaterialSlot>(edge.outputSlot.slotId));
}
}
else if (!goingBackwards && slot.isOutputSlot)
foreach (var edge in node.owner.GetEdges(slot.slotReference))
foreach (var edge in graph.GetEdges(slot.slotReference))
var connectedNode = node.owner.GetNodeFromGuid(goingBackwards ? edge.outputSlot.nodeGuid : edge.inputSlot.nodeGuid);
var connectedSlot = goingBackwards ? connectedNode.FindOutputSlot<MaterialSlot>(edge.outputSlot.slotId) : connectedNode.FindInputSlot<MaterialSlot>(edge.inputSlot.slotId);
if (connectedSlot.shaderStage == ShaderStage.Dynamic)
s_NodeStack.Push(connectedNode);
var node = graph.GetNodeFromGuid(edge.inputSlot.nodeGuid);
s_SlotStack.Push(node.FindInputSlot<MaterialSlot>(edge.inputSlot.slotId));
}
}
shaderStage = connectedSlot.shaderStage;
break;
var ownerSlots = Enumerable.Empty<MaterialSlot>();
if (goingBackwards && slot.isOutputSlot)
ownerSlots = slot.owner.GetInputSlots<MaterialSlot>();
else if (!goingBackwards && slot.isInputSlot)
ownerSlots = slot.owner.GetOutputSlots<MaterialSlot>();
foreach (var ownerSlot in ownerSlots)
s_SlotStack.Push(ownerSlot);
// We default to fragment shader stage if all connected nodes were compatible with both.
return ShaderStage.Fragment;
}
public static ShaderStageCapability GetEffectiveShaderStageCapability(MaterialSlot initialSlot, bool goingBackwards)
{
var graph = initialSlot.owner.owner;
s_SlotStack.Clear();
s_SlotStack.Push(initialSlot);
while (s_SlotStack.Any())
{
var slot = s_SlotStack.Pop();
ShaderStage stage;
if (slot.stageCapability.TryGetShaderStage(out stage))
return slot.stageCapability;
if (goingBackwards && slot.isInputSlot)
{
foreach (var edge in graph.GetEdges(slot.slotReference))
{
var node = graph.GetNodeFromGuid(edge.outputSlot.nodeGuid);
s_SlotStack.Push(node.FindOutputSlot<MaterialSlot>(edge.outputSlot.slotId));
}
}
else if (!goingBackwards && slot.isOutputSlot)
{
foreach (var edge in graph.GetEdges(slot.slotReference))
{
var node = graph.GetNodeFromGuid(edge.inputSlot.nodeGuid);
s_SlotStack.Push(node.FindInputSlot<MaterialSlot>(edge.inputSlot.slotId));
}
shaderStage = slot.shaderStage;
{
var ownerSlots = Enumerable.Empty<MaterialSlot>();
if (goingBackwards && slot.isOutputSlot)
ownerSlots = slot.owner.GetInputSlots<MaterialSlot>();
else if (!goingBackwards && slot.isInputSlot)
ownerSlots = slot.owner.GetOutputSlots<MaterialSlot>();
foreach (var ownerSlot in ownerSlots)
s_SlotStack.Push(ownerSlot);
return shaderStage;
return ShaderStageCapability.All;
}
public static string GetSlotDimension(ConcreteSlotValueType slotValue)

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IGeneratesFunction.cs


{
public interface IGeneratesFunction
{
void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode);
void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode);
}
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireBitangent.cs


{
public interface IMayRequireBitangent
{
NeededCoordinateSpace RequiresBitangent();
NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequireBitangentExtensions

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireMeshUV.cs


{
public interface IMayRequireMeshUV
{
bool RequiresMeshUV(UVChannel channel);
bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequireMeshUVExtensions

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireNormal.cs


{
public interface IMayRequireNormal
{
NeededCoordinateSpace RequiresNormal();
NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequireNormalExtensions

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequirePosition.cs


{
public interface IMayRequirePosition
{
NeededCoordinateSpace RequiresPosition();
NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequirePositionExtensions

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireScreenPosition.cs


{
public interface IMayRequireScreenPosition
{
bool RequiresScreenPosition();
bool RequiresScreenPosition(ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequireScreenPositionExtensions

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireTangent.cs


{
public interface IMayRequireTangent
{
NeededCoordinateSpace RequiresTangent();
NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequireTangentExtensions

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireVertexColor.cs


{
interface IMayRequireVertexColor
{
bool RequiresVertexColor();
bool RequiresVertexColor(ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequireVertexColorExtensions

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireViewDirection.cs


{
interface IMayRequireViewDirection
{
NeededCoordinateSpace RequiresViewDirection();
NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequireViewDirectionExtensions

60
ShaderGraph/com.unity.shadergraph/Editor/Data/MasterNodes/PBRMasterNode.cs


{
[Serializable]
[Title("Master", "PBR")]
public class PBRMasterNode : MasterNode<IPBRSubShader>, IMayRequireNormal
public class PBRMasterNode : MasterNode<IPBRSubShader>, IMayRequirePosition, IMayRequireNormal
{
public const string AlbedoSlotName = "Albedo";
public const string NormalSlotName = "Normal";

public const string OcclusionSlotName = "Occlusion";
public const string AlphaSlotName = "Alpha";
public const string AlphaClipThresholdSlotName = "AlphaClipThreshold";
public const string VertexOffsetName = "VertexPosition";
public const string PositionName = "Position";
public const int AlbedoSlotId = 0;
public const int NormalSlotId = 1;

public const int OcclusionSlotId = 6;
public const int AlphaSlotId = 7;
public const int AlphaThresholdSlotId = 8;
public const int PositionSlotId = 9;
public enum Model
{

{
base.UpdateNodeAfterDeserialization();
name = "PBR Master";
AddSlot(new ColorRGBMaterialSlot(AlbedoSlotId, AlbedoSlotName, AlbedoSlotName, SlotType.Input, Color.grey, ShaderStage.Fragment));
AddSlot(new NormalMaterialSlot(NormalSlotId, NormalSlotName, NormalSlotName, CoordinateSpace.Tangent, ShaderStage.Fragment));
AddSlot(new ColorRGBMaterialSlot(EmissionSlotId, EmissionSlotName, EmissionSlotName, SlotType.Input, Color.black, ShaderStage.Fragment));
AddSlot(new PositionMaterialSlot(PositionSlotId, PositionName, PositionName, CoordinateSpace.Object, ShaderStageCapability.Vertex));
AddSlot(new ColorRGBMaterialSlot(AlbedoSlotId, AlbedoSlotName, AlbedoSlotName, SlotType.Input, Color.grey, ShaderStageCapability.Fragment));
AddSlot(new NormalMaterialSlot(NormalSlotId, NormalSlotName, NormalSlotName, CoordinateSpace.Tangent, ShaderStageCapability.Fragment));
AddSlot(new ColorRGBMaterialSlot(EmissionSlotId, EmissionSlotName, EmissionSlotName, SlotType.Input, Color.black, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(MetallicSlotId, MetallicSlotName, MetallicSlotName, SlotType.Input, 0, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(MetallicSlotId, MetallicSlotName, MetallicSlotName, SlotType.Input, 0, ShaderStageCapability.Fragment));
AddSlot(new ColorRGBMaterialSlot(SpecularSlotId, SpecularSlotName, SpecularSlotName, SlotType.Input, Color.grey, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(SmoothnessSlotId, SmoothnessSlotName, SmoothnessSlotName, SlotType.Input, 0.5f, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(OcclusionSlotId, OcclusionSlotName, OcclusionSlotName, SlotType.Input, 1f, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, 1f, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaThresholdSlotId, AlphaClipThresholdSlotName, AlphaClipThresholdSlotName, SlotType.Input, 0f, ShaderStage.Fragment));
AddSlot(new ColorRGBMaterialSlot(SpecularSlotId, SpecularSlotName, SpecularSlotName, SlotType.Input, Color.grey, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(SmoothnessSlotId, SmoothnessSlotName, SmoothnessSlotName, SlotType.Input, 0.5f, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(OcclusionSlotId, OcclusionSlotName, OcclusionSlotName, SlotType.Input, 1f, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, 1f, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaThresholdSlotId, AlphaClipThresholdSlotName, AlphaClipThresholdSlotName, SlotType.Input, 0f, ShaderStageCapability.Fragment));
// clear out slot names that do not match the slots
// we support

PositionSlotId,
AlbedoSlotId,
NormalSlotId,
EmissionSlotId,

}, true);
}
public NeededCoordinateSpace RequiresNormal()
protected override VisualElement CreateCommonSettingsElement()
List<ISlot> slots = new List<ISlot>();
return new PBRSettingsView(this);
}
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
{
List<MaterialSlot> slots = new List<MaterialSlot>();
return slots.OfType<IMayRequireNormal>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresNormal());
List<MaterialSlot> validSlots = new List<MaterialSlot>();
for(int i = 0; i < slots.Count; i++)
{
if(slots[i].stageCapability != ShaderStageCapability.All && slots[i].stageCapability != stageCapability)
continue;
validSlots.Add(slots[i]);
}
return validSlots.OfType<IMayRequireNormal>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresNormal(stageCapability));
protected override VisualElement CreateCommonSettingsElement()
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
return new PBRSettingsView(this);
List<MaterialSlot> slots = new List<MaterialSlot>();
GetSlots(slots);
List<MaterialSlot> validSlots = new List<MaterialSlot>();
for(int i = 0; i < slots.Count; i++)
{
if(slots[i].stageCapability != ShaderStageCapability.All && slots[i].stageCapability != stageCapability)
continue;
validSlots.Add(slots[i]);
}
return validSlots.OfType<IMayRequirePosition>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresPosition(stageCapability));
}
}
}

30
ShaderGraph/com.unity.shadergraph/Editor/Data/MasterNodes/UnlitMasterNode.cs


using System;
using System.Linq;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing;
using UnityEditor.ShaderGraph.Drawing.Controls;

{
[Serializable]
[Title("Master", "Unlit")]
public class UnlitMasterNode : MasterNode<IUnlitSubShader>
public class UnlitMasterNode : MasterNode<IUnlitSubShader>, IMayRequirePosition
public const string VertexOffsetName = "VertexPosition";
public const string PositionName = "Position";
public const int PositionSlotId = 9;
[SerializeField]
SurfaceType m_SurfaceType;

{
base.UpdateNodeAfterDeserialization();
name = "Unlit Master";
AddSlot(new ColorRGBMaterialSlot(ColorSlotId, ColorSlotName, ColorSlotName, SlotType.Input, Color.grey, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, 1, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaThresholdSlotId, AlphaClipThresholdSlotName, AlphaClipThresholdSlotName, SlotType.Input, 0f, ShaderStage.Fragment));
AddSlot(new PositionMaterialSlot(PositionSlotId, PositionName, PositionName, CoordinateSpace.Object, ShaderStageCapability.Vertex));
AddSlot(new ColorRGBMaterialSlot(ColorSlotId, ColorSlotName, ColorSlotName, SlotType.Input, Color.grey, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, 1, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaThresholdSlotId, AlphaClipThresholdSlotName, AlphaClipThresholdSlotName, SlotType.Input, 0f, ShaderStageCapability.Fragment));
// clear out slot names that do not match the slots
// we support

PositionSlotId,
ColorSlotId,
AlphaSlotId,
AlphaThresholdSlotId

protected override VisualElement CreateCommonSettingsElement()
{
return new UnlitSettingsView(this);
}
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
{
List<MaterialSlot> slots = new List<MaterialSlot>();
GetSlots(slots);
List<MaterialSlot> validSlots = new List<MaterialSlot>();
for(int i = 0; i < slots.Count; i++)
{
if(slots[i].stageCapability != ShaderStageCapability.All && slots[i].stageCapability != stageCapability)
continue;
validSlots.Add(slots[i]);
}
return validSlots.OfType<IMayRequirePosition>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresPosition(stageCapability));
}
}
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Artistic/Adjustment/ChannelMixerNode.cs


});
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
public void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
{
registry.ProvideFunction(GetFunctionName(), s =>
{

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Artistic/Adjustment/InvertColorsNode.cs


});
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
public void GenerateNodeFunction(ShaderGenerator visitor, GraphContext graphContext, GenerationMode generationMode)
{
var sb = new ShaderStringBuilder();
sb.AppendLine("void {0}({1} In, {2} InvertColors, out {3} Out)",

visitor.AddShaderChunk(sb.ToString(), true);
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
public void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
{
registry.ProvideFunction(GetFunctionName(), s =>
{

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Artistic/Mask/ChannelMaskNode.cs


return GetFunctionName() + " (" + inputValue + ", " + outputValue + ");";
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
public void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
{
ValidateChannelCount();
registry.ProvideFunction(GetFunctionName(), s =>

12
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Artistic/Normal/NormalCreateNode.cs


AddSlot(new SamplerStateMaterialSlot(SamplerInputId, k_SamplerInputName, k_SamplerInputName, SlotType.Input));
AddSlot(new Vector1MaterialSlot(OffsetInputId, k_OffsetInputName, k_OffsetInputName, SlotType.Input, 0.5f));
AddSlot(new Vector1MaterialSlot(StrengthInputId, k_StrengthInputName, k_StrengthInputName, SlotType.Input, 8f));
AddSlot(new Vector3MaterialSlot(OutputSlotId, k_OutputSlotName, k_OutputSlotName, SlotType.Output, Vector3.zero));
AddSlot(new Vector3MaterialSlot(OutputSlotId, k_OutputSlotName, k_OutputSlotName, SlotType.Output, Vector3.zero, ShaderStageCapability.Fragment));
RemoveSlotsNameNotMatching(new[] { TextureInputId, UVInputId, SamplerInputId, OffsetInputId, StrengthInputId, OutputSlotId });
}

sb.AppendLine("{0}2 offsetU = float2(UV.x + Offset, UV.y);", precision);
sb.AppendLine("{0}2 offsetV = float2(UV.x, UV.y + Offset);", precision);
sb.AppendLine("{0} normalSample = Texture.Sample(Sampler, UV);", precision);
sb.AppendLine("{0} uSample = Texture.Sample(Sampler, offsetU);", precision);
sb.AppendLine("{0} vSample = Texture.Sample(Sampler, offsetV);", precision);
sb.AppendLine("{0} normalSample = Texture.Sample(Sampler, UV).x;", precision);
sb.AppendLine("{0} uSample = Texture.Sample(Sampler, offsetU).x;", precision);
sb.AppendLine("{0} vSample = Texture.Sample(Sampler, offsetV).x;", precision);
sb.AppendLine("{0}3 va = float3(1, 0, (uSample - normalSample) * Strength);", precision);
sb.AppendLine("{0}3 vb = float3(0, 1, (vSample - normalSample) * Strength);", precision);

visitor.AddShaderChunk(sb.ToString(), true);
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
public void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
{
registry.ProvideFunction(GetFunctionName(), s =>
{

});
}
public bool RequiresMeshUV(UVChannel channel)
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
{
foreach (var slot in this.GetInputSlots<MaterialSlot>().OfType<IMayRequireMeshUV>())
{

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Channel/FlipNode.cs


});
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
public void GenerateNodeFunction(ShaderGenerator visitor, GraphContext graphContext, GenerationMode generationMode)
{
var sb = new ShaderStringBuilder();
sb.AppendLine("void {0}({1} In, {2} Flip, out {3} Out)",

visitor.AddShaderChunk(sb.ToString(), true);
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
public void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
{
registry.ProvideFunction(GetFunctionName(), s =>
{

91
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/CodeFunctionNode.cs


public Binding binding { get; private set; }
public bool hidden { get; private set; }
public Vector4? defaultValue { get; private set; }
public ShaderStageCapability stageCapability { get; private set; }
public SlotAttribute(int mSlotId, Binding mImplicitBinding)
public SlotAttribute(int mSlotId, Binding mImplicitBinding, ShaderStageCapability mStageCapability = ShaderStageCapability.All)
stageCapability = mStageCapability;
public SlotAttribute(int mSlotId, Binding mImplicitBinding, bool mHidden)
public SlotAttribute(int mSlotId, Binding mImplicitBinding, bool mHidden, ShaderStageCapability mStageCapability = ShaderStageCapability.All)
stageCapability = mStageCapability;
public SlotAttribute(int mSlotId, Binding mImplicitBinding, float defaultX, float defaultY, float defaultZ, float defaultW)
public SlotAttribute(int mSlotId, Binding mImplicitBinding, float defaultX, float defaultY, float defaultZ, float defaultW, ShaderStageCapability mStageCapability = ShaderStageCapability.All)
stageCapability = mStageCapability;
}
}

MaterialSlot s;
if (attribute.binding == Binding.None && !par.IsOut && par.ParameterType == typeof(Color))
s = new ColorRGBAMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, hidden: attribute.hidden);
s = new ColorRGBAMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, stageCapability: attribute.stageCapability, hidden: attribute.hidden);
s = new ColorRGBAMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, hidden: attribute.hidden);
s = new ColorRGBAMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, stageCapability: attribute.stageCapability, hidden: attribute.hidden);
s = new ColorRGBMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, hidden: attribute.hidden);
s = new ColorRGBMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, stageCapability: attribute.stageCapability, hidden: attribute.hidden);
else if (attribute.binding == Binding.None || par.IsOut)
s = MaterialSlot.CreateMaterialSlot(
ConvertTypeToSlotValueType(par),

par.IsOut ? SlotType.Output : SlotType.Input,
attribute.defaultValue ?? Vector4.zero,
shaderStageCapability: attribute.stageCapability,
s = CreateBoundSlot(attribute.binding, attribute.slotId, name, par.Name, attribute.hidden);
s = CreateBoundSlot(attribute.binding, attribute.slotId, name, par.Name, attribute.stageCapability, attribute.hidden);
slots.Add(s);
m_Slots.Add(attribute);

RemoveSlotsNameNotMatching(slots.Select(x => x.id));
}
private static MaterialSlot CreateBoundSlot(Binding attributeBinding, int slotId, string displayName, string shaderOutputName, bool hidden)
private static MaterialSlot CreateBoundSlot(Binding attributeBinding, int slotId, string displayName, string shaderOutputName, ShaderStageCapability shaderStageCapability, bool hidden)
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object);
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability);
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View);
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability);
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World);
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability);
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent);
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV0);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV0, shaderStageCapability);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV1);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV1, shaderStageCapability);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV2);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV2, shaderStageCapability);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV3);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV3, shaderStageCapability);
return new ScreenPositionMaterialSlot(slotId, displayName, shaderOutputName, ScreenSpaceType.Default);
return new ScreenPositionMaterialSlot(slotId, displayName, shaderOutputName, ScreenSpaceType.Default, shaderStageCapability);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability);
return new VertexColorMaterialSlot(slotId, displayName, shaderOutputName);
return new VertexColorMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability);
default:
throw new ArgumentOutOfRangeException("attributeBinding", attributeBinding, null);
}

return result;
}
public virtual void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
public virtual void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
{
registry.ProvideFunction(GetFunctionName(), s =>
{

return attrs.FirstOrDefault();
}
public NeededCoordinateSpace RequiresNormal()
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
{
var binding = NeededCoordinateSpace.None;
s_TempSlots.Clear();

return binding;
}
public NeededCoordinateSpace RequiresViewDirection()
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability)
{
var binding = NeededCoordinateSpace.None;
s_TempSlots.Clear();

return binding;
}
public NeededCoordinateSpace RequiresPosition()
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

return binding;
}
public NeededCoordinateSpace RequiresTangent()
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

return binding;
}
public NeededCoordinateSpace RequiresBitangent()
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

return binding;
}
public bool RequiresMeshUV(UVChannel channel)
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

return false;
}
public bool RequiresScreenPosition()
public bool RequiresScreenPosition(ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

return false;
}
public bool RequiresVertexColor()
public bool RequiresVertexColor(ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

8
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Basic/ColorNode.cs


@"{0}4 {1} = IsGammaSpace() ? {0}4({2}, {3}, {4}, {5}) : {0}4(SRGBToLinear({0}3({2}, {3}, {4})), {5});"
, precision
, GetVariableNameForNode()
, color.color.r
, color.color.g
, color.color.b
, color.color.a), true);
, NodeUtils.FloatToShaderValue(color.color.r)
, NodeUtils.FloatToShaderValue(color.color.g)
, NodeUtils.FloatToShaderValue(color.color.b)
, NodeUtils.FloatToShaderValue(color.color.a)), true);
}
public override string GetVariableNameForSlot(int slotId)

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/BitangentVectorNode.cs


return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.BiTangent));
}
public NeededCoordinateSpace RequiresBitangent()
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
{
return space.ToNeededCoordinateSpace();
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/NormalVectorNode.cs


return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Normal));
}
public NeededCoordinateSpace RequiresNormal()
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
{
return space.ToNeededCoordinateSpace();
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/PositionNode.cs


return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Position));
}
public NeededCoordinateSpace RequiresPosition()
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
{
return space.ToNeededCoordinateSpace();
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ScreenPositionNode.cs


visitor.AddShaderChunk(string.Format("{0}4 {1} = {2};", precision, GetVariableNameForSlot(kOutputSlotId), m_ScreenSpaceType.ToValueAsVariable()), true);
}
public bool RequiresScreenPosition()
public bool RequiresScreenPosition(ShaderStageCapability stageCapability)
{
return true;
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/TangentVectorNode.cs


return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Tangent));
}
public NeededCoordinateSpace RequiresTangent()
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
{
return space.ToNeededCoordinateSpace();
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/UVNode.cs


visitor.AddShaderChunk(string.Format("{0}4 {1} = IN.{2};", precision, GetVariableNameForSlot(OutputSlotId), m_OutputChannel.GetUVName()), true);
}
public bool RequiresMeshUV(UVChannel channel)
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
{
return channel == uvChannel;
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/VertexColorNode.cs


return string.Format("IN.{0}", ShaderGeneratorNames.VertexColor);
}
public bool RequiresVertexColor()
public bool RequiresVertexColor(ShaderStageCapability stageCapability)
{
return true;
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs


return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.ViewDirection));
}
public NeededCoordinateSpace RequiresViewDirection()
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability)
{
return space.ToNeededCoordinateSpace();
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Gradient/GradientNode.cs


RemoveSlotsNameNotMatching(new[] { OutputSlotId });
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
public void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
{
if(generationMode == GenerationMode.Preview)
{

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Scene/FogNode.cs


GetVariableNameForSlot(OutputSlotId), GetVariableNameForSlot(OutputSlot1Id)), false);
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
public void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
{
registry.ProvideFunction(GetFunctionName(), s =>
{

});
}
public NeededCoordinateSpace RequiresPosition()
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
{
return CoordinateSpace.Object.ToNeededCoordinateSpace();
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Texture/SampleCubemapNode.cs


visitor.AddShaderChunk(result, true);
}
public NeededCoordinateSpace RequiresViewDirection()
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability)
{
var viewDirSlot = FindInputSlot<MaterialSlot>(ViewDirInputId);
var edgesViewDir = owner.GetEdges(viewDirSlot.slotReference);

return NeededCoordinateSpace.None;
}
public NeededCoordinateSpace RequiresNormal()
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
{
var normalSlot = FindInputSlot<MaterialSlot>(NormalInputId);
var edgesNormal = owner.GetEdges(normalSlot.slotReference);

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Texture/SampleTexture2DArrayNode.cs


visitor.AddShaderChunk(string.Format("{0} {1} = {2}.a;", precision, GetVariableNameForSlot(OutputSlotAId), GetVariableNameForSlot(OutputSlotRGBAId)), true);
}
public bool RequiresMeshUV(UVChannel channel)
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

12
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Texture/SampleTexture2DNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new Vector4MaterialSlot(OutputSlotRGBAId, kOutputSlotRGBAName, kOutputSlotRGBAName, SlotType.Output, Vector4.zero));
AddSlot(new Vector1MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, 0));
AddSlot(new Vector4MaterialSlot(OutputSlotRGBAId, kOutputSlotRGBAName, kOutputSlotRGBAName, SlotType.Output, Vector4.zero, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, 0, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, 0, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, 0, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, 0, ShaderStageCapability.Fragment));
AddSlot(new Texture2DInputMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName));
AddSlot(new UVMaterialSlot(UVInput, kUVInputName, kUVInputName, UVChannel.UV0));
AddSlot(new SamplerStateMaterialSlot(SamplerInput, kSamplerInputName, kSamplerInputName, SlotType.Input));

visitor.AddShaderChunk(string.Format("{0} {1} = {2}.a;", precision, GetVariableNameForSlot(OutputSlotAId), GetVariableNameForSlot(OutputSlotRGBAId)), true);
}
public bool RequiresMeshUV(UVChannel channel)
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

34
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/MasterNode.cs


foreach (var activeNode in activeNodeList.OfType<AbstractMaterialNode>())
activeNode.CollectShaderProperties(shaderProperties, mode);
var finalShader = new ShaderGenerator();
finalShader.AddShaderChunk(string.Format(@"Shader ""{0}""", outputName), false);
finalShader.AddShaderChunk("{", false);
finalShader.Indent();
finalShader.AddShaderChunk("Properties", false);
finalShader.AddShaderChunk("{", false);
finalShader.Indent();
finalShader.AddShaderChunk(shaderProperties.GetPropertiesBlock(2), false);
finalShader.Deindent();
finalShader.AddShaderChunk("}", false);
foreach (var subShader in m_SubShaders)
finalShader.AddShaderChunk(subShader.GetSubshader(this, mode), true);
finalShader.AddShaderChunk(@"FallBack ""Hidden/InternalErrorShader""", false);
finalShader.Deindent();
finalShader.AddShaderChunk("}", false);
var finalShader = new ShaderStringBuilder();
finalShader.AppendLine(@"Shader ""{0}""", outputName);
using(finalShader.BlockScope())
{
finalShader.AppendLine("Properties");
using(finalShader.BlockScope())
{
finalShader.AppendLine(shaderProperties.GetPropertiesBlock(0));
}
foreach (var subShader in m_SubShaders)
finalShader.AppendLines(subShader.GetSubshader(this, mode));
finalShader.AppendLine(@"FallBack ""Hidden/InternalErrorShader""");
}
return finalShader.GetShaderString(0);
return finalShader.ToString();
}
public bool IsPipelineCompatible(IRenderPipeline renderPipeline)

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Math/Basic/MultiplyNode.cs


FindInputSlot<MaterialSlot>(Input2SlotId).concreteValueType.ToString(precision));
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
public void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
{
registry.ProvideFunction(GetFunctionName(), s =>
{

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Math/Matrix/MatrixConstructionNode.cs


visitor.AddShaderChunk(sb.ToString(), false);
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
public void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
{
registry.ProvideFunction(GetFunctionName(), s =>
{

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Math/Vector/TransformNode.cs


return false;
}
public NeededCoordinateSpace RequiresTangent()
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
{
if(RequiresWorldSpaceTangentTransform())
return NeededCoordinateSpace.World;

public NeededCoordinateSpace RequiresBitangent()
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
{
if (RequiresWorldSpaceTangentTransform())
return NeededCoordinateSpace.World;

public NeededCoordinateSpace RequiresNormal()
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
{
if (RequiresWorldSpaceTangentTransform())
return NeededCoordinateSpace.World;

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Procedural/CheckerboardNode.cs


[Slot(1, Binding.None, 0.2f, 0.2f, 0.2f, 1f)] ColorRGB ColorA,
[Slot(2, Binding.None, 0.7f, 0.7f, 0.7f, 1f)] ColorRGB ColorB,
[Slot(3, Binding.None, 1f, 1f, 1f, 1f)] Vector2 Frequency,
[Slot(4, Binding.None)] out Vector3 Out)
[Slot(4, Binding.None, ShaderStageCapability.Fragment)] out Vector3 Out)
{
Out = Vector2.zero;
return

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Procedural/Noise/GradientNoiseNode.cs


return "{ Out = unity_gradientNoise(UV * Scale) + 0.5; }";
}
public override void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
public override void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
{
registry.ProvideFunction("unity_gradientNoise_dir", s => s.Append(@"
float2 unity_gradientNoise_dir(float2 p)

}
"));
base.GenerateNodeFunction(registry, generationMode);
base.GenerateNodeFunction(registry, graphContext, generationMode);
}
}
}

部分文件因为文件数量过多而无法显示

正在加载...
取消
保存