mesh_linespace.glsl 6.79 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

Johannes Braun's avatar
Johannes Braun committed
70
uvec2 getPatch(const in Linespace linespace, vec3 at_position, int axis, int face){
unknown's avatar
unknown committed
71
	bool flip_indices = face != axis;
72
	return !flip_indices
Johannes Braun's avatar
Johannes Braun committed
73
74
75
		?	uvec2(at_position[face_width_axis[axis]] / linespace.patch_size[face_width_axis[axis]], at_position[face_height_axis[axis]] / linespace.patch_size[face_height_axis[axis]])
		:	uvec2(linespace.resolution[face_width_axis[axis]], linespace.resolution[face_height_axis[axis]]) -
			uvec2(at_position[face_width_axis[axis]] / linespace.patch_size[face_width_axis[axis]], at_position[face_height_axis[axis]] / linespace.patch_size[face_height_axis[axis]])- 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;
};

Johannes Braun's avatar
Johannes Braun committed
87
uint lineIndex(const in Ray ray, const in Mesh mesh, int ls_index, float tmin, float tmax, int face_in, int face_out, inout bool direction_swapped)
88
{
Johannes Braun's avatar
Johannes Braun committed
89
	Linespace linespace = mesh.linespaces[ls_index];
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
	//(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.
Johannes Braun's avatar
Johannes Braun committed
114
115
	entry_info.patch_index = getPatch(linespace, entry_info.position, entry_info.axis, entry_info.face);
	exit_info.patch_index = getPatch(linespace, 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

127
128
129
130
131
	uint cunt = linespace.line_count;
	
	if((offset + start+end) * 2 + 1 > cunt)
	  	return 0;

unknown's avatar
unknown committed
132
133
134
	return offset + start + end;
}

Johannes Braun's avatar
Johannes Braun committed
135
bool traverseLineSpace(const in Mesh mesh, int index, const in Ray local_ray, const in bool use_first, const in float max_distance, inout Hit hit, inout float t_min)
136
{
unknown's avatar
unknown committed
137
138
139
140
	float tmin;
	float tmax;
	int face_tmin;
	int face_tmax;
141

142
143
144
	// LS can be empty.
	if (mesh.linespaces[index].line_count == 0) return false;

Johannes Braun's avatar
Johannes Braun committed
145
146
147
	Ray loc = local_ray;
	loc.origin += 0.05f * loc.direction;

148
	if(!loc.intersectsBounds(mesh.linespaces[index].bounds, tmin, tmax, face_tmin, face_tmax) || t_min <= tmin || tmin > max_distance)
unknown's avatar
unknown committed
149
	{
unknown's avatar
unknown committed
150
151
		return false;
	}
152
	
unknown's avatar
unknown committed
153
	bool swapped = false;
154
	uint line_id = lineIndex(loc, mesh, index, tmin, tmax, face_tmin, face_tmax, swapped);
Johannes Braun's avatar
Johannes Braun committed
155

Johannes Braun's avatar
Johannes Braun committed
156
157
	Line line_near = mesh.linespaces[index].lines[line_id * 2];
	Line line_far = mesh.linespaces[index].lines[line_id * 2 + 1];
158

159
	int near_data = swapped ? line_far.triangle : line_near.triangle;
160
161
	Hit nearer;
	float t;
162

163
	if(near_data != -1)
164
	{
165
		nearer.triangle = near_data;
166
		nearer.mesh = mesh.id;
Johannes Braun's avatar
Johannes Braun committed
167
		if(loc.intersectsTrianglePlane(near_data, mesh, t, nearer.barycentric.x, nearer.barycentric.y))
168
		{
169
			float nearest_distance = t;
170
			if(nearest_distance > 0 && max_distance > nearest_distance && t < t_min){
171
172
173
174
175
176
				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
177
	}
178

179
	near_data = swapped ? line_near.triangle : line_far.triangle;
180
	if(near_data != -1)
181
	{
182
		nearer.triangle = near_data;
183
		nearer.mesh = mesh.id;
Johannes Braun's avatar
Johannes Braun committed
184
		if(loc.intersectsTrianglePlane(near_data, mesh, t, nearer.barycentric.x, nearer.barycentric.y))
185
		{
186
			float farthest_distance = t;
unknown's avatar
unknown committed
187

188
			if(farthest_distance > 0 && max_distance > farthest_distance && t < t_min){
189
190
191
192
193
194
				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
195
	}
196

unknown's avatar
unknown committed
197
	return false;
unknown's avatar
unknown committed
198

unknown's avatar
unknown committed
199
200
}

201
#endif //INCLUDE_PATHTRACER_LINESPACE_GLSL