public string GetSubshader(IMasterNode iMasterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // HDPBRSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("c4e8610eb7ce19747bb637c68acc55cd")); // HDSubShaderUtilities.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("713ced4e6eef4a44799a4dd59041484b")); } var masterNode = iMasterNode as PBRMasterNode; var subShader = new ShaderGenerator(); subShader.AddShaderChunk("SubShader", true); subShader.AddShaderChunk("{", true); subShader.Indent(); { SurfaceMaterialOptions materialOptions = HDSubShaderUtilities.BuildMaterialOptions(masterNode.surfaceType, masterNode.alphaMode, masterNode.twoSided.isOn); // Add tags at the SubShader level { var tagsVisitor = new ShaderStringBuilder(); materialOptions.GetTags(tagsVisitor); subShader.AddShaderChunk(tagsVisitor.ToString(), false); } // generate the necessary shader passes bool opaque = (masterNode.surfaceType == SurfaceType.Opaque); bool transparent = (masterNode.surfaceType != SurfaceType.Opaque); bool distortionActive = false; bool transparentDepthPrepassActive = transparent && false; bool transparentBackfaceActive = transparent && false; bool transparentDepthPostpassActive = transparent && false; if (opaque) { GenerateShaderPassLit(masterNode, m_PassGBuffer, mode, materialOptions, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassGBufferWithPrepass, mode, materialOptions, subShader, sourceAssetDependencyPaths); } GenerateShaderPassLit(masterNode, m_PassMETA, mode, materialOptions, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassShadowCaster, mode, materialOptions, subShader, sourceAssetDependencyPaths); if (opaque) { GenerateShaderPassLit(masterNode, m_PassDepthOnly, mode, materialOptions, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassMotionVectors, mode, materialOptions, subShader, sourceAssetDependencyPaths); } if (distortionActive) { GenerateShaderPassLit(masterNode, m_PassDistortion, mode, materialOptions, subShader, sourceAssetDependencyPaths); } if (transparentDepthPrepassActive) { GenerateShaderPassLit(masterNode, m_PassTransparentDepthPrepass, mode, materialOptions, subShader, sourceAssetDependencyPaths); } if (transparentBackfaceActive) { GenerateShaderPassLit(masterNode, m_PassTransparentBackface, mode, materialOptions, subShader, sourceAssetDependencyPaths); } GenerateShaderPassLit(masterNode, m_PassForward, mode, materialOptions, subShader, sourceAssetDependencyPaths); if (transparentDepthPostpassActive) { GenerateShaderPassLit(masterNode, m_PassTransparentDepthPostpass, mode, materialOptions, subShader, sourceAssetDependencyPaths); } } subShader.Deindent(); subShader.AddShaderChunk("}", true); return(subShader.GetShaderString(0)); }
public string GetSubshader(IMasterNode iMasterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // HDUnlitSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("1c44ec077faa54145a89357de68e5d26")); // HDSubShaderUtilities.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("713ced4e6eef4a44799a4dd59041484b")); } var masterNode = iMasterNode as HDUnlitMasterNode; var subShader = new ShaderGenerator(); subShader.AddShaderChunk("SubShader", true); subShader.AddShaderChunk("{", true); subShader.Indent(); { //Handle data migration here as we need to have a renderingPass already set with accurate data at this point. if (masterNode.renderingPass == HDRenderQueue.RenderQueueType.Unknown) { switch (masterNode.surfaceType) { case SurfaceType.Opaque: masterNode.renderingPass = HDRenderQueue.RenderQueueType.Opaque; break; case SurfaceType.Transparent: #pragma warning disable CS0618 // Type or member is obsolete if (masterNode.m_DrawBeforeRefraction) { masterNode.m_DrawBeforeRefraction = false; #pragma warning restore CS0618 // Type or member is obsolete masterNode.renderingPass = HDRenderQueue.RenderQueueType.PreRefraction; } else { masterNode.renderingPass = HDRenderQueue.RenderQueueType.Transparent; } break; default: throw new System.ArgumentException("Unknown SurfaceType"); } } HDMaterialTags materialTags = HDSubShaderUtilities.BuildMaterialTags(masterNode.renderingPass, masterNode.sortPriority, masterNode.alphaTest.isOn, HDMaterialTags.RenderType.HDUnlitShader); // Add tags at the SubShader level { var tagsVisitor = new ShaderStringBuilder(); materialTags.GetTags(tagsVisitor, HDRenderPipeline.k_ShaderTagName); subShader.AddShaderChunk(tagsVisitor.ToString(), false); } // generate the necessary shader passes bool opaque = (masterNode.surfaceType == SurfaceType.Opaque); bool transparent = !opaque; bool distortionActive = transparent && masterNode.distortion.isOn; GenerateShaderPassLit(masterNode, m_PassMETA, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassShadowCaster, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_SceneSelectionPass, mode, subShader, sourceAssetDependencyPaths); if (opaque) { GenerateShaderPassLit(masterNode, m_PassDepthForwardOnly, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassMotionVectors, mode, subShader, sourceAssetDependencyPaths); } if (distortionActive) { GenerateShaderPassLit(masterNode, m_PassDistortion, mode, subShader, sourceAssetDependencyPaths); } GenerateShaderPassLit(masterNode, m_PassForwardOnly, mode, subShader, sourceAssetDependencyPaths); } subShader.Deindent(); subShader.AddShaderChunk("}", true); subShader.AddShaderChunk(@"CustomEditor ""UnityEditor.Experimental.Rendering.HDPipeline.HDUnlitGUI"""); return(subShader.GetShaderString(0)); }
public string GetSubshader(IMasterNode iMasterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // HairSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("c3f20efb64673e0488a2c8e986a453fa")); // HDSubShaderUtilities.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("713ced4e6eef4a44799a4dd59041484b")); } var masterNode = iMasterNode as HairMasterNode; var subShader = new ShaderGenerator(); subShader.AddShaderChunk("SubShader", true); subShader.AddShaderChunk("{", true); subShader.Indent(); { SurfaceMaterialTags materialTags = HDSubShaderUtilities.BuildMaterialTags(masterNode.surfaceType, masterNode.alphaTest.isOn, false, masterNode.sortPriority); // Add tags at the SubShader level { var tagsVisitor = new ShaderStringBuilder(); materialTags.GetTags(tagsVisitor); subShader.AddShaderChunk(tagsVisitor.ToString(), false); } // generate the necessary shader passes bool opaque = (masterNode.surfaceType == SurfaceType.Opaque); bool transparent = !opaque; bool transparentBackfaceActive = transparent && masterNode.backThenFrontRendering.isOn; bool transparentDepthPrepassActive = transparent && masterNode.alphaTest.isOn && masterNode.alphaTestDepthPrepass.isOn; bool transparentDepthPostpassActive = transparent && masterNode.alphaTest.isOn && masterNode.alphaTestDepthPostpass.isOn; GenerateShaderPassHair(masterNode, m_PassMETA, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassHair(masterNode, m_PassShadowCaster, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassHair(masterNode, m_SceneSelectionPass, mode, subShader, sourceAssetDependencyPaths); if (opaque) { GenerateShaderPassHair(masterNode, m_PassDepthForwardOnly, mode, subShader, sourceAssetDependencyPaths); } GenerateShaderPassHair(masterNode, m_PassMotionVectors, mode, subShader, sourceAssetDependencyPaths); if (transparentBackfaceActive) { GenerateShaderPassHair(masterNode, m_PassTransparentBackface, mode, subShader, sourceAssetDependencyPaths); } if (transparentDepthPrepassActive) { GenerateShaderPassHair(masterNode, m_PassTransparentDepthPrepass, mode, subShader, sourceAssetDependencyPaths); } GenerateShaderPassHair(masterNode, m_PassForwardOnly, mode, subShader, sourceAssetDependencyPaths); if (transparentDepthPostpassActive) { GenerateShaderPassHair(masterNode, m_PassTransparentDepthPostpass, mode, subShader, sourceAssetDependencyPaths); } } subShader.Deindent(); subShader.AddShaderChunk("}", true); subShader.AddShaderChunk(@"CustomEditor ""UnityEditor.Experimental.Rendering.HDPipeline.HairGUI"""); return(subShader.GetShaderString(0)); }
public string GetSubshader(IMasterNode iMasterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // FabricSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("059cc3132f0336e40886300f3d2d7f12")); // HDSubShaderUtilities.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("713ced4e6eef4a44799a4dd59041484b")); } var masterNode = iMasterNode as FabricMasterNode; var subShader = new ShaderGenerator(); subShader.AddShaderChunk("SubShader", true); subShader.AddShaderChunk("{", true); subShader.Indent(); { // generate the necessary shader passes bool opaque = (masterNode.surfaceType == SurfaceType.Opaque); bool transparent = !opaque; // Add tags at the SubShader level var renderingPass = masterNode.surfaceType == SurfaceType.Opaque ? HDRenderQueue.RenderQueueType.Opaque : HDRenderQueue.RenderQueueType.Transparent; int queue = HDRenderQueue.ChangeType(renderingPass, masterNode.sortPriority, masterNode.alphaTest.isOn); HDSubShaderUtilities.AddTags(subShader, HDRenderPipeline.k_ShaderTagName, HDRenderTypeTags.HDLitShader, queue); GenerateShaderPassLit(masterNode, m_PassShadowCaster, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassMETA, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_SceneSelectionPass, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassDepthForwardOnly, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassMotionVectors, mode, subShader, sourceAssetDependencyPaths); // Assign define here based on opaque or transparent to save some variant m_PassForwardOnly.ExtraDefines = opaque ? HDSubShaderUtilities.s_ExtraDefinesForwardOpaque : HDSubShaderUtilities.s_ExtraDefinesForwardTransparent; GenerateShaderPassLit(masterNode, m_PassForwardOnly, mode, subShader, sourceAssetDependencyPaths); } subShader.Deindent(); subShader.AddShaderChunk("}", true); if (mode == GenerationMode.ForReals) { subShader.AddShaderChunk("SubShader", false); subShader.AddShaderChunk("{", false); subShader.Indent(); HDSubShaderUtilities.AddTags(subShader, HDRenderPipeline.k_ShaderTagName); { GenerateShaderPassLit(masterNode, m_PassRaytracingIndirect, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassRaytracingVisibility, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassRaytracingForward, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassRaytracingGBuffer, mode, subShader, sourceAssetDependencyPaths); } subShader.Deindent(); subShader.AddShaderChunk("}", false); } subShader.AddShaderChunk(@"CustomEditor ""UnityEditor.Rendering.HighDefinition.FabricGUI"""); return(subShader.GetShaderString(0)); }
private static string GetShaderPassFromTemplate( string template, UnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions) { 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 shaderProperties = new PropertyCollector(); surfaceInputs.AddShaderChunk("struct SurfaceInputs{", false); surfaceInputs.Indent(); var activeNodeList = ListPool <INode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots); 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); if (requirements.requiresVertexColor) { surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.VertexColor), false); } if (requirements.requiresScreenPosition) { surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.ScreenPosition), false); } foreach (var channel in requirements.requiresMeshUVs.Distinct()) { surfaceInputs.AddShaderChunk(string.Format("half4 {0};", channel.GetUVName()), false); } surfaceInputs.Deindent(); surfaceInputs.AddShaderChunk("};", false); surfaceVertexShader.AddShaderChunk("GraphVertexInput PopulateVertexData(GraphVertexInput v){", false); surfaceVertexShader.Indent(); surfaceVertexShader.AddShaderChunk("return v;", false); surfaceVertexShader.Deindent(); surfaceVertexShader.AddShaderChunk("}", false); var slots = new List <MaterialSlot>(); foreach (var id in pass.PixelShaderSlots) { var slot = masterNode.FindSlot <MaterialSlot>(id); if (slot != null) { slots.Add(slot); } } GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, slots, true); var usedSlots = new List <MaterialSlot>(); foreach (var id in pass.PixelShaderSlots) { usedSlots.Add(masterNode.FindSlot <MaterialSlot>(id)); } GraphUtil.GenerateSurfaceDescription( activeNodeList, masterNode, masterNode.owner as AbstractMaterialGraph, surfaceDescriptionFunction, functionRegistry, shaderProperties, requirements, mode, "PopulateSurfaceData", "SurfaceDescription", null, 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); var blendingVisitor = new ShaderGenerator(); var cullingVisitor = new ShaderGenerator(); var zTestVisitor = new ShaderGenerator(); var zWriteVisitor = new ShaderGenerator(); materialOptions.GetBlend(blendingVisitor); materialOptions.GetCull(cullingVisitor); materialOptions.GetDepthTest(zTestVisitor); materialOptions.GetDepthWrite(zWriteVisitor); var interpolators = new ShaderGenerator(); var localVertexShader = new ShaderGenerator(); var localPixelShader = new ShaderGenerator(); var localSurfaceInputs = new ShaderGenerator(); var surfaceOutputRemap = new ShaderGenerator(); var reqs = ShaderGraphRequirements.none; ShaderGenerator.GenerateStandardTransforms( 3, 10, interpolators, localVertexShader, localPixelShader, localSurfaceInputs, requirements, reqs, CoordinateSpace.World); ShaderGenerator defines = new ShaderGenerator(); if (masterNode.IsSlotConnected(UnlitMasterNode.AlphaThresholdSlotId)) { defines.AddShaderChunk("#define _AlphaClip 1", true); } if (masterNode.surfaceType == SurfaceType.Transparent && masterNode.alphaMode == AlphaMode.Premultiply) { defines.AddShaderChunk("#define _ALPHAPREMULTIPLY_ON 1", true); } var templateLocation = GetTemplatePath(template); foreach (var slot in usedSlots) { surfaceOutputRemap.AddShaderChunk(slot.shaderOutputName + " = surf." + slot.shaderOutputName + ";", true); } if (!File.Exists(templateLocation)) { return(string.Empty); } 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("${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)); return(resultPass); }
private static bool GenerateShaderPassUnlit(AbstractMaterialNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions, ShaderGenerator result, List <string> sourceAssetDependencyPaths) { var templateLocation = Path.Combine(Path.Combine(Path.Combine(HDEditorUtils.GetHDRenderPipelinePath(), "Editor"), "ShaderGraph"), pass.TemplateName); if (!File.Exists(templateLocation)) { // TODO: produce error here return(false); } if (sourceAssetDependencyPaths != null) { sourceAssetDependencyPaths.Add(templateLocation); } // grab all of the active nodes (for pixel and vertex graphs) var vertexNodes = ListPool <INode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots); var pixelNodes = ListPool <INode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots); // graph requirements describe what the graph itself requires var pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false); // TODO: is ShaderStageCapability.Fragment correct? var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false); // Function Registry tracks functions to remove duplicates, it wraps a string builder that stores the combined function string ShaderStringBuilder graphNodeFunctions = new ShaderStringBuilder(); graphNodeFunctions.IncreaseIndent(); var functionRegistry = new FunctionRegistry(graphNodeFunctions); // TODO: this can be a shared function for all HDRP master nodes -- From here through GraphUtil.GenerateSurfaceDescription(..) // Build the list of active slots based on what the pass requires var pixelSlots = HDSubShaderUtilities.FindMaterialSlotsOnNode(pass.PixelShaderSlots, masterNode); var vertexSlots = HDSubShaderUtilities.FindMaterialSlotsOnNode(pass.VertexShaderSlots, masterNode); // properties used by either pixel and vertex shader PropertyCollector sharedProperties = new PropertyCollector(); // build the graph outputs structure to hold the results of each active slots (and fill out activeFields to indicate they are active) string pixelGraphInputStructName = "SurfaceDescriptionInputs"; string pixelGraphOutputStructName = "SurfaceDescription"; string pixelGraphEvalFunctionName = "SurfaceDescriptionFunction"; ShaderStringBuilder pixelGraphEvalFunction = new ShaderStringBuilder(); ShaderStringBuilder pixelGraphOutputs = new ShaderStringBuilder(); // dependency tracker -- set of active fields HashSet <string> activeFields = GetActiveFieldsFromMasterNode(masterNode, pass); // build initial requirements HDRPShaderStructs.AddActiveFieldsFromPixelGraphRequirements(activeFields, pixelRequirements); // build the graph outputs structure, and populate activeFields with the fields of that structure GraphUtil.GenerateSurfaceDescriptionStruct(pixelGraphOutputs, pixelSlots, true, pixelGraphOutputStructName, activeFields); // Build the graph evaluation code, to evaluate the specified slots GraphUtil.GenerateSurfaceDescriptionFunction( pixelNodes, masterNode, masterNode.owner as AbstractMaterialGraph, pixelGraphEvalFunction, functionRegistry, sharedProperties, pixelRequirements, // TODO : REMOVE UNUSED mode, pixelGraphEvalFunctionName, pixelGraphOutputStructName, null, pixelSlots, pixelGraphInputStructName); string vertexGraphInputStructName = "VertexDescriptionInputs"; string vertexGraphOutputStructName = "VertexDescription"; string vertexGraphEvalFunctionName = "VertexDescriptionFunction"; ShaderStringBuilder vertexGraphEvalFunction = new ShaderStringBuilder(); ShaderStringBuilder vertexGraphOutputs = new ShaderStringBuilder(); // check for vertex animation -- enables HAVE_VERTEX_MODIFICATION bool vertexActive = false; if (masterNode.IsSlotConnected(PBRMasterNode.PositionSlotId)) { vertexActive = true; activeFields.Add("features.modifyMesh"); HDRPShaderStructs.AddActiveFieldsFromVertexGraphRequirements(activeFields, vertexRequirements); // ------------------------------------- // Generate Output structure for Vertex Description function GraphUtil.GenerateVertexDescriptionStruct(vertexGraphOutputs, vertexSlots, vertexGraphOutputStructName, activeFields); // ------------------------------------- // Generate Vertex Description function GraphUtil.GenerateVertexDescriptionFunction( masterNode.owner as AbstractMaterialGraph, vertexGraphEvalFunction, functionRegistry, sharedProperties, mode, vertexNodes, vertexSlots, vertexGraphInputStructName, vertexGraphEvalFunctionName, vertexGraphOutputStructName); } 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); HDRPShaderStructs.AddRequiredFields(pass.RequiredFields, activeFields); // apply dependencies to the active fields, and build interpolators (TODO: split this function) var packedInterpolatorCode = new ShaderGenerator(); HDRPShaderStructs.Generate( packedInterpolatorCode, activeFields); // debug output all active fields var interpolatorDefines = new ShaderGenerator(); { interpolatorDefines.AddShaderChunk("// ACTIVE FIELDS:"); foreach (string f in activeFields) { interpolatorDefines.AddShaderChunk("// " + f); } } // build graph inputs structures ShaderGenerator pixelGraphInputs = new ShaderGenerator(); ShaderSpliceUtil.BuildType(typeof(HDRPShaderStructs.SurfaceDescriptionInputs), activeFields, pixelGraphInputs); ShaderGenerator vertexGraphInputs = new ShaderGenerator(); ShaderSpliceUtil.BuildType(typeof(HDRPShaderStructs.VertexDescriptionInputs), activeFields, vertexGraphInputs); ShaderGenerator defines = new ShaderGenerator(); { defines.AddShaderChunk(string.Format("#define SHADERPASS {0}", pass.ShaderPassName), true); if (pass.ExtraDefines != null) { foreach (var define in pass.ExtraDefines) { defines.AddShaderChunk(define); } } defines.AddGenerator(interpolatorDefines); } var shaderPassIncludes = new ShaderGenerator(); if (pass.Includes != null) { foreach (var include in pass.Includes) { shaderPassIncludes.AddShaderChunk(include); } } // build graph code var graph = new ShaderGenerator(); { graph.AddShaderChunk("// Shared Graph Properties (uniform inputs)"); graph.AddShaderChunk(sharedProperties.GetPropertiesDeclaration(1)); if (vertexActive) { graph.AddShaderChunk("// Vertex Graph Inputs"); graph.Indent(); graph.AddGenerator(vertexGraphInputs); graph.Deindent(); graph.AddShaderChunk("// Vertex Graph Outputs"); graph.Indent(); graph.AddShaderChunk(vertexGraphOutputs.ToString()); graph.Deindent(); } graph.AddShaderChunk("// Pixel Graph Inputs"); graph.Indent(); graph.AddGenerator(pixelGraphInputs); graph.Deindent(); graph.AddShaderChunk("// Pixel Graph Outputs"); graph.Indent(); graph.AddShaderChunk(pixelGraphOutputs.ToString()); graph.Deindent(); graph.AddShaderChunk("// Shared Graph Node Functions"); graph.AddShaderChunk(graphNodeFunctions.ToString()); if (vertexActive) { graph.AddShaderChunk("// Vertex Graph Evaluation"); graph.Indent(); graph.AddShaderChunk(vertexGraphEvalFunction.ToString()); graph.Deindent(); } graph.AddShaderChunk("// Pixel Graph Evaluation"); graph.Indent(); graph.AddShaderChunk(pixelGraphEvalFunction.ToString()); 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()); // process the template to generate the shader code for this pass TODO: could make this a shared function string[] templateLines = File.ReadAllLines(templateLocation); System.Text.StringBuilder builder = new System.Text.StringBuilder(); foreach (string line in templateLines) { ShaderSpliceUtil.PreprocessShaderCode(line, activeFields, namedFragments, builder); builder.AppendLine(); } result.AddShaderChunk(builder.ToString(), false); return(true); }
private static bool GenerateShaderPass(UnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions, ShaderGenerator result) { var templateLocation = ShaderGenerator.GetTemplatePath(pass.TemplateName); if (!File.Exists(templateLocation)) { // TODO: produce error here return(false); } // grab all of the active nodes var activeNodeList = ListPool <INode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots); // graph requirements describe what the graph itself requires var graphRequirements = ShaderGraphRequirements.FromNodes(activeNodeList, ShaderStageCapability.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>(); foreach (var id in pass.PixelShaderSlots) { MaterialSlot slot = masterNode.FindSlot <MaterialSlot>(id); if (slot != null) { activeSlots.Add(slot); } } // build the graph outputs structure to hold the results of each active slots (and fill out activeFields to indicate they are active) string graphInputStructName = "SurfaceDescriptionInputs"; string graphOutputStructName = "SurfaceDescription"; string graphEvalFunctionName = "SurfaceDescriptionFunction"; var graphEvalFunction = new ShaderStringBuilder(); var graphOutputs = new ShaderStringBuilder(); PropertyCollector graphProperties = new PropertyCollector(); // build the graph outputs structure, and populate activeFields with the fields of that structure HashSet <string> activeFields = new HashSet <string>(); GraphUtil.GenerateSurfaceDescriptionStruct(graphOutputs, activeSlots, true); // Build the graph evaluation code, to evaluate the specified slots GraphUtil.GenerateSurfaceDescriptionFunction( activeNodeList, masterNode, masterNode.owner as AbstractMaterialGraph, graphEvalFunction, functionRegistry, graphProperties, graphRequirements, // TODO : REMOVE UNUSED mode, graphEvalFunctionName, graphOutputStructName, null, activeSlots, graphInputStructName); var blendCode = new ShaderStringBuilder(); var cullCode = new ShaderStringBuilder(); var zTestCode = new ShaderStringBuilder(); var zWriteCode = new ShaderStringBuilder(); var stencilCode = new ShaderStringBuilder(); var colorMaskCode = new ShaderStringBuilder(); HDSubShaderUtilities.BuildRenderStatesFromPassAndMaterialOptions(pass, materialOptions, blendCode, cullCode, zTestCode, zWriteCode, stencilCode, colorMaskCode); if (masterNode.twoSided.isOn) { activeFields.Add("DoubleSided"); if (pass.ShaderPassName != "SHADERPASS_VELOCITY") // HACK to get around lack of a good interpolator dependency system { // we need to be able to build interpolators using multiple input structs // also: should only require isFrontFace if Normals are required... activeFields.Add("DoubleSided.Mirror"); // TODO: change this depending on what kind of normal flip you want.. activeFields.Add("FragInputs.isFrontFace"); // will need this for determining normal flip mode } } if (pass.PixelShaderSlots != null) { foreach (var slotId in pass.PixelShaderSlots) { var slot = masterNode.FindSlot <MaterialSlot>(slotId); if (slot != null) { var rawSlotName = slot.RawDisplayName().ToString(); var descriptionVar = string.Format("{0}.{1}", graphOutputStructName, rawSlotName); activeFields.Add(descriptionVar); } } } var packedInterpolatorCode = new ShaderGenerator(); var graphInputs = new ShaderGenerator(); HDRPShaderStructs.Generate( packedInterpolatorCode, graphInputs, graphRequirements, pass.RequiredFields, CoordinateSpace.World, activeFields); // debug output all active fields var interpolatorDefines = new ShaderGenerator(); { interpolatorDefines.AddShaderChunk("// ACTIVE FIELDS:"); foreach (string f in activeFields) { interpolatorDefines.AddShaderChunk("// " + f); } } ShaderGenerator defines = new ShaderGenerator(); { defines.AddShaderChunk(string.Format("#define SHADERPASS {0}", pass.ShaderPassName), true); if (pass.ExtraDefines != null) { foreach (var define in pass.ExtraDefines) { defines.AddShaderChunk(define); } } defines.AddGenerator(interpolatorDefines); } var shaderPassIncludes = new ShaderGenerator(); if (pass.Includes != null) { foreach (var include in pass.Includes) { shaderPassIncludes.AddShaderChunk(include); } } // build graph code var graph = new ShaderGenerator(); graph.AddShaderChunk("// Graph Inputs"); graph.Indent(); graph.AddGenerator(graphInputs); graph.Deindent(); graph.AddShaderChunk("// Graph Outputs"); graph.Indent(); graph.AddShaderChunk(graphOutputs.ToString()); //graph.AddGenerator(graphOutputs); graph.Deindent(); graph.AddShaderChunk("// Graph Properties (uniform inputs)"); graph.AddShaderChunk(graphProperties.GetPropertiesDeclaration(1)); graph.AddShaderChunk("// Graph Node Functions"); graph.AddShaderChunk(graphNodeFunctions.ToString()); graph.AddShaderChunk("// Graph Evaluation"); graph.Indent(); graph.AddShaderChunk(graphEvalFunction.ToString()); //graph.AddGenerator(graphEvalFunction); graph.Deindent(); // build the hash table of all named fragments TODO: could make this Dictionary<string, ShaderGenerator / string> ? Dictionary <string, string> namedFragments = new Dictionary <string, string>(); namedFragments.Add("${Defines}", defines.GetShaderString(2, false)); namedFragments.Add("${Graph}", graph.GetShaderString(2, false)); namedFragments.Add("${LightMode}", pass.LightMode); namedFragments.Add("${PassName}", pass.Name); namedFragments.Add("${Includes}", shaderPassIncludes.GetShaderString(2, false)); namedFragments.Add("${InterpolatorPacking}", packedInterpolatorCode.GetShaderString(2, false)); namedFragments.Add("${Blending}", blendCode.ToString()); namedFragments.Add("${Culling}", cullCode.ToString()); namedFragments.Add("${ZTest}", zTestCode.ToString()); namedFragments.Add("${ZWrite}", zWriteCode.ToString()); namedFragments.Add("${Stencil}", stencilCode.ToString()); namedFragments.Add("${ColorMask}", colorMaskCode.ToString()); namedFragments.Add("${LOD}", materialOptions.lod.ToString()); namedFragments.Add("${VariantDefines}", GetVariantDefines(masterNode)); // process the template to generate the shader code for this pass TODO: could make this a shared function string[] templateLines = File.ReadAllLines(templateLocation); System.Text.StringBuilder builder = new System.Text.StringBuilder(); foreach (string line in templateLines) { ShaderSpliceUtil.PreprocessShaderCode(line, activeFields, namedFragments, builder); builder.AppendLine(); } result.AddShaderChunk(builder.ToString(), false); return(true); }
public static bool GenerateShaderPass(AbstractMaterialNode masterNode, ShaderPass pass, GenerationMode mode, ActiveFields activeFields, ShaderGenerator result, List <string> sourceAssetDependencyPaths, List <Dependency[]> dependencies, string resourceClassName, string assemblyName) { // -------------------------------------------------- // Debug // Get scripting symbols BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup; string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup); bool isDebug = defines.Contains(kDebugSymbol); // -------------------------------------------------- // Setup // Initiailize Collectors var propertyCollector = new PropertyCollector(); var keywordCollector = new KeywordCollector(); masterNode.owner.CollectShaderKeywords(keywordCollector, mode); // Get upstream nodes from ShaderPass port mask List <AbstractMaterialNode> vertexNodes; List <AbstractMaterialNode> pixelNodes; GetUpstreamNodesForShaderPass(masterNode, pass, out vertexNodes, out pixelNodes); // Track permutation indices for all nodes List <int>[] vertexNodePermutations = new List <int> [vertexNodes.Count]; List <int>[] pixelNodePermutations = new List <int> [pixelNodes.Count]; // Get active fields from upstream Node requirements ShaderGraphRequirementsPerKeyword graphRequirements; GetActiveFieldsAndPermutationsForNodes(masterNode, pass, keywordCollector, vertexNodes, pixelNodes, vertexNodePermutations, pixelNodePermutations, activeFields, out graphRequirements); // GET CUSTOM ACTIVE FIELDS HERE! // Get active fields from ShaderPass AddRequiredFields(pass.requiredAttributes, activeFields.baseInstance); AddRequiredFields(pass.requiredVaryings, activeFields.baseInstance); // Get Port references from ShaderPass var pixelSlots = FindMaterialSlotsOnNode(pass.pixelPorts, masterNode); var vertexSlots = FindMaterialSlotsOnNode(pass.vertexPorts, masterNode); // Function Registry var functionBuilder = new ShaderStringBuilder(); var functionRegistry = new FunctionRegistry(functionBuilder); // Hash table of named $splice(name) commands // Key: splice token // Value: string to splice Dictionary <string, string> spliceCommands = new Dictionary <string, string>(); // -------------------------------------------------- // Dependencies // Propagate active field requirements using dependencies // Must be executed before types are built foreach (var instance in activeFields.all.instances) { ShaderSpliceUtil.ApplyDependencies(instance, dependencies); } // -------------------------------------------------- // Pass Setup // Name if (!string.IsNullOrEmpty(pass.displayName)) { spliceCommands.Add("PassName", $"Name \"{pass.displayName}\""); } else { spliceCommands.Add("PassName", "// Name: <None>"); } // Tags if (!string.IsNullOrEmpty(pass.lightMode)) { spliceCommands.Add("LightMode", $"\"LightMode\" = \"{pass.lightMode}\""); } else { spliceCommands.Add("LightMode", "// LightMode: <None>"); } // Render state BuildRenderStatesFromPass(pass, ref spliceCommands); // -------------------------------------------------- // Pass Code // Pragmas using (var passPragmaBuilder = new ShaderStringBuilder()) { if (pass.pragmas != null) { foreach (string pragma in pass.pragmas) { passPragmaBuilder.AppendLine($"#pragma {pragma}"); } } if (passPragmaBuilder.length == 0) { passPragmaBuilder.AppendLine("// PassPragmas: <None>"); } spliceCommands.Add("PassPragmas", passPragmaBuilder.ToCodeBlack()); } // Includes using (var passIncludeBuilder = new ShaderStringBuilder()) { if (pass.includes != null) { foreach (string include in pass.includes) { passIncludeBuilder.AppendLine($"#include \"{include}\""); } } if (passIncludeBuilder.length == 0) { passIncludeBuilder.AppendLine("// PassIncludes: <None>"); } spliceCommands.Add("PassIncludes", passIncludeBuilder.ToCodeBlack()); } // Keywords using (var passKeywordBuilder = new ShaderStringBuilder()) { if (pass.keywords != null) { foreach (KeywordDescriptor keyword in pass.keywords) { passKeywordBuilder.AppendLine(keyword.ToDeclarationString()); } } if (passKeywordBuilder.length == 0) { passKeywordBuilder.AppendLine("// PassKeywords: <None>"); } spliceCommands.Add("PassKeywords", passKeywordBuilder.ToCodeBlack()); } // -------------------------------------------------- // Graph Vertex var vertexBuilder = new ShaderStringBuilder(); // If vertex modification enabled if (activeFields.baseInstance.Contains("features.graphVertex")) { // Setup string vertexGraphInputName = "VertexDescriptionInputs"; string vertexGraphOutputName = "VertexDescription"; string vertexGraphFunctionName = "VertexDescriptionFunction"; var vertexGraphInputGenerator = new ShaderGenerator(); var vertexGraphFunctionBuilder = new ShaderStringBuilder(); var vertexGraphOutputBuilder = new ShaderStringBuilder(); // Build vertex graph inputs ShaderSpliceUtil.BuildType(GetTypeForStruct("VertexDescriptionInputs", resourceClassName, assemblyName), activeFields, vertexGraphInputGenerator, isDebug); // Build vertex graph outputs // Add struct fields to active fields SubShaderGenerator.GenerateVertexDescriptionStruct(vertexGraphOutputBuilder, vertexSlots, vertexGraphOutputName, activeFields.baseInstance); // Build vertex graph functions from ShaderPass vertex port mask SubShaderGenerator.GenerateVertexDescriptionFunction( masterNode.owner as GraphData, vertexGraphFunctionBuilder, functionRegistry, propertyCollector, keywordCollector, mode, masterNode, vertexNodes, vertexNodePermutations, vertexSlots, vertexGraphInputName, vertexGraphFunctionName, vertexGraphOutputName); // Generate final shader strings vertexBuilder.AppendLines(vertexGraphInputGenerator.GetShaderString(0, false)); vertexBuilder.AppendNewLine(); vertexBuilder.AppendLines(vertexGraphOutputBuilder.ToString()); vertexBuilder.AppendNewLine(); vertexBuilder.AppendLines(vertexGraphFunctionBuilder.ToString()); } // Add to splice commands if (vertexBuilder.length == 0) { vertexBuilder.AppendLine("// GraphVertex: <None>"); } spliceCommands.Add("GraphVertex", vertexBuilder.ToCodeBlack()); // -------------------------------------------------- // Graph Pixel // Setup string pixelGraphInputName = "SurfaceDescriptionInputs"; string pixelGraphOutputName = "SurfaceDescription"; string pixelGraphFunctionName = "SurfaceDescriptionFunction"; var pixelGraphInputGenerator = new ShaderGenerator(); var pixelGraphOutputBuilder = new ShaderStringBuilder(); var pixelGraphFunctionBuilder = new ShaderStringBuilder(); // Build pixel graph inputs ShaderSpliceUtil.BuildType(GetTypeForStruct("SurfaceDescriptionInputs", resourceClassName, assemblyName), activeFields, pixelGraphInputGenerator, isDebug); // Build pixel graph outputs // Add struct fields to active fields SubShaderGenerator.GenerateSurfaceDescriptionStruct(pixelGraphOutputBuilder, pixelSlots, pixelGraphOutputName, activeFields.baseInstance); // Build pixel graph functions from ShaderPass pixel port mask SubShaderGenerator.GenerateSurfaceDescriptionFunction( pixelNodes, pixelNodePermutations, masterNode, masterNode.owner as GraphData, pixelGraphFunctionBuilder, functionRegistry, propertyCollector, keywordCollector, mode, pixelGraphFunctionName, pixelGraphOutputName, null, pixelSlots, pixelGraphInputName); using (var pixelBuilder = new ShaderStringBuilder()) { // Generate final shader strings pixelBuilder.AppendLines(pixelGraphInputGenerator.GetShaderString(0, false)); pixelBuilder.AppendNewLine(); pixelBuilder.AppendLines(pixelGraphOutputBuilder.ToString()); pixelBuilder.AppendNewLine(); pixelBuilder.AppendLines(pixelGraphFunctionBuilder.ToString()); // Add to splice commands if (pixelBuilder.length == 0) { pixelBuilder.AppendLine("// GraphPixel: <None>"); } spliceCommands.Add("GraphPixel", pixelBuilder.ToCodeBlack()); } // -------------------------------------------------- // Graph Functions if (functionBuilder.length == 0) { functionBuilder.AppendLine("// GraphFunctions: <None>"); } spliceCommands.Add("GraphFunctions", functionBuilder.ToCodeBlack()); // -------------------------------------------------- // Graph Keywords using (var keywordBuilder = new ShaderStringBuilder()) { keywordCollector.GetKeywordsDeclaration(keywordBuilder, mode); if (keywordBuilder.length == 0) { keywordBuilder.AppendLine("// GraphKeywords: <None>"); } spliceCommands.Add("GraphKeywords", keywordBuilder.ToCodeBlack()); } // -------------------------------------------------- // Graph Properties using (var propertyBuilder = new ShaderStringBuilder()) { propertyCollector.GetPropertiesDeclaration(propertyBuilder, mode, masterNode.owner.concretePrecision); if (propertyBuilder.length == 0) { propertyBuilder.AppendLine("// GraphProperties: <None>"); } spliceCommands.Add("GraphProperties", propertyBuilder.ToCodeBlack()); } // -------------------------------------------------- // Graph Defines using (var graphDefines = new ShaderStringBuilder()) { graphDefines.AppendLine("#define {0}", pass.referenceName); if (graphRequirements.permutationCount > 0) { List <int> activePermutationIndices; // Depth Texture activePermutationIndices = graphRequirements.allPermutations.instances .Where(p => p.requirements.requiresDepthTexture) .Select(p => p.permutationIndex) .ToList(); if (activePermutationIndices.Count > 0) { graphDefines.AppendLine(KeywordUtil.GetKeywordPermutationSetConditional(activePermutationIndices)); graphDefines.AppendLine("#define REQUIRE_DEPTH_TEXTURE"); graphDefines.AppendLine("#endif"); } // Opaque Texture activePermutationIndices = graphRequirements.allPermutations.instances .Where(p => p.requirements.requiresCameraOpaqueTexture) .Select(p => p.permutationIndex) .ToList(); if (activePermutationIndices.Count > 0) { graphDefines.AppendLine(KeywordUtil.GetKeywordPermutationSetConditional(activePermutationIndices)); graphDefines.AppendLine("#define REQUIRE_OPAQUE_TEXTURE"); graphDefines.AppendLine("#endif"); } } else { // Depth Texture if (graphRequirements.baseInstance.requirements.requiresDepthTexture) { graphDefines.AppendLine("#define REQUIRE_DEPTH_TEXTURE"); } // Opaque Texture if (graphRequirements.baseInstance.requirements.requiresCameraOpaqueTexture) { graphDefines.AppendLine("#define REQUIRE_OPAQUE_TEXTURE"); } } // Add to splice commands spliceCommands.Add("GraphDefines", graphDefines.ToCodeBlack()); } // -------------------------------------------------- // Main // Main include is expected to contain vert/frag definitions for the pass // This must be defined after all graph code using (var mainBuilder = new ShaderStringBuilder()) { mainBuilder.AppendLine($"#include \"{pass.varyingsInclude}\""); mainBuilder.AppendLine($"#include \"{pass.passInclude}\""); // Add to splice commands spliceCommands.Add("MainInclude", mainBuilder.ToCodeBlack()); } // -------------------------------------------------- // Debug // Debug output all active fields using (var debugBuilder = new ShaderStringBuilder()) { if (isDebug) { // Active fields debugBuilder.AppendLine("// ACTIVE FIELDS:"); foreach (string field in activeFields.baseInstance.fields) { debugBuilder.AppendLine("// " + field); } } if (debugBuilder.length == 0) { debugBuilder.AppendLine("// <None>"); } // Add to splice commands spliceCommands.Add("Debug", debugBuilder.ToCodeBlack()); } // -------------------------------------------------- // Finalize // Get Template string templateLocation = GetTemplatePath("PassMesh.template"); if (!File.Exists(templateLocation)) { return(false); } // Get Template preprocessor string templatePath = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Templates"; var templatePreprocessor = new ShaderSpliceUtil.TemplatePreprocessor(activeFields, spliceCommands, isDebug, templatePath, sourceAssetDependencyPaths, assemblyName, resourceClassName); // Process Template templatePreprocessor.ProcessTemplateFile(templateLocation); result.AddShaderChunk(templatePreprocessor.GetShaderCode().ToString(), false); return(true); }
public string GetSubshader(IMasterNode iMasterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // HDUnlitSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("1c44ec077faa54145a89357de68e5d26")); // HDSubShaderUtilities.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("713ced4e6eef4a44799a4dd59041484b")); } var masterNode = iMasterNode as HDUnlitMasterNode; var subShader = new ShaderGenerator(); subShader.AddShaderChunk("SubShader", true); subShader.AddShaderChunk("{", true); subShader.Indent(); { // Add tags at the SubShader level int queue = HDRenderQueue.ChangeType(masterNode.renderingPass, masterNode.sortPriority, masterNode.alphaTest.isOn); HDSubShaderUtilities.AddTags(subShader, HDRenderPipeline.k_ShaderTagName, HDRenderTypeTags.HDUnlitShader, queue); // For preview only we generate the passes that are enabled bool opaque = (masterNode.surfaceType == SurfaceType.Opaque); bool transparent = !opaque; bool distortionActive = transparent && masterNode.distortion.isOn; GenerateShaderPassUnlit(masterNode, m_PassShadowCaster, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassUnlit(masterNode, m_PassMETA, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassUnlit(masterNode, m_SceneSelectionPass, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassUnlit(masterNode, m_PassDepthForwardOnly, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassUnlit(masterNode, m_PassMotionVectors, mode, subShader, sourceAssetDependencyPaths); if (distortionActive) { GenerateShaderPassUnlit(masterNode, m_PassDistortion, mode, subShader, sourceAssetDependencyPaths); } GenerateShaderPassUnlit(masterNode, m_PassForwardOnly, mode, subShader, sourceAssetDependencyPaths); } subShader.Deindent(); subShader.AddShaderChunk("}", false); #if ENABLE_RAYTRACING if (mode == GenerationMode.ForReals) { subShader.AddShaderChunk("SubShader", false); subShader.AddShaderChunk("{", false); subShader.Indent(); { GenerateShaderPassUnlit(masterNode, m_PassRaytracingIndirect, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassUnlit(masterNode, m_PassRaytracingVisibility, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassUnlit(masterNode, m_PassRaytracingForward, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassUnlit(masterNode, m_PassRaytracingGBuffer, mode, subShader, sourceAssetDependencyPaths); } subShader.Deindent(); subShader.AddShaderChunk("}", false); } #endif subShader.AddShaderChunk(@"CustomEditor ""UnityEditor.Rendering.HighDefinition.HDUnlitGUI"""); return(subShader.GetShaderString(0)); }
private static string GetVariantDefines(UnlitMasterNode masterNode) { 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); } // if (kTesselationMode != TessellationMode.None) // { // defines.AddShaderChunk("#define _TESSELLATION_PHONG 1", true); // } // #pragma shader_feature _ _VERTEX_DISPLACEMENT _PIXEL_DISPLACEMENT // switch (kDisplacementMode) // { // case DisplacementMode.None: // break; // case DisplacementMode.Vertex: // defines.AddShaderChunk("#define _VERTEX_DISPLACEMENT 1", true); // break; // case DisplacementMode.Pixel: // defines.AddShaderChunk("#define _PIXEL_DISPLACEMENT 1", true); // Depth offset is only enabled if per pixel displacement is // if (kDepthOffsetEnable) // { // // #pragma shader_feature _DEPTHOFFSET_ON // defines.AddShaderChunk("#define _DEPTHOFFSET_ON 1", true); // } // break; // case DisplacementMode.Tessellation: // if (kTessellationEnabled) // { // defines.AddShaderChunk("#define _TESSELLATION_DISPLACEMENT 1", true); // } // break; // } // #pragma shader_feature _VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE // #pragma shader_feature _DISPLACEMENT_LOCK_TILING_SCALE // #pragma shader_feature _PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE // #pragma shader_feature _VERTEX_WIND // #pragma shader_feature _ _REFRACTION_PLANE _REFRACTION_SPHERE // // #pragma shader_feature _ _MAPPING_PLANAR _MAPPING_TRIPLANAR // MOVE to a node // #pragma shader_feature _NORMALMAP_TANGENT_SPACE // #pragma shader_feature _ _REQUIRE_UV2 _REQUIRE_UV3 // #pragma shader_feature _MASKMAP // #pragma shader_feature _BENTNORMALMAP // #pragma shader_feature _EMISSIVE_COLOR_MAP // #pragma shader_feature _ENABLESPECULAROCCLUSION // #pragma shader_feature _HEIGHTMAP // #pragma shader_feature _TANGENTMAP // #pragma shader_feature _ANISOTROPYMAP // #pragma shader_feature _DETAIL_MAP // MOVE to a node // #pragma shader_feature _SUBSURFACE_RADIUS_MAP // #pragma shader_feature _THICKNESSMAP // #pragma shader_feature _SPECULARCOLORMAP // #pragma shader_feature _TRANSMITTANCECOLORMAP // Keywords for transparent // #pragma shader_feature _SURFACE_TYPE_TRANSPARENT if (masterNode.surfaceType != SurfaceType.Opaque) { // transparent-only defines defines.AddShaderChunk("#define _SURFACE_TYPE_TRANSPARENT 1", true); // #pragma shader_feature _ _BLENDMODE_ALPHA _BLENDMODE_ADD _BLENDMODE_PRE_MULTIPLY if (masterNode.alphaMode == AlphaMode.Alpha) { defines.AddShaderChunk("#define _BLENDMODE_ALPHA 1", true); } else if (masterNode.alphaMode == AlphaMode.Additive) { defines.AddShaderChunk("#define _BLENDMODE_ADD 1", true); } // else if (masterNode.alphaMode == PBRMasterNode.AlphaMode.PremultiplyAlpha) // TODO // { // defines.AddShaderChunk("#define _BLENDMODE_PRE_MULTIPLY 1", true); // } // #pragma shader_feature _BLENDMODE_PRESERVE_SPECULAR_LIGHTING // if (kEnableBlendModePreserveSpecularLighting) // { // defines.AddShaderChunk("#define _BLENDMODE_PRESERVE_SPECULAR_LIGHTING 1", true); // } // #pragma shader_feature _ENABLE_FOG_ON_TRANSPARENT // if (kEnableFogOnTransparent) // { // defines.AddShaderChunk("#define _ENABLE_FOG_ON_TRANSPARENT 1", true); // } } else { // opaque-only defines } // enable dithering LOD crossfade // #pragma multi_compile _ LOD_FADE_CROSSFADE // TODO: We should have this keyword only if VelocityInGBuffer is enable, how to do that ? //#pragma multi_compile VELOCITYOUTPUT_OFF VELOCITYOUTPUT_ON return(defines.GetShaderString(2)); }
public void GenerateNodeCode(ShaderGenerator visitor, GraphContext graphContext, GenerationMode generationMode) { visitor.AddShaderChunk(precision + " " + GetVariableNameForSlot(0) + " = " + m_DiffusionProfile.selectedEntry + ";", true); }
private static bool GenerateShaderPass(CustomRenderTextureNode masterNode, GenerationMode mode, ShaderGenerator result, List <string> sourceAssetDependencyPaths) { string templateLocation = Path.Combine( HDUtils.GetHDRenderPipelinePath(), "Editor", "CustomRenderTextureShaderGraph", "CustomRenderTexturePass.template"); if (!File.Exists(templateLocation)) { Debug.LogError("Template not found: " + templateLocation); return(false); } var activeFields = new HashSet <string>() { "uv0" }; var pixelNodes = ListPool <AbstractMaterialNode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, CustomRenderTextureNode.AllSlots); var pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false); var graphNodeFunctions = new ShaderStringBuilder(); graphNodeFunctions.IncreaseIndent(); var functionRegistry = new FunctionRegistry(graphNodeFunctions); var pixelSlots = HDSubShaderUtilities.FindMaterialSlotsOnNode(CustomRenderTextureNode.AllSlots, masterNode); // build the graph outputs structure to hold the results of each active slots (and fill out activeFields to indicate they are active) string pixelGraphInputStructName = "SurfaceDescriptionInputs"; string pixelGraphOutputStructName = "SurfaceDescriptionOutputs"; string pixelGraphEvalFunctionName = "SurfaceDescriptionFunction"; var sharedProperties = new PropertyCollector(); var pixelGraphEvalFunction = new ShaderStringBuilder(); // Build the graph evaluation code, to evaluate the specified slots GraphUtil.GenerateSurfaceDescriptionFunction( pixelNodes, masterNode, masterNode.owner as GraphData, pixelGraphEvalFunction, functionRegistry, sharedProperties, pixelRequirements, mode, pixelGraphEvalFunctionName, pixelGraphOutputStructName, null, pixelSlots, pixelGraphInputStructName); // build graph inputs structures ShaderGenerator pixelGraphInputs = new ShaderGenerator(); ShaderSpliceUtil.BuildType(typeof(HDRPShaderStructs.SurfaceDescriptionInputs), activeFields, pixelGraphInputs); // build graph code var graph = new ShaderGenerator(); { graph.AddShaderChunk("// Shared Graph Properties (uniform inputs)"); graph.AddShaderChunk(sharedProperties.GetPropertiesDeclaration(1, mode)); graph.AddShaderChunk("// Shared Graph Node Functions"); graph.AddShaderChunk(graphNodeFunctions.ToString()); graph.AddShaderChunk("// Pixel Graph Evaluation"); graph.Indent(); graph.AddShaderChunk(pixelGraphEvalFunction.ToString()); graph.Deindent(); } var namedFragments = new Dictionary <string, string>() { { "Graph", graph.GetShaderString(2, false) }, }; string sharedTemplatePath = Path.Combine(HDUtils.GetHDRenderPipelinePath(), "Editor", "ShaderGraph"); string buildTypeAssemblyNameFormat = "UnityEditor.Experimental.Rendering.HDPipeline.HDRPShaderStructs+{0}, " + typeof(HDSubShaderUtilities).Assembly.FullName.ToString(); var templatePreprocessor = new ShaderSpliceUtil.TemplatePreprocessor(activeFields, namedFragments, false, sharedTemplatePath, sourceAssetDependencyPaths, buildTypeAssemblyNameFormat); templatePreprocessor.ProcessTemplateFile(templateLocation); result.AddShaderChunk(templatePreprocessor.GetShaderCode().ToString(), false); return(true); }
public static bool GenerateShaderPass(AbstractMaterialNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions, HashSet <string> activeFields, ShaderGenerator result, List <string> sourceAssetDependencyPaths, bool vertexActive) { string templatePath = Path.Combine(HDUtils.GetHDRenderPipelinePath(), "Editor/Material"); string templateLocation = Path.Combine(Path.Combine(Path.Combine(templatePath, pass.MaterialName), "ShaderGraph"), pass.TemplateName); if (!File.Exists(templateLocation)) { // TODO: produce error here Debug.LogError("Template not found: " + templateLocation); return(false); } bool debugOutput = false; // grab all of the active nodes (for pixel and vertex graphs) var vertexNodes = ListPool <INode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots); var pixelNodes = ListPool <INode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots); // graph requirements describe what the graph itself requires var pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false); // TODO: is ShaderStageCapability.Fragment correct? var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false); var graphRequirements = pixelRequirements.Union(vertexRequirements); // Function Registry tracks functions to remove duplicates, it wraps a string builder that stores the combined function string ShaderStringBuilder graphNodeFunctions = new ShaderStringBuilder(); graphNodeFunctions.IncreaseIndent(); var functionRegistry = new FunctionRegistry(graphNodeFunctions); // TODO: this can be a shared function for all HDRP master nodes -- From here through GraphUtil.GenerateSurfaceDescription(..) // Build the list of active slots based on what the pass requires var pixelSlots = HDSubShaderUtilities.FindMaterialSlotsOnNode(pass.PixelShaderSlots, masterNode); var vertexSlots = HDSubShaderUtilities.FindMaterialSlotsOnNode(pass.VertexShaderSlots, masterNode); // properties used by either pixel and vertex shader PropertyCollector sharedProperties = new PropertyCollector(); // build the graph outputs structure to hold the results of each active slots (and fill out activeFields to indicate they are active) string pixelGraphInputStructName = "SurfaceDescriptionInputs"; string pixelGraphOutputStructName = "SurfaceDescription"; string pixelGraphEvalFunctionName = "SurfaceDescriptionFunction"; ShaderStringBuilder pixelGraphEvalFunction = new ShaderStringBuilder(); ShaderStringBuilder pixelGraphOutputs = new ShaderStringBuilder(); // build initial requirements HDRPShaderStructs.AddActiveFieldsFromPixelGraphRequirements(activeFields, pixelRequirements); // build the graph outputs structure, and populate activeFields with the fields of that structure GraphUtil.GenerateSurfaceDescriptionStruct(pixelGraphOutputs, pixelSlots, true, pixelGraphOutputStructName, activeFields); // Build the graph evaluation code, to evaluate the specified slots GraphUtil.GenerateSurfaceDescriptionFunction( pixelNodes, masterNode, masterNode.owner as AbstractMaterialGraph, pixelGraphEvalFunction, functionRegistry, sharedProperties, pixelRequirements, // TODO : REMOVE UNUSED mode, pixelGraphEvalFunctionName, pixelGraphOutputStructName, null, pixelSlots, pixelGraphInputStructName); string vertexGraphInputStructName = "VertexDescriptionInputs"; string vertexGraphOutputStructName = "VertexDescription"; string vertexGraphEvalFunctionName = "VertexDescriptionFunction"; ShaderStringBuilder vertexGraphEvalFunction = new ShaderStringBuilder(); ShaderStringBuilder vertexGraphOutputs = new ShaderStringBuilder(); // check for vertex animation -- enables HAVE_VERTEX_MODIFICATION if (vertexActive) { vertexActive = true; activeFields.Add("features.modifyMesh"); HDRPShaderStructs.AddActiveFieldsFromVertexGraphRequirements(activeFields, vertexRequirements); // ------------------------------------- // Generate Output structure for Vertex Description function GraphUtil.GenerateVertexDescriptionStruct(vertexGraphOutputs, vertexSlots, vertexGraphOutputStructName, activeFields); // ------------------------------------- // Generate Vertex Description function GraphUtil.GenerateVertexDescriptionFunction( masterNode.owner as AbstractMaterialGraph, vertexGraphEvalFunction, functionRegistry, sharedProperties, mode, vertexNodes, vertexSlots, vertexGraphInputStructName, vertexGraphEvalFunctionName, vertexGraphOutputStructName); } var blendCode = new ShaderStringBuilder(); var cullCode = new ShaderStringBuilder(); var zTestCode = new ShaderStringBuilder(); var zWriteCode = new ShaderStringBuilder(); var zClipCode = new ShaderStringBuilder(); var stencilCode = new ShaderStringBuilder(); var colorMaskCode = new ShaderStringBuilder(); HDSubShaderUtilities.BuildRenderStatesFromPassAndMaterialOptions(pass, materialOptions, blendCode, cullCode, zTestCode, zWriteCode, zClipCode, stencilCode, colorMaskCode); HDRPShaderStructs.AddRequiredFields(pass.RequiredFields, activeFields); // propagate active field requirements using dependencies ShaderSpliceUtil.ApplyDependencies( activeFields, new List <Dependency[]>() { HDRPShaderStructs.FragInputs.dependencies, HDRPShaderStructs.VaryingsMeshToPS.standardDependencies, HDRPShaderStructs.SurfaceDescriptionInputs.dependencies, HDRPShaderStructs.VertexDescriptionInputs.dependencies }); // debug output all active fields var interpolatorDefines = new ShaderGenerator(); if (debugOutput) { interpolatorDefines.AddShaderChunk("// ACTIVE FIELDS:"); foreach (string f in activeFields) { interpolatorDefines.AddShaderChunk("// " + f); } } // build graph inputs structures ShaderGenerator pixelGraphInputs = new ShaderGenerator(); ShaderSpliceUtil.BuildType(typeof(HDRPShaderStructs.SurfaceDescriptionInputs), activeFields, pixelGraphInputs); ShaderGenerator vertexGraphInputs = new ShaderGenerator(); ShaderSpliceUtil.BuildType(typeof(HDRPShaderStructs.VertexDescriptionInputs), activeFields, vertexGraphInputs); 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); } } if (graphRequirements.requiresDepthTexture) { defines.AddShaderChunk("#define REQUIRE_DEPTH_TEXTURE"); } defines.AddGenerator(interpolatorDefines); } var shaderPassIncludes = new ShaderGenerator(); if (pass.Includes != null) { foreach (var include in pass.Includes) { shaderPassIncludes.AddShaderChunk(include); } } // build graph code var graph = new ShaderGenerator(); { graph.AddShaderChunk("// Shared Graph Properties (uniform inputs)"); graph.AddShaderChunk(sharedProperties.GetPropertiesDeclaration(1)); if (vertexActive) { graph.AddShaderChunk("// Vertex Graph Inputs"); graph.Indent(); graph.AddGenerator(vertexGraphInputs); graph.Deindent(); graph.AddShaderChunk("// Vertex Graph Outputs"); graph.Indent(); graph.AddShaderChunk(vertexGraphOutputs.ToString()); graph.Deindent(); } graph.AddShaderChunk("// Pixel Graph Inputs"); graph.Indent(); graph.AddGenerator(pixelGraphInputs); graph.Deindent(); graph.AddShaderChunk("// Pixel Graph Outputs"); graph.Indent(); graph.AddShaderChunk(pixelGraphOutputs.ToString()); graph.Deindent(); graph.AddShaderChunk("// Shared Graph Node Functions"); graph.AddShaderChunk(graphNodeFunctions.ToString()); if (vertexActive) { graph.AddShaderChunk("// Vertex Graph Evaluation"); graph.Indent(); graph.AddShaderChunk(vertexGraphEvalFunction.ToString()); graph.Deindent(); } graph.AddShaderChunk("// Pixel Graph Evaluation"); graph.Indent(); graph.AddShaderChunk(pixelGraphEvalFunction.ToString()); 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("Blending", blendCode.ToString()); namedFragments.Add("Culling", cullCode.ToString()); namedFragments.Add("ZTest", zTestCode.ToString()); namedFragments.Add("ZWrite", zWriteCode.ToString()); namedFragments.Add("ZClip", zClipCode.ToString()); namedFragments.Add("Stencil", stencilCode.ToString()); namedFragments.Add("ColorMask", colorMaskCode.ToString()); namedFragments.Add("LOD", materialOptions.lod.ToString()); // this is the format string for building the 'C# qualified assembly type names' for $buildType() commands string buildTypeAssemblyNameFormat = "UnityEditor.Experimental.Rendering.HDPipeline.HDRPShaderStructs+{0}, " + typeof(HDSubShaderUtilities).Assembly.FullName.ToString(); string sharedTemplatePath = Path.Combine(Path.Combine(HDUtils.GetHDRenderPipelinePath(), "Editor"), "ShaderGraph"); // process the template to generate the shader code for this pass ShaderSpliceUtil.TemplatePreprocessor templatePreprocessor = new ShaderSpliceUtil.TemplatePreprocessor(activeFields, namedFragments, debugOutput, sharedTemplatePath, sourceAssetDependencyPaths, buildTypeAssemblyNameFormat); templatePreprocessor.ProcessTemplateFile(templateLocation); result.AddShaderChunk(templatePreprocessor.GetShaderCode().ToString(), false); return(true); }
public string GetSubshader(IMasterNode iMasterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // HairSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("c3f20efb64673e0488a2c8e986a453fa")); // HDSubShaderUtilities.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("713ced4e6eef4a44799a4dd59041484b")); } var masterNode = iMasterNode as HairMasterNode; var subShader = new ShaderGenerator(); subShader.AddShaderChunk("SubShader", true); subShader.AddShaderChunk("{", true); subShader.Indent(); { // Add tags at the SubShader level var renderingPass = masterNode.surfaceType == SurfaceType.Opaque ? HDRenderQueue.RenderQueueType.Opaque : HDRenderQueue.RenderQueueType.Transparent; int queue = HDRenderQueue.ChangeType(renderingPass, masterNode.sortPriority, masterNode.alphaTest.isOn); HDSubShaderUtilities.AddTags(subShader, HDRenderPipeline.k_ShaderTagName, HDRenderTypeTags.HDLitShader, queue); // generate the necessary shader passes bool opaque = (masterNode.surfaceType == SurfaceType.Opaque); bool transparent = !opaque; bool transparentBackfaceActive = transparent && masterNode.backThenFrontRendering.isOn; bool transparentDepthPrepassActive = transparent && masterNode.alphaTest.isOn && masterNode.alphaTestDepthPrepass.isOn; bool transparentDepthPostpassActive = transparent && masterNode.alphaTest.isOn && masterNode.alphaTestDepthPostpass.isOn; GenerateShaderPassHair(masterNode, m_PassMETA, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassHair(masterNode, m_PassShadowCaster, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassHair(masterNode, m_SceneSelectionPass, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassHair(masterNode, m_PassDepthForwardOnly, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassHair(masterNode, m_PassMotionVectors, mode, subShader, sourceAssetDependencyPaths); if (transparentBackfaceActive) { GenerateShaderPassHair(masterNode, m_PassTransparentBackface, mode, subShader, sourceAssetDependencyPaths); } if (transparentDepthPrepassActive) { GenerateShaderPassHair(masterNode, m_PassTransparentDepthPrepass, mode, subShader, sourceAssetDependencyPaths); } // Assign define here based on opaque or transparent to save some variant m_PassForwardOnly.ExtraDefines = opaque ? HDSubShaderUtilities.s_ExtraDefinesForwardOpaque : HDSubShaderUtilities.s_ExtraDefinesForwardTransparent; GenerateShaderPassHair(masterNode, m_PassForwardOnly, mode, subShader, sourceAssetDependencyPaths); if (transparentDepthPostpassActive) { GenerateShaderPassHair(masterNode, m_PassTransparentDepthPostpass, mode, subShader, sourceAssetDependencyPaths); } } subShader.Deindent(); subShader.AddShaderChunk("}", true); subShader.AddShaderChunk(@"CustomEditor ""UnityEditor.Experimental.Rendering.HDPipeline.HairGUI"""); return(subShader.GetShaderString(0)); }
public string GetSubshader(IMasterNode iMasterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // HDLitSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("bac1a9627cfec924fa2ea9c65af8eeca")); // HDSubShaderUtilities.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("713ced4e6eef4a44799a4dd59041484b")); } var masterNode = iMasterNode as HDLitMasterNode; var subShader = new ShaderGenerator(); subShader.AddShaderChunk("SubShader", true); subShader.AddShaderChunk("{", true); subShader.Indent(); { SurfaceMaterialTags materialTags = HDSubShaderUtilities.BuildMaterialTags(masterNode.surfaceType, masterNode.alphaTest.isOn, masterNode.drawBeforeRefraction.isOn, masterNode.sortPriority); // Add tags at the SubShader level { var tagsVisitor = new ShaderStringBuilder(); materialTags.GetTags(tagsVisitor); subShader.AddShaderChunk(tagsVisitor.ToString(), false); } // generate the necessary shader passes bool opaque = (masterNode.surfaceType == SurfaceType.Opaque); bool transparent = !opaque; bool distortionActive = transparent && masterNode.distortion.isOn; bool transparentBackfaceActive = transparent && masterNode.backThenFrontRendering.isOn; bool transparentDepthPrepassActive = transparent && masterNode.alphaTest.isOn && masterNode.alphaTestDepthPrepass.isOn; bool transparentDepthPostpassActive = transparent && masterNode.alphaTest.isOn && masterNode.alphaTestDepthPostpass.isOn; GenerateShaderPassLit(masterNode, m_PassGBuffer, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassMETA, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassShadowCaster, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_SceneSelectionPass, mode, subShader, sourceAssetDependencyPaths); if (opaque) { GenerateShaderPassLit(masterNode, m_PassDepthOnly, mode, subShader, sourceAssetDependencyPaths); } GenerateShaderPassLit(masterNode, m_PassMotionVectors, mode, subShader, sourceAssetDependencyPaths); if (distortionActive) { GenerateShaderPassLit(masterNode, m_PassDistortion, mode, subShader, sourceAssetDependencyPaths); } if (transparentBackfaceActive) { GenerateShaderPassLit(masterNode, m_PassTransparentBackface, mode, subShader, sourceAssetDependencyPaths); } GenerateShaderPassLit(masterNode, m_PassForward, mode, subShader, sourceAssetDependencyPaths); if (transparentDepthPrepassActive) { GenerateShaderPassLit(masterNode, m_PassTransparentDepthPrepass, mode, subShader, sourceAssetDependencyPaths); } if (transparentDepthPostpassActive) { GenerateShaderPassLit(masterNode, m_PassTransparentDepthPostpass, mode, subShader, sourceAssetDependencyPaths); } } subShader.Deindent(); subShader.AddShaderChunk("}", true); subShader.AddShaderChunk(@"CustomEditor ""UnityEditor.ShaderGraph.HDLitGUI"""); return(subShader.GetShaderString(0)); }
public string GetSubshader(IMasterNode iMasterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // HDLitSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("bac1a9627cfec924fa2ea9c65af8eeca")); // HDSubShaderUtilities.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("713ced4e6eef4a44799a4dd59041484b")); } var masterNode = iMasterNode as HDLitMasterNode; var subShader = new ShaderGenerator(); subShader.AddShaderChunk("SubShader", false); subShader.AddShaderChunk("{", false); subShader.Indent(); { //Handle data migration here as we need to have a renderingPass already set with accurate data at this point. if (masterNode.renderingPass == HDRenderQueue.RenderQueueType.Unknown) { switch (masterNode.surfaceType) { case SurfaceType.Opaque: masterNode.renderingPass = HDRenderQueue.RenderQueueType.Opaque; break; case SurfaceType.Transparent: #pragma warning disable CS0618 // Type or member is obsolete if (masterNode.m_DrawBeforeRefraction) { masterNode.m_DrawBeforeRefraction = false; #pragma warning restore CS0618 // Type or member is obsolete masterNode.renderingPass = HDRenderQueue.RenderQueueType.PreRefraction; } else { masterNode.renderingPass = HDRenderQueue.RenderQueueType.Transparent; } break; default: throw new System.ArgumentException("Unknown SurfaceType"); } } HDMaterialTags materialTags = HDSubShaderUtilities.BuildMaterialTags(masterNode.renderingPass, masterNode.sortPriority, masterNode.alphaTest.isOn); // Add tags at the SubShader level { var tagsVisitor = new ShaderStringBuilder(); materialTags.GetTags(tagsVisitor, HDRenderPipeline.k_ShaderTagName); subShader.AddShaderChunk(tagsVisitor.ToString(), false); } // generate the necessary shader passes bool opaque = (masterNode.surfaceType == SurfaceType.Opaque); bool transparent = !opaque; bool distortionActive = transparent && masterNode.distortion.isOn; bool transparentBackfaceActive = transparent && masterNode.backThenFrontRendering.isOn; bool transparentDepthPrepassActive = transparent && masterNode.alphaTest.isOn && masterNode.alphaTestDepthPrepass.isOn; bool transparentDepthPostpassActive = transparent && masterNode.alphaTest.isOn && masterNode.alphaTestDepthPostpass.isOn; GenerateShaderPassLit(masterNode, m_PassMETA, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassShadowCaster, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_SceneSelectionPass, mode, subShader, sourceAssetDependencyPaths); if (opaque) { GenerateShaderPassLit(masterNode, m_PassDepthOnly, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassGBuffer, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassMotionVectors, mode, subShader, sourceAssetDependencyPaths); } if (distortionActive) { GenerateShaderPassLit(masterNode, m_PassDistortion, mode, subShader, sourceAssetDependencyPaths); } if (transparentBackfaceActive) { GenerateShaderPassLit(masterNode, m_PassTransparentBackface, mode, subShader, sourceAssetDependencyPaths); } // Assign define here based on opaque or transparent to save some variant m_PassForward.ExtraDefines = opaque ? HDSubShaderUtilities.s_ExtraDefinesForwardOpaque : HDSubShaderUtilities.s_ExtraDefinesForwardTransparent; GenerateShaderPassLit(masterNode, m_PassForward, mode, subShader, sourceAssetDependencyPaths); if (transparentDepthPrepassActive) { GenerateShaderPassLit(masterNode, m_PassTransparentDepthPrepass, mode, subShader, sourceAssetDependencyPaths); } if (transparentDepthPostpassActive) { GenerateShaderPassLit(masterNode, m_PassTransparentDepthPostpass, mode, subShader, sourceAssetDependencyPaths); } } subShader.Deindent(); subShader.AddShaderChunk("}", false); #if ENABLE_RAYTRACING if (mode == GenerationMode.ForReals) { subShader.AddShaderChunk("SubShader", false); subShader.AddShaderChunk("{", false); subShader.Indent(); { GenerateShaderPassLit(masterNode, m_PassRaytracingIndirect, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassRaytracingVisibility, mode, subShader, sourceAssetDependencyPaths); GenerateShaderPassLit(masterNode, m_PassRaytracingForward, mode, subShader, sourceAssetDependencyPaths); } subShader.Deindent(); subShader.AddShaderChunk("}", false); } #endif subShader.AddShaderChunk(@"CustomEditor ""UnityEditor.Experimental.Rendering.HDPipeline.HDLitGUI"""); return(subShader.GetShaderString(0)); }
public string GetSubshader(IMasterNode iMasterNode, GenerationMode mode) { var masterNode = iMasterNode as PBRMasterNode; var subShader = new ShaderGenerator(); subShader.AddShaderChunk("SubShader", true); subShader.AddShaderChunk("{", true); subShader.Indent(); { SurfaceMaterialOptions materialOptions = HDSubShaderUtilities.BuildMaterialOptions(masterNode.surfaceType, masterNode.alphaMode, masterNode.twoSided.isOn); // Add tags at the SubShader level { var tagsVisitor = new ShaderStringBuilder(); materialOptions.GetTags(tagsVisitor); subShader.AddShaderChunk(tagsVisitor.ToString(), false); } // generate the necessary shader passes bool opaque = (masterNode.surfaceType == SurfaceType.Opaque); bool transparent = (masterNode.surfaceType != SurfaceType.Opaque); bool distortionActive = false; bool transparentDepthPrepassActive = transparent && false; bool transparentBackfaceActive = transparent && false; bool transparentDepthPostpassActive = transparent && false; if (opaque) { GenerateShaderPass(masterNode, m_PassGBuffer, mode, materialOptions, subShader); GenerateShaderPass(masterNode, m_PassGBufferWithPrepass, mode, materialOptions, subShader); } GenerateShaderPass(masterNode, m_PassMETA, mode, materialOptions, subShader); GenerateShaderPass(masterNode, m_PassShadowCaster, mode, materialOptions, subShader); if (opaque) { GenerateShaderPass(masterNode, m_PassDepthOnly, mode, materialOptions, subShader); GenerateShaderPass(masterNode, m_PassMotionVectors, mode, materialOptions, subShader); } if (distortionActive) { GenerateShaderPass(masterNode, m_PassDistortion, mode, materialOptions, subShader); } if (transparentDepthPrepassActive) { GenerateShaderPass(masterNode, m_PassTransparentDepthPrepass, mode, materialOptions, subShader); } if (transparentBackfaceActive) { GenerateShaderPass(masterNode, m_PassTransparentBackface, mode, materialOptions, subShader); } GenerateShaderPass(masterNode, m_PassForward, mode, materialOptions, subShader); if (transparentDepthPostpassActive) { GenerateShaderPass(masterNode, m_PassTransparentDepthPostpass, mode, materialOptions, subShader); } } subShader.Deindent(); subShader.AddShaderChunk("}", true); return(subShader.GetShaderString(0)); }