private static string GetShaderPassFromTemplate(string template, UnlitMasterNode masterNode, Pass pass, GenerationMode mode) { // ----------------------------------------------------- // // SETUP // // ----------------------------------------------------- // // ------------------------------------- // String builders var shaderProperties = new PropertyCollector(); var functionBuilder = new ShaderStringBuilder(1); var functionRegistry = new FunctionRegistry(functionBuilder); var defines = new ShaderStringBuilder(1); var graph = new ShaderStringBuilder(0); var surfaceDescriptionInputStruct = new ShaderStringBuilder(1); var surfaceDescriptionFunction = new ShaderStringBuilder(1); var surfaceDescriptionStruct = new ShaderStringBuilder(1); var pixelShader = new ShaderStringBuilder(2); var pixelShaderSurfaceInputs = new ShaderStringBuilder(2); var pixelShaderSurfaceRemap = new ShaderStringBuilder(2); // ------------------------------------- // Get Slot and Node lists per stage 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 pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes); // ----------------------------------------------------- // // START SHADER GENERATION // // ----------------------------------------------------- // // ------------------------------------- // Calculate material options var tagsBuilder = new ShaderStringBuilder(1); var blendingBuilder = new ShaderStringBuilder(1); var cullingBuilder = new ShaderStringBuilder(1); var zTestBuilder = new ShaderStringBuilder(1); var zWriteBuilder = new ShaderStringBuilder(1); var materialOptions = new SurfaceMaterialOptions(); materialOptions.GetTags(tagsBuilder); materialOptions.GetBlend(blendingBuilder); materialOptions.GetCull(cullingBuilder); materialOptions.GetDepthTest(zTestBuilder); materialOptions.GetDepthWrite(zWriteBuilder); // ------------------------------------- // Generate defines defines.AppendLine("#define SHADERPASS {0}", pass.ShaderPassName); foreach (var channel in pixelRequirements.requiresMeshUVs.Distinct()) { defines.AppendLine("#define ATTRIBUTES_NEED_TEXCOORD{0}", (int)channel); defines.AppendLine("#define VARYINGS_NEED_TEXCOORD{0}", (int)channel); } if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId)) defines.AppendLine("#define _ALPHATEST_ON"); // ----------------------------------------------------- // // 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", false); using(surfaceDescriptionInputStruct.BlockSemicolonScope()) { ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(pixelRequirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(pixelRequirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(pixelRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(pixelRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(pixelRequirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct); if (pixelRequirements.requiresVertexColor) surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor); if (pixelRequirements.requiresScreenPosition) surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition); foreach (var channel in pixelRequirements.requiresMeshUVs.Distinct()) { surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName()); } } // ------------------------------------- // Generate Output structure for Surface Description function GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots, true); // ------------------------------------- // Generate Surface Description function GraphUtil.GenerateSurfaceDescriptionFunction( pixelNodes, masterNode, masterNode.owner as AbstractMaterialGraph, surfaceDescriptionFunction, functionRegistry, shaderProperties, pixelRequirements, mode, "PopulateSurfaceData", "SurfaceDescription", null, pixelSlots); // ----------------------------------------------------- // // GENERATE VERTEX > PIXEL PIPELINE // // ----------------------------------------------------- // // ------------------------------------- // TODO - Why is this not a full generation? // Generate standard transformations foreach (var channel in pixelRequirements.requiresMeshUVs.Distinct()) pixelShaderSurfaceInputs.AppendLine("surfaceInput.{0} = {1};", channel.GetUVName(), string.Format("half4(input.texCoord{0}, 0, 0)", (int)channel)); // ------------------------------------- // Generate pixel shader surface remap foreach (var slot in pixelSlots) { pixelShaderSurfaceRemap.AppendLine("{0} = surf.{0};", slot.shaderOutputName); } // ----------------------------------------------------- // // FINALIZE // // ----------------------------------------------------- // // ------------------------------------- // Combine Graph sections graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1)); graph.AppendLine(functionBuilder.ToString()); graph.AppendLine(surfaceDescriptionInputStruct.ToString()); graph.AppendLine(surfaceDescriptionStruct.ToString()); graph.AppendLine(surfaceDescriptionFunction.ToString()); // ------------------------------------- // Generate final subshader var resultPass = template.Replace("${Tags}", tagsBuilder.ToString()); 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("${LOD}", "" + materialOptions.lod); resultPass = resultPass.Replace("${LightMode}", pass.Name); resultPass = resultPass.Replace("${ShaderPassInclude}", pass.ShaderPassInclude); resultPass = resultPass.Replace("${Graph}", graph.ToString()); resultPass = resultPass.Replace("${PixelShader}", pixelShader.ToString()); resultPass = resultPass.Replace("${PixelShaderSurfaceInputs}", pixelShaderSurfaceInputs.ToString()); resultPass = resultPass.Replace("${PixelShaderSurfaceRemap}", pixelShaderSurfaceRemap.ToString()); return resultPass; }
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); } var templateLocation = ShaderGenerator.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); }