Created
February 20, 2025 21:22
-
-
Save erichlof/f309a059d79d8e58ad6d6e430948bfe1 to your computer and use it in GitHub Desktop.
shader (glsl) file for experimental sphere BVH (as opposed to typical AABB BVH)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| precision highp float; | |
| precision highp int; | |
| precision highp sampler2D; | |
| #include <pathtracing_uniforms_and_defines> | |
| uniform sampler2D tTriangleTexture; | |
| uniform sampler2D tAABBTexture; | |
| uniform sampler2D tAlbedoTextures[8]; // 8 = max number of diffuse albedo textures per model | |
| //float InvTextureWidth = 0.000244140625; // (1 / 4096 texture width) | |
| //float InvTextureWidth = 0.00048828125; // (1 / 2048 texture width) | |
| //float InvTextureWidth = 0.0009765625; // (1 / 1024 texture width) | |
| #define INV_TEXTURE_WIDTH 0.000244140625 | |
| #define N_SPHERES 3 | |
| #define N_BOXES 2 | |
| //----------------------------------------------------------------------- | |
| vec3 rayOrigin, rayDirection; | |
| // recorded intersection data: | |
| vec3 hitNormal, hitEmission, hitColor; | |
| vec2 hitUV; | |
| float hitObjectID = -INFINITY; | |
| int hitType = -100; | |
| struct Sphere { float radius; vec3 position; vec3 emission; vec3 color; int type; }; | |
| struct Box { vec3 minCorner; vec3 maxCorner; vec3 emission; vec3 color; int type; }; | |
| Sphere spheres[N_SPHERES]; | |
| Box boxes[N_BOXES]; | |
| #include <pathtracing_random_functions> | |
| #include <pathtracing_calc_fresnel_reflectance> | |
| #include <pathtracing_sphere_intersect> | |
| #include <pathtracing_box_intersect> | |
| #include <pathtracing_bvhTriangle_intersect> | |
| #include <pathtracing_sample_sphere_light> | |
| vec2 stackLevels[32]; | |
| void GetSphereNodeData(const in float i, inout vec4 sphereNodeData) | |
| { | |
| // each bounding sphere node's data is encoded in only 1 rgba(or xyzw) texture slot | |
| ivec2 uv = ivec2( mod(i, 4096.0), i * INV_TEXTURE_WIDTH ); | |
| sphereNodeData = texelFetch(tAABBTexture, uv, 0); | |
| } | |
| //-------------------------------------------------------------------------------------------------------------- | |
| float SceneIntersect( out int isRayExiting ) | |
| //-------------------------------------------------------------------------------------------------------------- | |
| { | |
| vec4 currentSphereNodeData, nodeAData, nodeBData, tmpNodeData; | |
| vec4 vd0, vd1, vd2, vd3, vd4, vd5, vd6, vd7; | |
| vec3 normal; | |
| vec3 hitPos; | |
| vec2 currentStackData, stackDataA, stackDataB, tmpStackData; | |
| ivec2 uv0, uv1, uv2, uv3, uv4, uv5, uv6, uv7; | |
| float d; | |
| float t = INFINITY; | |
| float q; | |
| float stackptr = 0.0; | |
| float id = 0.0; | |
| float tu, tv; | |
| float triangleID = 0.0; | |
| float triangleU = 0.0; | |
| float triangleV = 0.0; | |
| float triangleW = 0.0; | |
| int objectCount = 0; | |
| hitObjectID = -INFINITY; | |
| int skip = FALSE; | |
| int triangleLookupNeeded = FALSE; | |
| GetSphereNodeData(stackptr, currentSphereNodeData); | |
| currentStackData = vec2(stackptr, SphereIntersect(fract(abs(currentSphereNodeData.x)) * 1000.0, currentSphereNodeData.yzw, rayOrigin, rayDirection)); | |
| stackLevels[0] = currentStackData; | |
| skip = (currentStackData.y < t) ? TRUE : FALSE; | |
| while (true) | |
| { | |
| if (skip == FALSE) | |
| { | |
| // decrease pointer by 1 (0.0 is root level, 27.0 is maximum depth) | |
| if (--stackptr < 0.0) // went past the root level, terminate loop | |
| break; | |
| currentStackData = stackLevels[int(stackptr)]; | |
| if (currentStackData.y >= t) | |
| continue; | |
| GetSphereNodeData(floor(abs(currentStackData.x)), currentSphereNodeData); | |
| } | |
| skip = FALSE; // reset skip | |
| if (currentSphereNodeData.x < 0.0) // leafOrChild_ID < 0.0 signifies an inner node | |
| { | |
| GetSphereNodeData(floor(abs(currentSphereNodeData.x)), nodeAData); | |
| GetSphereNodeData(floor(abs(currentSphereNodeData.x)) + 1.0, nodeBData); | |
| stackDataA = vec2(currentSphereNodeData.x, SphereIntersect( fract(abs(nodeAData.x)) * 1000.0, nodeAData.yzw, rayOrigin, rayDirection )); | |
| stackDataB = vec2(currentSphereNodeData.x - 1.0, SphereIntersect( fract(abs(nodeBData.x)) * 1000.0, nodeBData.yzw, rayOrigin, rayDirection )); | |
| /* d = SphereIntersect(fract(abs(currentSphereNodeData.x)) * 1000.0, currentSphereNodeData.yzw, rayOrigin, rayDirection); | |
| if (stackptr == 0.0 && d < t) | |
| { | |
| t = d; | |
| hitNormal = (rayOrigin + rayDirection * t) - currentSphereNodeData.yzw; | |
| hitEmission = vec3(0); | |
| hitColor = vec3(1, 0, 1); | |
| hitType = REFR; | |
| hitObjectID = 2.0; | |
| //break; | |
| } */ | |
| /* d = SphereIntersect(fract(abs(nodeAData.x)) * 1000.0, nodeAData.yzw, rayOrigin, rayDirection); | |
| if (stackptr == 1.0 && d < t) | |
| { | |
| t = d; | |
| hitNormal = (rayOrigin + rayDirection * t) - nodeAData.yzw; | |
| hitEmission = vec3(0); | |
| hitColor = vec3(1, 0, 1); | |
| hitType = DIFF; | |
| hitObjectID = 2.0; | |
| //break; | |
| } | |
| d = SphereIntersect(fract(abs(nodeBData.x)) * 1000.0, nodeBData.yzw, rayOrigin, rayDirection); | |
| if (stackptr == 1.0 && d < t) | |
| { | |
| t = d; | |
| hitNormal = (rayOrigin + rayDirection * t) - nodeBData.yzw; | |
| hitEmission = vec3(0); | |
| hitColor = vec3(1, 1, 0); | |
| hitType = DIFF; | |
| hitObjectID = 2.0; | |
| //break; | |
| } */ | |
| // first sort the branch node data so that 'a' is the smallest | |
| if (stackDataB.y < stackDataA.y) | |
| { | |
| tmpStackData = stackDataB; | |
| stackDataB = stackDataA; | |
| stackDataA = tmpStackData; | |
| tmpNodeData = nodeBData; | |
| nodeBData = nodeAData; | |
| nodeAData = tmpNodeData; | |
| } // branch 'b' now has the larger rayT value of 'a' and 'b' | |
| if (stackDataB.y < INFINITY) // see if branch 'b' (the larger rayT) needs to be processed | |
| { | |
| currentStackData = stackDataB; | |
| currentSphereNodeData = nodeBData; | |
| skip = TRUE; // this will prevent the stackptr from decreasing by 1 | |
| } | |
| if (stackDataA.y < INFINITY) // see if branch 'a' (the smaller rayT) needs to be processed | |
| { | |
| if (skip == TRUE) // if larger branch 'b' needed to be processed also, | |
| stackLevels[int(stackptr++)] = stackDataB; // cue larger branch 'b' for future round | |
| // also, increase pointer by 1 | |
| currentStackData = stackDataA; | |
| currentSphereNodeData = nodeAData; | |
| skip = TRUE; // this will prevent the stackptr from decreasing by 1 | |
| } | |
| continue; | |
| } // end if (currentSphereNodeData.x < 0.0) // inner node | |
| // else this is a leaf | |
| // each triangle's data is encoded in 8 rgba(or xyzw) texture slots | |
| id = 8.0 * floor(currentSphereNodeData.x); | |
| uv0 = ivec2( mod(id + 0.0, 4096.0), (id + 0.0) * INV_TEXTURE_WIDTH ); | |
| uv1 = ivec2( mod(id + 1.0, 4096.0), (id + 1.0) * INV_TEXTURE_WIDTH ); | |
| uv2 = ivec2( mod(id + 2.0, 4096.0), (id + 2.0) * INV_TEXTURE_WIDTH ); | |
| vd0 = texelFetch(tTriangleTexture, uv0, 0); | |
| vd1 = texelFetch(tTriangleTexture, uv1, 0); | |
| vd2 = texelFetch(tTriangleTexture, uv2, 0); | |
| d = BVH_TriangleIntersect( vec3(vd0.xyz), vec3(vd0.w, vd1.xy), vec3(vd1.zw, vd2.x), rayOrigin, rayDirection, tu, tv ); | |
| if (d < t) | |
| { | |
| t = d; | |
| triangleID = id; | |
| triangleU = tu; | |
| triangleV = tv; | |
| triangleLookupNeeded = TRUE; | |
| } | |
| } // end while (TRUE) | |
| if (triangleLookupNeeded == TRUE) | |
| { | |
| uv0 = ivec2( mod(triangleID + 0.0, 4096.0), (triangleID + 0.0) * INV_TEXTURE_WIDTH ); | |
| uv1 = ivec2( mod(triangleID + 1.0, 4096.0), (triangleID + 1.0) * INV_TEXTURE_WIDTH ); | |
| uv2 = ivec2( mod(triangleID + 2.0, 4096.0), (triangleID + 2.0) * INV_TEXTURE_WIDTH ); | |
| uv3 = ivec2( mod(triangleID + 3.0, 4096.0), (triangleID + 3.0) * INV_TEXTURE_WIDTH ); | |
| uv4 = ivec2( mod(triangleID + 4.0, 4096.0), (triangleID + 4.0) * INV_TEXTURE_WIDTH ); | |
| uv5 = ivec2( mod(triangleID + 5.0, 4096.0), (triangleID + 5.0) * INV_TEXTURE_WIDTH ); | |
| uv6 = ivec2( mod(triangleID + 6.0, 4096.0), (triangleID + 6.0) * INV_TEXTURE_WIDTH ); | |
| uv7 = ivec2( mod(triangleID + 7.0, 4096.0), (triangleID + 7.0) * INV_TEXTURE_WIDTH ); | |
| vd0 = texelFetch(tTriangleTexture, uv0, 0); | |
| vd1 = texelFetch(tTriangleTexture, uv1, 0); | |
| vd2 = texelFetch(tTriangleTexture, uv2, 0); | |
| vd3 = texelFetch(tTriangleTexture, uv3, 0); | |
| vd4 = texelFetch(tTriangleTexture, uv4, 0); | |
| vd5 = texelFetch(tTriangleTexture, uv5, 0); | |
| vd6 = texelFetch(tTriangleTexture, uv6, 0); | |
| vd7 = texelFetch(tTriangleTexture, uv7, 0); | |
| // face normal for flat-shaded polygon look | |
| //hitNormal = cross(vec3(vd0.w, vd1.xy) - vec3(vd0.xyz), vec3(vd1.zw, vd2.x) - vec3(vd0.xyz)); | |
| // interpolated normal using triangle intersection's uv's | |
| triangleW = 1.0 - triangleU - triangleV; | |
| hitNormal = (triangleW * vec3(vd2.yzw)) + (triangleU * vec3(vd3.xyz)) + (triangleV * vec3(vd3.w, vd4.xy)); | |
| hitEmission = vec3(1, 0, 1); // use this if hitType will be LIGHT | |
| hitColor = vd6.yzw; | |
| hitUV = triangleW * vec2(vd4.zw) + triangleU * vec2(vd5.xy) + triangleV * vec2(vd5.zw); | |
| //hitType = int(vd6.x); | |
| //hitAlbedoTextureID = int(vd7.x); | |
| hitType = COAT; | |
| hitObjectID = float(objectCount); | |
| } | |
| objectCount++; | |
| d = SphereIntersect( spheres[0].radius, spheres[0].position, rayOrigin, rayDirection ); | |
| if (d < t) | |
| { | |
| t = d; | |
| hitNormal = (rayOrigin + rayDirection * t) - spheres[0].position; | |
| hitEmission = spheres[0].emission; | |
| hitColor = spheres[0].color; | |
| hitType = spheres[0].type; | |
| hitObjectID = float(objectCount); | |
| } | |
| objectCount++; | |
| d = SphereIntersect( spheres[1].radius, spheres[1].position, rayOrigin, rayDirection ); | |
| if (d < t) | |
| { | |
| t = d; | |
| hitNormal = (rayOrigin + rayDirection * t) - spheres[1].position; | |
| hitEmission = spheres[1].emission; | |
| hitColor = spheres[1].color; | |
| hitType = spheres[1].type; | |
| hitObjectID = float(objectCount); | |
| } | |
| objectCount++; | |
| d = SphereIntersect( spheres[2].radius, spheres[2].position, rayOrigin, rayDirection ); | |
| if (d < t) | |
| { | |
| t = d; | |
| hitPos = rayOrigin + (rayDirection * t); | |
| hitNormal = hitPos - spheres[2].position; | |
| hitEmission = spheres[2].emission; | |
| q = clamp( mod( dot( floor(hitPos.xz * 0.04), vec2(1.0) ), 2.0 ) , 0.0, 1.0 ); | |
| hitColor = mix(vec3(0.5), spheres[2].color, q); | |
| hitType = spheres[2].type; | |
| hitObjectID = float(objectCount); | |
| } | |
| objectCount++; | |
| d = BoxIntersect( boxes[0].minCorner, boxes[0].maxCorner, rayOrigin, rayDirection, normal, isRayExiting ); | |
| if (d < t) | |
| { | |
| t = d; | |
| hitNormal = normal; | |
| hitEmission = boxes[0].emission; | |
| hitColor = boxes[0].color; | |
| hitType = boxes[0].type; | |
| hitObjectID = float(objectCount); | |
| } | |
| objectCount++; | |
| d = BoxIntersect( boxes[1].minCorner, boxes[1].maxCorner, rayOrigin, rayDirection, normal, isRayExiting ); | |
| if (d < t) | |
| { | |
| t = d; | |
| hitNormal = normal; | |
| hitEmission = boxes[1].emission; | |
| hitColor = boxes[1].color; | |
| hitType = boxes[1].type; | |
| hitObjectID = float(objectCount); | |
| } | |
| return t; | |
| } // end float SceneIntersect( out int isRayExiting ) | |
| //---------------------------------------------------------------------------------------------------------------------------------------------------- | |
| vec3 CalculateRadiance( out vec3 objectNormal, out vec3 objectColor, out float objectID, out float pixelSharpness ) | |
| //---------------------------------------------------------------------------------------------------------------------------------------------------- | |
| { | |
| Sphere light = spheres[1]; | |
| vec3 accumCol = vec3(0); | |
| vec3 mask = vec3(1); | |
| vec3 reflectionMask = vec3(1); | |
| vec3 reflectionRayOrigin = vec3(0); | |
| vec3 reflectionRayDirection = vec3(0); | |
| vec3 dirToLight; | |
| vec3 x, n, nl; | |
| float t; | |
| float nc, nt, ratioIoR, Re, Tr; | |
| float weight; | |
| float thickness = 0.1; | |
| float previousObjectID; | |
| int reflectionBounces = -1; | |
| int diffuseCount = 0; | |
| int previousIntersecType = -100; | |
| hitType = -100; | |
| int bounceIsSpecular = TRUE; | |
| int sampleLight = FALSE; | |
| int isRayExiting = FALSE; | |
| int willNeedReflectionRay = FALSE; | |
| int isReflectionTime = FALSE; | |
| int reflectionNeedsToBeSharp = FALSE; | |
| for (int bounces = 0; bounces < 7; bounces++) | |
| { | |
| if (isReflectionTime == TRUE) | |
| reflectionBounces++; | |
| previousIntersecType = hitType; | |
| previousObjectID = hitObjectID; | |
| t = SceneIntersect(isRayExiting); | |
| // shouldn't happen because we are inside a huge sphere, but just in case | |
| if (t == INFINITY) | |
| { | |
| break; | |
| } | |
| // large sphere light surrounding the scene | |
| if (hitType == LIGHT) | |
| { | |
| // this makes the object edges sharp against the background | |
| if (bounces == 0 || (bounces == 1 && previousIntersecType == SPEC)) | |
| pixelSharpness = 1.01; | |
| accumCol += mask * hitEmission; | |
| if (willNeedReflectionRay == TRUE) | |
| { | |
| mask = reflectionMask; | |
| rayOrigin = reflectionRayOrigin; | |
| rayDirection = reflectionRayDirection; | |
| diffuseCount = 0; | |
| willNeedReflectionRay = FALSE; | |
| bounceIsSpecular = TRUE; | |
| sampleLight = FALSE; | |
| isReflectionTime = TRUE; | |
| continue; | |
| } | |
| // reached a light, so we can exit | |
| break; | |
| } | |
| // useful data | |
| n = normalize(hitNormal); | |
| nl = dot(n, rayDirection) < 0.0 ? n : -n; | |
| x = rayOrigin + rayDirection * t; | |
| if (bounces == 0) | |
| { | |
| objectID = hitObjectID; | |
| } | |
| if (isReflectionTime == FALSE && diffuseCount == 0 && hitObjectID != previousObjectID) | |
| { | |
| objectNormal = nl; | |
| objectColor = hitColor; | |
| } | |
| if (reflectionNeedsToBeSharp == TRUE && reflectionBounces == 0) | |
| { | |
| objectNormal = nl; | |
| objectColor = hitColor; | |
| } | |
| if (hitType == POINT_LIGHT) | |
| { | |
| if (diffuseCount == 0 && isReflectionTime == FALSE) | |
| pixelSharpness = 1.0; | |
| if (isReflectionTime == TRUE && bounceIsSpecular == TRUE) | |
| { | |
| objectNormal = nl; | |
| //objectColor = hitColor; | |
| objectID = hitObjectID; | |
| } | |
| if (bounceIsSpecular == TRUE) | |
| { | |
| if (bounces == 0) // looking directly at light | |
| accumCol += mask * clamp(hitEmission, 0.0, 5.0); | |
| else //if (bounces < 3) // bounce reflection or refraction | |
| accumCol += mask * clamp(hitEmission, 0.0, 100.0); | |
| } | |
| if (sampleLight == TRUE) | |
| accumCol += mask * hitEmission; | |
| if (willNeedReflectionRay == TRUE) | |
| { | |
| mask = reflectionMask; | |
| rayOrigin = reflectionRayOrigin; | |
| rayDirection = reflectionRayDirection; | |
| diffuseCount = 0; | |
| willNeedReflectionRay = FALSE; | |
| bounceIsSpecular = TRUE; | |
| sampleLight = FALSE; | |
| isReflectionTime = TRUE; | |
| continue; | |
| } | |
| // reached a light, so we can exit | |
| break; | |
| } | |
| // if we get here and sampleLight is still TRUE, shadow ray failed to find the light source | |
| // the ray hit an occluding object along its way to the light | |
| if (sampleLight == TRUE) | |
| { | |
| if (willNeedReflectionRay == TRUE) | |
| { | |
| mask = reflectionMask; | |
| rayOrigin = reflectionRayOrigin; | |
| rayDirection = reflectionRayDirection; | |
| diffuseCount = 0; | |
| willNeedReflectionRay = FALSE; | |
| bounceIsSpecular = TRUE; | |
| sampleLight = FALSE; | |
| isReflectionTime = TRUE; | |
| continue; | |
| } | |
| break; | |
| } | |
| if (hitType == DIFF) // Ideal DIFFUSE reflection | |
| { | |
| diffuseCount++; | |
| mask *= hitColor; | |
| bounceIsSpecular = FALSE; | |
| if (diffuseCount == 1 && rand() < 0.5) | |
| { | |
| mask *= 2.0; | |
| // choose random Diffuse sample vector | |
| rayDirection = randomCosWeightedDirectionInHemisphere(nl); | |
| rayOrigin = x + nl * uEPS_intersect; | |
| continue; | |
| } | |
| dirToLight = sampleSphereLight(x, nl, light, weight); | |
| mask *= diffuseCount == 1 ? 2.0 : 1.0; | |
| mask *= weight; | |
| rayDirection = dirToLight; | |
| rayOrigin = x + nl * uEPS_intersect; | |
| sampleLight = TRUE; | |
| continue; | |
| } // end if (hitType == DIFF) | |
| if (hitType == SPEC) // Ideal SPECULAR reflection | |
| { | |
| mask *= hitColor; | |
| rayDirection = reflect(rayDirection, nl); | |
| rayOrigin = x + nl * uEPS_intersect; | |
| //bounceIsSpecular = TRUE; // turn on mirror caustics | |
| continue; | |
| } | |
| if (hitType == REFR) // Ideal dielectric REFRACTION | |
| { | |
| nc = 1.0; // IOR of Air | |
| nt = 1.5; // IOR of common Glass | |
| Re = calcFresnelReflectance(rayDirection, n, nc, nt, ratioIoR); | |
| Tr = 1.0 - Re; | |
| if (Re == 1.0) | |
| { | |
| rayDirection = reflect(rayDirection, nl); | |
| rayOrigin = x + nl * uEPS_intersect; | |
| continue; | |
| } | |
| if (diffuseCount == 0 && hitObjectID != previousObjectID && n == nl) | |
| { | |
| reflectionMask = mask * Re; | |
| reflectionRayDirection = reflect(rayDirection, nl); // reflect ray from surface | |
| reflectionRayOrigin = x + nl * uEPS_intersect; | |
| willNeedReflectionRay = TRUE; | |
| if (bounces == 0 && hitColor == vec3(0.2,0.9,0.7) && isRayExiting == FALSE) | |
| reflectionNeedsToBeSharp = TRUE; | |
| } | |
| // transmit ray through surface | |
| // is ray leaving a solid object from the inside? | |
| // If so, attenuate ray color with object color by how far ray has travelled through the medium | |
| if (isRayExiting == TRUE) | |
| { | |
| mask *= exp(log(hitColor) * thickness * t); | |
| } | |
| mask *= Tr; | |
| rayDirection = refract(rayDirection, nl, ratioIoR); | |
| rayOrigin = x - nl * uEPS_intersect; | |
| if (bounces == 1) | |
| bounceIsSpecular = TRUE; // turn on refracting caustics | |
| continue; | |
| } // end if (hitType == REFR) | |
| if (hitType == COAT) // Diffuse object underneath with ClearCoat on top | |
| { | |
| nc = 1.0; // IOR of Air | |
| nt = 1.5; // IOR of Clear Coat | |
| Re = calcFresnelReflectance(rayDirection, nl, nc, nt, ratioIoR); | |
| Tr = 1.0 - Re; | |
| if (diffuseCount == 0 && hitObjectID != previousObjectID) | |
| { | |
| reflectionMask = mask * Re; | |
| reflectionRayDirection = reflect(rayDirection, nl); // reflect ray from surface | |
| reflectionRayOrigin = x + nl * uEPS_intersect; | |
| willNeedReflectionRay = TRUE; | |
| } | |
| diffuseCount++; | |
| mask *= Tr; | |
| mask *= hitColor; | |
| bounceIsSpecular = FALSE; | |
| if (diffuseCount == 1 && rand() < 0.5) | |
| { | |
| mask *= 2.0; | |
| // choose random Diffuse sample vector | |
| rayDirection = randomCosWeightedDirectionInHemisphere(nl); | |
| rayOrigin = x + nl * uEPS_intersect; | |
| continue; | |
| } | |
| dirToLight = sampleSphereLight(x, nl, light, weight); | |
| mask *= diffuseCount == 1 ? 2.0 : 1.0; | |
| mask *= weight; | |
| rayDirection = dirToLight; | |
| rayOrigin = x + nl * uEPS_intersect; | |
| sampleLight = TRUE; | |
| continue; | |
| } //end if (hitType == COAT) | |
| } // end for (int bounces = 0; bounces < 7; bounces++) | |
| return max(vec3(0), accumCol); | |
| } // end vec3 CalculateRadiance( out vec3 objectNormal, out vec3 objectColor, out float objectID, out float pixelSharpness ) | |
| //----------------------------------------------------------------------- | |
| void SetupScene(void) | |
| //----------------------------------------------------------------------- | |
| { | |
| vec3 z = vec3(0); | |
| vec3 L1 = vec3(0.5, 0.7, 1.0) * 1.0;//0.01;// Blueish sky light | |
| vec3 L2 = vec3(1.0, 0.9, 0.8) * 1000.0;// Bright white light bulb | |
| spheres[0] = Sphere( 10000.0, vec3(0, 0, 0), L1, z, LIGHT);//large spherical sky light | |
| spheres[1] = Sphere( 0.5, vec3(-10, 35, -10), L2, z, POINT_LIGHT);//small spherical point light | |
| spheres[2] = Sphere( 4000.0, vec3(0, -4000, 0), z, vec3(1.0, 1.0, 1.0), DIFF);//Checkered Floor | |
| boxes[0] = Box( vec3(-20.0, 11.0, -110.0), vec3(70.0, 18.0, -20.0), z, vec3(0.2, 0.9, 0.7), REFR);//Glass Box | |
| boxes[1] = Box( vec3(-14.0, 13.0, -104.0), vec3(64.0, 16.0, -26.0), z, vec3(0, 0, 0), DIFF);//Inner Box | |
| } | |
| #include <pathtracing_main> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment