-
Notifications
You must be signed in to change notification settings - Fork 869
Expand file tree
/
Copy pathUVFallbackBufferGeneration.shader
More file actions
106 lines (89 loc) · 4.09 KB
/
UVFallbackBufferGeneration.shader
File metadata and controls
106 lines (89 loc) · 4.09 KB
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
Shader "Hidden/UVFallbackBufferGeneration"
{
SubShader
{
Pass
{
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 5.0
#include "GeometryUtils.hlsl"
#define INSIDE_EPS 0.01f // Epsilon chosen to be 1 order of magnitude larger than the maximum
// distance between subsequent floats in range [0; 8192]
#define PARALLEL_EPS 1e-6f
struct v2f
{
float4 vertex : SV_POSITION;
nointerpolation float2 vertices[3] : TEXCOORD0;
};
uint g_Width;
uint g_Height;
float g_WidthScale;
float g_HeightScale;
StructuredBuffer<float2> g_VertexBuffer;
v2f vert (uint vertexId : SV_VertexID)
{
v2f o;
// Expand the triangle.
uint2 resolution = uint2(g_Width, g_Height);
float2 tri[3];
float4 unusedAABB;
const float eps = 0.01f;
ReadParentTriangle(g_VertexBuffer, vertexId, float4(g_WidthScale, g_HeightScale, 0, 0), tri);
ExpandTriangleForConservativeRasterization(resolution, tri, vertexId, unusedAABB, o.vertex, PARALLEL_EPS);
// Scale the triangle to screen coordinates, pass it to fragment shader.
o.vertices[0] = tri[0] * resolution;
o.vertices[1] = tri[1] * resolution;
o.vertices[2] = tri[2] * resolution;
return o;
}
float2 frag (v2f i, out float depth : SV_Depth) : SV_Target
{
float2 a = i.vertices[0];
float2 b = i.vertices[1];
float2 c = i.vertices[2];
// First check the easy case: If the texel center is inside the triangle, no need to clip at all. Just pick it.
// We need to shrink the triangle by a small epsilon to avoid picking a point precisely on the edge of the triangle,
// as our intersector cannot handle such points. Epsilon chosen to be 1 order of magnitude larger than the maximum
// distance between subsequent floats in range [0; 8192]
float2 texelCenter = i.vertex.xy;
if (IsInside(texelCenter, c, b, INSIDE_EPS) && IsInside(texelCenter, b, a, INSIDE_EPS) && IsInside(texelCenter, a, c, INSIDE_EPS))
{
#if UNITY_REVERSED_Z
depth = 1.0;
#else
depth = 0.0;
#endif
return 0.5;
}
// 6 length since clipping a triangle with a quad results in at most a hexagon.
float2 result[6] = { a, b, c, float2(0, 0), float2(0, 0), float2(0, 0) };
uint resultSize = 3;
// Clip to the texel.
ClipPolygonWithTexel(texelCenter, result, resultSize, INSIDE_EPS, PARALLEL_EPS);
// Discard removed triangles.
if (resultSize <= 0)
discard;
// Use the centroid of the clipped triangle as the UV.
float2 center = float2(0, 0);
for (uint i = 0; i < resultSize; i++)
center += result[i];
center /= resultSize;
float2 offset = center - floor(texelCenter);
// If the centroid lies on the boundary of the texel, discard - this is a singularity.
if (offset.x <= 0 || offset.x >= 1.0 || offset.y <= 0 || offset.y >= 1.0)
discard;
// Use the zbuffer to pick the triangle with the smallest distance from centroid to texel center.
float dist = distance(0.5, offset);
depth = (dist / sqrt(0.5));
#if UNITY_REVERSED_Z
depth = 1.0 - depth;
#endif
return offset;
}
ENDCG
}
}
}