Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Question SkinnedRenderer.GetPreviousVertexBuffer not working in shell texturing example

Discussion in 'Shaders' started by BotsOP, Oct 14, 2022.

  1. BotsOP

    BotsOP

    Joined:
    Jun 9, 2020
    Posts:
    9
    Im trying to use the previous vertex buffer to get the velocity per vertex.
    But no matter what I try whenever I try to pass the previous vertex position it doesnt render anything.
    I have read the previous vertex buffer back to the cpu, stored it in a new texcoord then read it back and read the drawTriangles buffer and all of them seem correct none of them return NaN but actual numbers. I have tried passing extra paremeters through the drawTriangles buffer and packing it in different variables but nothing works. I have been banging my head against this bug the enitre day now and Im stumped.

    Left is my shell texturing where I want to get the previous vertex position to. And right is a quick test to see if previous vertex buffer works without the shell texturing. Which appears to work. Im using unity urp 2021.3.10f.
    no_sway.gif

    here is my c# code
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.Runtime.InteropServices;
    5. using UnityEngine;
    6. using UnityEngine.Rendering;
    7. using UnityEngine.UI;
    8.  
    9. [RequireComponent(typeof(SkinnedMeshRenderer))]
    10. public class ShellTexturingAnimated : MonoBehaviour
    11. {
    12.     [Serializable, StructLayout(LayoutKind.Sequential)]
    13.     public struct InputVertex
    14.     {
    15.         public Vector3 position;
    16.         public Vector3 normal;
    17.         public Vector2 uv;
    18.     }
    19.  
    20.     [Serializable, StructLayout(LayoutKind.Sequential)]
    21.     public struct InputTriangle
    22.     {
    23.         public InputVertex vertex0;
    24.         public InputVertex vertex1;
    25.         public InputVertex vertex2;
    26.     }
    27.  
    28.     [SerializeField] private ComputeShader shellTextureCS;
    29.     [SerializeField] private Material renderingMaterial;
    30.     [SerializeField] private Transform originalOffset;
    31.     [SerializeField] private Transform parentOffset;
    32.     [SerializeField] private Transform transformOffset;
    33.     [Min(1)]
    34.     [SerializeField] private int layers = 1;
    35.     [SerializeField] private float heightOffset = 0;
    36.     [SerializeField] private Vector2 uvScale = new(1, 1);
    37.  
    38.     private int kernelID;
    39.     private int threadGroupSize;
    40.  
    41.     private int[] indirectArgs = new[] { 0, 1, 0, 0 };
    42.  
    43.     private List<InputTriangle> inputTriangles;
    44.     private ComputeBuffer drawTrianglesBuffer;
    45.     private ComputeBuffer indirectArgsBuffer;
    46.  
    47.     private GraphicsBuffer inputVertexBuffer;
    48.     private GraphicsBuffer inputPreviousVertexBuffer;
    49.     private GraphicsBuffer inputUVBuffer;
    50.     private GraphicsBuffer inputIndexBuffer;
    51.    
    52.     private const int DRAWTRIANGLES_STRIDE = (3 * (3 + 3 + 2 + 4)) * sizeof(float);
    53.     private const int INDIRECTARGS_STRIDE = 4 * sizeof(int);
    54.  
    55.     private Mesh mesh;
    56.     private SkinnedMeshRenderer skinnedMeshRenderer;
    57.     private int triangleCount;
    58.     private bool initialized = false;
    59.     private Vector3 startParenOffset;
    60.  
    61.     private void OnEnable()
    62.     {
    63.         mesh = GetComponent<SkinnedMeshRenderer>().sharedMesh;
    64.         skinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>();
    65.         triangleCount = mesh.triangles.Length / 3;
    66.         startParenOffset = parentOffset.position;
    67.        
    68.         SetupBuffers();
    69.        
    70.     }
    71.  
    72.     private void OnDisable()
    73.     {
    74.         ReleaseBuffers();
    75.     }
    76.  
    77.     private void OnValidate()
    78.     {
    79.         SetupData();
    80.         GenerateGeometry();
    81.     }
    82.  
    83.     private void SetupData()
    84.     {
    85.         if (mesh == null)
    86.         {
    87.             return;
    88.         }
    89.  
    90.         skinnedMeshRenderer.vertexBufferTarget |= GraphicsBuffer.Target.Raw;
    91.         mesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw;
    92.         mesh.indexBufferTarget |= GraphicsBuffer.Target.Raw;
    93.        
    94.         mesh.SetVertexBufferParams(mesh.vertexCount,
    95.             new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, dimension:3,stream:0),
    96.             new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, dimension:3,stream:0),
    97.             new VertexAttributeDescriptor(VertexAttribute.Tangent, VertexAttributeFormat.Float32, dimension:4,stream:0),
    98.             new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, dimension:2,stream:1),
    99.             new VertexAttributeDescriptor(VertexAttribute.BlendWeight, VertexAttributeFormat.Float32, dimension:4,stream:2),
    100.             new VertexAttributeDescriptor(VertexAttribute.BlendIndices, VertexAttributeFormat.UInt32, dimension:4,stream:2)
    101.         );
    102.  
    103.         drawTrianglesBuffer.SetCounterValue(0);
    104.         indirectArgsBuffer.SetData(indirectArgs);
    105.  
    106.         initialized = true;
    107.     }
    108.  
    109.     private void GenerateGeometry()
    110.     {
    111.         if (mesh == null || shellTextureCS == null || renderingMaterial == null)
    112.         {
    113.             return;
    114.         }
    115.  
    116.         inputVertexBuffer ??= skinnedMeshRenderer.GetVertexBuffer();
    117.         inputPreviousVertexBuffer ??= skinnedMeshRenderer.GetPreviousVertexBuffer();
    118.         inputUVBuffer ??= mesh.GetVertexBuffer(1);
    119.         inputIndexBuffer ??= mesh.GetIndexBuffer();
    120.  
    121.         kernelID = shellTextureCS.FindKernel("ShellTextureGeoAnim");
    122.         shellTextureCS.GetKernelThreadGroupSizes(kernelID, out uint threadGroupSizeX, out _, out _);
    123.         threadGroupSize = Mathf.CeilToInt((float)triangleCount / threadGroupSizeX);
    124.        
    125.         shellTextureCS.SetBuffer(kernelID, "_DrawTrianglesBuffer", drawTrianglesBuffer);
    126.         shellTextureCS.SetBuffer(kernelID, "_IndirectArgsBuffer", indirectArgsBuffer);
    127.         shellTextureCS.SetBuffer(kernelID, "_InputVertexBuffer", inputVertexBuffer);
    128.         shellTextureCS.SetBuffer(kernelID, "_InputPreviousVertexBuffer", inputPreviousVertexBuffer);
    129.         shellTextureCS.SetBuffer(kernelID, "_InputUVBuffer", inputUVBuffer);
    130.         shellTextureCS.SetBuffer(kernelID, "_InputIndexBuffer", inputIndexBuffer);
    131.        
    132.         shellTextureCS.SetMatrix("_LocalToWorld", transform.localToWorldMatrix);
    133.         shellTextureCS.SetMatrix("_Offset", transformOffset.localToWorldMatrix);
    134.         shellTextureCS.SetInt("_TriangleCount", triangleCount);
    135.         shellTextureCS.SetInt("_Layers", layers);
    136.         shellTextureCS.SetFloat("_HeightOffset", heightOffset);
    137.         shellTextureCS.SetVector("_UVScale", uvScale);
    138.        
    139.         renderingMaterial.SetBuffer("_DrawTrianglesBuffer", drawTrianglesBuffer);
    140.        
    141.         shellTextureCS.Dispatch(kernelID, threadGroupSize, 1, 1);
    142.     }
    143.  
    144.     private void Update()
    145.     {
    146.         if (!initialized)
    147.         {
    148.             if (Time.time > 1)
    149.             {
    150.                 SetupData();
    151.                 GenerateGeometry();
    152.             }
    153.             return;
    154.         }
    155.  
    156.         transformOffset.position = originalOffset.position - startParenOffset;
    157.         transformOffset.rotation = originalOffset.rotation;
    158.         transformOffset.localScale = originalOffset.localScale;
    159.        
    160.         indirectArgsBuffer.SetData(indirectArgs);
    161.         shellTextureCS.SetMatrix("_Offset", transformOffset.localToWorldMatrix);
    162.         shellTextureCS.Dispatch(kernelID, threadGroupSize, 1, 1);
    163.  
    164.         Graphics.DrawProceduralIndirect(
    165.             renderingMaterial,
    166.             skinnedMeshRenderer.bounds,
    167.             MeshTopology.Triangles,
    168.             indirectArgsBuffer,
    169.             0,
    170.             null,
    171.             null,
    172.             ShadowCastingMode.On,
    173.             true,
    174.             gameObject.layer
    175.         );
    176.        
    177.         drawTrianglesBuffer.SetCounterValue(0);
    178.     }
    179.    
    180.     private void SetupBuffers()
    181.     {
    182.         drawTrianglesBuffer = new ComputeBuffer(triangleCount * layers, DRAWTRIANGLES_STRIDE, ComputeBufferType.Append);
    183.         indirectArgsBuffer = new ComputeBuffer(1, INDIRECTARGS_STRIDE, ComputeBufferType.IndirectArguments);
    184.     }
    185.    
    186.     private void ReleaseBuffers()
    187.     {
    188.         ReleaseBuffer(drawTrianglesBuffer);
    189.         ReleaseBuffer(indirectArgsBuffer);
    190.         ReleaseBuffer(inputVertexBuffer);
    191.         ReleaseBuffer(inputUVBuffer);
    192.         ReleaseBuffer(inputIndexBuffer);
    193.     }
    194.    
    195.     private void ReleaseBuffer(ComputeBuffer buffer)
    196.     {
    197.         if (buffer != null)
    198.         {
    199.             buffer.Release();
    200.             buffer = null;
    201.         }
    202.     }
    203.    
    204.     private void ReleaseBuffer(GraphicsBuffer buffer)
    205.     {
    206.         if (buffer != null)
    207.         {
    208.             buffer.Release();
    209.             buffer = null;
    210.         }
    211.     }
    212. }


    Here is my compute shader code
    Code (CSharp):
    1. // Each #kernel tells which function to compile; you can have many kernels
    2. #pragma kernel ShellTextureGeo
    3. #pragma kernel ShellTextureGeoAnim
    4.  
    5. struct InputVertex
    6. {
    7.     float3 position;
    8.     float3 normal;
    9.     float2 uv;
    10. };
    11.  
    12. struct InputTriangle
    13. {
    14.     InputVertex vertex0;
    15.     InputVertex vertex1;
    16.     InputVertex vertex2;
    17. };
    18.  
    19. struct DrawVertex
    20. {
    21.     float3 position;
    22.     float3 normal;
    23.     float2 uv;
    24.     float4 color;
    25. };
    26.  
    27. struct DrawTriangle
    28. {
    29.     DrawVertex drawVertices[3];
    30. };
    31.  
    32. struct IndirectArgs
    33. {
    34.     uint numVerticesPerInstance;
    35.     uint numInstances;
    36.     uint startVertexIndex;
    37.     uint startInstanceIndex;
    38. };
    39.  
    40. StructuredBuffer<InputTriangle> _InputTrianglesBuffer;
    41. AppendStructuredBuffer<DrawTriangle> _DrawTrianglesBuffer;
    42. RWStructuredBuffer<IndirectArgs> _IndirectArgsBuffer;
    43.  
    44. RWByteAddressBuffer _InputVertexBuffer;
    45. RWByteAddressBuffer _InputPreviousVertexBuffer;
    46. RWByteAddressBuffer _InputIndexBuffer;
    47. RWByteAddressBuffer _InputUVBuffer;
    48.  
    49. int _TriangleCount;
    50. float4x4 _LocalToWorld;
    51. float4x4 _Offset;
    52. int _Layers;
    53. float _HeightOffset;
    54. float4 _UVScale;
    55.  
    56. DrawVertex GetVertex(float3 position, float3 normal, float2 uv, float4 color)
    57. {
    58.     DrawVertex output = (DrawVertex) 0;
    59.     float3 pos = mul(_Offset, float4(position, 1.0));
    60.     output.position = mul(_LocalToWorld, float4(pos, 1.0)).xyz;
    61.    
    62.     // float3 prevPos = mul(_Offset, float4(color.yzw, 1.0));
    63.     // output.color.yzw = mul(_LocalToWorld, float4(prevPos, 1.0)).xyz;
    64.    
    65.     output.color.yzw = color.yzw;
    66.     output.normal = mul(_LocalToWorld, float4(normal, 0.0)).xyz;
    67.     output.uv = uv;
    68.     output.color.x = color.x;
    69.     return output;
    70. }
    71.  
    72. [numthreads(64,1,1)]
    73. void ShellTextureGeo (uint3 id : SV_DispatchThreadID)
    74. {
    75.     if((int)id.x >= _TriangleCount)
    76.     {
    77.         return;
    78.     }
    79.    
    80.    
    81.     InputTriangle inputTriangle = _InputTrianglesBuffer[id.x];
    82.    
    83.     DrawTriangle tri = (DrawTriangle) 0;
    84.    
    85.     for (int i = 0; i < _Layers; i++)
    86.     {
    87.         DrawVertex drawVertices[3];
    88.        
    89.         float factor = (float)(i + 1) / (float) _Layers;
    90.        
    91.         float3 position = inputTriangle.vertex0.position +
    92.             inputTriangle.vertex0.normal * _HeightOffset * factor;
    93.         drawVertices[0] = GetVertex(position, inputTriangle.vertex0.normal,
    94.             inputTriangle.vertex0.uv, float4(factor, 0, 0, 1.0));
    95.        
    96.         position = inputTriangle.vertex1.position +
    97.             inputTriangle.vertex1.normal * _HeightOffset * factor;
    98.         drawVertices[1] = GetVertex(position, inputTriangle.vertex1.normal,
    99.             inputTriangle.vertex1.uv, float4(factor, 0, 0, 1.0));
    100.        
    101.         position = inputTriangle.vertex2.position +
    102.             inputTriangle.vertex2.normal * _HeightOffset * factor;
    103.         drawVertices[2] = GetVertex(position, inputTriangle.vertex2.normal,
    104.             inputTriangle.vertex2.uv, float4(factor, 0, 0, 1.0));
    105.        
    106.        
    107.         tri.drawVertices[0] = drawVertices[0];
    108.         tri.drawVertices[1] = drawVertices[1];
    109.         tri.drawVertices[2] = drawVertices[2];
    110.         _DrawTrianglesBuffer.Append(tri);
    111.     }
    112.    
    113.     InterlockedAdd(_IndirectArgsBuffer[0].numVerticesPerInstance, 3 * _Layers);
    114. }
    115.  
    116. [numthreads(64,1,1)]
    117. void ShellTextureGeoAnim (uint3 id : SV_DispatchThreadID)
    118. {
    119.     if((int)id.x >= _TriangleCount)
    120.     {
    121.         return;
    122.     }
    123.  
    124.     int index1 = _InputIndexBuffer.Load((id.x * 3) * 4);
    125.     int index2 = _InputIndexBuffer.Load((id.x * 3 + 1) * 4);
    126.     int index3 = _InputIndexBuffer.Load((id.x * 3 + 2) * 4);
    127.  
    128.     InputVertex vertex0;
    129.     vertex0.position = asfloat(_InputVertexBuffer.Load3(index1 * 40));
    130.     vertex0.normal = asfloat(_InputVertexBuffer.Load3(index1 * 40 + 12));
    131.     vertex0.uv = asfloat(_InputUVBuffer.Load2(index1 * 8)) * _UVScale.xy;
    132.  
    133.     InputVertex vertex1;
    134.     vertex1.position = asfloat(_InputVertexBuffer.Load3(index2 * 40));
    135.     vertex1.normal = asfloat(_InputVertexBuffer.Load3(index2 * 40 + 12));
    136.     vertex1.uv = asfloat(_InputUVBuffer.Load2(index2 * 8)) * _UVScale.xy;
    137.  
    138.     InputVertex vertex2;
    139.     vertex2.position = asfloat(_InputVertexBuffer.Load3(index3 * 40));
    140.     vertex2.normal = asfloat(_InputVertexBuffer.Load3(index3 * 40 + 12));
    141.     vertex2.uv = asfloat(_InputUVBuffer.Load2(index3 * 8)) * _UVScale.xy;
    142.  
    143.     float3 vel = float3(0,0,0);
    144.     float3 vel1 = float3(0,0,0);
    145.     float3 vel2 = float3(0,0,0);
    146.  
    147.     //Just loading these values in and assigning them to the drawVertices buffer makes it not render when Im not even using these values anywhere else
    148.     vel = asfloat(_InputPreviousVertexBuffer.Load3(index1 * 40));
    149.     vel1 = asfloat(_InputPreviousVertexBuffer.Load3(index2 * 40));
    150.     vel2 = asfloat(_InputPreviousVertexBuffer.Load3(index3 * 40));
    151.    
    152.     InputTriangle inputTriangle;
    153.     inputTriangle.vertex0 = vertex0;
    154.     inputTriangle.vertex1 = vertex1;
    155.     inputTriangle.vertex2 = vertex2;
    156.    
    157.     DrawTriangle tri = (DrawTriangle) 0;
    158.  
    159.     for (int i = 0; i < _Layers; i++)
    160.     {
    161.         DrawVertex drawVertices[3];
    162.        
    163.         float factor = (float)(i + 1) / (float) _Layers;
    164.        
    165.         float3 position = inputTriangle.vertex0.position + inputTriangle.vertex0.normal * _HeightOffset * factor;
    166.         drawVertices[0] = GetVertex(position, inputTriangle.vertex0.normal, inputTriangle.vertex0.uv, float4(factor, vel));
    167.        
    168.         position = inputTriangle.vertex1.position + inputTriangle.vertex1.normal * _HeightOffset * factor;
    169.         drawVertices[1] = GetVertex(position, inputTriangle.vertex1.normal, inputTriangle.vertex1.uv, float4(factor, vel1));
    170.        
    171.         position = inputTriangle.vertex2.position + inputTriangle.vertex2.normal * _HeightOffset * factor;
    172.         drawVertices[2] = GetVertex(position, inputTriangle.vertex2.normal, inputTriangle.vertex2.uv, float4(factor, vel2));
    173.        
    174.         tri.drawVertices[0] = drawVertices[0];
    175.         tri.drawVertices[1] = drawVertices[1];
    176.         tri.drawVertices[2] = drawVertices[2];
    177.         _DrawTrianglesBuffer.Append(tri);
    178.     }
    179.    
    180.     InterlockedAdd(_IndirectArgsBuffer[0].numVerticesPerInstance, 3 * _Layers);
    181. }
    182.  


    here is my urp shader code
    Code (CSharp):
    1. Shader "Custom/ShellTexturingLit" {
    2.     Properties{
    3.         [Header(Surface options)]
    4.         [MainTexture] _ColorMap("Color", 2D) = "white" {}
    5.         [MainTexture] _NoiseMap("Noise map", 2D) = "white" {}
    6.         [MainColor] _ColorTint("Tint", Color) = (1, 1, 1, 1)
    7.         _Smoothness("Smoothness", Float) = 0
    8.        
    9.         [HideInInspector] _SourceBlend("Source blend", float) = 0
    10.         [HideInInspector] _DestBlend("Destination blend", float) = 0
    11.         [HideInInspector] _Zwrite("Zwrite", float) = 0
    12.        
    13.         [HideInInspector] _SurfaceType("Surface type", float) = 0
    14.     }
    15.     SubShader {
    16.         Tags {"RenderPipeline" = "UniversalPipeline" "RenderType" = "Opaque"}
    17.  
    18.         Pass {
    19.             Name "ForwardLit"
    20.             Tags{"LightMode" = "UniversalForward" }
    21.             // "UniversalForward" tells Unity this is the main lighting pass of this shader
    22.            
    23.             Cull off
    24.             blend [_SourceBlend] [_DestBlend]
    25.             Zwrite [_Zwrite]
    26.  
    27.             HLSLPROGRAM
    28.  
    29.             #define _SPECULAR_COLOR
    30.  
    31.             // Shader variant keywords
    32.             // Unity automatically discards unused variants created using "shader_feature" from your final game build,
    33.             // however it keeps all variants created using "multi_compile"
    34.             // For this reason, multi_compile is good for global keywords or keywords that can change at runtime
    35.             // while shader_feature is good for keywords set per material which will not change at runtime
    36.  
    37.             // Global URP keywords
    38. #if UNITY_VERSION >= 202120
    39.             #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE
    40. #else
    41.             #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
    42.             #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
    43. #endif
    44.             #pragma multi_compile_fragment _ _SHADOWS_SOFT
    45.  
    46.             #pragma vertex Vertex
    47.             #pragma fragment Fragment
    48.             #pragma target 5.0
    49.  
    50.             #include "ShellTexturingLitPass.hlsl"
    51.             ENDHLSL
    52.         }
    53.  
    54.         Pass {
    55.             Name "ShadowCaster"
    56.             Tags{"LightMode" = "ShadowCaster"}
    57.  
    58.             ColorMask 0 // No color output, only depth
    59.            
    60.  
    61.             HLSLPROGRAM
    62.             #pragma vertex Vertex
    63.             #pragma fragment Fragment
    64.  
    65.             #pragma shader_feature_local _ALPHA_CUTOUT
    66.            
    67.             #include "ShellTexturingShadowCastPass.hlsl"
    68.             ENDHLSL
    69.         }
    70.     }
    71.    
    72.     CustomEditor "LitCustomInspector"
    73. }
    Code (CSharp):
    1. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
    2.  
    3. // Textures
    4. TEXTURE2D(_ColorMap); SAMPLER(sampler_ColorMap);
    5. TEXTURE2D(_NoiseMap); SAMPLER(sampler_NoiseMap);
    6.  
    7. float4 _ColorMap_ST; // This is automatically set by Unity. Used in TRANSFORM_TEX to apply UV tiling
    8. float4 _ColorTint;
    9. float _Smoothness;
    10.  
    11. struct Attributes {
    12.     uint id : SV_VertexID;
    13. };
    14.  
    15. struct Interpolators {
    16.     float4 positionCS : SV_POSITION;
    17.     float2 uv : TEXCOORD0;
    18.     float3 positionWS : TEXCOORD1;
    19.     float3 normalWS : TEXCOORD2;
    20.     float4 color : COLOR;
    21. };
    22.  
    23. struct DrawVertex
    24. {
    25.     float3 position;
    26.     float3 normal;
    27.     float2 uv;
    28.     float4 color;
    29. };
    30.  
    31. struct DrawTriangle
    32. {
    33.     DrawVertex drawVertices[3];
    34. };
    35.  
    36. StructuredBuffer<DrawTriangle> _DrawTrianglesBuffer;
    37.  
    38. half3 CalculateDiffuse(Light light, InputData inputData, SurfaceData surfaceData)
    39. {
    40.     half3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation);
    41.     half3 lightColor = LightingLambert(attenuatedLightColor, light.direction, inputData.normalWS);
    42.  
    43.     lightColor *= surfaceData.albedo;
    44.  
    45.     #if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR)
    46.     half smoothness = exp2(10 * surfaceData.smoothness + 1);
    47.  
    48.     //lightColor += LightingSpecular(attenuatedLightColor, light.direction, inputData.normalWS, inputData.viewDirectionWS, half4(surfaceData.specular, 1), smoothness);
    49.     #endif
    50.  
    51.     return lightColor;
    52. }
    53.  
    54. half4 UniversalFragment(InputData inputData, SurfaceData surfaceData)
    55. {
    56.     #if defined(DEBUG_DISPLAY)
    57.     half4 debugColor;
    58.  
    59.     if (CanDebugOverrideOutputColor(inputData, surfaceData, debugColor))
    60.     {
    61.         return debugColor;
    62.     }
    63.     #endif
    64.  
    65.     uint meshRenderingLayers = GetMeshRenderingLightLayer();
    66.     half4 shadowMask = CalculateShadowMask(inputData);
    67.     AmbientOcclusionFactor aoFactor = CreateAmbientOcclusionFactor(inputData, surfaceData);
    68.     Light mainLight = GetMainLight(inputData, shadowMask, aoFactor);
    69.  
    70.     MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, aoFactor);
    71.  
    72.     inputData.bakedGI *= surfaceData.albedo;
    73.  
    74.     LightingData lightingData = CreateLightingData(inputData, surfaceData);
    75.     if (IsMatchingLightLayer(mainLight.layerMask, meshRenderingLayers))
    76.     {
    77.         lightingData.mainLightColor += CalculateDiffuse(mainLight, inputData, surfaceData);
    78.     }
    79.  
    80.     #if defined(_ADDITIONAL_LIGHTS)
    81.     uint pixelLightCount = GetAdditionalLightsCount();
    82.  
    83.     #if USE_CLUSTERED_LIGHTING
    84.     for (uint lightIndex = 0; lightIndex < min(_AdditionalLightsDirectionalCount, MAX_VISIBLE_LIGHTS); lightIndex++)
    85.     {
    86.         Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
    87.         if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
    88.         {
    89.             lightingData.additionalLightsColor += CalculateBlinnPhong(light, inputData, surfaceData);
    90.         }
    91.     }
    92.     #endif
    93.  
    94.     LIGHT_LOOP_BEGIN(pixelLightCount)
    95.         Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
    96.         if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
    97.         {
    98.             lightingData.additionalLightsColor += CalculateBlinnPhong(light, inputData, surfaceData);
    99.         }
    100.     LIGHT_LOOP_END
    101.     #endif
    102.  
    103.     #if defined(_ADDITIONAL_LIGHTS_VERTEX)
    104.     lightingData.vertexLightingColor += inputData.vertexLighting * surfaceData.albedo;
    105.     #endif
    106.  
    107.     return CalculateFinalColor(lightingData, surfaceData.alpha);
    108. }
    109.  
    110.  
    111. Interpolators Vertex(Attributes input) {
    112.     Interpolators output;
    113.  
    114.     DrawTriangle tri = _DrawTrianglesBuffer[input.id / 3];
    115.     DrawVertex v = tri.drawVertices[input.id  % 3];
    116.    
    117.     VertexPositionInputs posnInputs = GetVertexPositionInputs(v.position);
    118.     VertexNormalInputs normInputs = GetVertexNormalInputs(v.normal);
    119.    
    120.     output.positionCS = posnInputs.positionCS;
    121.     output.uv = v.uv;
    122.     output.normalWS = normInputs.normalWS;
    123.     output.positionWS = posnInputs.positionWS;
    124.     output.color = v.color;
    125.  
    126.     return output;
    127. }
    128.  
    129. float4 Fragment(Interpolators input) : SV_TARGET{
    130.     float2 uv = input.uv;
    131.     float4 color = SAMPLE_TEXTURE2D(_ColorMap, sampler_ColorMap, uv);
    132.     float tex = SAMPLE_TEXTURE2D(_NoiseMap, sampler_NoiseMap, uv).x;
    133.     clip(tex - input.color.x);
    134.  
    135.     InputData lightingInput = (InputData)0;
    136.     lightingInput.positionWS = input.positionWS;
    137.     lightingInput.normalWS = normalize(input.normalWS);
    138.     lightingInput.viewDirectionWS = GetWorldSpaceNormalizeViewDir(input.positionWS);
    139.     lightingInput.shadowCoord = TransformWorldToShadowCoord(input.positionWS);
    140.    
    141.     SurfaceData surfaceInput = (SurfaceData)0;
    142.     surfaceInput.albedo = _ColorTint * input.color.x;
    143.     surfaceInput.albedo = input.color.yzw;
    144.     surfaceInput.alpha = 1;
    145.     surfaceInput.specular = 1;
    146.     surfaceInput.smoothness = _Smoothness;
    147.  
    148. #if UNITY_VERSION >= 202120
    149.     return UniversalFragment(lightingInput, surfaceInput);
    150. #else
    151.     return UniversalFragmentBlinnPhong(lightingInput, surfaceInput.albedo, float4(surfaceInput.specular, 1), surfaceInput.smoothness, surfaceInput.emission, surfaceInput.alpha);
    152. #endif
    153. }
    Code (CSharp):
    1. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
    2.  
    3. struct Attributes {
    4.     uint id : SV_VertexID;
    5. };
    6.  
    7. struct Interpolators {
    8.     float4 positionCS : SV_POSITION;
    9.     float2 uv : TEXCOORD0;
    10.     float4 color : COLOR;
    11. };
    12.  
    13. struct DrawVertex
    14. {
    15.     float3 position;
    16.     float3 normal;
    17.     float2 uv;
    18.     float4 color;
    19. };
    20.  
    21. struct DrawTriangle
    22. {
    23.     DrawVertex drawVertices[3];
    24. };
    25.  
    26. StructuredBuffer<DrawTriangle> _DrawTrianglesBuffer;
    27.  
    28. float3 _LightDirection;
    29.  
    30. float4 GetShadowCasterPositionCS(float3 positionWS, float3 normalWS) {
    31.     float3 lightDirectionWS = _LightDirection;
    32.     float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, lightDirectionWS));
    33.    
    34.     // We have to make sure that the shadow bias didn't push the shadow out of
    35.     // the camera's view area. This is slightly different depending on the graphics API
    36.     #if UNITY_REVERSED_Z
    37.     positionCS.z = min(positionCS.z, UNITY_NEAR_CLIP_VALUE);
    38.     #else
    39.     positionCS.z = max(positionCS.z, UNITY_NEAR_CLIP_VALUE);
    40.     #endif
    41.     return positionCS;
    42. }
    43.  
    44. Interpolators Vertex(Attributes input) {
    45.     Interpolators output;
    46.  
    47.     DrawTriangle tri = _DrawTrianglesBuffer[input.id / 3];
    48.     DrawVertex v = tri.drawVertices[input.id  % 3];
    49.  
    50.     output.uv = v.uv;
    51.     output.color = v.color;
    52.  
    53.     VertexPositionInputs posnInputs = GetVertexPositionInputs(v.position);
    54.     VertexNormalInputs normInputs = GetVertexNormalInputs(v.normal);
    55.  
    56.     output.positionCS = GetShadowCasterPositionCS(posnInputs.positionWS, normInputs.normalWS);
    57.     return output;
    58. }
    59.  
    60. TEXTURE2D(_ColorMap); SAMPLER(sampler_ColorMap);
    61.  
    62.  
    63. float4 Fragment(Interpolators input) : SV_TARGET {
    64.     float tex = SAMPLE_TEXTURE2D(_ColorMap, sampler_ColorMap, input.uv).x;
    65.     clip(tex - input.color.x);
    66.     return 0;
    67. }