Skip to content

Commit 006ac82

Browse files
Tessellation from SV_VertexID
1 parent 15bea28 commit 006ac82

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed

Diff for: VertexShaderTessellation.cs

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using UnityEngine;
2+
using System;
3+
using System.Collections.Generic;
4+
5+
[RequireComponent (typeof(Camera))]
6+
public class VertexShaderTessellation : MonoBehaviour
7+
{
8+
public Shader TessellationShader;
9+
[Range(1, 1024)] public int TessellationFactor = 5;
10+
public UnityEngine.Rendering.CullMode CullMode = UnityEngine.Rendering.CullMode.Off;
11+
12+
ComputeBuffer _VertexBuffer;
13+
Material _Material;
14+
int _VertexCount = 0;
15+
Vector4[] _Vertices;
16+
17+
byte[] ToByteArray(Vector4[] vectors)
18+
{
19+
byte[] bytes = new byte[sizeof(float) * vectors.Length * 4];
20+
for (int i = 0; i < vectors.Length * 4; i++)
21+
Buffer.BlockCopy(BitConverter.GetBytes(vectors[i / 4][i % 4]), 0, bytes, i*sizeof(float), sizeof(float));
22+
return bytes;
23+
}
24+
25+
void Start()
26+
{
27+
Mesh mesh = Resources.GetBuiltinResource<Mesh>("Quad.fbx");
28+
List<Vector4> vertices = new List<Vector4>();
29+
for (int i = 0; i < mesh.triangles.Length; i++)
30+
{
31+
Vector3 p = mesh.vertices[mesh.triangles[i]];
32+
vertices.Add(new Vector4(p.x, p.y, p.z, 1.0f));
33+
}
34+
_Vertices = vertices.ToArray();
35+
Camera.main.clearFlags = CameraClearFlags.SolidColor;
36+
_Material = new Material(TessellationShader);
37+
_VertexBuffer = new ComputeBuffer(4 * _Vertices.Length, sizeof(float), ComputeBufferType.Raw);
38+
byte[] bytes = ToByteArray(_Vertices);
39+
_VertexBuffer.SetData(bytes);
40+
}
41+
42+
void OnPreRender()
43+
{
44+
GL.wireframe = true;
45+
}
46+
47+
void OnPostRender()
48+
{
49+
_Material.SetBuffer("_VertexBuffer", _VertexBuffer);
50+
_Material.SetInt("_TessellationFactor", TessellationFactor);
51+
_Material.SetInt("_CullMode", (int)CullMode);
52+
_Material.SetPass(0);
53+
_VertexCount = TessellationFactor * TessellationFactor * _Vertices.Length;
54+
Graphics.DrawProcedural(MeshTopology.Triangles, _VertexCount, 1);
55+
}
56+
57+
void OnGUI()
58+
{
59+
GL.wireframe = false;
60+
GUI.Label(new Rect(10, 10, 200, 30), "Vertex Count: " + _VertexCount.ToString());
61+
}
62+
63+
void OnDestroy()
64+
{
65+
_VertexBuffer.Release();
66+
Destroy(_Material);
67+
}
68+
}

Diff for: VertexShaderTessellation.shader

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// GPU PRO 3, Advanced Rendering Techniques, A K Peters/CRC Press 2012
2+
// Chapter 1 - Vertex shader tessellation, Holger Gruen
3+
4+
Shader "Vertex Shader Tessellation"
5+
{
6+
SubShader
7+
{
8+
Pass
9+
{
10+
Cull [_CullMode]
11+
CGPROGRAM
12+
#pragma vertex VSMain
13+
#pragma fragment PSMain
14+
#pragma target 5.0
15+
16+
ByteAddressBuffer _VertexBuffer;
17+
int _TessellationFactor;
18+
19+
float4 VSMain (uint id : SV_VertexID) : SV_POSITION
20+
{
21+
uint subtriangles = (_TessellationFactor * _TessellationFactor);
22+
float triangleID = float (( id / 3 ) % subtriangles);
23+
float row = floor (sqrt( triangleID ));
24+
uint column = triangleID - ( row * row );
25+
float incuv = 1.0 / _TessellationFactor;
26+
float u = ( 1.0 + row ) / _TessellationFactor;
27+
float v = incuv * floor (float(column) * 0.5);
28+
u -= v;
29+
float w = 1.0 - u - v;
30+
uint address = id / (3u * subtriangles) * 3u;
31+
float3 p1 = asfloat(_VertexBuffer.Load4(((address + 0) * 4) << 2)).xyz;
32+
float3 p2 = asfloat(_VertexBuffer.Load4(((address + 1) * 4) << 2)).xyz;
33+
float3 p3 = asfloat(_VertexBuffer.Load4(((address + 2) * 4) << 2)).xyz;
34+
uint vertexID = ((id / 3u) / subtriangles) * 3u + (id % 3u);
35+
switch(vertexID % 3)
36+
{
37+
case 0u:
38+
if ((column & 1u) != 0)
39+
{
40+
v += incuv, u -= incuv;
41+
}
42+
break;
43+
case 1u:
44+
if ((column & 1u) == 0)
45+
{
46+
v += incuv, u -= incuv;
47+
}
48+
else
49+
{
50+
v += incuv, u -= incuv;
51+
w += incuv, u -= incuv;
52+
}
53+
break;
54+
case 2u:
55+
if ((column & 1u) == 0)
56+
{
57+
u -= incuv, w += incuv;
58+
}
59+
else
60+
{
61+
w += incuv, u -= incuv;
62+
}
63+
break;
64+
}
65+
return UnityObjectToClipPos(float4(u * p1 + v * p2 + w * p3, 1.0));
66+
}
67+
68+
float4 PSMain (float4 vertex : SV_POSITION) : SV_TARGET
69+
{
70+
return (float4) 1.0;
71+
}
72+
ENDCG
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)