From 35b4fa8c516d1ac0e91a1079b2eaca87ff85d774 Mon Sep 17 00:00:00 2001 From: Francisco Avila Date: Mon, 3 Feb 2020 10:03:06 -0800 Subject: [PATCH] Release 0.6.2 --- build/RayTracingRenderer.es5.js | 10 +++++++--- build/RayTracingRenderer.js | 25 +++++++++++++++++++------ package-lock.json | 2 +- package.json | 2 +- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/build/RayTracingRenderer.es5.js b/build/RayTracingRenderer.es5.js index 219f5c3..ac4c12a 100644 --- a/build/RayTracingRenderer.es5.js +++ b/build/RayTracingRenderer.es5.js @@ -815,7 +815,7 @@ var fragment = { outputs: ['position', 'normal', 'faceNormal', 'color', 'matProps'], includes: [constants$1, materialBuffer], - source: "\n in vec3 vPosition;\n in vec3 vNormal;\n in vec2 vUv;\n flat in ivec2 vMaterialMeshIndex;\n\n vec3 faceNormals(vec3 pos) {\n vec3 fdx = dFdx(pos);\n vec3 fdy = dFdy(pos);\n return cross(fdx, fdy);\n }\n\n void main() {\n int materialIndex = vMaterialMeshIndex.x;\n int meshIndex = vMaterialMeshIndex.y;\n\n vec2 uv = fract(vUv);\n\n vec3 color = getMatColor(materialIndex, uv);\n float roughness = getMatRoughness(materialIndex, uv);\n float metalness = getMatMetalness(materialIndex, uv);\n float materialType = getMatType(materialIndex);\n\n roughness = clamp(roughness, ROUGHNESS_MIN, 1.0);\n metalness = clamp(metalness, 0.0, 1.0);\n\n vec3 normal = vNormal;\n vec3 faceNormal = faceNormals(vPosition);\n normal *= sign(dot(normal, faceNormal));\n\n #ifdef NUM_NORMAL_MAPS\n vec3 dp1 = dFdx(vPosition);\n vec3 dp2 = dFdy(vPosition);\n vec2 duv1 = dFdx(vUv);\n vec2 duv2 = dFdy(vUv);\n normal = getMatNormal(materialIndex, uv, normal, dp1, dp2, duv1, duv2);\n #endif\n\n out_position = vec4(vPosition, float(meshIndex) + EPS);\n out_normal = vec4(normal, materialType);\n out_faceNormal = vec4(faceNormal, 0);\n out_color = vec4(color, 0);\n out_matProps = vec4(roughness, metalness, 0, 0);\n }\n" + source: "\n in vec3 vPosition;\n in vec3 vNormal;\n in vec2 vUv;\n flat in ivec2 vMaterialMeshIndex;\n\n vec3 faceNormals(vec3 pos) {\n vec3 fdx = dFdx(pos);\n vec3 fdy = dFdy(pos);\n return cross(fdx, fdy);\n }\n\n void main() {\n int materialIndex = vMaterialMeshIndex.x;\n int meshIndex = vMaterialMeshIndex.y;\n\n vec2 uv = fract(vUv);\n\n vec3 color = getMatColor(materialIndex, uv);\n float roughness = getMatRoughness(materialIndex, uv);\n float metalness = getMatMetalness(materialIndex, uv);\n float materialType = getMatType(materialIndex);\n\n roughness = clamp(roughness, ROUGHNESS_MIN, 1.0);\n metalness = clamp(metalness, 0.0, 1.0);\n\n vec3 normal = normalize(vNormal);\n vec3 faceNormal = normalize(faceNormals(vPosition));\n normal *= sign(dot(normal, faceNormal));\n\n #ifdef NUM_NORMAL_MAPS\n vec3 dp1 = dFdx(vPosition);\n vec3 dp2 = dFdy(vPosition);\n vec2 duv1 = dFdx(vUv);\n vec2 duv2 = dFdy(vUv);\n normal = getMatNormal(materialIndex, uv, normal, dp1, dp2, duv1, duv2);\n #endif\n\n out_position = vec4(vPosition, float(meshIndex) + EPS);\n out_normal = vec4(normal, materialType);\n out_faceNormal = vec4(faceNormal, 0);\n out_color = vec4(color, 0);\n out_matProps = vec4(roughness, metalness, 0, 0);\n }\n" }; function makeGBufferPass(gl, _ref) { @@ -886,6 +886,10 @@ } function setAttribute(gl, location, bufferAttribute) { + if (location === undefined) { + return; + } + var itemSize = bufferAttribute.itemSize, array = bufferAttribute.array; gl.enableVertexAttribArray(location); @@ -2374,7 +2378,7 @@ var intersect = "\n\nuniform sampler2D positions;\nuniform sampler2D normals;\nuniform sampler2D uvs;\nuniform sampler2D bvh;\n\nstruct Triangle {\n vec3 p0;\n vec3 p1;\n vec3 p2;\n};\n\nvoid surfaceInteractionFromBVH(inout SurfaceInteraction si, Triangle tri, vec3 barycentric, ivec3 index, vec3 faceNormal, int materialIndex) {\n si.hit = true;\n si.faceNormal = faceNormal;\n si.position = barycentric.x * tri.p0 + barycentric.y * tri.p1 + barycentric.z * tri.p2;\n ivec2 i0 = unpackTexel(index.x, VERTEX_COLUMNS);\n ivec2 i1 = unpackTexel(index.y, VERTEX_COLUMNS);\n ivec2 i2 = unpackTexel(index.z, VERTEX_COLUMNS);\n\n vec3 n0 = texelFetch(normals, i0, 0).xyz;\n vec3 n1 = texelFetch(normals, i1, 0).xyz;\n vec3 n2 = texelFetch(normals, i2, 0).xyz;\n vec3 normal = normalize(barycentric.x * n0 + barycentric.y * n1 + barycentric.z * n2);\n\n #if defined(NUM_DIFFUSE_MAPS) || defined(NUM_NORMAL_MAPS) || defined(NUM_PBR_MAPS)\n vec2 uv0 = texelFetch(uvs, i0, 0).xy;\n vec2 uv1 = texelFetch(uvs, i1, 0).xy;\n vec2 uv2 = texelFetch(uvs, i2, 0).xy;\n vec2 uv = fract(barycentric.x * uv0 + barycentric.y * uv1 + barycentric.z * uv2);\n #else\n vec2 uv = vec2(0.0);\n #endif\n\n si.materialType = int(getMatType(materialIndex));\n si.color = getMatColor(materialIndex, uv);\n si.roughness = getMatRoughness(materialIndex, uv);\n si.metalness = getMatMetalness(materialIndex, uv);\n\n #ifdef NUM_NORMAL_MAPS\n vec3 dp1 = tri.p0 - tri.p2;\n vec3 dp2 = tri.p1 - tri.p2;\n vec2 duv1 = uv0 - uv2;\n vec2 duv2 = uv1 - uv2;\n si.normal = getMatNormal(materialIndex, uv, normal, dp1, dp2, duv1, duv2);\n #else\n si.normal = normal;\n #endif\n}\n\nstruct TriangleIntersect {\n float t;\n vec3 barycentric;\n};\n\n// Triangle-ray intersection\n// Faster than the classic M\xF6ller\u2013Trumbore intersection algorithm\n// http://www.pbr-book.org/3ed-2018/Shapes/Triangle_Meshes.html#TriangleIntersection\nTriangleIntersect intersectTriangle(Ray r, Triangle tri, int maxDim, vec3 shear) {\n TriangleIntersect ti;\n vec3 d = r.d;\n\n // translate vertices based on ray origin\n vec3 p0t = tri.p0 - r.o;\n vec3 p1t = tri.p1 - r.o;\n vec3 p2t = tri.p2 - r.o;\n\n // permute components of triangle vertices\n if (maxDim == 0) {\n p0t = p0t.yzx;\n p1t = p1t.yzx;\n p2t = p2t.yzx;\n } else if (maxDim == 1) {\n p0t = p0t.zxy;\n p1t = p1t.zxy;\n p2t = p2t.zxy;\n }\n\n // apply shear transformation to translated vertex positions\n p0t.xy += shear.xy * p0t.z;\n p1t.xy += shear.xy * p1t.z;\n p2t.xy += shear.xy * p2t.z;\n\n // compute edge function coefficients\n vec3 e = vec3(\n p1t.x * p2t.y - p1t.y * p2t.x,\n p2t.x * p0t.y - p2t.y * p0t.x,\n p0t.x * p1t.y - p0t.y * p1t.x\n );\n\n // check if intersection is inside triangle\n if (any(lessThan(e, vec3(0))) && any(greaterThan(e, vec3(0)))) {\n return ti;\n }\n\n float det = e.x + e.y + e.z;\n\n // not needed?\n // if (det == 0.) {\n // return ti;\n // }\n\n p0t.z *= shear.z;\n p1t.z *= shear.z;\n p2t.z *= shear.z;\n float tScaled = (e.x * p0t.z + e.y * p1t.z + e.z * p2t.z);\n\n // not needed?\n // if (sign(det) != sign(tScaled)) {\n // return ti;\n // }\n\n // check if closer intersection already exists\n if (abs(tScaled) > abs(r.tMax * det)) {\n return ti;\n }\n\n float invDet = 1. / det;\n ti.t = tScaled * invDet;\n ti.barycentric = e * invDet;\n\n return ti;\n}\n\nstruct Box {\n vec3 min;\n vec3 max;\n};\n\n// Branchless ray/box intersection\n// https://tavianator.com/fast-branchless-raybounding-box-intersections/\nfloat intersectBox(Ray r, Box b) {\n vec3 tBot = (b.min - r.o) * r.invD;\n vec3 tTop = (b.max - r.o) * r.invD;\n vec3 tNear = min(tBot, tTop);\n vec3 tFar = max(tBot, tTop);\n float t0 = max(tNear.x, max(tNear.y, tNear.z));\n float t1 = min(tFar.x, min(tFar.y, tFar.z));\n\n return (t0 > t1 || t0 > r.tMax) ? -1.0 : (t0 > 0.0 ? t0 : t1);\n}\n\nint maxDimension(vec3 v) {\n return v.x > v.y ? (v.x > v.z ? 0 : 2) : (v.y > v.z ? 1 : 2);\n}\n\n// Traverse BVH, find closest triangle intersection, and return surface information\nvoid intersectScene(inout Ray ray, inout SurfaceInteraction si) {\n si.hit = false;\n\n int maxDim = maxDimension(abs(ray.d));\n\n // Permute space so that the z dimension is the one where the absolute value of the ray's direction is largest.\n // Then create a shear transformation that aligns ray direction with the +z axis\n vec3 shear;\n if (maxDim == 0) {\n shear = vec3(-ray.d.y, -ray.d.z, 1.0) * ray.invD.x;\n } else if (maxDim == 1) {\n shear = vec3(-ray.d.z, -ray.d.x, 1.0) * ray.invD.y;\n } else {\n shear = vec3(-ray.d.x, -ray.d.y, 1.0) * ray.invD.z;\n }\n\n int nodesToVisit[STACK_SIZE];\n int stack = 0;\n\n nodesToVisit[0] = 0;\n\n while(stack >= 0) {\n int i = nodesToVisit[stack--];\n\n vec4 r1 = fetchData(bvh, i, BVH_COLUMNS);\n vec4 r2 = fetchData(bvh, i + 1, BVH_COLUMNS);\n\n int splitAxisOrNumPrimitives = floatBitsToInt(r1.w);\n\n if (splitAxisOrNumPrimitives >= 0) {\n // Intersection is a bounding box. Test for box intersection and keep traversing BVH\n int splitAxis = splitAxisOrNumPrimitives;\n\n Box bbox = Box(r1.xyz, r2.xyz);\n\n if (intersectBox(ray, bbox) > 0.0) {\n // traverse near node to ray first, and far node to ray last\n if (ray.d[splitAxis] > 0.0) {\n nodesToVisit[++stack] = floatBitsToInt(r2.w);\n nodesToVisit[++stack] = i + 2;\n } else {\n nodesToVisit[++stack] = i + 2;\n nodesToVisit[++stack] = floatBitsToInt(r2.w);\n }\n }\n } else {\n ivec3 index = floatBitsToInt(r1.xyz);\n Triangle tri = Triangle(\n fetchData(positions, index.x, VERTEX_COLUMNS).xyz,\n fetchData(positions, index.y, VERTEX_COLUMNS).xyz,\n fetchData(positions, index.z, VERTEX_COLUMNS).xyz\n );\n TriangleIntersect hit = intersectTriangle(ray, tri, maxDim, shear);\n\n if (hit.t > 0.0) {\n ray.tMax = hit.t;\n int materialIndex = floatBitsToInt(r2.w);\n vec3 faceNormal = r2.xyz;\n surfaceInteractionFromBVH(si, tri, hit.barycentric, index, faceNormal, materialIndex);\n }\n }\n }\n\n // Values must be clamped outside of intersection loop. Clamping inside the loop produces incorrect numbers on some devices.\n si.roughness = clamp(si.roughness, ROUGHNESS_MIN, 1.0);\n si.metalness = clamp(si.metalness, 0.0, 1.0);\n}\n\nbool intersectSceneShadow(inout Ray ray) {\n int maxDim = maxDimension(abs(ray.d));\n\n // Permute space so that the z dimension is the one where the absolute value of the ray's direction is largest.\n // Then create a shear transformation that aligns ray direction with the +z axis\n vec3 shear;\n if (maxDim == 0) {\n shear = vec3(-ray.d.y, -ray.d.z, 1.0) * ray.invD.x;\n } else if (maxDim == 1) {\n shear = vec3(-ray.d.z, -ray.d.x, 1.0) * ray.invD.y;\n } else {\n shear = vec3(-ray.d.x, -ray.d.y, 1.0) * ray.invD.z;\n }\n\n int nodesToVisit[STACK_SIZE];\n int stack = 0;\n\n nodesToVisit[0] = 0;\n\n while(stack >= 0) {\n int i = nodesToVisit[stack--];\n\n vec4 r1 = fetchData(bvh, i, BVH_COLUMNS);\n vec4 r2 = fetchData(bvh, i + 1, BVH_COLUMNS);\n\n int splitAxisOrNumPrimitives = floatBitsToInt(r1.w);\n\n if (splitAxisOrNumPrimitives >= 0) {\n int splitAxis = splitAxisOrNumPrimitives;\n\n Box bbox = Box(r1.xyz, r2.xyz);\n\n if (intersectBox(ray, bbox) > 0.0) {\n if (ray.d[splitAxis] > 0.0) {\n nodesToVisit[++stack] = floatBitsToInt(r2.w);\n nodesToVisit[++stack] = i + 2;\n } else {\n nodesToVisit[++stack] = i + 2;\n nodesToVisit[++stack] = floatBitsToInt(r2.w);\n }\n }\n } else {\n ivec3 index = floatBitsToInt(r1.xyz);\n Triangle tri = Triangle(\n fetchData(positions, index.x, VERTEX_COLUMNS).xyz,\n fetchData(positions, index.y, VERTEX_COLUMNS).xyz,\n fetchData(positions, index.z, VERTEX_COLUMNS).xyz\n );\n\n if (intersectTriangle(ray, tri, maxDim, shear).t > 0.0) {\n return true;\n }\n }\n }\n\n return false;\n}\n\n"; - var surfaceInteractionDirect = "\n\n uniform sampler2D gPosition;\n uniform sampler2D gNormal;\n uniform sampler2D gFaceNormal;\n uniform sampler2D gColor;\n uniform sampler2D gMatProps;\n\n void surfaceInteractionDirect(vec2 coord, inout SurfaceInteraction si) {\n si.position = texture(gPosition, coord).xyz;\n\n vec4 normalMaterialType = texture(gNormal, coord);\n\n si.normal = normalize(normalMaterialType.xyz);\n si.materialType = int(normalMaterialType.w);\n\n si.faceNormal = normalize(texture(gFaceNormal, coord).xyz);\n\n si.color = texture(gColor, coord).rgb;\n\n vec4 matProps = texture(gMatProps, coord);\n si.roughness = matProps.x;\n si.metalness = matProps.y;\n\n si.hit = dot(si.normal, si.normal) > 0.0 ? true : false;\n }\n"; + var surfaceInteractionDirect = "\n\n uniform sampler2D gPosition;\n uniform sampler2D gNormal;\n uniform sampler2D gFaceNormal;\n uniform sampler2D gColor;\n uniform sampler2D gMatProps;\n\n void surfaceInteractionDirect(vec2 coord, inout SurfaceInteraction si) {\n vec4 positionAndMeshIndex = texture(gPosition, coord);\n\n si.position = positionAndMeshIndex.xyz;\n\n float meshIndex = positionAndMeshIndex.w;\n\n vec4 normalMaterialType = texture(gNormal, coord);\n\n si.normal = normalize(normalMaterialType.xyz);\n si.materialType = int(normalMaterialType.w);\n\n si.faceNormal = normalize(texture(gFaceNormal, coord).xyz);\n\n si.color = texture(gColor, coord).rgb;\n\n vec4 matProps = texture(gMatProps, coord);\n si.roughness = matProps.x;\n si.metalness = matProps.y;\n\n si.hit = meshIndex > 0.0 ? true : false;\n }\n"; var random = "\n\n// Noise texture used to generate a different random number for each pixel.\n// We use blue noise in particular, but any type of noise will work.\nuniform sampler2D noise;\n\nuniform float stratifiedSamples[SAMPLING_DIMENSIONS];\nuniform float strataSize;\n\n// Every time we call randomSample() in the shader, and for every call to render,\n// we want that specific bit of the shader to fetch a sample from the same position in stratifiedSamples\n// This allows us to use stratified sampling for each random variable in our path tracing\nint sampleIndex = 0;\n\nfloat pixelSeed;\n\nvoid initRandom() {\n vec2 noiseSize = vec2(textureSize(noise, 0));\n\n // tile the small noise texture across the entire screen\n pixelSeed = texture(noise, vCoord / (pixelSize * noiseSize)).r;\n}\n\nfloat randomSample() {\n float stratifiedSample = stratifiedSamples[sampleIndex++];\n\n float random = fract((stratifiedSample + pixelSeed) * strataSize); // blue noise + stratified samples\n\n // transform random number between [0, 1] to (0, 1)\n return EPS + (1.0 - 2.0 * EPS) * random;\n}\n\nvec2 randomSampleVec2() {\n return vec2(randomSample(), randomSample());\n}\n"; @@ -2826,7 +2830,7 @@ var fragment$3 = { includes: [textureLinear], outputs: ['color'], - source: "\n in vec2 vCoord;\n\n uniform sampler2D light;\n uniform sampler2D position;\n\n uniform vec2 lightScale;\n\n // Tonemapping functions from THREE.js\n\n vec3 linear(vec3 color) {\n return color;\n }\n // https://www.cs.utah.edu/~reinhard/cdrom/\n vec3 reinhard(vec3 color) {\n return clamp(color / (vec3(1.0) + color), vec3(0.0), vec3(1.0));\n }\n // http://filmicworlds.com/blog/filmic-tonemapping-operators/\n #define uncharted2Helper(x) max(((x * (0.15 * x + 0.10 * 0.50) + 0.20 * 0.02) / (x * (0.15 * x + 0.50) + 0.20 * 0.30)) - 0.02 / 0.30, vec3(0.0))\n const vec3 uncharted2WhitePoint = 1.0 / uncharted2Helper(vec3(WHITE_POINT));\n vec3 uncharted2( vec3 color ) {\n // John Hable's filmic operator from Uncharted 2 video game\n return clamp(uncharted2Helper(color) * uncharted2WhitePoint, vec3(0.0), vec3(1.0));\n }\n // http://filmicworlds.com/blog/filmic-tonemapping-operators/\n vec3 cineon( vec3 color ) {\n // optimized filmic operator by Jim Hejl and Richard Burgess-Dawson\n color = max(vec3( 0.0 ), color - 0.004);\n return pow((color * (6.2 * color + 0.5)) / (color * (6.2 * color + 1.7) + 0.06), vec3(2.2));\n }\n // https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/\n vec3 acesFilmic( vec3 color ) {\n return clamp((color * (2.51 * color + 0.03)) / (color * (2.43 * color + 0.59) + 0.14), vec3(0.0), vec3(1.0));\n }\n\n #ifdef EDGE_PRESERVING_UPSCALE\n vec4 getUpscaledLight(vec2 coord) {\n float meshId = texture(position, coord).w;\n\n vec2 sizef = lightScale * vec2(textureSize(position, 0));\n vec2 texelf = coord * sizef - 0.5;\n ivec2 texel = ivec2(texelf);\n vec2 f = fract(texelf);\n\n ivec2 texels[] = ivec2[](\n texel + ivec2(0, 0),\n texel + ivec2(1, 0),\n texel + ivec2(0, 1),\n texel + ivec2(1, 1)\n );\n\n float weights[] = float[](\n (1.0 - f.x) * (1.0 - f.y),\n f.x * (1.0 - f.y),\n (1.0 - f.x) * f.y,\n f.x * f.y\n );\n\n vec4 upscaledLight;\n float sum;\n for (int i = 0; i < 4; i++) {\n vec2 pCoord = (vec2(texels[i]) + 0.5) / sizef;\n float isValid = texture(position, pCoord).w == meshId ? 1.0 : 0.0;\n float weight = isValid * weights[i];\n upscaledLight += weight * texelFetch(light, texels[i], 0);\n sum += weight;\n }\n\n if (sum > 0.0) {\n upscaledLight /= sum;\n } else {\n upscaledLight = texture(light, lightScale * coord);\n }\n\n return upscaledLight;\n }\n #endif\n\n void main() {\n #ifdef EDGE_PRESERVING_UPSCALE\n vec4 upscaledLight = getUpscaledLight(vCoord);\n #else\n vec4 upscaledLight = texture(light, lightScale * vCoord);\n #endif\n\n // alpha channel stores the number of samples progressively rendered\n // divide the sum of light by alpha to obtain average contribution of light\n\n // in addition, alpha contains a scale factor for the shadow catcher material\n // dividing by alpha normalizes the brightness of the shadow catcher to match the background envmap.\n vec3 light = upscaledLight.rgb / upscaledLight.a;\n\n light *= EXPOSURE;\n\n light = TONE_MAPPING(light);\n\n light = pow(light, vec3(1.0 / 2.2)); // gamma correction\n\n out_color = vec4(light, 1.0);\n }\n" + source: "\n in vec2 vCoord;\n\n uniform sampler2D light;\n uniform sampler2D position;\n\n uniform vec2 lightScale;\n\n // Tonemapping functions from THREE.js\n\n vec3 linear(vec3 color) {\n return color;\n }\n // https://www.cs.utah.edu/~reinhard/cdrom/\n vec3 reinhard(vec3 color) {\n return clamp(color / (vec3(1.0) + color), vec3(0.0), vec3(1.0));\n }\n // http://filmicworlds.com/blog/filmic-tonemapping-operators/\n #define uncharted2Helper(x) max(((x * (0.15 * x + 0.10 * 0.50) + 0.20 * 0.02) / (x * (0.15 * x + 0.50) + 0.20 * 0.30)) - 0.02 / 0.30, vec3(0.0))\n const vec3 uncharted2WhitePoint = 1.0 / uncharted2Helper(vec3(WHITE_POINT));\n vec3 uncharted2( vec3 color ) {\n // John Hable's filmic operator from Uncharted 2 video game\n return clamp(uncharted2Helper(color) * uncharted2WhitePoint, vec3(0.0), vec3(1.0));\n }\n // http://filmicworlds.com/blog/filmic-tonemapping-operators/\n vec3 cineon( vec3 color ) {\n // optimized filmic operator by Jim Hejl and Richard Burgess-Dawson\n color = max(vec3( 0.0 ), color - 0.004);\n return pow((color * (6.2 * color + 0.5)) / (color * (6.2 * color + 1.7) + 0.06), vec3(2.2));\n }\n // https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/\n vec3 acesFilmic( vec3 color ) {\n return clamp((color * (2.51 * color + 0.03)) / (color * (2.43 * color + 0.59) + 0.14), vec3(0.0), vec3(1.0));\n }\n\n #ifdef EDGE_PRESERVING_UPSCALE\n\n float getMeshId(sampler2D meshIdTex, vec2 vCoord) {\n return floor(texture(meshIdTex, vCoord).w);\n }\n\n vec4 getUpscaledLight(vec2 coord) {\n float meshId = getMeshId(position, coord);\n\n vec2 sizef = lightScale * vec2(textureSize(position, 0));\n vec2 texelf = coord * sizef - 0.5;\n ivec2 texel = ivec2(texelf);\n vec2 f = fract(texelf);\n\n ivec2 texels[] = ivec2[](\n texel + ivec2(0, 0),\n texel + ivec2(1, 0),\n texel + ivec2(0, 1),\n texel + ivec2(1, 1)\n );\n\n float weights[] = float[](\n (1.0 - f.x) * (1.0 - f.y),\n f.x * (1.0 - f.y),\n (1.0 - f.x) * f.y,\n f.x * f.y\n );\n\n vec4 upscaledLight;\n float sum;\n for (int i = 0; i < 4; i++) {\n vec2 pCoord = (vec2(texels[i]) + 0.5) / sizef;\n float isValid = getMeshId(position, pCoord) == meshId ? 1.0 : 0.0;\n float weight = isValid * weights[i];\n upscaledLight += weight * texelFetch(light, texels[i], 0);\n sum += weight;\n }\n\n if (sum > 0.0) {\n upscaledLight /= sum;\n } else {\n upscaledLight = texture(light, lightScale * coord);\n }\n\n return upscaledLight;\n }\n #endif\n\n void main() {\n #ifdef EDGE_PRESERVING_UPSCALE\n vec4 upscaledLight = getUpscaledLight(vCoord);\n #else\n vec4 upscaledLight = texture(light, lightScale * vCoord);\n #endif\n\n // alpha channel stores the number of samples progressively rendered\n // divide the sum of light by alpha to obtain average contribution of light\n\n // in addition, alpha contains a scale factor for the shadow catcher material\n // dividing by alpha normalizes the brightness of the shadow catcher to match the background envmap.\n vec3 light = upscaledLight.rgb / upscaledLight.a;\n\n light *= EXPOSURE;\n\n light = TONE_MAPPING(light);\n\n light = pow(light, vec3(1.0 / 2.2)); // gamma correction\n\n out_color = vec4(light, 1.0);\n }\n" }; var _toneMapFunctions; diff --git a/build/RayTracingRenderer.js b/build/RayTracingRenderer.js index beecb5f..3d476dc 100644 --- a/build/RayTracingRenderer.js +++ b/build/RayTracingRenderer.js @@ -713,8 +713,8 @@ vec3 getMatNormal(int materialIndex, vec2 uv, vec3 normal, vec3 dp1, vec3 dp2, v roughness = clamp(roughness, ROUGHNESS_MIN, 1.0); metalness = clamp(metalness, 0.0, 1.0); - vec3 normal = vNormal; - vec3 faceNormal = faceNormals(vPosition); + vec3 normal = normalize(vNormal); + vec3 faceNormal = normalize(faceNormals(vPosition)); normal *= sign(dot(normal, faceNormal)); #ifdef NUM_NORMAL_MAPS @@ -808,6 +808,10 @@ vec3 getMatNormal(int materialIndex, vec2 uv, vec3 normal, vec3 dp1, vec3 dp2, v } function setAttribute(gl, location, bufferAttribute) { + if (location === undefined) { + return; + } + const { itemSize, array } = bufferAttribute; gl.enableVertexAttribArray(location); @@ -2509,7 +2513,11 @@ bool intersectSceneShadow(inout Ray ray) { uniform sampler2D gMatProps; void surfaceInteractionDirect(vec2 coord, inout SurfaceInteraction si) { - si.position = texture(gPosition, coord).xyz; + vec4 positionAndMeshIndex = texture(gPosition, coord); + + si.position = positionAndMeshIndex.xyz; + + float meshIndex = positionAndMeshIndex.w; vec4 normalMaterialType = texture(gNormal, coord); @@ -2524,7 +2532,7 @@ bool intersectSceneShadow(inout Ray ray) { si.roughness = matProps.x; si.metalness = matProps.y; - si.hit = dot(si.normal, si.normal) > 0.0 ? true : false; + si.hit = meshIndex > 0.0 ? true : false; } `; @@ -3802,8 +3810,13 @@ void sampleGlassSpecular(SurfaceInteraction si, int bounce, inout Path path) { } #ifdef EDGE_PRESERVING_UPSCALE + + float getMeshId(sampler2D meshIdTex, vec2 vCoord) { + return floor(texture(meshIdTex, vCoord).w); + } + vec4 getUpscaledLight(vec2 coord) { - float meshId = texture(position, coord).w; + float meshId = getMeshId(position, coord); vec2 sizef = lightScale * vec2(textureSize(position, 0)); vec2 texelf = coord * sizef - 0.5; @@ -3828,7 +3841,7 @@ void sampleGlassSpecular(SurfaceInteraction si, int bounce, inout Path path) { float sum; for (int i = 0; i < 4; i++) { vec2 pCoord = (vec2(texels[i]) + 0.5) / sizef; - float isValid = texture(position, pCoord).w == meshId ? 1.0 : 0.0; + float isValid = getMeshId(position, pCoord) == meshId ? 1.0 : 0.0; float weight = isValid * weights[i]; upscaledLight += weight * texelFetch(light, texels[i], 0); sum += weight; diff --git a/package-lock.json b/package-lock.json index ba179e3..c3a9311 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ray-tracing-renderer", - "version": "0.6.1", + "version": "0.6.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index e749f23..7701b4b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ray-tracing-renderer", - "version": "0.6.1", + "version": "0.6.2", "description": "A [Three.js](https://github.com/mrdoob/three.js/) renderer which utilizes path tracing to render a scene with true photorealism. The renderer supports global illumination, reflections, soft shadows, and realistic environment lighting.", "main": "build/RayTracingRenderer.js", "scripts": {