자라고싶다
[HLSL]Tessellation + Displacement 본문
/////////////////////////////////////////////////////////////////////////////////////////////////
//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 |