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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
//TEST:LANG_SERVER(filecheck=CHECK):
RWTexture2D<float4> texFrame; // Output texture
uniform float iTime;
// In seconds
uniform float2 iResolution; // Screen size
static const float kInfinity = asfloat(0x7f800000);
static const uint32_t kIdNone = 0xFFFFFFFF;
struct Intersection
{
float t = kInfinity;
uint32_t id = kIdNone;
bool missed() {
return id == kIdNone;
}
[mutating]
void update(uint32_t newId, float newT)
{
if(newT >= 0 && newT < t)
{
t = newT;
id = newId;
}
}
};
struct Ray
{
float3 origin;
float3 direction;
float3 at(float t)
{
return mad(origin, direction, float3(t));
}
};
// Returns the t-value of the intersection of the infinite line
// with the plane given by
// `dot(planeNormal, p) == planeDist`.
float intersectPlane(Ray ray, float3 planeNormal, float planeDist)
{
// dot(planeNormal, o + d * t) == planeDist
// -> dot(planeNormal, o) + t * dot(planeNormal, d) == planeDist
// -> t = (planeDist - dot(planeNormal, o)) / dot(planeNormal, d)
return (planeDist - dot(planeNormal, ray.origin))
/ dot(planeNormal, ray.direction);
}
float2 sortLoHi(float2 v)
{
struct OBB
{
// Note that these are more parameters than we need;
// technically, the sides of an OBB must all be perpendicular,
// so there's only 3 (position) + 3 (side lengths) + 3 (rotation)
// degrees of freedom.
float3 corner;
float3 edges[3];
// Returns the t-value of the intersection of the OBB with
// the ray.
// The returned t-value may be negative; i.e. this assumes
// the camera is outside of the box.
// On miss, returns infinity.
float intersect(Ray ray)
{
ray.origin -= corner;
float2 tCloseFar;
float tFar;
[ForceUnroll]
for(int i = 0; i < 3; i++)
{
const float3 edge = edges[i];
const float edgeDist = dot(edge, ray.origin);
const float factor = rcp(dot(edge, ray.direction));
float2 slab = (float2(0, dot(edge, edge)) - edgeDist)
* factor;
slab =
if(i == 0)
{
tClose = min(slab.x, slab.y);
tFar = max(slab.x, slab.y);
}
else
{
tClose = min3(tClose, slab.x, slab.y);
tFar = max3(tFar, slab.x, slab.y);
}
thisSlab = sortLoHi(thisSlab);
tCloseFar.x =
}
return kInfinity;
}
};
[shader("compute")]
[numthreads(16, 16, 1)]
void main(uint2 thread: SV_DispatchThreadID)
{
float2 uv = (2.0 * float2(thread) - iResolution.xy) / iResolution.y;
// Right-handed Z-up coordinate system, same as Blender's
Ray ray;
ray.origin = float3(0, -4, 4);
static const float kSqrtP5 = sqrt(.5);
ray.direction = float3(
uv.x,
kSqrtP5 -kSqrtP5 * uv.y,
-kSqrtP5 -kSqrtP5 * uv.y
);
Intersection intersection;
intersection.update(0, intersectPlane(ray, float3(0,0,1), 0));
OBB obb = OBB(float3(-1,-1,-1),{float3(2,0,0),float3(0,2,0), float3(0,0,2)});
intersection.update(1, obb.intersect(ray));
float3 color;
if(intersection.missed())
{
color = float3(0.0, 0.0, 1.0);
}
else
{
color = float3(intersection.t / 10.0);
}
//COMPLETE:134,31
texFrame[thread] = float4(color, 1.0);
}
// CHECK: color
|