mesh_linespace.glsl 6.52 KB
Newer Older
1
2
#ifndef INCLUDE_PATHTRACER_LINESPACE_GLSL
#define INCLUDE_PATHTRACER_LINESPACE_GLSL
unknown's avatar
unknown committed
3

4
5
6
7
#include <util/scene/mesh.glsl>
#include <util/tracing/intersections.glsl>
#include <util/tracing/linespace.glsl>
#include <util/tracing/tracing.glsl>
unknown's avatar
unknown committed
8

9
uint configurationID(uint in_face, uint out_face)
unknown's avatar
unknown committed
10
11
12
13
{
	return uint((((-0.5f * float(in_face)) + 4.5f)*float(in_face))) - 1u + out_face;
}

14
uint linesBetweenFaces(const in Linespace linespace, uint inface, uint outface)
unknown's avatar
unknown committed
15
{
16
17
	uint axis_in_width = linespace.resolution[face_width_axis[inface % 3]];
	uint axis_in_height = linespace.resolution[face_height_axis[inface % 3]];
18

19
20
	uint axis_out_width = linespace.resolution[face_width_axis[outface % 3]];
	uint axis_out_height = linespace.resolution[face_height_axis[outface % 3]];
21
22
23
24
25
26
27
28
29

	return axis_in_width * axis_in_height * axis_out_width * axis_out_height;
}

uint offsetOf(const in Linespace linespace, uint inface, uint outface)
{
	uint offset = 0;

	// Caution! Fallthrough switch. Seemed to perform much better than a for-loop, usually even being faster than precalculated offsets in release builds.
30
	switch (configurationID(inface, outface))
unknown's avatar
unknown committed
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
	case 15:
		offset += linesBetweenFaces(linespace, 4, 5);
	case 14:
		offset += linesBetweenFaces(linespace, 3, 5);
	case 13:
		offset += linesBetweenFaces(linespace, 3, 4);
	case 12:
		offset += linesBetweenFaces(linespace, 2, 5);
	case 11:
		offset += linesBetweenFaces(linespace, 2, 4);
	case 10:
		offset += linesBetweenFaces(linespace, 2, 3);
	case 9:
		offset += linesBetweenFaces(linespace, 1, 5);
	case 8:
		offset += linesBetweenFaces(linespace, 1, 4);
	case 7:
		offset += linesBetweenFaces(linespace, 1, 3);
	case 6:
		offset += linesBetweenFaces(linespace, 1, 2);
	case 5:
		offset += linesBetweenFaces(linespace, 0, 5);
	case 4:
		offset += linesBetweenFaces(linespace, 0, 4);
	case 3:
		offset += linesBetweenFaces(linespace, 0, 3);
	case 2:
		offset += linesBetweenFaces(linespace, 0, 2);
	case 1:
		offset += linesBetweenFaces(linespace, 0, 1);
	case 0:
	default:
		break;
unknown's avatar
unknown committed
65
66
	}

67
68
	return offset;
}
unknown's avatar
unknown committed
69

unknown's avatar
unknown committed
70
71
uvec2 getPatch(const in Mesh mesh, vec3 at_position, int axis, int face){
	bool flip_indices = face != axis;
72
	return !flip_indices
73
74
75
		?	uvec2(at_position[face_width_axis[axis]] / mesh.linespace.patch_size, at_position[face_height_axis[axis]] / mesh.linespace.patch_size)
		:	uvec2(mesh.linespace.resolution[face_width_axis[axis]], mesh.linespace.resolution[face_height_axis[axis]]) -
			uvec2(at_position[face_width_axis[axis]] / mesh.linespace.patch_size, at_position[face_height_axis[axis]] / mesh.linespace.patch_size)- 1;
unknown's avatar
unknown committed
76
77
78
79
80
81
82
83
84
85
86
}

struct PatchInfo
{
	int face;
	int axis;
	uvec2 patch_index;
	vec3 position;
	float t;
};

87
uint lineIndex(const in Ray ray, const in Mesh mesh, float tmin, float tmax, int face_in, int face_out, inout bool direction_swapped)
88
{
unknown's avatar
unknown committed
89
	Linespace linespace = mesh.linespace;
90

unknown's avatar
unknown committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
	PatchInfo entry_info;
	PatchInfo exit_info;

	// face_in > face_out is an unsupported configuration for reasons of generation performance and memory conservation.
	// If that happens, flip tmin, tmax and the two faces accordingly and mark it as flipped to we can take the farthest intersection in the shaft instead of the nearest.
	direction_swapped = face_in > face_out;
	// -------- t values -------------
	entry_info.t = direction_swapped ? tmax : tmin;
	exit_info.t = direction_swapped ? tmin : tmax;
	// -------- faces ----------------
	entry_info.face = direction_swapped ? face_out : face_in;
	exit_info.face = direction_swapped ? face_in : face_out;
	/////////////////////////////////////////////////////////////

105
	//calculate entry and exit points on the minimum-normalized bounding box
unknown's avatar
unknown committed
106
107
108
109
110
111
112
113
114
115
	//(so that bounds.min is at (0,0,0) and bounds.max is at the former bounding box's size)
	entry_info.position = ray.origin + entry_info.t * ray.direction - linespace.bounds.min.xyz;
	exit_info.position = ray.origin + exit_info.t * ray.direction - linespace.bounds.min.xyz;

	entry_info.axis = entry_info.face % 3;
	exit_info.axis = exit_info.face % 3;

	// getPatch mirrors the patches on the negative axises per definition.
	entry_info.patch_index = getPatch(mesh, entry_info.position, entry_info.axis, entry_info.face);
	exit_info.patch_index = getPatch(mesh, exit_info.position, exit_info.axis, exit_info.face);
116

unknown's avatar
unknown committed
117
	//Now with all that information, we can retrieve the line index.
118
	uint offset = offsetOf(linespace, entry_info.face, exit_info.face);
unknown's avatar
unknown committed
119

120
121
122
	uint start_height = linespace.resolution[face_height_axis[entry_info.axis]];
	uint end_width = linespace.resolution[face_width_axis[exit_info.axis]];
	uint end_height = linespace.resolution[face_height_axis[exit_info.axis]];
unknown's avatar
unknown committed
123
124
125

	uint start = (entry_info.patch_index.y + entry_info.patch_index.x * start_height) * end_width * end_height;
	uint end = (exit_info.patch_index.y + exit_info.patch_index.x * end_height);
126

unknown's avatar
unknown committed
127
128
129
	return offset + start + end;
}

130
bool traverseLineSpace(const in Mesh mesh, const in Ray local_ray, const in bool use_first, const in float max_distance, inout Hit hit, inout float t_min)
131
{
unknown's avatar
unknown committed
132
133
134
135
	float tmin;
	float tmax;
	int face_tmin;
	int face_tmax;
136
137

	float offset = mesh.linespace.patch_size;//1;//e-2;//1000;//mesh.linespace.patch_size;
unknown's avatar
unknown committed
138

unknown's avatar
unknown committed
139
	Ray offset_ray = local_ray;
unknown's avatar
unknown committed
140
	offset_ray.origin += local_ray.direction * offset;
141

unknown's avatar
unknown committed
142
	if(!offset_ray.intersectsBounds(mesh.linespace.bounds, tmin, tmax, face_tmin, face_tmax) || t_min <= tmin-offset || tmin-offset > max_distance)
unknown's avatar
unknown committed
143
	{
unknown's avatar
unknown committed
144
145
		return false;
	}
146

unknown's avatar
unknown committed
147
	bool swapped = false;
148
	uint line_id = lineIndex(offset_ray, mesh, tmin, tmax, face_tmin, face_tmax, swapped);
149
	Line line = mesh.linespace.lines[line_id];
150

151
	int near_data = swapped ? line.farthest : line.nearest;
152
153
	Hit nearer;
	float t;
154

155
	if(near_data != -1)
156
	{
157
		nearer.triangle = near_data;
158
		nearer.mesh = mesh.id;
159
		if(local_ray.intersectsTrianglePlane(near_data, mesh, t, nearer.barycentric.x, nearer.barycentric.y))
160
		{
unknown's avatar
unknown committed
161
162
			float nearest_distance = t-offset;
			if(nearest_distance > 0 && max_distance > nearest_distance){
163
164
165
166
167
168
				hit = nearer;
				t_min = t;
				//Found an intersected shaft. But we don't yet know whether it contains geometry, so look it up as a last step.
				return true;
			}
		}
unknown's avatar
unknown committed
169
	}
170

171
	near_data = swapped ? line.nearest : line.farthest;
172
	if(near_data != -1)
173
	{
174
		nearer.triangle = near_data;
175
		nearer.mesh = mesh.id;
176
		if(local_ray.intersectsTrianglePlane(near_data, mesh, t, nearer.barycentric.x, nearer.barycentric.y))
177
		{
unknown's avatar
unknown committed
178
179
180
			float farthest_distance = t-offset;

			if(farthest_distance > 0 && max_distance > farthest_distance){
181
182
183
184
185
186
				hit = nearer;
				t_min = t;
				//Found an intersected shaft. But we don't yet know whether it contains geometry, so look it up as a last step.
				return true;
			}
		}
unknown's avatar
unknown committed
187
	}
188

unknown's avatar
unknown committed
189
	return false;
unknown's avatar
unknown committed
190

unknown's avatar
unknown committed
191
192
}

193
#endif //INCLUDE_PATHTRACER_LINESPACE_GLSL