-
Notifications
You must be signed in to change notification settings - Fork 1
/
intersect.glsl
147 lines (116 loc) · 5.82 KB
/
intersect.glsl
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
138
139
140
141
142
143
144
145
146
147
#ifndef INTERSECT_GLSL
#define INTERSECT_GLSL
#include "../defines.glsl"
#include "../raycommon.glsl"
#include "aabb.glsl"
#include "svo.glsl"
#include "svdag.glsl"
#include "svdag_occupancy_field.glsl"
float intersect_minDistancePointBox(in const vec3 p, in const vec3 bmin, in const vec3 bmax) {
vec3 d = max(vec3(0), max(bmin - p, p - bmax));
return length(d);
}
float hitSphere(const vec3 sphereCenter, const float sphereRadius, const vec3 rayOrigin, const vec3 rayDirection) {
vec3 oc = rayOrigin - sphereCenter;
float a = dot(rayDirection, rayDirection);
float b = 2.0 * dot(oc, rayDirection);
float c = dot(oc, oc) - sphereRadius * sphereRadius;
float discriminant = b * b - 4 * a * c;
if (discriminant < 0) {
return -1.0;
} else {
return (-b - sqrt(discriminant)) / (2.0 * a);
}
}
bool intersect(in const int objectDescriptorId, in const int primitiveId, in vec3 origin, in vec3 direction, in const mat4x3 objectToWorld, in const mat4x3 worldToObject, out float tHit) {
const ObjectDescriptor objectDescriptor = g_objectDescriptors[objectDescriptorId];
buffer_aabb aabbs = buffer_aabb(objectDescriptor.aabbAddress);
const AABB aabb = aabbs.g_aabbs[primitiveId];
// if (aabb.materialId != 27) {
// return false;
// }
if (g_spheres != 0) {
const vec3 aabbMin = vec3(aabb.minX, aabb.minY, aabb.minZ);
const vec3 aabbMax = vec3(aabb.maxX, aabb.maxY, aabb.maxZ);
const vec3 aabbMinWorld = objectToWorld * vec4(aabbMin.xyz, 1.0);
const vec3 aabbMaxWorld = objectToWorld * vec4(aabbMax.xyz, 1.0);
vec3 center = 0.5 * (aabbMinWorld + aabbMaxWorld);
float radius = 0.5 * min(min(aabbMaxWorld.x - aabbMinWorld.x, aabbMaxWorld.y - aabbMinWorld.y), aabbMaxWorld.z - aabbMinWorld.z);
tHit = hitSphere(center, radius, origin, direction);
return tHit >= 0;
}
if (g_lodType == LOD_TYPE_SVDAG_OCCUPANCY_FIELD) {
const vec3 aabbMin = vec3(aabb.minX, aabb.minY, aabb.minZ);
const vec3 aabbMax = vec3(aabb.maxX, aabb.maxY, aabb.maxZ);
const vec3 aabbMinWorld = objectToWorld * vec4(aabbMin.xyz, 1.0);
const vec3 aabbMaxWorld = objectToWorld * vec4(aabbMax.xyz, 1.0);
origin = worldToObject * vec4(origin, 1);
direction = worldToObject * vec4(direction, 0);
if (aabb_intersect(aabbMin, aabbMax, origin, 1 / direction, tHit)) {
if (g_lod == 0 || (g_frame == 0 && g_lodDisableOnFirstFrame != 0) || objectDescriptor.lodAddress == 0) {
return true;
}
const float dist = g_lodDistance == 0 ? 0 : intersect_minDistancePointBox(vec3(g_ray_origin_x, g_ray_origin_y, g_ray_origin_z), aabbMinWorld, aabbMaxWorld);
if (dist > g_lodDistanceOctree) { // no LOD, only AABBs
return true;
}
const bool traverseOccupancyFields = dist <= g_lodDistanceVoxel;
int iterations;
origin = origin + tHit * direction;
origin = origin - aabbMin;// translate lod to (0,0,0), LOD is then in [(0,0,0), lodSize]
tHit += svdag_occupancy_field_traverse(objectDescriptor.lodAddress, origin, direction, aabb.lod, traverseOccupancyFields, iterations);
if (tHit >= FLT_MAX) {
return false;
}
return true;
}
return false;
}
if (g_lodType == LOD_TYPE_SVDAG) {
const vec3 aabbMin = vec3(aabb.minX, aabb.minY, aabb.minZ);
const vec3 aabbMax = vec3(aabb.maxX, aabb.maxY, aabb.maxZ);
const vec3 aabbMinWorld = objectToWorld * vec4(aabbMin.xyz, 1.0);
const vec3 aabbMaxWorld = objectToWorld * vec4(aabbMax.xyz, 1.0);
origin = worldToObject * vec4(origin, 1);
direction = worldToObject * vec4(direction, 0);
if (aabb_intersect(aabbMin, aabbMax, origin, 1 / direction, tHit)) {
if (g_lod == 0 || (g_frame == 0 && g_lodDisableOnFirstFrame != 0) || objectDescriptor.lodAddress == 0) {
return true;
}
const float dist = g_lodDistance == 0 ? 0 : intersect_minDistancePointBox(vec3(g_ray_origin_x, g_ray_origin_y, g_ray_origin_z), aabbMinWorld, aabbMaxWorld);
if (dist > g_lodDistanceOctree) { // no LOD, only AABBs
return true;
}
int iterations;
origin = origin + tHit * direction;
origin = origin - aabbMin;// translate lod to (0,0,0), LOD is then in [(0,0,0), lodSize]
tHit += svdag_traverse(objectDescriptor.lodAddress, origin, direction, aabb.lod, iterations);
if (tHit >= FLT_MAX) {
return false;
}
return true;
}
return false;
}
if (g_lodType == LOD_TYPE_SVO) {
const vec3 aabbMin = vec3(aabb.minX, aabb.minY, aabb.minZ);
const vec3 aabbMax = vec3(aabb.maxX, aabb.maxY, aabb.maxZ);
const vec3 aabbMinWorld = objectToWorld * vec4(aabbMin.xyz, 1.0);
const vec3 aabbMaxWorld = objectToWorld * vec4(aabbMax.xyz, 1.0);
const float dist = g_lodDistance == 0 ? 0 : intersect_minDistancePointBox(vec3(g_ray_origin_x, g_ray_origin_y, g_ray_origin_z), aabbMinWorld, aabbMaxWorld);
if (g_lod == 0 || (g_frame == 0 && g_lodDisableOnFirstFrame != 0) || objectDescriptor.lodAddress == 0 || dist > g_lodDistanceOctree) {
if (aabb_intersect(aabbMin, aabbMax, origin, 1 / direction, tHit)) {
return true;
}
return false;
}
int iterations;
tHit = svo_traverse(objectDescriptor.lodAddress, origin, direction, 1 / direction, aabb.lod, ivec3(aabb.minX, aabb.minY, aabb.minZ), iterations);
if (tHit >= FLT_MAX) {
return false;
}
return true;
}
return false;
}
#endif