void DoTessellation() { GUILayout.Label("Tessellation", EditorStyles.boldLabel); EditorGUI.indentLevel += 2; TessellationMode mode = TessellationMode.Uniform; if (IsKeywordEnabled("_TESSELLATION_EDGE")) { mode = TessellationMode.Edge; } EditorGUI.BeginChangeCheck(); mode = (TessellationMode)EditorGUILayout.EnumPopup(MakeLabel("Mode"), mode); if (EditorGUI.EndChangeCheck()) { RecordAction("Tessellation Mode"); SetKeyword("_TESSELLATION_EDGE", mode == TessellationMode.Edge); } if (mode == TessellationMode.Uniform) { editor.ShaderProperty( FindProperty("_TessellationUniform"), MakeLabel("Uniform") ); } else { editor.ShaderProperty( FindProperty("_TessellationEdgeLength"), MakeLabel("Edge Length") ); } EditorGUI.indentLevel -= 2; }
void ApplyTessellation(Material material) { if (material.HasProperty(kTessellationMode)) { TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode); SetKeyword(material, "_TESSELLATION_PHONG", tessMode == TessellationMode.Phong); } }
public static void SetMaterialKeywords(Material material) { if (material.HasProperty("_TessellationMode")) { TessellationMode tessMode = (TessellationMode)material.GetFloat("_TessellationMode"); CoreUtils.SetKeyword(material, "_TESSELLATION_PHONG", tessMode == TessellationMode.Phong); } }
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if ocde change static public void SetupBaseLitKeywords(Material material) { SetupBaseUnlitKeywords(material); bool doubleSidedEnable = material.GetFloat(kDoubleSidedEnable) > 0.0f; bool doubleSidedMirrorEnable = material.GetFloat(kDoubleSidedMirrorEnable) > 0.0f; if (doubleSidedEnable) { if (doubleSidedMirrorEnable) { // Mirror mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, -1.0f, 0.0f)); } else { // Flip mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(-1.0f, -1.0f, -1.0f, 0.0f)); } } bool depthOffsetEnable = material.GetFloat(kDepthOffsetEnable) > 0.0f; SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable); if (material.HasProperty(kMaterialID)) { material.SetInt("_StencilRef", 1 + (int)material.GetFloat(kMaterialID)); // See 'StencilBits'. } bool enablePerPixelDisplacement = material.GetFloat(kEnablePerPixelDisplacement) > 0.0f; SetKeyword(material, "_PER_PIXEL_DISPLACEMENT", enablePerPixelDisplacement); if (material.HasProperty(kTessellationMode)) { TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode); if (tessMode == TessellationMode.Phong) { material.DisableKeyword("_TESSELLATION_DISPLACEMENT"); material.DisableKeyword("_TESSELLATION_DISPLACEMENT_PHONG"); } else if (tessMode == TessellationMode.Displacement) { material.EnableKeyword("_TESSELLATION_DISPLACEMENT"); material.DisableKeyword("_TESSELLATION_DISPLACEMENT_PHONG"); } else { material.DisableKeyword("_TESSELLATION_DISPLACEMENT"); material.EnableKeyword("_TESSELLATION_DISPLACEMENT_PHONG"); } bool tessellationObjectScaleEnable = material.GetFloat(kTessellationObjectScale) == 1.0; SetKeyword(material, "_TESSELLATION_OBJECT_SCALE", tessellationObjectScaleEnable); } }
public override float DrawInner(ref Rect r) { float prevYpos = r.y; r.y = 0; r.xMin += 20; r.y += 20; cullMode = (CullMode)UndoableLabeledEnumPopup(r, "Face Culling", cullMode, "face culling"); r.y += 20; GUI.enabled = ps.catLighting.renderPath == SFPSC_Lighting.RenderPath.Forward; normalQuality = (NormalQuality)UndoableContentScaledToolbar(r, "Normal Quality", (int)normalQuality, strNormalQuality, "normal quality"); GUI.enabled = true; r.y += 20; vertexPositioning = (VertexPositioning)UndoableContentScaledToolbar(r, "Vertex Positioning", (int)vertexPositioning, strVertexPositioning, "vertex positioning"); r.y += 20; GUI.enabled = ps.mOut.normal.IsConnectedEnabledAndAvailable(); normalSpace = (NormalSpace)UndoableContentScaledToolbar(r, "Normal Space", (int)normalSpace, strNormalSpace, "normal space"); GUI.enabled = true; r.y += 20; vertexOffsetMode = (VertexOffsetMode)UndoableContentScaledToolbar(r, "Vertex offset mode", (int)vertexOffsetMode, vertexOffsetModeStr, "vertex offset mode"); r.y += 20; GUI.enabled = ps.HasTessellation(); tessellationMode = (TessellationMode)UndoableLabeledEnumPopupNamed(r, "Tessellation Mode", tessellationMode, tessModeStr, "tessellation mode"); GUI.enabled = true; r.y += 20; GUI.enabled = ps.HasOutline(); outlineMode = (OutlineMode)UndoableLabeledEnumPopupNamed(r, "Outline Extrude Direction", outlineMode, outlineModeStr, "outline mode"); GUI.enabled = true; r.y += 20; highQualityScreenCoords = UndoableToggle(r, highQualityScreenCoords, "Per-pixel screen coordinates", "per-pixel screen coordinates", null); r.y += 20; showPixelSnap = UndoableToggle(r, showPixelSnap, "Show 2D sprite pixel snap option in material", "show pixel snap", null); r.y += 20; //billboard. billboard = (BILLBOARD_TYPE)UndoableContentScaledToolbar(r, "billboard", (int)billboard, strBillboard, "NONE"); r.y += 20; r.y += prevYpos; return((int)r.yMax); }
public override float DrawInner(ref Rect r) { float prevYpos = r.y; r.y = 0; r.xMin += 20; r.y += 20; cullMode = (CullMode)UndoableLabeledEnumPopup(r, "面剔除", cullMode, "face culling"); r.y += 20; GUI.enabled = ps.catLighting.renderPath == SFPSC_Lighting.RenderPath.Forward; normalQuality = (NormalQuality)UndoableContentScaledToolbar(r, "法线质量", (int)normalQuality, strNormalQuality, "normal quality"); GUI.enabled = true; r.y += 20; vertexPositioning = (VertexPositioning)UndoableContentScaledToolbar(r, "顶点定位", (int)vertexPositioning, strVertexPositioning, "vertex positioning"); r.y += 20; GUI.enabled = ps.mOut.normal.IsConnectedEnabledAndAvailable(); normalSpace = (NormalSpace)UndoableContentScaledToolbar(r, "法线空间", (int)normalSpace, strNormalSpace, "normal space"); GUI.enabled = true; r.y += 20; vertexOffsetMode = (VertexOffsetMode)UndoableContentScaledToolbar(r, "顶点偏移模式", (int)vertexOffsetMode, vertexOffsetModeStr, "vertex offset mode"); r.y += 20; GUI.enabled = ps.HasTessellation(); tessellationMode = (TessellationMode)UndoableLabeledEnumPopupNamed(r, "细分曲面模式", tessellationMode, tessModeStr, "tessellation mode"); GUI.enabled = true; r.y += 20; GUI.enabled = ps.HasOutline(); outlineMode = (OutlineMode)UndoableLabeledEnumPopupNamed(r, "描边拉伸方向", outlineMode, outlineModeStr, "outline mode"); GUI.enabled = true; r.y += 20; highQualityScreenCoords = UndoableToggle(r, highQualityScreenCoords, "每像素屏幕坐标(开启:像素 关闭:顶点)", "per-pixel screen coordinates", null); r.y += 20; showPixelSnap = UndoableToggle(r, showPixelSnap, "在材质中显示二维切片 Pixel snap(像素捕捉)选项", "show pixel snap", null); r.y += 20; r.y += prevYpos; return((int)r.yMax); }
public override void Deserialize(string key, string value) { switch (key) { case "billboard": billboard = (BILLBOARD_TYPE)int.Parse(value); break; case "vtps": vertexPositioning = (VertexPositioning)int.Parse(value); break; case "nrmq": normalQuality = (NormalQuality)int.Parse(value); break; case "nrsp": normalSpace = (NormalSpace)int.Parse(value); break; case "vomd": vertexOffsetMode = (VertexOffsetMode)int.Parse(value); break; case "hqsc": highQualityScreenCoords = bool.Parse(value); break; case "spxs": showPixelSnap = bool.Parse(value); break; case "tesm": tessellationMode = (TessellationMode)int.Parse(value); break; case "olmd": outlineMode = (OutlineMode)int.Parse(value); break; case "culm": cullMode = (CullMode)int.Parse(value); break; } }
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if code change static public void SetupBaseLitKeywords(Material material) { SetupBaseUnlitKeywords(material); bool doubleSidedEnable = material.HasProperty(kDoubleSidedEnable) ? material.GetFloat(kDoubleSidedEnable) > 0.0f : false; if (doubleSidedEnable) { DoubleSidedNormalMode doubleSidedNormalMode = (DoubleSidedNormalMode)material.GetFloat(kDoubleSidedNormalMode); switch (doubleSidedNormalMode) { case DoubleSidedNormalMode.Mirror: // Mirror mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, -1.0f, 0.0f)); break; case DoubleSidedNormalMode.Flip: // Flip mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(-1.0f, -1.0f, -1.0f, 0.0f)); break; case DoubleSidedNormalMode.None: // None mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, 1.0f, 0.0f)); break; } } // Stencil usage rules: // DoesntReceiveSSR and DecalsForwardOutputNormalBuffer need to be tagged during depth prepass // LightingMask need to be tagged during either GBuffer or Forward pass // ObjectMotionVectors need to be tagged in velocity pass. // As motion vectors pass can be use as a replacement of depth prepass it also need to have DoesntReceiveSSR and DecalsForwardOutputNormalBuffer // As GBuffer pass can have no depth prepass, it also need to have DoesntReceiveSSR and DecalsForwardOutputNormalBuffer // Object motion vectors is always render after a full depth buffer (if there is no depth prepass for GBuffer all object motion vectors are render after GBuffer) // so we have a guarantee than when we write object motion vectors no other object will be draw on top (and so would have require to overwrite motion vectors). // Final combination is: // Prepass: DoesntReceiveSSR, DecalsForwardOutputNormalBuffer // Motion vectors: DoesntReceiveSSR, DecalsForwardOutputNormalBuffer, ObjectVelocity // GBuffer: LightingMask, DecalsForwardOutputNormalBuffer, ObjectVelocity // Forward: LightingMask int stencilRef = (int)StencilLightingUsage.RegularLighting; // Forward case int stencilWriteMask = (int)HDRenderPipeline.StencilBitMask.LightingMask; int stencilRefDepth = 0; int stencilWriteMaskDepth = 0; int stencilRefGBuffer = (int)StencilLightingUsage.RegularLighting; int stencilWriteMaskGBuffer = (int)HDRenderPipeline.StencilBitMask.LightingMask; int stencilRefMV = (int)HDRenderPipeline.StencilBitMask.ObjectMotionVectors; int stencilWriteMaskMV = (int)HDRenderPipeline.StencilBitMask.ObjectMotionVectors; if (material.HasProperty(kMaterialID) && (int)material.GetFloat(kMaterialID) == (int)MaterialId.LitSSS) { stencilRefGBuffer = stencilRef = (int)StencilLightingUsage.SplitLighting; } if (material.HasProperty(kReceivesSSR) && material.GetInt(kReceivesSSR) == 0) { stencilRefDepth |= (int)HDRenderPipeline.StencilBitMask.DoesntReceiveSSR; stencilRefGBuffer |= (int)HDRenderPipeline.StencilBitMask.DoesntReceiveSSR; stencilRefMV |= (int)HDRenderPipeline.StencilBitMask.DoesntReceiveSSR; } stencilWriteMaskDepth |= (int)HDRenderPipeline.StencilBitMask.DoesntReceiveSSR | (int)HDRenderPipeline.StencilBitMask.DecalsForwardOutputNormalBuffer; stencilWriteMaskGBuffer |= (int)HDRenderPipeline.StencilBitMask.DoesntReceiveSSR | (int)HDRenderPipeline.StencilBitMask.DecalsForwardOutputNormalBuffer; stencilWriteMaskMV |= (int)HDRenderPipeline.StencilBitMask.DoesntReceiveSSR | (int)HDRenderPipeline.StencilBitMask.DecalsForwardOutputNormalBuffer; // As we tag both during motion vector pass and Gbuffer pass we need a separate state and we need to use the write mask material.SetInt(kStencilRef, stencilRef); material.SetInt(kStencilWriteMask, stencilWriteMask); material.SetInt(kStencilRefDepth, stencilRefDepth); material.SetInt(kStencilWriteMaskDepth, stencilWriteMaskDepth); material.SetInt(kStencilRefGBuffer, stencilRefGBuffer); material.SetInt(kStencilWriteMaskGBuffer, stencilWriteMaskGBuffer); material.SetInt(kStencilRefMV, stencilRefMV); material.SetInt(kStencilWriteMaskMV, stencilWriteMaskMV); material.SetInt(kStencilRefDistortionVec, (int)HDRenderPipeline.StencilBitMask.DistortionVectors); material.SetInt(kStencilWriteMaskDistortionVec, (int)HDRenderPipeline.StencilBitMask.DistortionVectors); if (material.HasProperty(kDisplacementMode)) { bool enableDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) != DisplacementMode.None; bool enableVertexDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Vertex; bool enablePixelDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Pixel; bool enableTessellationDisplacement = ((DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Tessellation) && material.HasProperty(kTessellationMode); CoreUtils.SetKeyword(material, "_VERTEX_DISPLACEMENT", enableVertexDisplacement); CoreUtils.SetKeyword(material, "_PIXEL_DISPLACEMENT", enablePixelDisplacement); // Only set if tessellation exist CoreUtils.SetKeyword(material, "_TESSELLATION_DISPLACEMENT", enableTessellationDisplacement); bool displacementLockObjectScale = material.GetFloat(kDisplacementLockObjectScale) > 0.0; bool displacementLockTilingScale = material.GetFloat(kDisplacementLockTilingScale) > 0.0; // Tessellation reuse vertex flag. CoreUtils.SetKeyword(material, "_VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE", displacementLockObjectScale && (enableVertexDisplacement || enableTessellationDisplacement)); CoreUtils.SetKeyword(material, "_PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE", displacementLockObjectScale && enablePixelDisplacement); CoreUtils.SetKeyword(material, "_DISPLACEMENT_LOCK_TILING_SCALE", displacementLockTilingScale && enableDisplacement); // Depth offset is only enabled if per pixel displacement is bool depthOffsetEnable = (material.GetFloat(kDepthOffsetEnable) > 0.0f) && enablePixelDisplacement; CoreUtils.SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable); } bool windEnabled = material.HasProperty(kWindEnabled) && material.GetFloat(kWindEnabled) > 0.0f; CoreUtils.SetKeyword(material, "_VERTEX_WIND", windEnabled); if (material.HasProperty(kTessellationMode)) { TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode); CoreUtils.SetKeyword(material, "_TESSELLATION_PHONG", tessMode == TessellationMode.Phong); } SetupMainTexForAlphaTestGI("_BaseColorMap", "_BaseColor", material); // Use negation so we don't create keyword by default CoreUtils.SetKeyword(material, "_DISABLE_DECALS", material.HasProperty(kSupportDecals) && material.GetFloat(kSupportDecals) == 0.0); CoreUtils.SetKeyword(material, "_DISABLE_SSR", material.HasProperty(kReceivesSSR) && material.GetFloat(kReceivesSSR) == 0.0); CoreUtils.SetKeyword(material, "_ENABLE_GEOMETRIC_SPECULAR_AA", material.HasProperty(kEnableGeometricSpecularAA) && material.GetFloat(kEnableGeometricSpecularAA) == 1.0); }
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if code change static public void SetupBaseLitKeywords(Material material) { material.SetupBaseUnlitKeywords(); bool doubleSidedEnable = material.HasProperty(kDoubleSidedEnable) ? material.GetFloat(kDoubleSidedEnable) > 0.0f : false; if (doubleSidedEnable) { DoubleSidedNormalMode doubleSidedNormalMode = (DoubleSidedNormalMode)material.GetFloat(kDoubleSidedNormalMode); switch (doubleSidedNormalMode) { case DoubleSidedNormalMode.Mirror: // Mirror mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, -1.0f, 0.0f)); break; case DoubleSidedNormalMode.Flip: // Flip mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(-1.0f, -1.0f, -1.0f, 0.0f)); break; case DoubleSidedNormalMode.None: // None mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, 1.0f, 0.0f)); break; } } if (material.HasProperty(kDisplacementMode)) { bool enableDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) != DisplacementMode.None; bool enableVertexDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Vertex; bool enablePixelDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Pixel; bool enableTessellationDisplacement = ((DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Tessellation) && material.HasProperty(kTessellationMode); CoreUtils.SetKeyword(material, "_VERTEX_DISPLACEMENT", enableVertexDisplacement); CoreUtils.SetKeyword(material, "_PIXEL_DISPLACEMENT", enablePixelDisplacement); // Only set if tessellation exist CoreUtils.SetKeyword(material, "_TESSELLATION_DISPLACEMENT", enableTessellationDisplacement); bool displacementLockObjectScale = material.GetFloat(kDisplacementLockObjectScale) > 0.0; bool displacementLockTilingScale = material.GetFloat(kDisplacementLockTilingScale) > 0.0; // Tessellation reuse vertex flag. CoreUtils.SetKeyword(material, "_VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE", displacementLockObjectScale && (enableVertexDisplacement || enableTessellationDisplacement)); CoreUtils.SetKeyword(material, "_PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE", displacementLockObjectScale && enablePixelDisplacement); CoreUtils.SetKeyword(material, "_DISPLACEMENT_LOCK_TILING_SCALE", displacementLockTilingScale && enableDisplacement); // Depth offset is only enabled if per pixel displacement is bool depthOffsetEnable = (material.GetFloat(kDepthOffsetEnable) > 0.0f) && enablePixelDisplacement; CoreUtils.SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable); } CoreUtils.SetKeyword(material, "_VERTEX_WIND", false); if (material.HasProperty(kTessellationMode)) { TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode); CoreUtils.SetKeyword(material, "_TESSELLATION_PHONG", tessMode == TessellationMode.Phong); } material.SetupMainTexForAlphaTestGI("_BaseColorMap", "_BaseColor"); // Use negation so we don't create keyword by default CoreUtils.SetKeyword(material, "_DISABLE_DECALS", material.HasProperty(kSupportDecals) && material.GetFloat(kSupportDecals) == 0.0); CoreUtils.SetKeyword(material, "_DISABLE_SSR", material.HasProperty(kReceivesSSR) && material.GetFloat(kReceivesSSR) == 0.0); CoreUtils.SetKeyword(material, "_DISABLE_SSR_TRANSPARENT", material.HasProperty(kReceivesSSRTransparent) && material.GetFloat(kReceivesSSRTransparent) == 0.0); CoreUtils.SetKeyword(material, "_ENABLE_GEOMETRIC_SPECULAR_AA", material.HasProperty(kEnableGeometricSpecularAA) && material.GetFloat(kEnableGeometricSpecularAA) == 1.0); if (material.HasProperty(kRefractionModel)) { var refractionModelValue = (ScreenSpaceRefraction.RefractionModel)material.GetFloat(kRefractionModel); // We can't have refraction in pre-refraction queue and the material needs to be transparent var canHaveRefraction = material.GetSurfaceType() == SurfaceType.Transparent && !HDRenderQueue.k_RenderQueue_PreRefraction.Contains(material.renderQueue); CoreUtils.SetKeyword(material, "_REFRACTION_PLANE", (refractionModelValue == ScreenSpaceRefraction.RefractionModel.Box) && canHaveRefraction); CoreUtils.SetKeyword(material, "_REFRACTION_SPHERE", (refractionModelValue == ScreenSpaceRefraction.RefractionModel.Sphere) && canHaveRefraction); CoreUtils.SetKeyword(material, "_REFRACTION_THIN", (refractionModelValue == ScreenSpaceRefraction.RefractionModel.Thin) && canHaveRefraction); } if (material.HasProperty(kForceForwardEmissive)) { CoreUtils.SetKeyword(material, "_FORCE_FORWARD_EMISSIVE", material.GetInt(kForceForwardEmissive) != 0); } }
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if code change static public void SetupBaseLitKeywords(Material material) { SetupBaseUnlitKeywords(material); bool doubleSidedEnable = material.GetFloat(kDoubleSidedEnable) > 0.0f; if (doubleSidedEnable) { DoubleSidedNormalMode doubleSidedNormalMode = (DoubleSidedNormalMode)material.GetFloat(kDoubleSidedNormalMode); switch (doubleSidedNormalMode) { case DoubleSidedNormalMode.Mirror: // Mirror mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, -1.0f, 0.0f)); break; case DoubleSidedNormalMode.Flip: // Flip mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(-1.0f, -1.0f, -1.0f, 0.0f)); break; case DoubleSidedNormalMode.None: // None mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, 1.0f, 0.0f)); break; } } // Set the reference value for the stencil test. int stencilRef = (int)StencilLightingUsage.RegularLighting; if ((int)material.GetFloat(kMaterialID) == (int)BaseLitGUI.MaterialId.LitSSS) { stencilRef = (int)StencilLightingUsage.SplitLighting; } // As we tag both during velocity pass and Gbuffer pass we need a separate state and we need to use the write mask material.SetInt(kStencilRef, stencilRef); material.SetInt(kStencilWriteMask, (int)HDRenderPipeline.StencilBitMask.LightingMask); material.SetInt(kStencilRefMV, (int)HDRenderPipeline.StencilBitMask.ObjectVelocity); material.SetInt(kStencilWriteMaskMV, (int)HDRenderPipeline.StencilBitMask.ObjectVelocity); bool enableDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) != DisplacementMode.None; bool enableVertexDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Vertex; bool enablePixelDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Pixel; bool enableTessellationDisplacement = ((DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Tessellation) && material.HasProperty(kTessellationMode); CoreUtils.SetKeyword(material, "_VERTEX_DISPLACEMENT", enableVertexDisplacement); CoreUtils.SetKeyword(material, "_PIXEL_DISPLACEMENT", enablePixelDisplacement); // Only set if tessellation exist CoreUtils.SetKeyword(material, "_TESSELLATION_DISPLACEMENT", enableTessellationDisplacement); bool displacementLockObjectScale = material.GetFloat(kDisplacementLockObjectScale) > 0.0; bool displacementLockTilingScale = material.GetFloat(kDisplacementLockTilingScale) > 0.0; // Tessellation reuse vertex flag. CoreUtils.SetKeyword(material, "_VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE", displacementLockObjectScale && (enableVertexDisplacement || enableTessellationDisplacement)); CoreUtils.SetKeyword(material, "_PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE", displacementLockObjectScale && enablePixelDisplacement); CoreUtils.SetKeyword(material, "_DISPLACEMENT_LOCK_TILING_SCALE", displacementLockTilingScale && enableDisplacement); bool windEnabled = material.GetFloat(kWindEnabled) > 0.0f; CoreUtils.SetKeyword(material, "_VERTEX_WIND", windEnabled); // Depth offset is only enabled if per pixel displacement is bool depthOffsetEnable = (material.GetFloat(kDepthOffsetEnable) > 0.0f) && enablePixelDisplacement; CoreUtils.SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable); if (material.HasProperty(kTessellationMode)) { TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode); CoreUtils.SetKeyword(material, "_TESSELLATION_PHONG", tessMode == TessellationMode.Phong); } SetupMainTexForAlphaTestGI("_BaseColorMap", "_BaseColor", material); // Use negation so we don't create keyword by default CoreUtils.SetKeyword(material, "_DISABLE_DBUFFER", material.GetFloat(kSupportDBuffer) == 0.0); }
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if code change static public void SetupBaseLitKeywords(Material material) { material.SetupBaseUnlitKeywords(); bool doubleSidedEnable = material.HasProperty(kDoubleSidedEnable) ? material.GetFloat(kDoubleSidedEnable) > 0.0f : false; if (doubleSidedEnable) { DoubleSidedNormalMode doubleSidedNormalMode = (DoubleSidedNormalMode)material.GetFloat(kDoubleSidedNormalMode); switch (doubleSidedNormalMode) { case DoubleSidedNormalMode.Mirror: // Mirror mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, -1.0f, 0.0f)); break; case DoubleSidedNormalMode.Flip: // Flip mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(-1.0f, -1.0f, -1.0f, 0.0f)); break; case DoubleSidedNormalMode.None: // None mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, 1.0f, 0.0f)); break; } } if (material.HasProperty(kDisplacementMode)) { bool enableDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) != DisplacementMode.None; bool enableVertexDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Vertex; bool enablePixelDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Pixel; bool enableTessellationDisplacement = ((DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Tessellation) && material.HasProperty(kTessellationMode); CoreUtils.SetKeyword(material, "_VERTEX_DISPLACEMENT", enableVertexDisplacement); CoreUtils.SetKeyword(material, "_PIXEL_DISPLACEMENT", enablePixelDisplacement); // Only set if tessellation exist CoreUtils.SetKeyword(material, "_TESSELLATION_DISPLACEMENT", enableTessellationDisplacement); bool displacementLockObjectScale = material.GetFloat(kDisplacementLockObjectScale) > 0.0; bool displacementLockTilingScale = material.GetFloat(kDisplacementLockTilingScale) > 0.0; // Tessellation reuse vertex flag. CoreUtils.SetKeyword(material, "_VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE", displacementLockObjectScale && (enableVertexDisplacement || enableTessellationDisplacement)); CoreUtils.SetKeyword(material, "_PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE", displacementLockObjectScale && enablePixelDisplacement); CoreUtils.SetKeyword(material, "_DISPLACEMENT_LOCK_TILING_SCALE", displacementLockTilingScale && enableDisplacement); // Depth offset is only enabled if per pixel displacement is bool depthOffsetEnable = (material.GetFloat(kDepthOffsetEnable) > 0.0f) && enablePixelDisplacement; CoreUtils.SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable); } CoreUtils.SetKeyword(material, "_VERTEX_WIND", false); if (material.HasProperty(kTessellationMode)) { TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode); CoreUtils.SetKeyword(material, "_TESSELLATION_PHONG", tessMode == TessellationMode.Phong); } material.SetupMainTexForAlphaTestGI("_BaseColorMap", "_BaseColor"); // Use negation so we don't create keyword by default CoreUtils.SetKeyword(material, "_DISABLE_DECALS", material.HasProperty(kSupportDecals) && material.GetFloat(kSupportDecals) == 0.0); CoreUtils.SetKeyword(material, "_DISABLE_SSR", material.HasProperty(kReceivesSSR) && material.GetFloat(kReceivesSSR) == 0.0); CoreUtils.SetKeyword(material, "_ENABLE_GEOMETRIC_SPECULAR_AA", material.HasProperty(kEnableGeometricSpecularAA) && material.GetFloat(kEnableGeometricSpecularAA) == 1.0); }
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if ocde change static public void SetupBaseLitKeywords(Material material) { SetupBaseUnlitKeywords(material); bool doubleSidedEnable = material.GetFloat(kDoubleSidedEnable) > 0.0f; bool doubleSidedMirrorEnable = material.GetFloat(kDoubleSidedMirrorEnable) > 0.0f; if (doubleSidedEnable) { if (doubleSidedMirrorEnable) { // Mirror mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, -1.0f, 0.0f)); } else { // Flip mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(-1.0f, -1.0f, -1.0f, 0.0f)); } } bool depthOffsetEnable = material.GetFloat(kDepthOffsetEnable) > 0.0f; SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable); // Set the reference value for the stencil test. int stencilRef = (int)StencilBits.NonSSS; if (material.HasProperty(kMaterialID)) { if ((int)material.GetFloat(kMaterialID) == (int)UnityEngine.Experimental.Rendering.HDPipeline.Lit.MaterialId.LitSSS) { stencilRef = (int)StencilBits.SSS; } } material.SetInt(kStencilRef, stencilRef); bool enablePerPixelDisplacement = material.GetFloat(kEnablePerPixelDisplacement) > 0.0f; SetKeyword(material, "_PER_PIXEL_DISPLACEMENT", enablePerPixelDisplacement); if (material.HasProperty(kTessellationMode)) { TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode); if (tessMode == TessellationMode.Phong) { material.DisableKeyword("_TESSELLATION_DISPLACEMENT"); material.DisableKeyword("_TESSELLATION_DISPLACEMENT_PHONG"); } else if (tessMode == TessellationMode.Displacement) { material.EnableKeyword("_TESSELLATION_DISPLACEMENT"); material.DisableKeyword("_TESSELLATION_DISPLACEMENT_PHONG"); } else { material.DisableKeyword("_TESSELLATION_DISPLACEMENT"); material.EnableKeyword("_TESSELLATION_DISPLACEMENT_PHONG"); } bool tessellationObjectScaleEnable = material.GetFloat(kTessellationObjectScale) > 0.0; SetKeyword(material, "_TESSELLATION_OBJECT_SCALE", tessellationObjectScaleEnable); bool tessellationTilingScaleEnable = material.GetFloat(kTessellationTilingScale) > 0.0; SetKeyword(material, "_TESSELLATION_TILING_SCALE", tessellationTilingScaleEnable); } bool windEnabled = material.GetFloat(kWindEnabled) > 0.0f; SetKeyword(material, "_VERTEX_WIND", windEnabled); }
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if code change static public void SetupBaseLitKeywords(Material material) { SetupBaseUnlitKeywords(material); bool doubleSidedEnable = material.GetFloat(kDoubleSidedEnable) > 0.0f; if (doubleSidedEnable) { DoubleSidedNormalMode doubleSidedNormalMode = (DoubleSidedNormalMode)material.GetFloat(kDoubleSidedNormalMode); switch (doubleSidedNormalMode) { case DoubleSidedNormalMode.None: material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, 1.0f, 0.0f)); break; case DoubleSidedNormalMode.Mirror: // Mirror mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, -1.0f, 0.0f)); break; case DoubleSidedNormalMode.Flip: // Flip mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(-1.0f, -1.0f, -1.0f, 0.0f)); break; } } // Set the reference value for the stencil test. int stencilRef = (int)StencilLightingUsage.RegularLighting; if ((int)material.GetFloat(kMaterialID) == (int)Lit.MaterialId.LitSSS) { stencilRef = (int)StencilLightingUsage.SplitLighting; } material.SetInt(kStencilRef, stencilRef); bool enableDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) != DisplacementMode.None; bool enableVertexDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Vertex; bool enablePixelDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Pixel; bool enableTessellationDisplacement = ((DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Tessellation) && material.HasProperty(kTessellationMode); CoreUtils.SetKeyword(material, "_VERTEX_DISPLACEMENT", enableVertexDisplacement); CoreUtils.SetKeyword(material, "_PIXEL_DISPLACEMENT", enablePixelDisplacement); // Only set if tessellation exist CoreUtils.SetKeyword(material, "_TESSELLATION_DISPLACEMENT", enableTessellationDisplacement); bool displacementLockObjectScale = material.GetFloat(kDisplacementLockObjectScale) > 0.0; bool displacementLockTilingScale = material.GetFloat(kDisplacementLockTilingScale) > 0.0; // Tessellation reuse vertex flag. CoreUtils.SetKeyword(material, "_VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE", displacementLockObjectScale && (enableVertexDisplacement || enableTessellationDisplacement)); CoreUtils.SetKeyword(material, "_PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE", displacementLockObjectScale && enablePixelDisplacement); CoreUtils.SetKeyword(material, "_DISPLACEMENT_LOCK_TILING_SCALE", displacementLockTilingScale && enableDisplacement); bool windEnabled = material.GetFloat(kWindEnabled) > 0.0f; CoreUtils.SetKeyword(material, "_VERTEX_WIND", windEnabled); // Depth offset is only enabled if per pixel displacement is bool depthOffsetEnable = (material.GetFloat(kDepthOffsetEnable) > 0.0f) && enablePixelDisplacement; CoreUtils.SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable); if (material.HasProperty(kTessellationMode)) { TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode); CoreUtils.SetKeyword(material, "_TESSELLATION_PHONG", tessMode == TessellationMode.Phong); } SetupMainTexForAlphaTestGI("_BaseColorMap", "_BaseColor", material); }
public static void SetupBaseUnlitKeywords(this Material material) { // First thing, be sure to have an up to date RenderQueue material.ResetMaterialCustomRenderQueue(); bool alphaTestEnable = material.HasProperty(kAlphaCutoffEnabled) && material.GetFloat(kAlphaCutoffEnabled) > 0.0f; CoreUtils.SetKeyword(material, "_ALPHATEST_ON", alphaTestEnable); SurfaceType surfaceType = material.GetSurfaceType(); CoreUtils.SetKeyword(material, "_SURFACE_TYPE_TRANSPARENT", surfaceType == SurfaceType.Transparent); bool transparentWritesMotionVec = (surfaceType == SurfaceType.Transparent) && material.HasProperty(kTransparentWritingMotionVec) && material.GetInt(kTransparentWritingMotionVec) > 0; CoreUtils.SetKeyword(material, "_TRANSPARENT_WRITES_MOTION_VEC", transparentWritesMotionVec); if (material.HasProperty(kAddPrecomputedVelocity)) { CoreUtils.SetKeyword(material, "_ADD_PRECOMPUTED_VELOCITY", material.GetInt(kAddPrecomputedVelocity) != 0); } HDRenderQueue.RenderQueueType renderQueueType = HDRenderQueue.GetTypeByRenderQueueValue(material.renderQueue); bool needOffScreenBlendFactor = renderQueueType == HDRenderQueue.RenderQueueType.AfterPostprocessTransparent || renderQueueType == HDRenderQueue.RenderQueueType.LowTransparent; // Alpha tested materials always have a prepass where we perform the clip. // Then during Gbuffer pass we don't perform the clip test, so we need to use depth equal in this case. if (alphaTestEnable) { material.SetInt(kZTestGBuffer, (int)UnityEngine.Rendering.CompareFunction.Equal); } else { material.SetInt(kZTestGBuffer, (int)UnityEngine.Rendering.CompareFunction.LessEqual); } // If the material use the kZTestDepthEqualForOpaque it mean it require depth equal test for opaque but transparent are not affected if (material.HasProperty(kZTestDepthEqualForOpaque)) { if (surfaceType == SurfaceType.Opaque) { // When the material is after post process, we need to use LEssEqual because there is no depth prepass for unlit opaque if (HDRenderQueue.k_RenderQueue_AfterPostProcessOpaque.Contains(material.renderQueue)) { material.SetInt(kZTestDepthEqualForOpaque, (int)UnityEngine.Rendering.CompareFunction.LessEqual); } else { material.SetInt(kZTestDepthEqualForOpaque, (int)UnityEngine.Rendering.CompareFunction.Equal); } } else { material.SetInt(kZTestDepthEqualForOpaque, (int)material.GetTransparentZTest()); } } if (surfaceType == SurfaceType.Opaque) { material.SetOverrideTag("RenderType", alphaTestEnable ? "TransparentCutout" : ""); material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); // Caution: we need to setup One for src and Zero for Dst for all element as users could switch from transparent to Opaque and keep remaining value. // Unity will disable Blending based on these default value. // Note that for after postprocess we setup 0 in opacity inside the shaders, so we correctly end with 0 in opacity for the compositing pass material.SetInt("_AlphaSrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_AlphaDstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt(kZWrite, 1); } else { material.SetOverrideTag("RenderType", "Transparent"); material.SetInt(kZWrite, material.GetTransparentZWrite() ? 1 : 0); if (material.HasProperty(kBlendMode)) { BlendMode blendMode = material.GetBlendMode(); // When doing off-screen transparency accumulation, we change blend factors as described here: https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch23.html switch (blendMode) { // Alpha // color: src * src_a + dst * (1 - src_a) // src * src_a is done in the shader as it allow to reduce precision issue when using _BLENDMODE_PRESERVE_SPECULAR_LIGHTING (See Material.hlsl) case BlendMode.Alpha: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); if (needOffScreenBlendFactor) { material.SetInt("_AlphaSrcBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_AlphaDstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); } else { material.SetInt("_AlphaSrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_AlphaDstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); } break; // Additive // color: src * src_a + dst // src * src_a is done in the shader case BlendMode.Additive: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One); if (needOffScreenBlendFactor) { material.SetInt("_AlphaSrcBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_AlphaDstBlend", (int)UnityEngine.Rendering.BlendMode.One); } else { material.SetInt("_AlphaSrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_AlphaDstBlend", (int)UnityEngine.Rendering.BlendMode.One); } break; // PremultipliedAlpha // color: src * src_a + dst * (1 - src_a) // src is supposed to have been multiplied by alpha in the texture on artists side. case BlendMode.Premultiply: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); if (needOffScreenBlendFactor) { material.SetInt("_AlphaSrcBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_AlphaDstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); } else { material.SetInt("_AlphaSrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_AlphaDstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); } break; } } } bool fogEnabled = material.HasProperty(kEnableFogOnTransparent) && material.GetFloat(kEnableFogOnTransparent) > 0.0f && surfaceType == SurfaceType.Transparent; CoreUtils.SetKeyword(material, "_ENABLE_FOG_ON_TRANSPARENT", fogEnabled); if (material.HasProperty(kDistortionEnable) && material.HasProperty(kDistortionBlendMode)) { bool distortionDepthTest = material.GetFloat(kDistortionDepthTest) > 0.0f; if (material.HasProperty(kZTestModeDistortion)) { if (distortionDepthTest) { material.SetInt(kZTestModeDistortion, (int)UnityEngine.Rendering.CompareFunction.LessEqual); } else { material.SetInt(kZTestModeDistortion, (int)UnityEngine.Rendering.CompareFunction.Always); } } var distortionBlendMode = material.GetInt(kDistortionBlendMode); switch (distortionBlendMode) { default: case 0: // Add material.SetInt("_DistortionSrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DistortionDstBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DistortionBlurSrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DistortionBlurDstBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DistortionBlurBlendOp", (int)UnityEngine.Rendering.BlendOp.Add); break; case 1: // Multiply material.SetInt("_DistortionSrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor); material.SetInt("_DistortionDstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_DistortionBlurSrcBlend", (int)UnityEngine.Rendering.BlendMode.DstAlpha); material.SetInt("_DistortionBlurDstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_DistortionBlurBlendOp", (int)UnityEngine.Rendering.BlendOp.Add); break; case 2: // Replace material.SetInt("_DistortionSrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DistortionDstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_DistortionBlurSrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DistortionBlurDstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_DistortionBlurBlendOp", (int)UnityEngine.Rendering.BlendOp.Add); break; } } CullMode doubleSidedOffMode = (surfaceType == SurfaceType.Transparent) ? material.GetTransparentCullMode() : material.GetOpaqueCullMode(); bool isBackFaceEnable = material.HasProperty(kTransparentBackfaceEnable) && material.GetFloat(kTransparentBackfaceEnable) > 0.0f && surfaceType == SurfaceType.Transparent; bool doubleSidedEnable = material.HasProperty(kDoubleSidedEnable) && material.GetFloat(kDoubleSidedEnable) > 0.0f; DoubleSidedGIMode doubleSidedGIMode = DoubleSidedGIMode.Auto; if (material.HasProperty(kDoubleSidedGIMode)) { doubleSidedGIMode = (DoubleSidedGIMode)material.GetFloat(kDoubleSidedGIMode); } // Disable culling if double sided material.SetInt("_CullMode", doubleSidedEnable ? (int)UnityEngine.Rendering.CullMode.Off : (int)doubleSidedOffMode); // We have a separate cullmode (_CullModeForward) for Forward in case we use backface then frontface rendering, need to configure it if (isBackFaceEnable) { material.SetInt("_CullModeForward", (int)UnityEngine.Rendering.CullMode.Back); } else { material.SetInt("_CullModeForward", (int)(doubleSidedEnable ? UnityEngine.Rendering.CullMode.Off : doubleSidedOffMode)); } CoreUtils.SetKeyword(material, "_DOUBLESIDED_ON", doubleSidedEnable); // A material's GI flag internally keeps track of whether emission is enabled at all, it's enabled but has no effect // or is enabled and may be modified at runtime. This state depends on the values of the current flag and emissive color. // The fixup routine makes sure that the material is in the correct state if/when changes are made to the mode or color. if (material.HasProperty(kEmissionColor)) { material.SetColor(kEmissionColor, Color.white); // kEmissionColor must always be white to allow our own material to control the GI (this allow to fallback from builtin unity to our system). // as it happen with old material that it isn't the case, we force it. #if UNITY_EDITOR MaterialEditor.FixupEmissiveFlag(material); #endif } material.SetupMainTexForAlphaTestGI("_UnlitColorMap", "_UnlitColor"); // depth offset for ShaderGraphs (they don't have the displacement mode property) if (!material.HasProperty(kDisplacementMode) && material.HasProperty(kDepthOffsetEnable)) { // Depth offset is only enabled if per pixel displacement is bool depthOffsetEnable = (material.GetFloat(kDepthOffsetEnable) > 0.0f); CoreUtils.SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable); // conservative depth offset for ShaderGraphs if (material.HasProperty(kConservativeDepthOffsetEnable)) { // Depth offset is only enabled if per pixel displacement is bool conservativeDepthOffset = (material.GetFloat(kConservativeDepthOffsetEnable) > 0.0f); CoreUtils.SetKeyword(material, "_CONSERVATIVE_DEPTH_OFFSET", conservativeDepthOffset); } } if (material.HasProperty(kTessellationMode)) { TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode); CoreUtils.SetKeyword(material, "_TESSELLATION_PHONG", tessMode == TessellationMode.Phong); } // DoubleSidedGI has to be synced with our double sided toggle if (doubleSidedGIMode == DoubleSidedGIMode.Auto) { material.doubleSidedGI = doubleSidedEnable; } else if (doubleSidedGIMode == DoubleSidedGIMode.On) { material.doubleSidedGI = true; } else if (doubleSidedGIMode == DoubleSidedGIMode.Off) { material.doubleSidedGI = false; } }
protected void SetupCommonOptionsKeywords(Material material) { bool alphaTestEnable = material.GetFloat(kAlphaCutoffEnabled) == 1.0; SurfaceType surfaceType = (SurfaceType)material.GetFloat(kSurfaceType); BlendMode blendMode = (BlendMode)material.GetFloat(kBlendMode); DoubleSidedMode doubleSidedMode = (DoubleSidedMode)material.GetFloat(kDoubleSidedMode); if (surfaceType == SurfaceType.Opaque) { material.SetOverrideTag("RenderType", alphaTestEnable ? "TransparentCutout" : ""); material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_ZWrite", 1); material.renderQueue = alphaTestEnable ? (int)UnityEngine.Rendering.RenderQueue.AlphaTest : -1; } else { material.SetOverrideTag("RenderType", "Transparent"); material.SetInt("_ZWrite", 0); material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; switch (blendMode) { case BlendMode.Lerp: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); break; case BlendMode.Add: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One); break; case BlendMode.SoftAdd: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusDstColor); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One); break; case BlendMode.Multiply: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); break; case BlendMode.Premultiply: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); break; } } if (doubleSidedMode == DoubleSidedMode.None) { material.SetInt("_CullMode", (int)UnityEngine.Rendering.CullMode.Back); } else { material.SetInt("_CullMode", (int)UnityEngine.Rendering.CullMode.Off); } if (doubleSidedMode == DoubleSidedMode.DoubleSidedLightingFlip) { material.DisableKeyword("_DOUBLESIDED"); material.EnableKeyword("_DOUBLESIDED_LIGHTING_FLIP"); material.DisableKeyword("_DOUBLESIDED_LIGHTING_MIRROR"); } else if (doubleSidedMode == DoubleSidedMode.DoubleSidedLightingMirror) { material.DisableKeyword("_DOUBLESIDED"); material.DisableKeyword("_DOUBLESIDED_LIGHTING_FLIP"); material.EnableKeyword("_DOUBLESIDED_LIGHTING_MIRROR"); } else if (doubleSidedMode == DoubleSidedMode.DoubleSided) { material.EnableKeyword("_DOUBLESIDED"); material.DisableKeyword("_DOUBLESIDED_LIGHTING_FLIP"); material.DisableKeyword("_DOUBLESIDED_LIGHTING_MIRROR"); } else { material.DisableKeyword("_DOUBLESIDED"); material.DisableKeyword("_DOUBLESIDED_LIGHTING_FLIP"); material.DisableKeyword("_DOUBLESIDED_LIGHTING_MIRROR"); } SetKeyword(material, "_ALPHATEST_ON", alphaTestEnable); bool distortionEnable = material.GetFloat(kDistortionEnable) == 1.0; bool distortionOnly = material.GetFloat(kDistortionOnly) == 1.0; bool distortionDepthTest = material.GetFloat(kDistortionDepthTest) == 1.0; bool depthOffsetEnable = material.GetFloat(kDepthOffsetEnable) == 1.0; if (distortionEnable) { material.SetShaderPassEnabled("DistortionVectors", true); } else { material.SetShaderPassEnabled("DistortionVectors", false); } if (distortionEnable && distortionOnly) { // Disable all passes except dbug material material.SetShaderPassEnabled("GBuffer", false); material.SetShaderPassEnabled("DebugViewMaterial", true); material.SetShaderPassEnabled("Meta", false); material.SetShaderPassEnabled("ShadowCaster", false); material.SetShaderPassEnabled("DepthOnly", false); material.SetShaderPassEnabled("MotionVectors", false); material.SetShaderPassEnabled("Forward", false); } else { material.SetShaderPassEnabled("GBuffer", true); material.SetShaderPassEnabled("DebugViewMaterial", true); material.SetShaderPassEnabled("Meta", true); material.SetShaderPassEnabled("ShadowCaster", true); material.SetShaderPassEnabled("DepthOnly", true); material.SetShaderPassEnabled("MotionVectors", true); material.SetShaderPassEnabled("Forward", true); } if (distortionDepthTest) { material.SetInt("_ZTestMode", (int)UnityEngine.Rendering.CompareFunction.LessEqual); } else { material.SetInt("_ZTestMode", (int)UnityEngine.Rendering.CompareFunction.Always); } SetKeyword(material, "_DISTORTION_ON", distortionEnable); SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable); SetupEmissionGIFlags(material); if (tessellationMode != null) { TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode); if (tessMode == TessellationMode.Phong) { material.DisableKeyword("_TESSELLATION_DISPLACEMENT"); material.DisableKeyword("_TESSELLATION_DISPLACEMENT_PHONG"); } else if (tessMode == TessellationMode.Displacement) { material.EnableKeyword("_TESSELLATION_DISPLACEMENT"); material.DisableKeyword("_TESSELLATION_DISPLACEMENT_PHONG"); } else { material.DisableKeyword("_TESSELLATION_DISPLACEMENT"); material.EnableKeyword("_TESSELLATION_DISPLACEMENT_PHONG"); } bool tessellationObjectScaleEnable = material.GetFloat(kTessellationObjectScale) == 1.0; SetKeyword(material, "_TESSELLATION_OBJECT_SCALE", tessellationObjectScaleEnable); } }
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if ocde change static public void SetupBaseLitKeywords(Material material) { SetupBaseUnlitKeywords(material); bool doubleSidedEnable = material.GetFloat(kDoubleSidedEnable) > 0.0f; bool doubleSidedMirrorEnable = material.GetFloat(kDoubleSidedMirrorEnable) > 0.0f; if (doubleSidedEnable) { if (doubleSidedMirrorEnable) { // Mirror mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, -1.0f, 0.0f)); } else { // Flip mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(-1.0f, -1.0f, -1.0f, 0.0f)); } } bool depthOffsetEnable = material.GetFloat(kDepthOffsetEnable) > 0.0f; SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable); int stencilRef = (int)UnityEngine.Experimental.Rendering.HDPipeline.StencilBits.Standard; // See 'StencilBits'. if (material.HasProperty(kMaterialID)) { int materialID = (int)material.GetFloat(kMaterialID); switch (materialID) { case (int)UnityEngine.Experimental.Rendering.HDPipeline.Lit.MaterialId.LitSSS: stencilRef = (int)UnityEngine.Experimental.Rendering.HDPipeline.StencilBits.SSS; break; case (int)UnityEngine.Experimental.Rendering.HDPipeline.Lit.MaterialId.LitStandard: stencilRef = (int)UnityEngine.Experimental.Rendering.HDPipeline.StencilBits.Standard; break; default: stencilRef = 1 + materialID; break; } } material.SetInt("_StencilRef", stencilRef); bool enablePerPixelDisplacement = material.GetFloat(kEnablePerPixelDisplacement) > 0.0f; SetKeyword(material, "_PER_PIXEL_DISPLACEMENT", enablePerPixelDisplacement); if (material.HasProperty(kTessellationMode)) { TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode); if (tessMode == TessellationMode.Phong) { material.DisableKeyword("_TESSELLATION_DISPLACEMENT"); material.DisableKeyword("_TESSELLATION_DISPLACEMENT_PHONG"); } else if (tessMode == TessellationMode.Displacement) { material.EnableKeyword("_TESSELLATION_DISPLACEMENT"); material.DisableKeyword("_TESSELLATION_DISPLACEMENT_PHONG"); } else { material.DisableKeyword("_TESSELLATION_DISPLACEMENT"); material.EnableKeyword("_TESSELLATION_DISPLACEMENT_PHONG"); } bool tessellationObjectScaleEnable = material.GetFloat(kTessellationObjectScale) > 0.0; SetKeyword(material, "_TESSELLATION_OBJECT_SCALE", tessellationObjectScaleEnable); bool tessellationTilingScaleEnable = material.GetFloat(kTessellationTilingScale) > 0.0; SetKeyword(material, "_TESSELLATION_TILING_SCALE", tessellationTilingScaleEnable); } }
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if code change static public void SetupBaseLitKeywords(Material material) { SetupBaseUnlitKeywords(material); bool doubleSidedEnable = material.GetFloat(kDoubleSidedEnable) > 0.0f; if (doubleSidedEnable) { DoubleSidedNormalMode doubleSidedNormalMode = (DoubleSidedNormalMode)material.GetFloat(kDoubleSidedNormalMode); switch (doubleSidedNormalMode) { case DoubleSidedNormalMode.Mirror: // Mirror mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, -1.0f, 0.0f)); break; case DoubleSidedNormalMode.Flip: // Flip mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(-1.0f, -1.0f, -1.0f, 0.0f)); break; case DoubleSidedNormalMode.None: // None mode (in tangent space) material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, 1.0f, 0.0f)); break; } } // Set the reference value for the stencil test. int stencilRef = (int)StencilLightingUsage.RegularLighting; if ((int)material.GetFloat(kMaterialID) == (int)BaseLitGUI.MaterialId.LitSSS) { stencilRef = (int)StencilLightingUsage.SplitLighting; } // As we tag both during velocity pass and Gbuffer pass we need a separate state and we need to use the write mask material.SetInt(kStencilRef, stencilRef); material.SetInt(kStencilWriteMask, (int)HDRenderPipeline.StencilBitMask.LightingMask); material.SetInt(kStencilRefMV, (int)HDRenderPipeline.StencilBitMask.ObjectVelocity); material.SetInt(kStencilWriteMaskMV, (int)HDRenderPipeline.StencilBitMask.ObjectVelocity); bool enableDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) != DisplacementMode.None; bool enableVertexDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Vertex; bool enablePixelDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Pixel; bool enableTessellationDisplacement = ((DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Tessellation) && material.HasProperty(kTessellationMode); CoreUtils.SetKeyword(material, "_VERTEX_DISPLACEMENT", enableVertexDisplacement); CoreUtils.SetKeyword(material, "_PIXEL_DISPLACEMENT", enablePixelDisplacement); // Only set if tessellation exist CoreUtils.SetKeyword(material, "_TESSELLATION_DISPLACEMENT", enableTessellationDisplacement); bool displacementLockObjectScale = material.GetFloat(kDisplacementLockObjectScale) > 0.0; bool displacementLockTilingScale = material.GetFloat(kDisplacementLockTilingScale) > 0.0; // Tessellation reuse vertex flag. CoreUtils.SetKeyword(material, "_VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE", displacementLockObjectScale && (enableVertexDisplacement || enableTessellationDisplacement)); CoreUtils.SetKeyword(material, "_PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE", displacementLockObjectScale && enablePixelDisplacement); CoreUtils.SetKeyword(material, "_DISPLACEMENT_LOCK_TILING_SCALE", displacementLockTilingScale && enableDisplacement); //forest-begin: Added vertex animation if (material.HasProperty(kWindEnabled)) { var windMode = material.GetFloat(kWindEnabled); CoreUtils.SetKeyword(material, "_ANIM_SINGLE_PIVOT_COLOR", windMode > 2.5f && windMode < 3.5f); CoreUtils.SetKeyword(material, "_ANIM_HIERARCHY_PIVOT", windMode > 3.5f && windMode < 4.5f); CoreUtils.SetKeyword(material, "_ANIM_PROCEDURAL_BRANCH", windMode > 5.5f && windMode < 6.5f); //forest-begin: G-Buffer motion vectors if (windMode > 2.5f) { var hdrpa = UnityEngine.Rendering.GraphicsSettings.renderPipelineAsset as HDRenderPipelineAsset; if (hdrpa && hdrpa.GetFrameSettings().enableGBufferMotionVectors) { material.SetInt(kStencilRef, stencilRef | (int)HDRenderPipeline.StencilBitMask.ObjectVelocity); material.SetInt(kStencilWriteMask, (int)HDRenderPipeline.StencilBitMask.LightingMask | (int)HDRenderPipeline.StencilBitMask.ObjectVelocity); } } //forest-end: } //forest-end: // Depth offset is only enabled if per pixel displacement is bool depthOffsetEnable = (material.GetFloat(kDepthOffsetEnable) > 0.0f) && enablePixelDisplacement; CoreUtils.SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable); if (material.HasProperty(kTessellationMode)) { TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode); CoreUtils.SetKeyword(material, "_TESSELLATION_PHONG", tessMode == TessellationMode.Phong); } SetupMainTexForAlphaTestGI("_BaseColorMap", "_BaseColor", material); // Use negation so we don't create keyword by default CoreUtils.SetKeyword(material, "_DISABLE_DBUFFER", material.GetFloat(kSupportDBuffer) == 0.0); CoreUtils.SetKeyword(material, "_ENABLE_GEOMETRIC_SPECULAR_AA", material.GetFloat(kEnableGeometricSpecularAA) == 1.0); }
public static void AddTessellationShaderProperties(PropertyCollector collector, TessellationMode tessellationMode, float tessellationFactorMinDistance, float tessellationFactorMaxDistance, float tessellationFactorTriangleSize, float tessellationShapeFactor, float tessellationBackFaceCullEpsilon, float tessellationMaxDisplacement) { collector.AddShaderProperty(new Vector1ShaderProperty { overrideReferenceName = kTessellationMode, floatType = FloatType.Enum, value = (int)tessellationMode, enumNames = { "None", "Phong" }, enumValues = { (int)TessellationMode.None, (int)TessellationMode.Phong }, hidden = true, overrideHLSLDeclaration = true, hlslDeclarationOverride = HLSLDeclaration.DoNotDeclare, }); collector.AddFloatProperty(kTessellationFactorMinDistance, tessellationFactorMinDistance, HLSLDeclaration.UnityPerMaterial); collector.AddFloatProperty(kTessellationFactorMaxDistance, tessellationFactorMaxDistance, HLSLDeclaration.UnityPerMaterial); collector.AddFloatProperty(kTessellationFactorTriangleSize, tessellationFactorTriangleSize, HLSLDeclaration.UnityPerMaterial); collector.AddSliderProperty(kTessellationShapeFactor, "Tessellation shape factor", tessellationShapeFactor, new Vector2(0.0f, 1.0f), HLSLDeclaration.UnityPerMaterial); collector.AddSliderProperty(kTessellationBackFaceCullEpsilon, "Tessellation back face epsilon", tessellationBackFaceCullEpsilon, new Vector2(-1.0f, 0.0f), HLSLDeclaration.UnityPerMaterial); collector.AddFloatProperty(kTessellationMaxDisplacement, tessellationMaxDisplacement, HLSLDeclaration.UnityPerMaterial); }