public string GetSubshader(IMasterNode masterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // LightWeightPBRSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("ca91dbeb78daa054c9bbe15fef76361c")); } var templatePath = GetTemplatePath("lightweightPBRForwardPass.template"); var extraPassesTemplatePath = GetTemplatePath("lightweightPBRExtraPasses.template"); if (!File.Exists(templatePath) || !File.Exists(extraPassesTemplatePath)) { return(string.Empty); } if (sourceAssetDependencyPaths != null) { sourceAssetDependencyPaths.Add(templatePath); sourceAssetDependencyPaths.Add(extraPassesTemplatePath); var shaderFiles = Directory.GetFiles( Path.GetFullPath("Packages/com.unity.render-pipelines.lightweight/ShaderLibrary")); sourceAssetDependencyPaths.AddRange(shaderFiles); } string forwardTemplate = File.ReadAllText(templatePath); string extraTemplate = File.ReadAllText(extraPassesTemplatePath); var pbrMasterNode = masterNode as PBRMasterNode; var pass = pbrMasterNode.model == PBRMasterNode.Model.Metallic ? m_ForwardPassMetallic : m_ForwardPassSpecular; var subShader = new ShaderStringBuilder(); subShader.AppendLine("SubShader"); using (subShader.BlockScope()) { var materialTags = ShaderGenerator.BuildMaterialTags(pbrMasterNode.surfaceType); var tagsBuilder = new ShaderStringBuilder(0); materialTags.GetTags(tagsBuilder, LightweightRenderPipeline.k_ShaderTagName); subShader.AppendLines(tagsBuilder.ToString()); var materialOptions = ShaderGenerator.GetMaterialOptions(pbrMasterNode.surfaceType, pbrMasterNode.alphaMode, pbrMasterNode.twoSided.isOn); subShader.AppendLines(GetShaderPassFromTemplate( forwardTemplate, pbrMasterNode, pass, mode, materialOptions)); subShader.AppendLines(GetShaderPassFromTemplate( extraTemplate, pbrMasterNode, m_DepthShadowPass, mode, materialOptions)); } subShader.Append("CustomEditor \"UnityEditor.ShaderGraph.PBRMasterGUI\""); return(subShader.ToString()); }
public string GetSubshader(IMasterNode masterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // LightWeightUnlitSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("3ef30c5c1d5fc412f88511ef5818b654")); } var templatePath = GetTemplatePath("lightweightUnlitPass.template"); var extraPassesTemplatePath = GetTemplatePath("lightweightUnlitExtraPasses.template"); if (!File.Exists(templatePath) || !File.Exists(extraPassesTemplatePath)) { return(string.Empty); } if (sourceAssetDependencyPaths != null) { sourceAssetDependencyPaths.Add(templatePath); sourceAssetDependencyPaths.Add(extraPassesTemplatePath); var relativePath = "Packages/com.unity.render-pipelines.lightweight/"; var fullPath = Path.GetFullPath(relativePath); var shaderFiles = Directory.GetFiles(Path.Combine(fullPath, "ShaderLibrary")).Select(x => Path.Combine(relativePath, x.Substring(fullPath.Length))); sourceAssetDependencyPaths.AddRange(shaderFiles); } string forwardTemplate = File.ReadAllText(templatePath); string extraTemplate = File.ReadAllText(extraPassesTemplatePath); var unlitMasterNode = masterNode as UnlitMasterNode; var pass = m_UnlitPass; var subShader = new ShaderStringBuilder(); subShader.AppendLine("SubShader"); using (subShader.BlockScope()) { var materialTags = ShaderGenerator.BuildMaterialTags(unlitMasterNode.surfaceType); var tagsBuilder = new ShaderStringBuilder(0); materialTags.GetTags(tagsBuilder, LightweightRenderPipeline.k_ShaderTagName); subShader.AppendLines(tagsBuilder.ToString()); var materialOptions = ShaderGenerator.GetMaterialOptions(unlitMasterNode.surfaceType, unlitMasterNode.alphaMode, unlitMasterNode.twoSided.isOn); subShader.AppendLines(GetShaderPassFromTemplate( forwardTemplate, unlitMasterNode, pass, mode, materialOptions)); subShader.AppendLines(GetShaderPassFromTemplate( extraTemplate, unlitMasterNode, m_DepthShadowPass, mode, materialOptions)); } return(subShader.ToString()); }
public string GetSubshader(IMasterNode masterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // LightWeightPBRSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("ca91dbeb78daa054c9bbe15fef76361c")); } var templatePath = GetTemplatePath("lightweightPBRForwardPass.template"); var extraPassesTemplatePath = GetTemplatePath("lightweightPBRExtraPasses.template"); if (!File.Exists(templatePath) || !File.Exists(extraPassesTemplatePath)) { return(string.Empty); } if (sourceAssetDependencyPaths != null) { sourceAssetDependencyPaths.Add(templatePath); sourceAssetDependencyPaths.Add(extraPassesTemplatePath); } string forwardTemplate = File.ReadAllText(templatePath); string extraTemplate = File.ReadAllText(extraPassesTemplatePath); var pbrMasterNode = masterNode as PBRMasterNode; var pass = pbrMasterNode.model == PBRMasterNode.Model.Metallic ? m_ForwardPassMetallic : m_ForwardPassSpecular; var subShader = new ShaderStringBuilder(); subShader.AppendLine("SubShader"); using (subShader.BlockScope()) { subShader.AppendLine("Tags{ \"RenderPipeline\" = \"LightweightPipeline\"}"); var materialTags = ShaderGenerator.BuildMaterialTags(pbrMasterNode.surfaceType); var tagsBuilder = new ShaderStringBuilder(0); materialTags.GetTags(tagsBuilder); subShader.AppendLines(tagsBuilder.ToString()); var materialOptions = ShaderGenerator.GetMaterialOptions(pbrMasterNode.surfaceType, pbrMasterNode.alphaMode, pbrMasterNode.twoSided.isOn); subShader.AppendLines(GetShaderPassFromTemplate( forwardTemplate, pbrMasterNode, pass, mode, materialOptions)); subShader.AppendLines(GetShaderPassFromTemplate( extraTemplate, pbrMasterNode, m_DepthShadowPass, mode, materialOptions)); } return(subShader.ToString()); }
public string GetSubshader(IMasterNode masterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // LightWeightUnlitSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("3ef30c5c1d5fc412f88511ef5818b654")); } var templatePath = GetTemplatePath("lightweightUnlitPass.template"); var extraPassesTemplatePath = GetTemplatePath("lightweightUnlitExtraPasses.template"); if (!File.Exists(templatePath) || !File.Exists(extraPassesTemplatePath)) { return(string.Empty); } if (sourceAssetDependencyPaths != null) { sourceAssetDependencyPaths.Add(templatePath); sourceAssetDependencyPaths.Add(extraPassesTemplatePath); } string forwardTemplate = File.ReadAllText(templatePath); string extraTemplate = File.ReadAllText(extraPassesTemplatePath); var unlitMasterNode = masterNode as UnlitMasterNode; var pass = m_UnlitPass; var subShader = new ShaderStringBuilder(); subShader.AppendLine("SubShader"); using (subShader.BlockScope()) { subShader.AppendLine("Tags{ \"RenderPipeline\" = \"LightweightPipeline\"}"); var materialTags = ShaderGenerator.BuildMaterialTags(unlitMasterNode.surfaceType); var tagsBuilder = new ShaderStringBuilder(0); materialTags.GetTags(tagsBuilder); subShader.AppendLines(tagsBuilder.ToString()); var materialOptions = ShaderGenerator.GetMaterialOptions(unlitMasterNode.surfaceType, unlitMasterNode.alphaMode, unlitMasterNode.twoSided.isOn); subShader.AppendLines(GetShaderPassFromTemplate( forwardTemplate, unlitMasterNode, pass, mode, materialOptions)); subShader.AppendLines(GetShaderPassFromTemplate( extraTemplate, unlitMasterNode, m_DepthShadowPass, mode, materialOptions)); } return(subShader.ToString()); }
public string GetSubshader(IMasterNode masterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // LightWeightPBRSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("f37ee8a3fc1e43646bab579fc6c4c68d")); } var templatePath = GetTemplatePath("AILWForwardPass.template", "2f6cfbf8aef97dc4d952a059147e69a6"); var extraPassesTemplatePath = GetTemplatePath("AILWExtraPasses.template", "e700d3e5b71bb764f83ce12de610be58"); if (!File.Exists(templatePath) || !File.Exists(extraPassesTemplatePath)) { return(string.Empty); } if (sourceAssetDependencyPaths != null) { sourceAssetDependencyPaths.Add(templatePath); sourceAssetDependencyPaths.Add(extraPassesTemplatePath); } string forwardTemplate = File.ReadAllText(templatePath); string extraTemplate = File.ReadAllText(extraPassesTemplatePath); var pbrMasterNode = masterNode as AILWMasterNode; var pass = pbrMasterNode.model == AILWMasterNode.Model.Metallic ? m_ForwardPassMetallic : m_ForwardPassSpecular; var subShader = new ShaderStringBuilder(); subShader.AppendLine("SubShader"); using (subShader.BlockScope()) { var materialTags = ShaderGenerator.BuildMaterialTags(pbrMasterNode.surfaceType); var tagsBuilder = new ShaderStringBuilder(0); materialTags.GetTags(tagsBuilder, LightweightRenderPipeline.k_ShaderTagName); subShader.AppendLines(tagsBuilder.ToString()); var materialOptions = ShaderGenerator.GetMaterialOptions(pbrMasterNode.surfaceType, pbrMasterNode.alphaMode, pbrMasterNode.twoSided.isOn); subShader.AppendLines(GetShaderPassFromTemplate( forwardTemplate, pbrMasterNode, pass, mode, materialOptions)); subShader.AppendLines(GetShaderPassFromTemplate( extraTemplate, pbrMasterNode, m_DepthShadowPass, mode, materialOptions)); } subShader.Append("CustomEditor \"UnityEditor.ShaderGraph.PBRMasterGUI\""); return(subShader.ToString()); }
public void GenerateNodeCode(ShaderStringBuilder sb, GraphContext graphContext, GenerationMode generationMode) { string amplitude = GetSlotValue(kAmplitudeSlotId, generationMode); string steps = GetSlotValue(kStepsSlotId, generationMode); string uvs = GetSlotValue(kUVsSlotId, generationMode); string lod = GetSlotValue(kLodSlotId, generationMode); string lodThreshold = GetSlotValue(kLodThresholdSlotId, generationMode); string tmpPOMParam = GetVariableNameForNode() + "_POM"; string tmpViewDir = GetVariableNameForNode() + "_ViewDir"; string tmpNdotV = GetVariableNameForNode() + "_NdotV"; string tmpMaxHeight = GetVariableNameForNode() + "_MaxHeight"; string tmpViewDirUV = GetVariableNameForNode() + "_ViewDirUV"; string tmpOutHeight = GetVariableNameForNode() + "_OutHeight"; sb.AppendLines(String.Format(@" $precision3 {4} = IN.{2} * GetDisplacementObjectScale().xzy; $precision {5} = {4}.z; $precision {6} = {3} * 0.01; // Transform the view vector into the UV space. $precision3 {7} = normalize($precision3({4}.xy * {6}, {4}.z)); // TODO: skip normalize PerPixelHeightDisplacementParam {1}; {1}.uv = {2};", tmpPOMParam, uvs, CoordinateSpace.Tangent.ToVariableName(InterpolatorType.ViewDirection), amplitude, // cm in the interface so we multiply by 0.01 in the shader to convert in meter tmpViewDir, tmpNdotV, tmpMaxHeight, tmpViewDirUV )); sb.AppendLines(String.Format(@" $precision {10}; $precision2 {0} = {8} + ParallaxOcclusionMapping({1}, {2}, {3}, {4}, {5}, {10}); $precision {6} = ({7} - {10} * {7}) / max({9}, 0.0001); ", GetVariableNameForSlot(kParallaxUVsOutputSlotId), lod, lodThreshold, steps, tmpViewDirUV, tmpPOMParam, GetVariableNameForSlot(kPixelDepthOffsetOutputSlotId), tmpMaxHeight, uvs, tmpNdotV, tmpOutHeight )); }
public string GetSubshader(IMasterNode masterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // LightWeightSpriteLitSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("62511ee827d14492a8c78ba0ef167e7f")); } string litPassTemplate = ReadTemplate("lightweightSpriteLitPass.template", sourceAssetDependencyPaths); string normalPassTemplate = ReadTemplate("lightweightSpriteNormalPass.template", sourceAssetDependencyPaths); string forwardPassTemplate = ReadTemplate("lightweightSpriteForwardPass.template", sourceAssetDependencyPaths); var litMasterNode = masterNode as SpriteLitMasterNode; var litPass = m_LitPass; var normalPass = m_NormalPass; var subShader = new ShaderStringBuilder(); subShader.AppendLine("SubShader"); using (subShader.BlockScope()) { subShader.AppendLine("Tags{ \"RenderPipeline\" = \"LightweightPipeline\"}"); var materialTags = ShaderGenerator.BuildMaterialTags(SurfaceType.Transparent); var tagsBuilder = new ShaderStringBuilder(0); materialTags.GetTags(tagsBuilder, LightweightRenderPipeline.k_ShaderTagName); subShader.AppendLines(tagsBuilder.ToString()); var materialOptions = ShaderGenerator.GetMaterialOptions(SurfaceType.Transparent, AlphaMode.Alpha, true); subShader.AppendLines(GetShaderPassFromTemplate( true, litPassTemplate, litMasterNode, litPass, mode, materialOptions)); subShader.AppendLines(GetShaderPassFromTemplate( false, normalPassTemplate, litMasterNode, normalPass, mode, materialOptions)); subShader.AppendLines(GetShaderPassFromTemplate( false, forwardPassTemplate, litMasterNode, normalPass, mode, materialOptions)); } return(subShader.ToString()); }
public static string GetSubShader <T>(T masterNode, SurfaceMaterialTags tags, SurfaceMaterialOptions options, Pass[] passes, GenerationMode mode, string customEditorPath = null, List <string> sourceAssetDependencyPaths = null) where T : IMasterNode { if (sourceAssetDependencyPaths != null) { var relativePath = "Packages/com.unity.render-pipelines.universal/"; var fullPath = Path.GetFullPath(relativePath); var shaderFiles = Directory.GetFiles(Path.Combine(fullPath, "ShaderLibrary")).Select(x => Path.Combine(relativePath, x.Substring(fullPath.Length))); sourceAssetDependencyPaths.AddRange(shaderFiles); } var subShader = new ShaderStringBuilder(); subShader.AppendLine("SubShader"); using (subShader.BlockScope()) { var tagsBuilder = new ShaderStringBuilder(0); tags.GetTags(tagsBuilder, UnityEngine.Rendering.Universal.UniversalRenderPipeline.k_ShaderTagName); subShader.AppendLines(tagsBuilder.ToString()); foreach (Pass pass in passes) { var templatePath = GetTemplatePath(pass.TemplatePath); if (!File.Exists(templatePath)) { continue; } if (sourceAssetDependencyPaths != null) { sourceAssetDependencyPaths.Add(templatePath); } string template = File.ReadAllText(templatePath); subShader.AppendLines(GetShaderPassFromTemplate( template, masterNode, pass, mode, options)); } } if (!string.IsNullOrEmpty(customEditorPath)) { subShader.Append($"CustomEditor \"{customEditorPath}\""); } return(subShader.ToString()); }
public string GetSubshader(IMasterNode masterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // LightWeightSpriteUnlitSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("62511ee827d14492a8c78ba0ef167e7f")); } var templatePath = GetTemplatePath("lightweightSpriteUnlitPass.template"); if (!File.Exists(templatePath)) { return(string.Empty); } if (sourceAssetDependencyPaths != null) { sourceAssetDependencyPaths.Add(templatePath); } string forwardTemplate = File.ReadAllText(templatePath); var unlitMasterNode = masterNode as SpriteUnlitMasterNode; var pass = m_UnlitPass; var subShader = new ShaderStringBuilder(); subShader.AppendLine("SubShader"); using (subShader.BlockScope()) { subShader.AppendLine("Tags{ \"RenderPipeline\" = \"LightweightPipeline\"}"); var materialTags = ShaderGenerator.BuildMaterialTags(SurfaceType.Transparent); var tagsBuilder = new ShaderStringBuilder(0); materialTags.GetTags(tagsBuilder, LightweightRenderPipeline.k_ShaderTagName); subShader.AppendLines(tagsBuilder.ToString()); var materialOptions = ShaderGenerator.GetMaterialOptions(SurfaceType.Transparent, AlphaMode.Alpha, true); subShader.AppendLines(GetShaderPassFromTemplate( forwardTemplate, unlitMasterNode, pass, mode, materialOptions)); } return(subShader.ToString()); }
public string GetSubshader(IMasterNode inMasterNode, GenerationMode mode) { var templatePath = GetTemplatePath("lightweightPBRForwardPass.template"); var extraPassesTemplatePath = GetTemplatePath("lightweightPBRExtraPasses.template"); if (!File.Exists(templatePath) || !File.Exists(extraPassesTemplatePath)) { return(string.Empty); } string forwardTemplate = File.ReadAllText(templatePath); string extraTemplate = File.ReadAllText(extraPassesTemplatePath); var masterNode = inMasterNode as PBRMasterNode; var pass = masterNode.model == PBRMasterNode.Model.Metallic ? m_ForwardPassMetallic : m_ForwardPassSpecular; var subShader = new ShaderStringBuilder(); subShader.AppendLine("SubShader"); using (subShader.BlockScope()) { subShader.AppendLine("Tags{ \"RenderPipeline\" = \"LightweightPipeline\"}"); var materialOptions = ShaderGenerator.GetMaterialOptions(masterNode.surfaceType, masterNode.alphaMode, masterNode.twoSided.isOn); var tagsBuilder = new ShaderStringBuilder(0); materialOptions.GetTags(tagsBuilder); subShader.AppendLines(tagsBuilder.ToString()); subShader.AppendLines(GetShaderPassFromTemplate( forwardTemplate, masterNode, pass, mode, materialOptions)); subShader.AppendLines(GetExtraPassesFromTemplate(extraTemplate, masterNode, pass, mode, materialOptions)); } return(subShader.ToString()); }
public string GetSubshader(IMasterNode masterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { //TODO: // if (sourceAssetDependencyPaths != null) // { // // LightWeightUnlitSubShader.cs // sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("3ef30c5c1d5fc412f88511ef5818b654")); // } var templatePath = GetTemplatePath("hdEffectPass.template"); // var extraPassesTemplatePath = GetTemplatePath("lightweightUnlitExtraPasses.template"); if (!File.Exists(templatePath) /*|| !File.Exists(extraPassesTemplatePath)*/) { return(string.Empty); } if (sourceAssetDependencyPaths != null) { sourceAssetDependencyPaths.Add(templatePath); // sourceAssetDependencyPaths.Add(extraPassesTemplatePath); } string forwardTemplate = File.ReadAllText(templatePath); // string extraTemplate = File.ReadAllText(extraPassesTemplatePath); var imageEffectMasterNode = masterNode as ImageEffectMasterNode; var pass = m_ImageEffectPass; var subShader = new ShaderStringBuilder(); subShader.AppendLine("SubShader"); using (subShader.BlockScope()) { subShader.AppendLine("Tags{ \"RenderPipeline\" = \"HDRenderPipeline\"}"); // var materialTags = ShaderGenerator.BuildMaterialTags(imageEffectMasterNode.surfaceType); // var tagsBuilder = new ShaderStringBuilder(0); // materialTags.GetTags(tagsBuilder); // subShader.AppendLines(tagsBuilder.ToString()); var materialOptions = ShaderGenerator.GetMaterialOptions(imageEffectMasterNode.surfaceType, imageEffectMasterNode.alphaMode, false); subShader.AppendLines(GetShaderPassFromTemplate( forwardTemplate, imageEffectMasterNode, pass, mode, materialOptions)); } return(subShader.ToString()); }
public string GetSubshader(IMasterNode masterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // LightWeightSpriteUnlitSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("f2df349d00ec920488971bb77440b7bc")); } string unlitTemplate = ReadTemplate("lightweightSpriteUnlitPass.template", sourceAssetDependencyPaths); var unlitMasterNode = masterNode as SpriteUnlitMasterNode; var pass = m_UnlitPass; var subShader = new ShaderStringBuilder(); subShader.AppendLine("SubShader"); using (subShader.BlockScope()) { subShader.AppendLine("Tags{ \"RenderPipeline\" = \"LightweightPipeline\"}"); var materialTags = ShaderGenerator.BuildMaterialTags(SurfaceType.Transparent); var tagsBuilder = new ShaderStringBuilder(0); materialTags.GetTags(tagsBuilder, LightweightRenderPipeline.k_ShaderTagName); subShader.AppendLines(tagsBuilder.ToString()); var materialOptions = ShaderGenerator.GetMaterialOptions(SurfaceType.Transparent, AlphaMode.Alpha, true); subShader.AppendLines(GetShaderPassFromTemplate( unlitTemplate, unlitMasterNode, pass, mode, materialOptions)); } return(subShader.ToString()); }
public string GetSubshader(IMasterNode masterNode, GenerationMode mode, List <string> sourceAssetDependencyPaths = null) { if (sourceAssetDependencyPaths != null) { // LightWeightPBRSubShader.cs sourceAssetDependencyPaths.Add(AssetDatabase.GUIDToAssetPath("16b8a010f96947c4f866705d757bc0a3")); } var templatePath = GetTemplatePath("lightweightToonForwardPass.template"); var extraPassesTemplatePath = GetTemplatePath("lightweightToonExtraPasses.template"); if (!File.Exists(templatePath) || !File.Exists(extraPassesTemplatePath)) { return(string.Empty); } if (sourceAssetDependencyPaths != null) { sourceAssetDependencyPaths.Add(templatePath); sourceAssetDependencyPaths.Add(extraPassesTemplatePath); var relativePath = "Packages/com.unity.render-pipelines.lightweight/"; var fullPath = Path.GetFullPath(relativePath); var shaderFiles = Directory.GetFiles(Path.Combine(fullPath, "ShaderLibrary")).Select(x => Path.Combine(relativePath, x.Substring(fullPath.Length))); sourceAssetDependencyPaths.AddRange(shaderFiles); } string forwardTemplate = File.ReadAllText(templatePath); string extraTemplate = File.ReadAllText(extraPassesTemplatePath); var pbrMasterNode = masterNode as ToonMasterNode; var pass = pbrMasterNode.model == ToonMasterNode.Model.Metallic ? m_ForwardPassMetallic : m_ForwardPassSpecular; var subShader = new ShaderStringBuilder(); subShader.AppendLine("SubShader"); using (subShader.BlockScope()) { var materialTags = ShaderGenerator.BuildMaterialTags(pbrMasterNode.surfaceType); var tagsBuilder = new ShaderStringBuilder(0); materialTags.GetTags(tagsBuilder, LightweightRenderPipeline.k_ShaderTagName); subShader.AppendLines(tagsBuilder.ToString()); var materialOptions = ShaderGenerator.GetMaterialOptions(pbrMasterNode.surfaceType, pbrMasterNode.alphaMode, pbrMasterNode.twoSided.isOn); subShader.AppendLines(GetShaderPassFromTemplate( forwardTemplate, pbrMasterNode, pass, mode, materialOptions)); subShader.AppendLines(GetShaderPassFromTemplate( extraTemplate, pbrMasterNode, m_DepthShadowPass, mode, materialOptions)); } subShader.Append("CustomEditor \"LiliumEditor.Toon.ToonMasterGUI\""); return(subShader.ToString()); }
static string GetShaderPassFromTemplate(string template, UnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions) { // ----------------------------------------------------- // // SETUP // // ----------------------------------------------------- // // ------------------------------------- // String builders var shaderProperties = new PropertyCollector(); var shaderPropertyUniforms = new ShaderStringBuilder(1); var functionBuilder = new ShaderStringBuilder(1); var functionRegistry = new FunctionRegistry(functionBuilder); var defines = new ShaderStringBuilder(1); var graph = new ShaderStringBuilder(0); var vertexDescriptionInputStruct = new ShaderStringBuilder(1); var vertexDescriptionStruct = new ShaderStringBuilder(1); var vertexDescriptionFunction = new ShaderStringBuilder(1); var surfaceDescriptionInputStruct = new ShaderStringBuilder(1); var surfaceDescriptionStruct = new ShaderStringBuilder(1); var surfaceDescriptionFunction = new ShaderStringBuilder(1); var vertexInputStruct = new ShaderStringBuilder(1); var vertexOutputStruct = new ShaderStringBuilder(2); var vertexShader = new ShaderStringBuilder(2); var vertexShaderDescriptionInputs = new ShaderStringBuilder(2); var vertexShaderOutputs = new ShaderStringBuilder(2); var pixelShader = new ShaderStringBuilder(2); var pixelShaderSurfaceInputs = new ShaderStringBuilder(2); var pixelShaderSurfaceRemap = new ShaderStringBuilder(2); // ------------------------------------- // Get Slot and Node lists per stage var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList(); var vertexNodes = ListPool <AbstractMaterialNode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots); var pixelSlots = pass.PixelShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList(); var pixelNodes = ListPool <AbstractMaterialNode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots); // ------------------------------------- // Get Requirements var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false); var pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment); var graphRequirements = pixelRequirements.Union(vertexRequirements); var surfaceRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false); var modelRequiements = ShaderGraphRequirements.none; modelRequiements.requiresNormal |= k_PixelCoordinateSpace; modelRequiements.requiresTangent |= k_PixelCoordinateSpace; modelRequiements.requiresBitangent |= k_PixelCoordinateSpace; modelRequiements.requiresPosition |= k_PixelCoordinateSpace; modelRequiements.requiresViewDir |= k_PixelCoordinateSpace; modelRequiements.requiresMeshUVs.Add(UVChannel.UV1); // ----------------------------------------------------- // // START SHADER GENERATION // // ----------------------------------------------------- // // ------------------------------------- // Calculate material options var blendingBuilder = new ShaderStringBuilder(1); var cullingBuilder = new ShaderStringBuilder(1); var zTestBuilder = new ShaderStringBuilder(1); var zWriteBuilder = new ShaderStringBuilder(1); materialOptions.GetBlend(blendingBuilder); materialOptions.GetCull(cullingBuilder); materialOptions.GetDepthTest(zTestBuilder); materialOptions.GetDepthWrite(zWriteBuilder); // ------------------------------------- // Generate defines if (masterNode.IsSlotConnected(UnlitMasterNode.AlphaThresholdSlotId)) { defines.AppendLine("#define _AlphaClip 1"); } if (masterNode.surfaceType == SurfaceType.Transparent && masterNode.alphaMode == AlphaMode.Premultiply) { defines.AppendLine("#define _ALPHAPREMULTIPLY_ON 1"); } if (graphRequirements.requiresDepthTexture) { defines.AppendLine("#define REQUIRE_DEPTH_TEXTURE"); } if (graphRequirements.requiresCameraOpaqueTexture) { defines.AppendLine("#define REQUIRE_OPAQUE_TEXTURE"); } // ----------------------------------------------------- // // START VERTEX DESCRIPTION // // ----------------------------------------------------- // // ------------------------------------- // Generate Input structure for Vertex Description function // TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs"); using (vertexDescriptionInputStruct.BlockSemicolonScope()) { ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct); if (vertexRequirements.requiresVertexColor) { vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor); } if (vertexRequirements.requiresScreenPosition) { vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition); } foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct()) { vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName()); } if (vertexRequirements.requiresTime) { vertexDescriptionInputStruct.AppendLine("float3 {0};", ShaderGeneratorNames.TimeParameters); } } // ------------------------------------- // Generate Output structure for Vertex Description function GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots); // ------------------------------------- // Generate Vertex Description function GraphUtil.GenerateVertexDescriptionFunction( masterNode.owner as GraphData, vertexDescriptionFunction, functionRegistry, shaderProperties, mode, vertexNodes, vertexSlots); // ----------------------------------------------------- // // START SURFACE DESCRIPTION // // ----------------------------------------------------- // // ------------------------------------- // Generate Input structure for Surface Description function // Surface Description Input requirements are needed to exclude intermediate translation spaces surfaceDescriptionInputStruct.AppendLine("struct SurfaceDescriptionInputs"); using (surfaceDescriptionInputStruct.BlockSemicolonScope()) { ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct); if (surfaceRequirements.requiresVertexColor) { surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor); } if (surfaceRequirements.requiresScreenPosition) { surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition); } if (surfaceRequirements.requiresFaceSign) { surfaceDescriptionInputStruct.AppendLine("float {0};", ShaderGeneratorNames.FaceSign); } foreach (var channel in surfaceRequirements.requiresMeshUVs.Distinct()) { surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName()); } if (surfaceRequirements.requiresTime) { surfaceDescriptionInputStruct.AppendLine("float3 {0};", ShaderGeneratorNames.TimeParameters); } } // ------------------------------------- // Generate Output structure for Surface Description function GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots); // ------------------------------------- // Generate Surface Description function GraphUtil.GenerateSurfaceDescriptionFunction( pixelNodes, masterNode, masterNode.owner as GraphData, surfaceDescriptionFunction, functionRegistry, shaderProperties, pixelRequirements, mode, "PopulateSurfaceData", "SurfaceDescription", null, pixelSlots); // ----------------------------------------------------- // // GENERATE VERTEX > PIXEL PIPELINE // // ----------------------------------------------------- // // ------------------------------------- // Property uniforms shaderProperties.GetPropertiesDeclaration(shaderPropertyUniforms, mode, masterNode.owner.concretePrecision); // ------------------------------------- // Generate Input structure for Vertex shader GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(pixelRequirements.Union(modelRequiements)), vertexInputStruct); // ------------------------------------- // Generate standard transformations // This method ensures all required transform data is available in vertex and pixel stages ShaderGenerator.GenerateStandardTransforms( 3, 10, vertexOutputStruct, vertexShader, vertexShaderDescriptionInputs, vertexShaderOutputs, pixelShader, pixelShaderSurfaceInputs, pixelRequirements, surfaceRequirements, modelRequiements, vertexRequirements, CoordinateSpace.World); // ------------------------------------- // Generate pixel shader surface remap foreach (var slot in pixelSlots) { pixelShaderSurfaceRemap.AppendLine("{0} = surf.{0};", slot.shaderOutputName); } // ------------------------------------- // Extra pixel shader work var faceSign = new ShaderStringBuilder(); if (pixelRequirements.requiresFaceSign) { faceSign.AppendLine(", half FaceSign : VFACE"); } // ----------------------------------------------------- // // FINALIZE // // ----------------------------------------------------- // // ------------------------------------- // Combine Graph sections graph.AppendLines(shaderPropertyUniforms.ToString()); graph.AppendLine(vertexDescriptionInputStruct.ToString()); graph.AppendLine(surfaceDescriptionInputStruct.ToString()); graph.AppendLine(functionBuilder.ToString()); graph.AppendLine(vertexDescriptionStruct.ToString()); graph.AppendLine(vertexDescriptionFunction.ToString()); graph.AppendLine(surfaceDescriptionStruct.ToString()); graph.AppendLine(surfaceDescriptionFunction.ToString()); graph.AppendLine(vertexInputStruct.ToString()); // ------------------------------------- // Generate final subshader var resultPass = template.Replace("${Tags}", string.Empty); resultPass = resultPass.Replace("${Blending}", blendingBuilder.ToString()); resultPass = resultPass.Replace("${Culling}", cullingBuilder.ToString()); resultPass = resultPass.Replace("${ZTest}", zTestBuilder.ToString()); resultPass = resultPass.Replace("${ZWrite}", zWriteBuilder.ToString()); resultPass = resultPass.Replace("${Defines}", defines.ToString()); resultPass = resultPass.Replace("${Graph}", graph.ToString()); resultPass = resultPass.Replace("${VertexOutputStruct}", vertexOutputStruct.ToString()); resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString()); resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexShaderDescriptionInputs.ToString()); resultPass = resultPass.Replace("${VertexShaderOutputs}", vertexShaderOutputs.ToString()); resultPass = resultPass.Replace("${FaceSign}", faceSign.ToString()); resultPass = resultPass.Replace("${PixelShader}", pixelShader.ToString()); resultPass = resultPass.Replace("${PixelShaderSurfaceInputs}", pixelShaderSurfaceInputs.ToString()); resultPass = resultPass.Replace("${PixelShaderSurfaceRemap}", pixelShaderSurfaceRemap.ToString()); return(resultPass); }
static string GetShaderPassFromTemplate(string template, IMasterNode iMasterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions) { // ----------------------------------------------------- // // SETUP // // ----------------------------------------------------- // AbstractMaterialNode masterNode = iMasterNode as AbstractMaterialNode; // ------------------------------------- // String builders var shaderProperties = new PropertyCollector(); var shaderKeywords = new KeywordCollector(); var shaderPropertyUniforms = new ShaderStringBuilder(1); var shaderKeywordDeclarations = new ShaderStringBuilder(1); var functionBuilder = new ShaderStringBuilder(1); var functionRegistry = new FunctionRegistry(functionBuilder); var defines = new ShaderStringBuilder(1); var graph = new ShaderStringBuilder(0); var vertexDescriptionInputStruct = new ShaderStringBuilder(1); var vertexDescriptionStruct = new ShaderStringBuilder(1); var vertexDescriptionFunction = new ShaderStringBuilder(1); var surfaceDescriptionInputStruct = new ShaderStringBuilder(1); var surfaceDescriptionStruct = new ShaderStringBuilder(1); var surfaceDescriptionFunction = new ShaderStringBuilder(1); var vertexInputStruct = new ShaderStringBuilder(1); var vertexOutputStruct = new ShaderStringBuilder(2); var vertexShader = new ShaderStringBuilder(2); var vertexShaderDescriptionInputs = new ShaderStringBuilder(2); var vertexShaderOutputs = new ShaderStringBuilder(2); var pixelShader = new ShaderStringBuilder(2); var pixelShaderSurfaceInputs = new ShaderStringBuilder(2); var pixelShaderSurfaceRemap = new ShaderStringBuilder(2); // ------------------------------------- // Get Slot and Node lists per stage var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList(); var vertexNodes = ListPool <AbstractMaterialNode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots); var pixelSlots = pass.PixelShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList(); var pixelNodes = ListPool <AbstractMaterialNode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots); // ------------------------------------- // Get Requirements var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false); var pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment); var graphRequirements = pixelRequirements.Union(vertexRequirements); var surfaceRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false); var modelRequirements = pass.Requirements; // ----------------------------------------------------- // // START SHADER GENERATION // // ----------------------------------------------------- // // ------------------------------------- // Calculate material options var blendingBuilder = new ShaderStringBuilder(1); var cullingBuilder = new ShaderStringBuilder(1); var zTestBuilder = new ShaderStringBuilder(1); var zWriteBuilder = new ShaderStringBuilder(1); materialOptions.GetBlend(blendingBuilder); materialOptions.GetCull(cullingBuilder); materialOptions.GetDepthTest(zTestBuilder); materialOptions.GetDepthWrite(zWriteBuilder); // ------------------------------------- // Generate defines pass.OnGeneratePass(iMasterNode, graphRequirements); foreach (string define in pass.ExtraDefines) { defines.AppendLine(define); } // ----------------------------------------------------- // // KEYWORDS // // ----------------------------------------------------- // // ------------------------------------- // Get keyword permutations masterNode.owner.CollectShaderKeywords(shaderKeywords, mode); // Track permutation indices for all nodes List <int>[] keywordPermutationsPerVertexNode = new List <int> [vertexNodes.Count]; List <int>[] keywordPermutationsPerPixelNode = new List <int> [pixelNodes.Count]; // ------------------------------------- // Evaluate all permutations for (int i = 0; i < shaderKeywords.permutations.Count; i++) { // Get active nodes for this permutation var localVertexNodes = ListPool <AbstractMaterialNode> .Get(); var localPixelNodes = ListPool <AbstractMaterialNode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(localVertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots, shaderKeywords.permutations[i]); NodeUtils.DepthFirstCollectNodesFromNode(localPixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots, shaderKeywords.permutations[i]); // Track each vertex node in this permutation foreach (AbstractMaterialNode vertexNode in localVertexNodes) { int nodeIndex = vertexNodes.IndexOf(vertexNode); if (keywordPermutationsPerVertexNode[nodeIndex] == null) { keywordPermutationsPerVertexNode[nodeIndex] = new List <int>(); } keywordPermutationsPerVertexNode[nodeIndex].Add(i); } // Track each pixel node in this permutation foreach (AbstractMaterialNode pixelNode in localPixelNodes) { int nodeIndex = pixelNodes.IndexOf(pixelNode); if (keywordPermutationsPerPixelNode[nodeIndex] == null) { keywordPermutationsPerPixelNode[nodeIndex] = new List <int>(); } keywordPermutationsPerPixelNode[nodeIndex].Add(i); } } // ----------------------------------------------------- // // START VERTEX DESCRIPTION // // ----------------------------------------------------- // // ------------------------------------- // Generate Input structure for Vertex Description function // TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs"); using (vertexDescriptionInputStruct.BlockSemicolonScope()) { ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct); if (vertexRequirements.requiresVertexColor) { vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor); } if (vertexRequirements.requiresScreenPosition) { vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition); } foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct()) { vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName()); } if (vertexRequirements.requiresTime) { vertexDescriptionInputStruct.AppendLine("float3 {0};", ShaderGeneratorNames.TimeParameters); } } // ------------------------------------- // Generate Output structure for Vertex Description function GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots); // ------------------------------------- // Generate Vertex Description function GraphUtil.GenerateVertexDescriptionFunction( masterNode.owner as GraphData, vertexDescriptionFunction, functionRegistry, shaderProperties, shaderKeywords, mode, masterNode, vertexNodes, keywordPermutationsPerVertexNode, vertexSlots); // ----------------------------------------------------- // // START SURFACE DESCRIPTION // // ----------------------------------------------------- // // ------------------------------------- // Generate Input structure for Surface Description function // Surface Description Input requirements are needed to exclude intermediate translation spaces surfaceDescriptionInputStruct.AppendLine("struct SurfaceDescriptionInputs"); using (surfaceDescriptionInputStruct.BlockSemicolonScope()) { ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct); ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct); if (surfaceRequirements.requiresVertexColor) { surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor); } if (surfaceRequirements.requiresScreenPosition) { surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition); } if (surfaceRequirements.requiresFaceSign) { surfaceDescriptionInputStruct.AppendLine("float {0};", ShaderGeneratorNames.FaceSign); } foreach (var channel in surfaceRequirements.requiresMeshUVs.Distinct()) { surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName()); } if (surfaceRequirements.requiresTime) { surfaceDescriptionInputStruct.AppendLine("float3 {0};", ShaderGeneratorNames.TimeParameters); } } // ------------------------------------- // Generate Output structure for Surface Description function GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots); // ------------------------------------- // Generate Surface Description function GraphUtil.GenerateSurfaceDescriptionFunction( pixelNodes, keywordPermutationsPerPixelNode, masterNode, masterNode.owner as GraphData, surfaceDescriptionFunction, functionRegistry, shaderProperties, shaderKeywords, mode, "PopulateSurfaceData", "SurfaceDescription", null, pixelSlots); // ----------------------------------------------------- // // GENERATE VERTEX > PIXEL PIPELINE // // ----------------------------------------------------- // // ------------------------------------- // Keyword declarations shaderKeywords.GetKeywordsDeclaration(shaderKeywordDeclarations, mode); // ------------------------------------- // Property uniforms shaderProperties.GetPropertiesDeclaration(shaderPropertyUniforms, mode, masterNode.owner.concretePrecision); // ------------------------------------- // Generate Input structure for Vertex shader GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(pixelRequirements.Union(modelRequirements)), vertexInputStruct); // ------------------------------------- // Generate standard transformations // This method ensures all required transform data is available in vertex and pixel stages ShaderGenerator.GenerateStandardTransforms( 3, 10, vertexOutputStruct, vertexShader, vertexShaderDescriptionInputs, vertexShaderOutputs, pixelShader, pixelShaderSurfaceInputs, pixelRequirements, surfaceRequirements, modelRequirements, vertexRequirements, CoordinateSpace.World); // ------------------------------------- // Generate pixel shader surface remap foreach (var slot in pixelSlots) { pixelShaderSurfaceRemap.AppendLine("{0} = surf.{0};", slot.shaderOutputName); } // ------------------------------------- // Extra pixel shader work var faceSign = new ShaderStringBuilder(); if (pixelRequirements.requiresFaceSign) { faceSign.AppendLine(", half FaceSign : VFACE"); } // ----------------------------------------------------- // // FINALIZE // // ----------------------------------------------------- // // ------------------------------------- // Combine Graph sections graph.AppendLines(shaderKeywordDeclarations.ToString()); graph.AppendLines(shaderPropertyUniforms.ToString()); graph.AppendLine(vertexDescriptionInputStruct.ToString()); graph.AppendLine(surfaceDescriptionInputStruct.ToString()); graph.AppendLine(functionBuilder.ToString()); graph.AppendLine(vertexDescriptionStruct.ToString()); graph.AppendLine(vertexDescriptionFunction.ToString()); graph.AppendLine(surfaceDescriptionStruct.ToString()); graph.AppendLine(surfaceDescriptionFunction.ToString()); graph.AppendLine(vertexInputStruct.ToString()); // ------------------------------------- // Generate final subshader var resultPass = template.Replace("${Tags}", string.Empty); resultPass = resultPass.Replace("${Blending}", blendingBuilder.ToString()); resultPass = resultPass.Replace("${Culling}", cullingBuilder.ToString()); resultPass = resultPass.Replace("${ZTest}", zTestBuilder.ToString()); resultPass = resultPass.Replace("${ZWrite}", zWriteBuilder.ToString()); resultPass = resultPass.Replace("${Defines}", defines.ToString()); resultPass = resultPass.Replace("${Graph}", graph.ToString()); resultPass = resultPass.Replace("${VertexOutputStruct}", vertexOutputStruct.ToString()); resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString()); resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexShaderDescriptionInputs.ToString()); resultPass = resultPass.Replace("${VertexShaderOutputs}", vertexShaderOutputs.ToString()); resultPass = resultPass.Replace("${FaceSign}", faceSign.ToString()); resultPass = resultPass.Replace("${PixelShader}", pixelShader.ToString()); resultPass = resultPass.Replace("${PixelShaderSurfaceInputs}", pixelShaderSurfaceInputs.ToString()); resultPass = resultPass.Replace("${PixelShaderSurfaceRemap}", pixelShaderSurfaceRemap.ToString()); return(resultPass); }
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); }
string GenerateGraph(CustomTextureMasterNode masterNode, string template) { // ----------------------------------------------------- // // SETUP // // ----------------------------------------------------- // // ------------------------------------- // String builders var shaderProperties = new PropertyCollector(); var shaderPropertyUniforms = new ShaderStringBuilder(1); var functionBuilder = new ShaderStringBuilder(1); var functionRegistry = new FunctionRegistry(functionBuilder); var defines = new ShaderStringBuilder(1); var graph = new ShaderStringBuilder(0); var surfaceDescriptionStruct = new ShaderStringBuilder(1); var surfaceDescriptionFunction = 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 = masterNode.GetSlots <MaterialSlot>().ToList(); // All slots are pixels var pixelNodes = ListPool <AbstractMaterialNode> .Get(); NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pixelSlots.Select(s => s.id).ToList()); // ------------------------------------- // Get Requirements var pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment); var graphRequirements = pixelRequirements; var surfaceRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false); // ----------------------------------------------------- // // START SHADER GENERATION // // ----------------------------------------------------- // // ------------------------------------- // Generate Output structure for Surface Description function SubShaderGenerator.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots); // ------------------------------------- // Generate Surface Description function List <int>[] perm = new List <int> [pixelNodes.Count]; SubShaderGenerator.GenerateSurfaceDescriptionFunction( pixelNodes, perm, masterNode, masterNode.owner as GraphData, surfaceDescriptionFunction, functionRegistry, shaderProperties, new KeywordCollector(), GenerationMode.ForReals); // pixelRequirements, // GenerationMode.ForReals, // we'll handle preview later // "PopulateSurfaceData", // "SurfaceDescription", // null, // pixelSlots); // ------------------------------------- // Property uniforms shaderProperties.GetPropertiesDeclaration(shaderPropertyUniforms, GenerationMode.ForReals, masterNode.owner.concretePrecision); // ------------------------------------- // Generate standard transformations // This method ensures all required transform data is available in vertex and pixel stages // ShaderGenerator.GenerateStandardTransforms( // 3, // 10, // // We don't need vertex things // new ShaderStringBuilder(), // new ShaderStringBuilder(), // new ShaderStringBuilder(), // new ShaderStringBuilder(), // pixelShader, // pixelShaderSurfaceInputs, // pixelRequirements, // surfaceRequirements, // modelRequirements, // new ShaderGraphRequirements(), // CoordinateSpace.World); // ------------------------------------- // Generate pixel shader surface remap foreach (var slot in pixelSlots) { pixelShaderSurfaceRemap.AppendLine("{0} = surf.{0};", slot.shaderOutputName); } // ------------------------------------- // Extra pixel shader work var faceSign = new ShaderStringBuilder(); if (pixelRequirements.requiresFaceSign) { faceSign.AppendLine(", half FaceSign : VFACE"); } // ----------------------------------------------------- // // FINALIZE // // ----------------------------------------------------- // // ------------------------------------- // Combine Graph sections graph.AppendLines(shaderPropertyUniforms.ToString()); graph.AppendLine(functionBuilder.ToString()); graph.AppendLine(surfaceDescriptionStruct.ToString()); graph.AppendLine(surfaceDescriptionFunction.ToString()); // ------------------------------------- // Generate final subshader var resultPass = template.Replace("${Tags}", string.Empty); resultPass = resultPass.Replace("${Graph}", graph.ToString()); resultPass = resultPass.Replace("${FaceSign}", faceSign.ToString()); resultPass = resultPass.Replace("${PixelShader}", pixelShader.ToString()); resultPass = resultPass.Replace("${PixelShaderSurfaceRemap}", pixelShaderSurfaceRemap.ToString()); return(resultPass); }