您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
236 行
9.9 KiB
236 行
9.9 KiB
using System.Collections.Generic;
|
|
using UnityEditor.Graphing;
|
|
using UnityEditor.ShaderGraph;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.Experimental.Rendering.HDPipeline;
|
|
|
|
namespace UnityEditor.Experimental.Rendering.HDPipeline
|
|
{
|
|
public class HDUnlitSubShader : IUnlitSubShader
|
|
{
|
|
Pass m_PassDepthOnly = new Pass()
|
|
{
|
|
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
|
|
},
|
|
VertexShaderSlots = new List<int>()
|
|
{
|
|
PBRMasterNode.PositionSlotId
|
|
}
|
|
};
|
|
|
|
Pass m_PassForward = new Pass()
|
|
{
|
|
Name = "Forward Unlit",
|
|
LightMode = "ForwardOnly",
|
|
TemplateName = "HDUnlitPassForward.template",
|
|
ShaderPassName = "SHADERPASS_FORWARD_UNLIT",
|
|
ExtraDefines = new List<string>()
|
|
{
|
|
"#pragma multi_compile _ DEBUG_DISPLAY"
|
|
},
|
|
Includes = new List<string>()
|
|
{
|
|
"#include \"HDRP/ShaderPass/ShaderPassForwardUnlit.hlsl\"",
|
|
},
|
|
PixelShaderSlots = new List<int>()
|
|
{
|
|
UnlitMasterNode.ColorSlotId,
|
|
UnlitMasterNode.AlphaSlotId,
|
|
UnlitMasterNode.AlphaThresholdSlotId
|
|
},
|
|
VertexShaderSlots = new List<int>()
|
|
{
|
|
PBRMasterNode.PositionSlotId
|
|
}
|
|
};
|
|
|
|
Pass m_PassMETA = new Pass()
|
|
{
|
|
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
|
|
},
|
|
PixelShaderSlots = new List<int>()
|
|
{
|
|
UnlitMasterNode.ColorSlotId,
|
|
UnlitMasterNode.AlphaSlotId,
|
|
UnlitMasterNode.AlphaThresholdSlotId
|
|
},
|
|
VertexShaderSlots = new List<int>()
|
|
{
|
|
//PBRMasterNode.PositionSlotId
|
|
}
|
|
};
|
|
|
|
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
|
|
},
|
|
VertexShaderSlots = new List<int>()
|
|
{
|
|
PBRMasterNode.PositionSlotId
|
|
},
|
|
};
|
|
|
|
private static HashSet<string> GetActiveFieldsFromMasterNode(INode iMasterNode, Pass pass)
|
|
{
|
|
HashSet<string> activeFields = new HashSet<string>();
|
|
|
|
UnlitMasterNode masterNode = iMasterNode as UnlitMasterNode;
|
|
if (masterNode == null)
|
|
{
|
|
return activeFields;
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
float constantAlpha = 0.0f;
|
|
if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId) ||
|
|
(float.TryParse(masterNode.GetSlotValue(PBRMasterNode.AlphaThresholdSlotId, GenerationMode.ForReals), out constantAlpha) && (constantAlpha > 0.0f)))
|
|
{
|
|
activeFields.Add("AlphaTest");
|
|
}
|
|
|
|
// Keywords for transparent
|
|
// #pragma shader_feature _SURFACE_TYPE_TRANSPARENT
|
|
if (masterNode.surfaceType != SurfaceType.Opaque)
|
|
{
|
|
// transparent-only defines
|
|
activeFields.Add("SurfaceType.Transparent");
|
|
|
|
// #pragma shader_feature _ _BLENDMODE_ALPHA _BLENDMODE_ADD _BLENDMODE_PRE_MULTIPLY
|
|
if (masterNode.alphaMode == AlphaMode.Alpha)
|
|
{
|
|
activeFields.Add("BlendMode.Alpha");
|
|
}
|
|
else if (masterNode.alphaMode == AlphaMode.Additive)
|
|
{
|
|
activeFields.Add("BlendMode.Add");
|
|
}
|
|
// else if (masterNode.alphaMode == PBRMasterNode.AlphaMode.PremultiplyAlpha) // TODO
|
|
// {
|
|
// defines.AddShaderChunk("#define _BLENDMODE_PRE_MULTIPLY 1", true);
|
|
// }
|
|
}
|
|
else
|
|
{
|
|
// opaque-only defines
|
|
}
|
|
|
|
// enable dithering LOD crossfade
|
|
// #pragma multi_compile _ LOD_FADE_CROSSFADE
|
|
// TODO: We should have this keyword only if VelocityInGBuffer is enable, how to do that ?
|
|
//#pragma multi_compile VELOCITYOUTPUT_OFF VELOCITYOUTPUT_ON
|
|
|
|
return activeFields;
|
|
}
|
|
|
|
private static bool GenerateShaderPassUnlit(AbstractMaterialNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions, ShaderGenerator result, List<string> sourceAssetDependencyPaths)
|
|
{
|
|
// apply master node options to active fields
|
|
HashSet<string> activeFields = GetActiveFieldsFromMasterNode(masterNode, pass);
|
|
|
|
// use standard shader pass generation
|
|
return HDSubShaderUtilities.GenerateShaderPass(masterNode, pass, mode, materialOptions, activeFields, result, sourceAssetDependencyPaths);
|
|
}
|
|
|
|
public string GetSubshader(IMasterNode iMasterNode, GenerationMode mode, List<string> sourceAssetDependencyPaths = null)
|
|
{
|
|
if (sourceAssetDependencyPaths != null)
|
|
{
|
|
// HDUnlitSubShader.cs
|
|
sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("292c6a3c80161fa4cb49a9d11d35cbe9"));
|
|
// HDSubShaderUtilities.cs
|
|
sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("713ced4e6eef4a44799a4dd59041484b"));
|
|
}
|
|
|
|
var masterNode = iMasterNode as UnlitMasterNode;
|
|
var subShader = new ShaderGenerator();
|
|
subShader.AddShaderChunk("SubShader", true);
|
|
subShader.AddShaderChunk("{", true);
|
|
subShader.Indent();
|
|
{
|
|
SurfaceMaterialOptions materialOptions = HDSubShaderUtilities.BuildMaterialOptions(masterNode.surfaceType, masterNode.alphaMode, masterNode.twoSided.isOn);
|
|
|
|
// Add tags at the SubShader level
|
|
{
|
|
var tagsVisitor = new ShaderStringBuilder();
|
|
materialOptions.GetTags(tagsVisitor);
|
|
subShader.AddShaderChunk(tagsVisitor.ToString(), false);
|
|
}
|
|
|
|
// generate the necessary shader passes
|
|
// bool opaque = (masterNode.surfaceType == SurfaceType.Opaque);
|
|
// bool transparent = (masterNode.surfaceType != SurfaceType.Opaque);
|
|
bool distortionActive = false;
|
|
|
|
GenerateShaderPassUnlit(masterNode, m_PassDepthOnly, mode, materialOptions, subShader, sourceAssetDependencyPaths);
|
|
GenerateShaderPassUnlit(masterNode, m_PassForward, mode, materialOptions, subShader, sourceAssetDependencyPaths);
|
|
GenerateShaderPassUnlit(masterNode, m_PassMETA, mode, materialOptions, subShader, sourceAssetDependencyPaths);
|
|
if (distortionActive)
|
|
{
|
|
GenerateShaderPassUnlit(masterNode, m_PassDistortion, mode, materialOptions, subShader, sourceAssetDependencyPaths);
|
|
}
|
|
}
|
|
subShader.Deindent();
|
|
subShader.AddShaderChunk("}", true);
|
|
|
|
return subShader.GetShaderString(0);
|
|
}
|
|
|
|
public bool IsPipelineCompatible(RenderPipelineAsset renderPipelineAsset)
|
|
{
|
|
return renderPipelineAsset is HDRenderPipelineAsset;
|
|
}
|
|
}
|
|
}
|