Skip to content

Commit b058cfc

Browse files
authored
Add files via upload
1 parent d758a4b commit b058cfc

File tree

1 file changed

+266
-0
lines changed

1 file changed

+266
-0
lines changed

js/RayTracing_In_One_Weekend.js

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
// scene/demo-specific variables go here
2+
let boxGeometry, boxMaterial;
3+
let boxMeshes = [];
4+
let boxGeometries = [];
5+
6+
let totalNumberOfShapes = 0;
7+
let sphereTestPosition = new THREE.Vector3();
8+
let testPoint = new THREE.Vector3(4, 0.2, 0);
9+
let spherePositions = [];
10+
let choose_mat = 0;
11+
let tempColor = new THREE.Color();
12+
let shape = new THREE.Object3D();
13+
let invMatrix = new THREE.Matrix4();
14+
let el; // elements of the invMatrix
15+
let shapeBoundingBox_minCorner = new THREE.Vector3();
16+
let shapeBoundingBox_maxCorner = new THREE.Vector3();
17+
let shapeBoundingBox_centroid = new THREE.Vector3();
18+
let shape_array;
19+
let shapeDataTexture;
20+
let aabb_array;
21+
let aabbDataTexture;
22+
let totalWorklist;
23+
24+
25+
26+
// called automatically from within initTHREEjs() function (located in InitCommon.js file)
27+
function initSceneData()
28+
{
29+
demoFragmentShaderFileName = 'RayTracing_InOneWeekend_Fragment.glsl';
30+
31+
// scene/demo-specific three.js objects setup goes here
32+
sceneIsDynamic = false;
33+
34+
cameraFlightSpeed = 10;
35+
36+
// pixelRatio is resolution - range: 0.5(half resolution) to 1.0(full resolution)
37+
pixelRatio = mouseControl ? 1.0 : 0.75;
38+
39+
EPS_intersect = 0.01;
40+
41+
// set camera's field of view
42+
worldCamera.fov = 25;
43+
apertureSize = 0.001;
44+
focusDistance = 10.0;
45+
apertureChangeSpeed = 0.005;
46+
focusDistanceChangeSpeed = 0.05;
47+
48+
// position and orient camera
49+
cameraControlsObject.position.set(13, 2, 3);
50+
// look left
51+
cameraControlsYawObject.rotation.y = 1.35;
52+
// look slightly downward
53+
cameraControlsPitchObject.rotation.x = -0.13;
54+
55+
56+
57+
58+
shape_array = new Float32Array(2048 * 2048 * 4);
59+
// 2048 = width of texture, 2048 = height of texture, 4 = r,g,b, and a components
60+
61+
aabb_array = new Float32Array(2048 * 2048 * 4);
62+
// 2048 = width of texture, 2048 = height of texture, 4 = r,g,b, and a components
63+
64+
65+
for (let a = -11; a < 11; a++)
66+
{
67+
for (let b = -11; b < 11; b++)
68+
{
69+
sphereTestPosition.set( a + (0.9 * Math.random()), 0.2, b + (0.9 * Math.random()) );
70+
71+
if (sphereTestPosition.distanceTo(testPoint) > 1.0)
72+
{
73+
spherePositions.push(new THREE.Vector3().copy(sphereTestPosition));
74+
totalNumberOfShapes++;
75+
}
76+
}
77+
}
78+
79+
console.log("Shape count: " + totalNumberOfShapes);
80+
totalWorklist = new Uint32Array(totalNumberOfShapes);
81+
82+
boxMaterial = new THREE.MeshBasicMaterial();
83+
let ix32 = 0;
84+
let ix9 = 0;
85+
86+
for (let i = 0; i < totalNumberOfShapes; i++)
87+
{
88+
ix32 = i * 32;
89+
ix9 = i * 9;
90+
91+
shape.position.copy(spherePositions[i]);
92+
shape.rotation.set(0, 0, 0);
93+
shape.scale.set(0.2, 0.2, 0.2);
94+
95+
shape.updateMatrixWorld(true); // 'true' forces immediate matrix update
96+
97+
invMatrix.copy(shape.matrixWorld).invert();
98+
el = invMatrix.elements;
99+
100+
//slot 0 Shape transform Matrix 4x4 (16 elements total)
101+
shape_array[ix32 + 0] = el[0]; // r or x // shape transform Matrix element[0]
102+
shape_array[ix32 + 1] = el[1]; // g or y // shape transform Matrix element[1]
103+
shape_array[ix32 + 2] = el[2]; // b or z // shape transform Matrix element[2]
104+
shape_array[ix32 + 3] = el[3]; // a or w // shape transform Matrix element[3]
105+
106+
//slot 1
107+
shape_array[ix32 + 4] = el[4]; // r or x // shape transform Matrix element[4]
108+
shape_array[ix32 + 5] = el[5]; // g or y // shape transform Matrix element[5]
109+
shape_array[ix32 + 6] = el[6]; // b or z // shape transform Matrix element[6]
110+
shape_array[ix32 + 7] = el[7]; // a or w // shape transform Matrix element[7]
111+
112+
//slot 2
113+
shape_array[ix32 + 8] = el[8]; // r or x // shape transform Matrix element[8]
114+
shape_array[ix32 + 9] = el[9]; // g or y // shape transform Matrix element[9]
115+
shape_array[ix32 + 10] = el[10]; // b or z // shape transform Matrix element[10]
116+
shape_array[ix32 + 11] = el[11]; // a or w // shape transform Matrix element[11]
117+
118+
//slot 3
119+
shape_array[ix32 + 12] = el[12]; // r or x // shape transform Matrix element[12]
120+
shape_array[ix32 + 13] = el[13]; // g or y // shape transform Matrix element[13]
121+
shape_array[ix32 + 14] = el[14]; // b or z // shape transform Matrix element[14]
122+
shape_array[ix32 + 15] = el[15]; // a or w // shape transform Matrix element[15]
123+
124+
//slot 4
125+
shape_array[ix32 + 16] = 1; // r or x // shape type id# (0: box, 1: sphere, 2: cylinder, 3: cone, 4: paraboloid, etc)
126+
//shape_array[ix32 + 17] = 1; // g or y // material type id# (0: LIGHT, 1: DIFF, 2: REFR, 3: SPEC, 4: COAT, etc)
127+
shape_array[ix32 + 18] = 0.0; // b or z // material Metalness - default: 0.0(no metal, a dielectric), 1.0 would be purely metal
128+
shape_array[ix32 + 19] = 0.0; // a or w // material Roughness - default: 0.0(no roughness, totally smooth)
129+
130+
choose_mat = Math.random();
131+
if (choose_mat < 0.8)
132+
{
133+
shape_array[ix32 + 17] = 1; // diffuse
134+
tempColor.set( Math.random() * Math.random(), Math.random() * Math.random(), Math.random() * Math.random() );
135+
136+
} else if (choose_mat < 0.95)
137+
{
138+
shape_array[ix32 + 17] = 3; // metal
139+
shape_array[ix32 + 19] = Math.random() * 0.5; // pick a random roughness between 0.0 and 0.5
140+
tempColor.set( (Math.random() * 0.5) + 0.5, (Math.random() * 0.5) + 0.5, (Math.random() * 0.5) + 0.5 );
141+
142+
} else
143+
{
144+
shape_array[ix32 + 17] = 2; // glass
145+
tempColor.set(1, 1, 1);
146+
}
147+
148+
//slot 5
149+
shape_array[ix32 + 20] = tempColor.r; // r or x // material albedo color R (if LIGHT, this is also its emissive color R)
150+
shape_array[ix32 + 21] = tempColor.g; // g or y // material albedo color G (if LIGHT, this is also its emissive color G)
151+
shape_array[ix32 + 22] = tempColor.b; // b or z // material albedo color B (if LIGHT, this is also its emissive color B)
152+
shape_array[ix32 + 23] = 1.0; // a or w // material Opacity (Alpha) - default: 1.0 (fully opaque), 0.0 is fully transparent
153+
154+
//slot 6
155+
shape_array[ix32 + 24] = 1.0; // r or x // material Index of Refraction(IoR) - default: 1.0(air) (or 1.5(glass), 1.33(water), etc)
156+
shape_array[ix32 + 25] = 0.0; // g or y // material ClearCoat Roughness - default: 0.0 (no roughness, totally smooth)
157+
shape_array[ix32 + 26] = 1.5; // b or z // material ClearCoat IoR - default: 1.5(thick ClearCoat)
158+
shape_array[ix32 + 27] = 0; // a or w // material data
159+
160+
//slot 7
161+
shape_array[ix32 + 28] = 0; // r or x // material data
162+
shape_array[ix32 + 29] = 0; // g or y // material data
163+
shape_array[ix32 + 30] = 0; // b or z // material data
164+
shape_array[ix32 + 31] = 0; // a or w // material data
165+
166+
// if this shape is a Box, use THREE.BoxGeometry as starting point for this shape's AABB
167+
//if (shape_array[ix32 + 16] == 0)
168+
boxGeometries[i] = new THREE.BoxGeometry(2, 2, 2);
169+
//else // else use THREE.SphereGeometry, as it produces a tighter-fitting AABB when shape is rotated
170+
// boxGeometries[i] = new THREE.SphereGeometry(1.4);
171+
172+
boxMeshes[i] = new THREE.Mesh( boxGeometries[i], boxMaterial );
173+
174+
boxMeshes[i].geometry.applyMatrix4(shape.matrixWorld);
175+
boxMeshes[i].geometry.computeBoundingBox();
176+
177+
shapeBoundingBox_minCorner.copy(boxMeshes[i].geometry.boundingBox.min);
178+
shapeBoundingBox_maxCorner.copy(boxMeshes[i].geometry.boundingBox.max);
179+
boxMeshes[i].geometry.boundingBox.getCenter(shapeBoundingBox_centroid);
180+
181+
182+
aabb_array[ix9 + 0] = shapeBoundingBox_minCorner.x;
183+
aabb_array[ix9 + 1] = shapeBoundingBox_minCorner.y;
184+
aabb_array[ix9 + 2] = shapeBoundingBox_minCorner.z;
185+
aabb_array[ix9 + 3] = shapeBoundingBox_maxCorner.x;
186+
aabb_array[ix9 + 4] = shapeBoundingBox_maxCorner.y;
187+
aabb_array[ix9 + 5] = shapeBoundingBox_maxCorner.z;
188+
aabb_array[ix9 + 6] = shapeBoundingBox_centroid.x;
189+
aabb_array[ix9 + 7] = shapeBoundingBox_centroid.y;
190+
aabb_array[ix9 + 8] = shapeBoundingBox_centroid.z;
191+
192+
totalWorklist[i] = i;
193+
} // end for (let i = 0; i < totalNumberOfShapes; i++)
194+
195+
196+
for (let i = 0; i < totalNumberOfShapes * 2; i++)
197+
buildnodes[i] = new BVH_Node();
198+
199+
console.log("BvhGeneration...");
200+
console.time("BvhGeneration");
201+
202+
BVH_QuickBuild(totalWorklist, aabb_array);
203+
204+
console.timeEnd("BvhGeneration");
205+
206+
207+
shapeDataTexture = new THREE.DataTexture(shape_array,
208+
2048,
209+
2048,
210+
THREE.RGBAFormat,
211+
THREE.FloatType,
212+
THREE.Texture.DEFAULT_MAPPING,
213+
THREE.ClampToEdgeWrapping,
214+
THREE.ClampToEdgeWrapping,
215+
THREE.NearestFilter,
216+
THREE.NearestFilter,
217+
1,
218+
THREE.NoColorSpace);
219+
220+
shapeDataTexture.flipY = false;
221+
shapeDataTexture.generateMipmaps = false;
222+
shapeDataTexture.needsUpdate = true;
223+
224+
aabbDataTexture = new THREE.DataTexture(aabb_array,
225+
2048,
226+
2048,
227+
THREE.RGBAFormat,
228+
THREE.FloatType,
229+
THREE.Texture.DEFAULT_MAPPING,
230+
THREE.ClampToEdgeWrapping,
231+
THREE.ClampToEdgeWrapping,
232+
THREE.NearestFilter,
233+
THREE.NearestFilter,
234+
1,
235+
THREE.NoColorSpace);
236+
237+
aabbDataTexture.flipY = false;
238+
aabbDataTexture.generateMipmaps = false;
239+
aabbDataTexture.needsUpdate = true;
240+
241+
242+
// In addition to the default GUI on all demos, add any special GUI elements that this particular demo requires
243+
244+
245+
// scene/demo-specific uniforms go here
246+
pathTracingUniforms.tShape_DataTexture = { value: shapeDataTexture };
247+
pathTracingUniforms.tAABB_DataTexture = { value: aabbDataTexture };
248+
249+
250+
} // end function initSceneData()
251+
252+
253+
254+
// called automatically from within the animate() function (located in InitCommon.js file)
255+
function updateVariablesAndUniforms()
256+
{
257+
pathTracingUniforms.uFocusDistance.value = focusDistance;
258+
259+
// INFO
260+
cameraInfoElement.innerHTML = "FOV: " + worldCamera.fov + " / Aperture: " + apertureSize.toFixed(3) + " / FocusDistance: " + focusDistance.toFixed(1) + "<br>" + "Samples: " + sampleCounter;
261+
262+
} // end function updateVariablesAndUniforms()
263+
264+
265+
266+
init(); // init app and start animating

0 commit comments

Comments
 (0)