光线追踪漫反射光照为何出现生硬截断?
光线追踪漫反射效果异常问题求助
我用JavaScript跟随《Ray Tracing In One Weekend》教程实现光线追踪,完成漫反射光照模块后,输出结果与预期不符:
- 预期效果:球体呈现柔和的漫反射光影过渡,色彩自然渐变
- 实际效果:球体表面出现生硬截断线条,效果近似镜面反射
我怀疑问题出在新射线的计算逻辑上,以下是核心代码片段,恳请帮忙排查:
射线颜色递归计算函数
function rayColour(r, world, depth) { if (depth <= 0) { return new Colour(0, 0, 0); } var rec = world.hit(r, 0, infinity, rec); if (rec[0]) { var target = rec[1].p.add(rec[1].normal).add(randomInUnitSphere()); return rayColour(new Ray(rec[1].p, target.subtract(rec[1].p)), world, depth-1).multiply(0.5); } var unitDirection = normalize(r.dir); var t = 0.5 * (unitDirection.y + 1); return new Colour(1, 1, 1).multiply(1-t).add(new Colour(0.5, 0.7, 1).multiply(t)); }
像素主渲染函数
for(var p = 0; p < ppt; p++) { var i = curPixel % WIDTH; var j = HEIGHT-1 - Math.floor(curPixel / WIDTH); var pixelColour = new Colour(0, 0, 0); for (var s = 0; s < samplesPerPixel; ++s) { var u = (i + Math.random()) / (WIDTH-1); var v = (j + Math.random()) / (HEIGHT-1); var r = cam.getRay(u, v); pixelColour = pixelColour.add(rayColour(r, world, maxDepth)); } putPixel(i, HEIGHT-1-j, pixelColour, samplesPerPixel); curPixel++; }
球体射线碰撞检测
hit(r, tMin, tMax, rec) { var oc = r.origin().subtract(this.center); var a = r.dir.lengthSquared(); var halfb = dot(oc, r.dir); var c = oc.lengthSquared() - this.radius*this.radius; var discriminant = halfb*halfb - a*c; if (discriminant < 0) return [false, rec]; var sqrtd = Math.sqrt(discriminant); // 寻找最近碰撞点 var root = (-halfb - sqrtd) / a; if (root < tMin || tMax < root) { root = (-halfb + sqrtd) / a; if (root < tMin || tMax < root) return [false, rec]; } rec.t = root; rec.p = r.at(rec.t); var outwardNormal = (rec.p.subtract(this.center)).divide(this.radius); rec.setFaceNormal(r, outwardNormal); return [true, rec]; }
物体列表碰撞检测
hit(r, tMin, tMax, rec) { var tempRec = new hitRecord(); var hitAnything = false; var closestSoFar = tMax; for (var i in this.list) { var tempRec = this.list[i].hit(r, tMin, closestSoFar, tempRec) if (tempRec[0]) { hitAnything = true; closestSoFar = tempRec[1].t; rec = tempRec[1]; } tempRec = new hitRecord(); } return [hitAnything, rec]; }
内容的提问来源于stack exchange,提问作者LemonHead
相关产品推荐
相关产品推荐

