Notice
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Tags
more
Archives
Today
Total
관리 메뉴

자라고싶다

[HLSL]Tessellation + Displacement 본문

Unity/UnityShader

[HLSL]Tessellation + Displacement

멍산 2023. 11. 23. 10:44

/////////////////////////////////////////////////////////////////////////////////////////////////
//Shader Reference: https://catlikecoding.com/unity/tutorials/advanced-rendering/tessellation/
/////////////////////////////////////////////////////////////////////////////////////////////////
Shader "Example/Tessellation"
{

    Properties{

        _TessellationUniform("TessellationUniform", Range(1,64)) = 1
        _TessellationEdgeLength("EdgeLength", Range(5,100)) = 50

        [Toggle(_TESSELLATION_EDGE)] _TESSELLATION_EDGE("_TESSELLATION_EDGE", Float) = 0

        _HeightMap("HeightMap", 2D) = "black"{}
        _Amount("Amount", Range(0,1)) = 0.5


    }


        SubShader
    {

        Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }

        Pass
        {

            HLSLPROGRAM

            #pragma target 5.0

            #pragma shader_feature _TESSELLATION_EDGE 
            #pragma vertex vert
            #pragma hull hp
            #pragma domain dp
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

              struct Attributes {
              float3 positionOS : POSITION;
              float3 normalOS : NORMAL;
              float2 uv : TEXCOORD0;
              };

              struct TessellationFactors {
              float edge[3] : SV_TessFactor;
              float inside : SV_InsideTessFactor;
              };


              struct TessellationControlPoint {
              float3 positionWS : INTERNALTESSPOS;
              float3 normalWS : NORMAL;
              float2 uv : TEXCOORD0;

              };

              struct Interpolators { 
              float3 normalWS       : TEXCOORD2;
              float3 positionWS     : TEXCOORD1;
              float4 positionCS     : SV_POSITION;
              };

              CBUFFER_START(UnityPerMaterial)
              float _TessellationUniform;
              float _TessellationEdgeLength;

              float4 _HeightMap_ST;
              float _Amount;
              CBUFFER_END

                  TEXTURE2D(_HeightMap);
              SAMPLER(sampler_HeightMap);

              TessellationControlPoint vert(Attributes input) {
              TessellationControlPoint output;

              VertexPositionInputs posnInputs = GetVertexPositionInputs(input.positionOS);
              VertexNormalInputs normalInputs = GetVertexNormalInputs(input.normalOS);


              output.positionWS = posnInputs.positionWS;
              output.normalWS = normalInputs.normalWS;
              output.uv = input.uv;
              return output;
              }


              float TessellationEdgeFactor(TessellationControlPoint cp0, TessellationControlPoint cp1) {

              #if defined(_TESSELLATION_EDGE) //viewDistance + edgeLength 에 따라 tess factor 변경
                  float3 p0 = (float4(cp0.positionWS.xyz, 1)).xyz;
                  float3 p1 = (float4(cp1.positionWS.xyz, 1)).xyz;
                  float edgeLength = distance(p0 , p1);

                  float3 edgeCenter = (p0 + p1) * 0.5;
                  float viewDistance = distance(edgeCenter, _WorldSpaceCameraPos);
				  
                  return edgeLength * _ScreenParams.y / (_TessellationEdgeLength * viewDistance);

              #else //tess factor 일괄
                  return _TessellationUniform;
              #endif
              }

              TessellationFactors PatchConstantFunction(InputPatch<TessellationControlPoint, 3> patch) {

                  TessellationFactors f;

                  f.edge[0] = TessellationEdgeFactor(patch[1], patch[2]);
                  f.edge[1] = TessellationEdgeFactor(patch[2], patch[0]);
                  f.edge[2] = TessellationEdgeFactor(patch[0], patch[1]);
                  f.inside = (TessellationEdgeFactor(patch[1], patch[2]) + TessellationEdgeFactor(patch[2], patch[0]) + TessellationEdgeFactor(patch[0], patch[1])) * (1 / 3.0);

                  return f;
              }

          [domain("tri")]
          [outputcontrolpoints(3)]
          [outputtopology("triangle_cw")]
          [patchconstantfunc("PatchConstantFunction")]
          [partitioning("integer")]
          //[partitioning("fractional_even")]
          //[partitioning("fractional_odd")]
          //[partitioning("pow2")]
          //[partitioning("fractional_odd")]

          TessellationControlPoint hp(InputPatch<TessellationControlPoint, 3> patch, uint id : SV_OutputControlPointID)
          {
              return patch[id];
          }


          #define BARYCENTRIC_INTERPOLATE(fieldName) \
		                patch[0].fieldName * barycentricCoordinates.x + \
		                patch[1].fieldName * barycentricCoordinates.y + \
		                patch[2].fieldName * barycentricCoordinates.z


              [domain("tri")]
              Interpolators dp(TessellationFactors factors, OutputPatch<TessellationControlPoint, 3> patch, float3 barycentricCoordinates : SV_DomainLocation) {

                    Interpolators output;
                    
                    float2 uv = BARYCENTRIC_INTERPOLATE(uv);
                    uv = TRANSFORM_TEX(uv, _HeightMap);

                    float4 height = SAMPLE_TEXTURE2D_LOD(_HeightMap, sampler_HeightMap, uv, 0); //HeightMap 샘플링
                    height *= _Amount;

                    float3 positionWS = BARYCENTRIC_INTERPOLATE(positionWS);
                    positionWS.y += height.r; //y 축으로 displacement
                    float3 normalWS = BARYCENTRIC_INTERPOLATE(normalWS);
                    
                    output.positionCS = TransformWorldToHClip(positionWS);
                    output.normalWS = normalWS;
                    output.positionWS = positionWS;

                    return output;
              }

              float4 frag(Interpolators input) : SV_Target{

                    half4 color = (1,1,1,1);
                    return color;
              }

            ENDHLSL
        }
    }
}

 

Reference

https://catlikecoding.com/unity/tutorials/advanced-rendering/tessellation/

 

Tessellation

A Unity Advanced Rendering tutorial about triangle tessellation, with a hull and domain shader.

catlikecoding.com

 

'Unity > UnityShader' 카테고리의 다른 글

[HLSL]Henyey-Greenstein Phase Function  (0) 2025.03.25
[CustomEditor]프로퍼티 #1  (0) 2024.04.23
[HLSL] Diffuse Wrap + Shadow Ramp  (0) 2023.10.17
[HLSL]2 Pass Outline  (0) 2023.10.16
[HLSL]Triplanar  (0) 2023.10.16