public void intersectPrimitive(Ray r, int primID, IntersectionState state) { if (primID < instances.Length) instances[primID].intersect(r, state); else lights[primID - instances.Length].intersect(r, state); }
public void intersectPrimitive(Ray r, int primID, IntersectionState state) { // intersect in local space float rd2x = r.dx * r.dx; float rd2y = r.dy * r.dy; float rd2z = r.dz * r.dz; float ro2x = r.ox * r.ox; float ro2y = r.oy * r.oy; float ro2z = r.oz * r.oz; // setup the quartic coefficients // some common terms could probably be shared across these double A = (rd2y * rd2y + rd2z * rd2z + rd2x * rd2x); double B = 4 * (r.oy * rd2y * r.dy + r.oz * r.dz * rd2z + r.ox * r.dx * rd2x); double C = (-rd2x - rd2y - rd2z + 6 * (ro2y * rd2y + ro2z * rd2z + ro2x * rd2x)); double D = 2 * (2 * ro2z * r.oz * r.dz - r.oz * r.dz + 2 * ro2x * r.ox * r.dx + 2 * ro2y * r.oy * r.dy - r.ox * r.dx - r.oy * r.dy); double E = 3.0f / 8.0f + (-ro2z + ro2z * ro2z - ro2y + ro2y * ro2y - ro2x + ro2x * ro2x); // solve equation double[] t = Solvers.solveQuartic(A, B, C, D, E); if (t != null) { // early rejection if (t[0] >= r.getMax() || t[t.Length - 1] <= r.getMin()) return; // find first intersection in front of the ray for (int i = 0; i < t.Length; i++) { if (t[i] > r.getMin()) { r.setMax((float)t[i]); state.setIntersection(0, 0, 0); return; } } } }
private ShadingState(ShadingState previous, IntersectionState istate, Ray r, int i, int d) { this.r = r; this.istate = istate; this.i = i; this.d = d; this.instance = istate.instance; // local copy this.primitiveID = istate.id; this.hitU = istate.u; this.hitV = istate.v; if (previous == null) { diffuseDepth = 0; reflectionDepth = 0; refractionDepth = 0; } else { diffuseDepth = previous.diffuseDepth; reflectionDepth = previous.reflectionDepth; refractionDepth = previous.refractionDepth; this.server = previous.server; this.map = previous.map; this.rx = previous.rx; this.ry = previous.ry; this.i += previous.i; this.d += previous.d; } behind = false; cosND = float.NaN; includeLights = includeSpecular = true; qmcD0I = QMC.halton(this.d, this.i); qmcD1I = QMC.halton(this.d + 1, this.i); result = null; }
/** * Get the radiance seen through a particular pixel * * @param istate intersection state for ray tracing * @param rx pixel x coordinate * @param ry pixel y coordinate * @param lensU DOF sampling variable * @param lensV DOF sampling variable * @param time motion blur sampling variable * @param instance QMC instance seed * @return a shading state for the intersected primitive, or * <code>null</code> if nothing is seen through the specifieFd * point */ public ShadingState getRadiance(IntersectionState istate, float rx, float ry, double lensU, double lensV, double time, int instance) { if (bakingPrimitives == null) { Ray r = camera.getRay(rx, ry, imageWidth, imageHeight, lensU, lensV, time); return(r != null?lightServer.getRadiance(rx, ry, instance, r, istate) : null); } else { Ray r = new Ray(rx / imageWidth, ry / imageHeight, -1, 0, 0, 1); traceBake(r, istate); if (!istate.hit()) { return(null); } ShadingState state = ShadingState.createState(istate, rx, ry, r, instance, lightServer); bakingPrimitives.prepareShadingState(state); if (bakingViewDependent) { state.setRay(camera.getRay(state.getPoint())); } else { Point3 p = state.getPoint(); Vector3 n = state.getNormal(); // create a ray coming from directly above the point being // shaded Ray incoming = new Ray(p.x + n.x, p.y + n.y, p.z + n.z, -n.x, -n.y, -n.z); incoming.setMax(1); state.setRay(incoming); } lightServer.shadeBakeResult(state); return(state); } }
void traceBake(Ray r, IntersectionState state) { // set the instance as if tracing a regular instanced object state.current = bakingInstance; // reset object state.instance = null; bakingAccel.intersect(r, state); }
public static ShadingState createPhotonState(Ray r, IntersectionState istate, int i, PhotonStore map, LightServer server) { ShadingState s = new ShadingState(null, istate, r, i, 4); s.server = server; s.map = map; return(s); }
public void accumulate(IntersectionState state) { numEyeRays += state.numEyeRays; numShadowRays += state.numShadowRays; numReflectionRays += state.numReflectionRays; numGlossyRays += state.numGlossyRays; numRefractionRays += state.numRefractionRays; numRays += state.numRays; }
public void intersect(Ray r, IntersectionState state) { Ray localRay = r.transform(w2o.sample(state.time)); state.current = this; geometry.intersect(localRay, state); // FIXME: transfer max distance to current ray r.setMax(localRay.getMax()); }
public static ShadingState createState(IntersectionState istate, float rx, float ry, Ray r, int i, LightServer server) { ShadingState s = new ShadingState(null, istate, r, i, 4); s.server = server; s.rx = rx; s.ry = ry; return(s); }
public ShadingState traceFinalGather(ShadingState previous, Ray r, int i) { if (previous.getDiffuseDepth() >= maxDiffuseDepth) { return(null); } IntersectionState istate = previous.getIntersectionState(); scene.trace(r, istate); return(istate.hit() ? ShadingState.createFinalGatherState(previous, r, i) : null); }
public void intersectPrimitive(Ray r, int primID, IntersectionState state) { if (primID < instances.Length) { instances[primID].intersect(r, state); } else { lights[primID - instances.Length].intersect(r, state); } }
public void intersect(Ray r, IntersectionState state) { if (builtTess == 0) { tesselate(); } if (builtAccel == 0) { build(); } accel.intersect(r, state); }
public Color traceRefraction(ShadingState previous, Ray r, int i) { // limit path depth and disable caustic paths if (previous.getRefractionDepth() >= maxRefractionDepth || previous.getDiffuseDepth() > 0) { return(Color.BLACK); } IntersectionState istate = previous.getIntersectionState(); scene.trace(r, istate); return(istate.hit() ? shadeHit(ShadingState.createRefractionBounceState(previous, r, i)) : Color.BLACK); }
public void trace(Ray r, IntersectionState state) { // reset object state.instance = null; state.current = null; for (int i = 0; i < infiniteInstanceList.getNumPrimitives(); i++) { infiniteInstanceList.intersectPrimitive(r, i, state); } // reset for next accel structure state.current = null; intAccel.intersect(r, state); }
public void Run() { ByteUtil.InitByteUtil(); IntersectionState istate = new IntersectionState(); for (int i = start; i < end; i++) { lock (lockObj) { UI.taskUpdate(server.photonCounter); server.photonCounter++; if (UI.taskCanceled()) { return; } } int qmcI = i + seed; double rand = QMC.halton(0, qmcI) * histogram[histogram.Length - 1]; int j = 0; while (rand >= histogram[j] && j < histogram.Length) { j++; } // make sure we didn't pick a zero-probability light if (j == histogram.Length) { continue; } double randX1 = (j == 0) ? rand / histogram[0] : (rand - histogram[j]) / (histogram[j] - histogram[j - 1]); double randY1 = QMC.halton(1, qmcI); double randX2 = QMC.halton(2, qmcI); double randY2 = QMC.halton(3, qmcI); Point3 pt = new Point3(); Vector3 dir = new Vector3(); Color power = new Color(); server.lights[j].getPhoton(randX1, randY1, randX2, randY2, pt, dir, power); power.mul(scale); Ray r = new Ray(pt, dir); server.scene.trace(r, istate); if (istate.hit()) { server.shadePhoton(ShadingState.createPhotonState(r, istate, qmcI, map, server), power); } } }
public void traceRefractionPhoton(ShadingState previous, Ray r, Color power) { if (previous.getRefractionDepth() >= maxRefractionDepth) { return; } IntersectionState istate = previous.getIntersectionState(); scene.trace(r, istate); if (previous.getIntersectionState().hit()) { // create a new shading context ShadingState state = ShadingState.createRefractionBounceState(previous, r, 0); shadePhoton(state, power); } }
public void run() { IntersectionState istate = new IntersectionState(); while (true) { uint bx, by; lock (renderer)//synchronized (SimpleRenderer.this) { { if (renderer.bucketCounter >= renderer.numBuckets) return; by = renderer.bucketCounter / renderer.numBucketsX; bx = renderer.bucketCounter % renderer.numBucketsX; renderer.bucketCounter++; } renderer.renderBucket(bx, by, istate); } }
public void intersectPrimitive(Ray r, int primID, IntersectionState state) { // intersect in local space float qa = r.dx * r.dx + r.dy * r.dy + r.dz * r.dz; float qb = 2 * ((r.dx * r.ox) + (r.dy * r.oy) + (r.dz * r.oz)); float qc = ((r.ox * r.ox) + (r.oy * r.oy) + (r.oz * r.oz)) - 1; double[] t = Solvers.solveQuadric(qa, qb, qc); if (t != null) { // early rejection if (t[0] >= r.getMax() || t[1] <= r.getMin()) return; if (t[0] > r.getMin()) r.setMax((float)t[0]); else r.setMax((float)t[1]); state.setIntersection(0, 0, 0); } }
private ShadingState(ShadingState previous, IntersectionState istate, Ray r, int i, int d) { this.r = r; this.istate = istate; this.i = i; this.d = d; time = istate.time; instance = istate.instance; // local copy primitiveID = istate.id; hitU = istate.u; hitV = istate.v; hitW = istate.w; // get matrices for current time o2w = instance.getObjectToWorld(time); w2o = instance.getWorldToObject(time); if (previous == null) { diffuseDepth = 0; reflectionDepth = 0; refractionDepth = 0; } else { diffuseDepth = previous.diffuseDepth; reflectionDepth = previous.reflectionDepth; refractionDepth = previous.refractionDepth; server = previous.server; map = previous.map; rx = previous.rx; ry = previous.ry; this.i += previous.i; this.d += previous.d; } behind = false; cosND = float.NaN; includeLights = includeSpecular = true; qmcD0I = QMC.halton(this.d, this.i); qmcD1I = QMC.halton(this.d + 1, this.i); result = null; bias = 0.001f; }
public void intersectPrimitive(Ray r, int primID, IntersectionState state) { int i3 = primID * 3; float ocx = r.ox - particles[i3 + 0]; float ocy = r.oy - particles[i3 + 1]; float ocz = r.oz - particles[i3 + 2]; float qa = r.dx * r.dx + r.dy * r.dy + r.dz * r.dz; float qb = 2 * ((r.dx * ocx) + (r.dy * ocy) + (r.dz * ocz)); float qc = ((ocx * ocx) + (ocy * ocy) + (ocz * ocz)) - r2; double[] t = Solvers.solveQuadric(qa, qb, qc); if (t != null) { // early rejection if (t[0] >= r.getMax() || t[1] <= r.getMin()) return; if (t[0] > r.getMin()) r.setMax((float)t[0]); else r.setMax((float)t[1]); state.setIntersection(primID); } }
public void intersectPrimitive(Ray r, int primID, IntersectionState state) { // intersect in local space float rd2x = r.dx * r.dx; float rd2y = r.dy * r.dy; float rd2z = r.dz * r.dz; float ro2x = r.ox * r.ox; float ro2y = r.oy * r.oy; float ro2z = r.oz * r.oz; // compute some common factors double alpha = rd2x + rd2y + rd2z; double beta = 2 * (r.ox * r.dx + r.oy * r.dy + r.oz * r.dz); double gamma = (ro2x + ro2y + ro2z) - ri2 - ro2; // setup quartic coefficients double A = alpha * alpha; double B = 2 * alpha * beta; double C = beta * beta + 2 * alpha * gamma + 4 * ro2 * rd2z; double D = 2 * beta * gamma + 8 * ro2 * r.oz * r.dz; double E = gamma * gamma + 4 * ro2 * ro2z - 4 * ro2 * ri2; // solve equation double[] t = Solvers.solveQuartic(A, B, C, D, E); if (t != null) { // early rejection if (t[0] >= r.getMax() || t[t.Length - 1] <= r.getMin()) return; // find first intersection in front of the ray for (int i = 0; i < t.Length; i++) { if (t[i] > r.getMin()) { r.setMax((float)t[i]); state.setIntersection(0, 0, 0); return; } } } }
public ShadingState getRadiance(float rx, float ry, int i, Ray r, IntersectionState istate) { lock (lockObj) { scene.trace(r, istate); if (istate.hit()) { ShadingState state = ShadingState.createState(istate, rx, ry, r, i, this); state.getInstance().prepareShadingState(state); IShader shader = getShader(state); if (shader == null) { state.setResult(Color.BLACK); return(state); } if (_shadingCache != null) { Color c = lookupShadingCache(state, shader); if (c != null) { state.setResult(c); return(state); } } state.setResult(shader.getRadiance(state)); if (_shadingCache != null) { addShadingCache(state, shader, state.getResult()); } return(state); } else { return(null); } } }
public void intersectPrimitiveRobust(Ray r, int primID, IntersectionState state) { // ray-triangle intersection here int tri = 3 * primID; int a = 3 * triangles[tri + 0]; int b = 3 * triangles[tri + 1]; int c = 3 * triangles[tri + 2]; float[] stack = state.getRobustStack(); for (int i = 0, i3 = 0; i < 3; i++, i3 += 3) { stack[i3 + 0] = points[a + i]; stack[i3 + 1] = points[b + i]; stack[i3 + 2] = points[c + i]; } stack[9] = float.PositiveInfinity; int stackpos = 0; float orgX = r.ox; float dirX = r.dx, invDirX = 1 / dirX; float orgY = r.oy; float dirY = r.dy, invDirY = 1 / dirY; float orgZ = r.oz; float dirZ = r.dz, invDirZ = 1 / dirZ; float t1, t2; float minx, maxx; float miny, maxy; float minz, maxz; float mint = r.getMin(); float maxt = r.getMax(); while (stackpos >= 0) { float intervalMin = mint; float intervalMax = maxt; float p0x = stack[stackpos + 0]; float p1x = stack[stackpos + 1]; float p2x = stack[stackpos + 2]; t1 = ((minx = MathUtils.min(p0x, p1x, p2x)) - orgX) * invDirX; t2 = ((maxx = MathUtils.max(p0x, p1x, p2x)) - orgX) * invDirX; if (invDirX > 0) { if (t1 > intervalMin) intervalMin = t1; if (t2 < intervalMax) intervalMax = t2; } else { if (t2 > intervalMin) intervalMin = t2; if (t1 < intervalMax) intervalMax = t1; } if (intervalMin > intervalMax) { stackpos -= 10; continue; } float p0y = stack[stackpos + 3]; float p1y = stack[stackpos + 4]; float p2y = stack[stackpos + 5]; t1 = ((miny = MathUtils.min(p0y, p1y, p2y)) - orgY) * invDirY; t2 = ((maxy = MathUtils.max(p0y, p1y, p2y)) - orgY) * invDirY; if (invDirY > 0) { if (t1 > intervalMin) intervalMin = t1; if (t2 < intervalMax) intervalMax = t2; } else { if (t2 > intervalMin) intervalMin = t2; if (t1 < intervalMax) intervalMax = t1; } if (intervalMin > intervalMax) { stackpos -= 10; continue; } float p0z = stack[stackpos + 6]; float p1z = stack[stackpos + 7]; float p2z = stack[stackpos + 8]; t1 = ((minz = MathUtils.min(p0z, p1z, p2z)) - orgZ) * invDirZ; t2 = ((maxz = MathUtils.max(p0z, p1z, p2z)) - orgZ) * invDirZ; if (invDirZ > 0) { if (t1 > intervalMin) intervalMin = t1; if (t2 < intervalMax) intervalMax = t2; } else { if (t2 > intervalMin) intervalMin = t2; if (t1 < intervalMax) intervalMax = t1; } if (intervalMin > intervalMax) { stackpos -= 10; continue; } // intersection was found - keep going float size = (maxx - minx) + (maxy - miny) + (maxz - minz); if (ByteUtil.floatToRawIntBits(stack[stackpos + 9]) == ByteUtil.floatToRawIntBits(size)) { // L1 norm is 0, we are done r.setMax(intervalMin); triaccel[primID].intersectBox(r, p0x, p0y, p0z, primID, state); return; // safe to return, only one intersection per primitive } // not small enough yet - subdivide float p01x = (p0x + p1x) * 0.5f; float p01y = (p0y + p1y) * 0.5f; float p01z = (p0z + p1z) * 0.5f; float p12x = (p1x + p2x) * 0.5f; float p12y = (p1y + p2y) * 0.5f; float p12z = (p1z + p2z) * 0.5f; float p20x = (p2x + p0x) * 0.5f; float p20y = (p2y + p0y) * 0.5f; float p20z = (p2z + p0z) * 0.5f; // triangle 0 stack[stackpos + 0] = p0x; stack[stackpos + 1] = p01x; stack[stackpos + 2] = p20x; stack[stackpos + 3] = p0y; stack[stackpos + 4] = p01y; stack[stackpos + 5] = p20y; stack[stackpos + 6] = p0z; stack[stackpos + 7] = p01z; stack[stackpos + 8] = p20z; stack[stackpos + 9] = size; stackpos += 10; // triangle 1 stack[stackpos + 0] = p1x; stack[stackpos + 1] = p12x; stack[stackpos + 2] = p01x; stack[stackpos + 3] = p1y; stack[stackpos + 4] = p12y; stack[stackpos + 5] = p01y; stack[stackpos + 6] = p1z; stack[stackpos + 7] = p12z; stack[stackpos + 8] = p01z; stack[stackpos + 9] = size; stackpos += 10; // triangle 2 stack[stackpos + 0] = p2x; stack[stackpos + 1] = p20x; stack[stackpos + 2] = p12x; stack[stackpos + 3] = p2y; stack[stackpos + 4] = p20y; stack[stackpos + 5] = p12y; stack[stackpos + 6] = p2z; stack[stackpos + 7] = p20z; stack[stackpos + 8] = p12z; stack[stackpos + 9] = size; stackpos += 10; // triangle 4 stack[stackpos + 0] = p20x; stack[stackpos + 1] = p12x; stack[stackpos + 2] = p01x; stack[stackpos + 3] = p20y; stack[stackpos + 4] = p12y; stack[stackpos + 5] = p01y; stack[stackpos + 6] = p20z; stack[stackpos + 7] = p12z; stack[stackpos + 8] = p01z; stack[stackpos + 9] = size; } }
public ShadingState getRadiance(float rx, float ry, float time, int i, int d, Ray r, IntersectionState istate, ShadingCache cache) { istate.time = time; scene.trace(r, istate); if (istate.hit()) { ShadingState state = ShadingState.createState(istate, rx, ry, time, r, i, d, this); state.getInstance().prepareShadingState(state); IShader shader = getShader(state); if (shader == null) { state.setResult(Color.BLACK); return(state); } if (cache != null) { Color c = cache.lookup(state, shader); if (c != null) { state.setResult(c); return(state); } } state.setResult(shader.GetRadiance(state)); if (cache != null) { cache.add(state, shader, state.getResult()); } checkNanInf(state.getResult()); return(state); } else { return(null); } }
public void accumulateStats(IntersectionState state) { stats.accumulate(state); }
public void intersect(Ray r, IntersectionState state) { float intervalMin = r.getMin(); float intervalMax = r.getMax(); float orgX = r.ox; float dirX = r.dx, invDirX = 1 / dirX; float t1, t2; t1 = (bounds.getMinimum().x - orgX) * invDirX; t2 = (bounds.getMaximum().x - orgX) * invDirX; if (invDirX > 0) { if (t1 > intervalMin) intervalMin = t1; if (t2 < intervalMax) intervalMax = t2; } else { if (t2 > intervalMin) intervalMin = t2; if (t1 < intervalMax) intervalMax = t1; } if (intervalMin > intervalMax) return; float orgY = r.oy; float dirY = r.dy, invDirY = 1 / dirY; t1 = (bounds.getMinimum().y - orgY) * invDirY; t2 = (bounds.getMaximum().y - orgY) * invDirY; if (invDirY > 0) { if (t1 > intervalMin) intervalMin = t1; if (t2 < intervalMax) intervalMax = t2; } else { if (t2 > intervalMin) intervalMin = t2; if (t1 < intervalMax) intervalMax = t1; } if (intervalMin > intervalMax) return; float orgZ = r.oz; float dirZ = r.dz, invDirZ = 1 / dirZ; t1 = (bounds.getMinimum().z - orgZ) * invDirZ; t2 = (bounds.getMaximum().z - orgZ) * invDirZ; if (invDirZ > 0) { if (t1 > intervalMin) intervalMin = t1; if (t2 < intervalMax) intervalMax = t2; } else { if (t2 > intervalMin) intervalMin = t2; if (t1 < intervalMax) intervalMax = t1; } if (intervalMin > intervalMax) return; // box is hit at [intervalMin, intervalMax] orgX += intervalMin * dirX; orgY += intervalMin * dirY; orgZ += intervalMin * dirZ; // locate starting point inside the grid // and set up 3D-DDA vars int indxX, indxY, indxZ; int stepX, stepY, stepZ; int stopX, stopY, stopZ; float deltaX, deltaY, deltaZ; float tnextX, tnextY, tnextZ; // stepping factors along X indxX = (int)((orgX - bounds.getMinimum().x) * invVoxelwx); if (indxX < 0) indxX = 0; else if (indxX >= nx) indxX = nx - 1; if (Math.Abs(dirX) < 1e-6f) { stepX = 0; stopX = indxX; deltaX = 0; tnextX = float.PositiveInfinity; } else if (dirX > 0) { stepX = 1; stopX = nx; deltaX = voxelwx * invDirX; tnextX = intervalMin + ((indxX + 1) * voxelwx + bounds.getMinimum().x - orgX) * invDirX; } else { stepX = -1; stopX = -1; deltaX = -voxelwx * invDirX; tnextX = intervalMin + (indxX * voxelwx + bounds.getMinimum().x - orgX) * invDirX; } // stepping factors along Y indxY = (int)((orgY - bounds.getMinimum().y) * invVoxelwy); if (indxY < 0) indxY = 0; else if (indxY >= ny) indxY = ny - 1; if (Math.Abs(dirY) < 1e-6f) { stepY = 0; stopY = indxY; deltaY = 0; tnextY = float.PositiveInfinity; } else if (dirY > 0) { stepY = 1; stopY = ny; deltaY = voxelwy * invDirY; tnextY = intervalMin + ((indxY + 1) * voxelwy + bounds.getMinimum().y - orgY) * invDirY; } else { stepY = -1; stopY = -1; deltaY = -voxelwy * invDirY; tnextY = intervalMin + (indxY * voxelwy + bounds.getMinimum().y - orgY) * invDirY; } // stepping factors along Z indxZ = (int)((orgZ - bounds.getMinimum().z) * invVoxelwz); if (indxZ < 0) indxZ = 0; else if (indxZ >= nz) indxZ = nz - 1; if (Math.Abs(dirZ) < 1e-6f) { stepZ = 0; stopZ = indxZ; deltaZ = 0; tnextZ = float.PositiveInfinity; } else if (dirZ > 0) { stepZ = 1; stopZ = nz; deltaZ = voxelwz * invDirZ; tnextZ = intervalMin + ((indxZ + 1) * voxelwz + bounds.getMinimum().z - orgZ) * invDirZ; } else { stepZ = -1; stopZ = -1; deltaZ = -voxelwz * invDirZ; tnextZ = intervalMin + (indxZ * voxelwz + bounds.getMinimum().z - orgZ) * invDirZ; } int cellstepX = stepX; int cellstepY = stepY * nx; int cellstepZ = stepZ * ny * nx; int cell = indxX + indxY * nx + indxZ * ny * nx; // trace through the grid for (; ; ) { if (tnextX < tnextY && tnextX < tnextZ) { if (cells[cell] != null) { foreach (int i in cells[cell]) primitives.intersectPrimitive(r, i, state); if (state.hit() && (r.getMax() < tnextX && r.getMax() < intervalMax)) return; } intervalMin = tnextX; if (intervalMin > intervalMax) return; indxX += stepX; if (indxX == stopX) return; tnextX += deltaX; cell += cellstepX; } else if (tnextY < tnextZ) { if (cells[cell] != null) { foreach (int i in cells[cell]) primitives.intersectPrimitive(r, i, state); if (state.hit() && (r.getMax() < tnextY && r.getMax() < intervalMax)) return; } intervalMin = tnextY; if (intervalMin > intervalMax) return; indxY += stepY; if (indxY == stopY) return; tnextY += deltaY; cell += cellstepY; } else { if (cells[cell] != null) { foreach (int i in cells[cell]) primitives.intersectPrimitive(r, i, state); if (state.hit() && (r.getMax() < tnextZ && r.getMax() < intervalMax)) return; } intervalMin = tnextZ; if (intervalMin > intervalMax) return; indxZ += stepZ; if (indxZ == stopZ) return; tnextZ += deltaZ; cell += cellstepZ; } } }
public BucketThread(int threadID, BucketRenderer renderer) { this.threadID = threadID; istate = new IntersectionState(); this.renderer = renderer; thread = new Thread(new ThreadStart(run)); thread.IsBackground = true; }
public void intersect(Ray r, IntersectionState state) { if (builtTess == 0) tesselate(); if (builtAccel == 0) build(); accel.intersect(r, state); }
private void intersectTriangleKensler(Ray r, int primID, IntersectionState state) { int tri = 3 * primID; int a = 3 * triangles[tri + 0]; int b = 3 * triangles[tri + 1]; int c = 3 * triangles[tri + 2]; float edge0x = points[b + 0] - points[a + 0]; float edge0y = points[b + 1] - points[a + 1]; float edge0z = points[b + 2] - points[a + 2]; float edge1x = points[a + 0] - points[c + 0]; float edge1y = points[a + 1] - points[c + 1]; float edge1z = points[a + 2] - points[c + 2]; float nx = edge0y * edge1z - edge0z * edge1y; float ny = edge0z * edge1x - edge0x * edge1z; float nz = edge0x * edge1y - edge0y * edge1x; float v = r.dot(nx, ny, nz); float iv = 1 / v; float edge2x = points[a + 0] - r.ox; float edge2y = points[a + 1] - r.oy; float edge2z = points[a + 2] - r.oz; float va = nx * edge2x + ny * edge2y + nz * edge2z; float t = iv * va; if (!r.isInside(t)) return; float ix = edge2y * r.dz - edge2z * r.dy; float iy = edge2z * r.dx - edge2x * r.dz; float iz = edge2x * r.dy - edge2y * r.dx; float v1 = ix * edge1x + iy * edge1y + iz * edge1z; float beta = iv * v1; if (beta < 0) return; float v2 = ix * edge0x + iy * edge0y + iz * edge0z; if ((v1 + v2) * v > v * v) return; float gamma = iv * v2; if (gamma < 0) return; r.setMax(t); state.setIntersection(primID, beta, gamma); }
public void intersectBox(Ray r, float hx, float hy, float hz, int primID, IntersectionState state) { switch (k) { case 0: { float hu = hy; float hv = hz; float u = hu * bnu + hv * bnv + bnd; if (u < 0.0f) u = 0; float v = hu * cnu + hv * cnv + cnd; if (v < 0.0f) v = 0; state.setIntersection(primID, u, v); return; } case 1: { float hu = hz; float hv = hx; float u = hu * bnu + hv * bnv + bnd; if (u < 0.0f) u = 0; float v = hu * cnu + hv * cnv + cnd; if (v < 0.0f) v = 0; state.setIntersection(primID, u, v); return; } case 2: { float hu = hx; float hv = hy; float u = hu * bnu + hv * bnv + bnd; if (u < 0.0f) u = 0; float v = hu * cnu + hv * cnv + cnd; if (v < 0.0f) v = 0; state.setIntersection(primID, u, v); return; } } }
public void intersectPrimitive(Ray r, int primID, IntersectionState state) { float uv00 = 0, uv01 = 0, uv10 = 0, uv11 = 0, uv20 = 0, uv21 = 0; switch (triangleMesh.uvs.interp) { case ParameterList.InterpolationType.NONE: case ParameterList.InterpolationType.FACE: default: return; case ParameterList.InterpolationType.VERTEX: { int tri = 3 * primID; int index0 = triangleMesh.triangles[tri + 0]; int index1 = triangleMesh.triangles[tri + 1]; int index2 = triangleMesh.triangles[tri + 2]; int i20 = 2 * index0; int i21 = 2 * index1; int i22 = 2 * index2; float[] uvs = triangleMesh.uvs.data; uv00 = uvs[i20 + 0]; uv01 = uvs[i20 + 1]; uv10 = uvs[i21 + 0]; uv11 = uvs[i21 + 1]; uv20 = uvs[i22 + 0]; uv21 = uvs[i22 + 1]; break; } case ParameterList.InterpolationType.FACEVARYING: { int idx = (3 * primID) << 1; float[] uvs = triangleMesh.uvs.data; uv00 = uvs[idx + 0]; uv01 = uvs[idx + 1]; uv10 = uvs[idx + 2]; uv11 = uvs[idx + 3]; uv20 = uvs[idx + 4]; uv21 = uvs[idx + 5]; break; } } double edge1x = uv10 - uv00; double edge1y = uv11 - uv01; double edge2x = uv20 - uv00; double edge2y = uv21 - uv01; double pvecx = r.dy * 0 - r.dz * edge2y; double pvecy = r.dz * edge2x - r.dx * 0; double pvecz = r.dx * edge2y - r.dy * edge2x; double qvecx, qvecy, qvecz; double u, v; double det = edge1x * pvecx + edge1y * pvecy + 0 * pvecz; if (det > 0) { double tvecx = r.ox - uv00; double tvecy = r.oy - uv01; double tvecz = r.oz; u = (tvecx * pvecx + tvecy * pvecy + tvecz * pvecz); if (u < 0.0 || u > det) return; qvecx = tvecy * 0 - tvecz * edge1y; qvecy = tvecz * edge1x - tvecx * 0; qvecz = tvecx * edge1y - tvecy * edge1x; v = (r.dx * qvecx + r.dy * qvecy + r.dz * qvecz); if (v < 0.0 || u + v > det) return; } else if (det < 0) { double tvecx = r.ox - uv00; double tvecy = r.oy - uv01; double tvecz = r.oz; u = (tvecx * pvecx + tvecy * pvecy + tvecz * pvecz); if (u > 0.0 || u < det) return; qvecx = tvecy * 0 - tvecz * edge1y; qvecy = tvecz * edge1x - tvecx * 0; qvecz = tvecx * edge1y - tvecy * edge1x; v = (r.dx * qvecx + r.dy * qvecy + r.dz * qvecz); if (v > 0.0 || u + v < det) return; } else return; double inv_det = 1.0 / det; float t = (float)((edge2x * qvecx + edge2y * qvecy + 0 * qvecz) * inv_det); if (r.isInside(t)) { r.setMax(t); state.setIntersection(primID, (float)(u * inv_det), (float)(v * inv_det)); } }
public void intersect(Ray r, IntersectionState state) { for (int i = 0; i < n; i++) primitives.intersectPrimitive(r, i, state); }
public void intersectPrimitive(Ray r, int primID, IntersectionState state) { instances[primID].intersect(r, state); }
public void renderBucket(uint bx, uint by, IntersectionState istate) { // pixel sized extents int x0 = (int)(bx * 32); int y0 = (int)(by * 32); int bw = Math.Min(32, imageWidth - x0); int bh = Math.Min(32, imageHeight - y0); Color[] bucketRGB = new Color[bw * bh]; for (int y = 0, i = 0; y < bh; y++) { for (int x = 0; x < bw; x++, i++) { ShadingState state = scene.getRadiance(istate, x0 + x, imageHeight - 1 - (y0 + y), 0.0, 0.0, 0.0, 0); bucketRGB[i] = (state != null) ? state.getResult() : Color.BLACK; } } // update pixels display.imageUpdate(x0, y0, bw, bh, bucketRGB); }
public void intersectPrimitive(Ray r, int primID, IntersectionState state) { // alternative test -- disabled for now // intersectPrimitiveRobust(r, primID, state); if (triaccel != null) { // optional fast intersection method triaccel[primID].intersect(r, primID, state); return; } intersectTriangleKensler(r, primID, state); }
public void intersect(Ray r, IntersectionState state) { float intervalMin = r.getMin(); float intervalMax = r.getMax(); float orgX = r.ox; float dirX = r.dx, invDirX = 1 / dirX; float t1, t2; t1 = (bounds.getMinimum ().x - orgX) * invDirX; t2 = (bounds.getMaximum ().x - orgX) * invDirX; if (invDirX > 0) { if (t1 > intervalMin) intervalMin = t1; if (t2 < intervalMax) intervalMax = t2; } else { if (t2 > intervalMin) intervalMin = t2; if (t1 < intervalMax) intervalMax = t1; } if (intervalMin > intervalMax) return; float orgY = r.oy; float dirY = r.dy, invDirY = 1 / dirY; t1 = (bounds.getMinimum ().y - orgY) * invDirY; t2 = (bounds.getMaximum ().y - orgY) * invDirY; if (invDirY > 0) { if (t1 > intervalMin) intervalMin = t1; if (t2 < intervalMax) intervalMax = t2; } else { if (t2 > intervalMin) intervalMin = t2; if (t1 < intervalMax) intervalMax = t1; } if (intervalMin > intervalMax) return; float orgZ = r.oz; float dirZ = r.dz, invDirZ = 1 / dirZ; t1 = (bounds.getMinimum ().z - orgZ) * invDirZ; t2 = (bounds.getMaximum ().z - orgZ) * invDirZ; if (invDirZ > 0) { if (t1 > intervalMin) intervalMin = t1; if (t2 < intervalMax) intervalMax = t2; } else { if (t2 > intervalMin) intervalMin = t2; if (t1 < intervalMax) intervalMax = t1; } if (intervalMin > intervalMax) return; // compute custom offsets from direction sign bit int offsetXFront = (int)((uint)(ByteUtil.floatToRawIntBits (dirX) & (1 << 31)) >> 30);//>>> int offsetYFront = (int)((uint)(ByteUtil.floatToRawIntBits (dirY) & (1 << 31)) >> 30);//>>> int offsetZFront = (int)((uint)(ByteUtil.floatToRawIntBits (dirZ) & (1 << 31)) >> 30);//>>> int offsetXBack = offsetXFront ^ 2; int offsetYBack = offsetYFront ^ 2; int offsetZBack = offsetZFront ^ 2; IntersectionState.StackNode[] stack = state.getStack (); int stackPos = 0; int node = 0; while (true) { int tn = tree [node]; int axis = tn & (3 << 30); int offset = tn & ~(3 << 30); switch (axis) { case 0: { float d = (ByteUtil.intBitsToFloat (tree [node + 1]) - orgX) * invDirX; int back = offset + offsetXBack; node = back; if (d < intervalMin) continue; node = offset + offsetXFront; // front if (d > intervalMax) continue; // push back node stack [stackPos].node = back; stack [stackPos].near = (d >= intervalMin) ? d : intervalMin; stack [stackPos].far = intervalMax; stackPos++; // update ray interval for front node intervalMax = (d <= intervalMax) ? d : intervalMax; continue; } case 1 << 30: { // y axis float d = (ByteUtil.intBitsToFloat (tree [node + 1]) - orgY) * invDirY; int back = offset + offsetYBack; node = back; if (d < intervalMin) continue; node = offset + offsetYFront; // front if (d > intervalMax) continue; // push back node stack [stackPos].node = back; stack [stackPos].near = (d >= intervalMin) ? d : intervalMin; stack [stackPos].far = intervalMax; stackPos++; // update ray interval for front node intervalMax = (d <= intervalMax) ? d : intervalMax; continue; } case 2 << 30: { // z axis float d = (ByteUtil.intBitsToFloat (tree [node + 1]) - orgZ) * invDirZ; int back = offset + offsetZBack; node = back; if (d < intervalMin) continue; node = offset + offsetZFront; // front if (d > intervalMax) continue; // push back node stack [stackPos].node = back; stack [stackPos].near = (d >= intervalMin) ? d : intervalMin; stack [stackPos].far = intervalMax; stackPos++; // update ray interval for front node intervalMax = (d <= intervalMax) ? d : intervalMax; continue; } default: { // leaf - test some objects int n = tree [node + 1]; while (n > 0) { primitiveList.intersectPrimitive (r, primitives [offset], state); n--; offset++; } if (r.getMax () < intervalMax) return; do { // stack is empty? if (stackPos == 0) return; // move back up the stack stackPos--; intervalMin = stack [stackPos].near; if (r.getMax () < intervalMin) continue; node = stack [stackPos].node; intervalMax = stack [stackPos].far; break; } while (true); break; } } // switch } // traversal loop }
public void intersect(Ray r, int primID, IntersectionState state) { switch (k) { case 0: { float det = 1.0f / (r.dx + nu * r.dy + nv * r.dz); float t = (nd - r.ox - nu * r.oy - nv * r.oz) * det; if (!r.isInside(t)) return; float hu = r.oy + t * r.dy; float hv = r.oz + t * r.dz; float u = hu * bnu + hv * bnv + bnd; if (u < 0.0f) return; float v = hu * cnu + hv * cnv + cnd; if (v < 0.0f) return; if (u + v > 1.0f) return; r.setMax(t); state.setIntersection(primID, u, v); return; } case 1: { float det = 1.0f / (r.dy + nu * r.dz + nv * r.dx); float t = (nd - r.oy - nu * r.oz - nv * r.ox) * det; if (!r.isInside(t)) return; float hu = r.oz + t * r.dz; float hv = r.ox + t * r.dx; float u = hu * bnu + hv * bnv + bnd; if (u < 0.0f) return; float v = hu * cnu + hv * cnv + cnd; if (v < 0.0f) return; if (u + v > 1.0f) return; r.setMax(t); state.setIntersection(primID, u, v); return; } case 2: { float det = 1.0f / (r.dz + nu * r.dx + nv * r.dy); float t = (nd - r.oz - nu * r.ox - nv * r.oy) * det; if (!r.isInside(t)) return; float hu = r.ox + t * r.dx; float hv = r.oy + t * r.dy; float u = hu * bnu + hv * bnv + bnd; if (u < 0.0f) return; float v = hu * cnu + hv * cnv + cnd; if (v < 0.0f) return; if (u + v > 1.0f) return; r.setMax(t); state.setIntersection(primID, u, v); return; } } }
public ShadingState getRadiance(float rx, float ry, int i, Ray r, IntersectionState istate) { lock (lockObj) { scene.trace(r, istate); if (istate.hit()) { ShadingState state = ShadingState.createState(istate, rx, ry, r, i, this); state.getInstance().prepareShadingState(state); IShader shader = getShader(state); if (shader == null) { state.setResult(Color.BLACK); return state; } if (_shadingCache != null) { Color c = lookupShadingCache(state, shader); if (c != null) { state.setResult(c); return state; } } state.setResult(shader.getRadiance(state)); if (_shadingCache != null) addShadingCache(state, shader, state.getResult()); return state; } else return null; } }
public void intersectPrimitive(Ray r, int primID, IntersectionState state) { float intervalMin = r.getMin(); float intervalMax = r.getMax(); float orgX = r.ox; float orgY = r.oy; float orgZ = r.oz; float dirX = r.dx, invDirX = 1 / dirX; float dirY = r.dy, invDirY = 1 / dirY; float dirZ = r.dz, invDirZ = 1 / dirZ; float t1, t2; t1 = (-1 - orgX) * invDirX; t2 = (+1 - orgX) * invDirX; int curr = -1; if (invDirX > 0) { if (t1 > intervalMin) { intervalMin = t1; curr = 0; } if (t2 < intervalMax) intervalMax = t2; if (intervalMin > intervalMax) return; } else { if (t2 > intervalMin) { intervalMin = t2; curr = 1; } if (t1 < intervalMax) intervalMax = t1; if (intervalMin > intervalMax) return; } t1 = (-1 - orgY) * invDirY; t2 = (+1 - orgY) * invDirY; if (invDirY > 0) { if (t1 > intervalMin) { intervalMin = t1; curr = 2; } if (t2 < intervalMax) intervalMax = t2; if (intervalMin > intervalMax) return; } else { if (t2 > intervalMin) { intervalMin = t2; curr = 3; } if (t1 < intervalMax) intervalMax = t1; if (intervalMin > intervalMax) return; } t1 = (-1 - orgZ) * invDirZ; t2 = (+1 - orgZ) * invDirZ; if (invDirZ > 0) { if (t1 > intervalMin) { intervalMin = t1; curr = 4; } if (t2 < intervalMax) intervalMax = t2; if (intervalMin > intervalMax) return; } else { if (t2 > intervalMin) { intervalMin = t2; curr = 5; } if (t1 < intervalMax) intervalMax = t1; if (intervalMin > intervalMax) return; } // box is hit at [intervalMin, intervalMax] orgX += intervalMin * dirX; orgY += intervalMin * dirY; orgZ += intervalMin * dirZ; // locate starting point inside the grid // and set up 3D-DDA vars int indxX, indxY, indxZ; int stepX, stepY, stepZ; int stopX, stopY, stopZ; float deltaX, deltaY, deltaZ; float tnextX, tnextY, tnextZ; // stepping factors along X indxX = (int)((orgX + 1) * invVoxelwx); if (indxX < 0) indxX = 0; else if (indxX >= nx) indxX = nx - 1; if (Math.Abs(dirX) < 1e-6f) { stepX = 0; stopX = indxX; deltaX = 0; tnextX = float.PositiveInfinity; } else if (dirX > 0) { stepX = 1; stopX = nx; deltaX = voxelwx * invDirX; tnextX = intervalMin + ((indxX + 1) * voxelwx - 1 - orgX) * invDirX; } else { stepX = -1; stopX = -1; deltaX = -voxelwx * invDirX; tnextX = intervalMin + (indxX * voxelwx - 1 - orgX) * invDirX; } // stepping factors along Y indxY = (int)((orgY + 1) * invVoxelwy); if (indxY < 0) indxY = 0; else if (indxY >= ny) indxY = ny - 1; if (Math.Abs(dirY) < 1e-6f) { stepY = 0; stopY = indxY; deltaY = 0; tnextY = float.PositiveInfinity; } else if (dirY > 0) { stepY = 1; stopY = ny; deltaY = voxelwy * invDirY; tnextY = intervalMin + ((indxY + 1) * voxelwy - 1 - orgY) * invDirY; } else { stepY = -1; stopY = -1; deltaY = -voxelwy * invDirY; tnextY = intervalMin + (indxY * voxelwy - 1 - orgY) * invDirY; } // stepping factors along Z indxZ = (int)((orgZ + 1) * invVoxelwz); if (indxZ < 0) indxZ = 0; else if (indxZ >= nz) indxZ = nz - 1; if (Math.Abs(dirZ) < 1e-6f) { stepZ = 0; stopZ = indxZ; deltaZ = 0; tnextZ = float.PositiveInfinity; } else if (dirZ > 0) { stepZ = 1; stopZ = nz; deltaZ = voxelwz * invDirZ; tnextZ = intervalMin + ((indxZ + 1) * voxelwz - 1 - orgZ) * invDirZ; } else { stepZ = -1; stopZ = -1; deltaZ = -voxelwz * invDirZ; tnextZ = intervalMin + (indxZ * voxelwz - 1 - orgZ) * invDirZ; } // are we starting inside the cube bool isInside = inside(indxX, indxY, indxZ) && bounds.contains(r.ox, r.oy, r.oz); // trace through the grid for (; ; ) { if (inside(indxX, indxY, indxZ) != isInside) { // we hit a boundary r.setMax(intervalMin); // if we are inside, the last bit needs to be flipped if (isInside) curr ^= 1; state.setIntersection(curr); return; } if (tnextX < tnextY && tnextX < tnextZ) { curr = dirX > 0 ? 0 : 1; intervalMin = tnextX; if (intervalMin > intervalMax) return; indxX += stepX; if (indxX == stopX) return; tnextX += deltaX; } else if (tnextY < tnextZ) { curr = dirY > 0 ? 2 : 3; intervalMin = tnextY; if (intervalMin > intervalMax) return; indxY += stepY; if (indxY == stopY) return; tnextY += deltaY; } else { curr = dirZ > 0 ? 4 : 5; intervalMin = tnextZ; if (intervalMin > intervalMax) return; indxZ += stepZ; if (indxZ == stopZ) return; tnextZ += deltaZ; } } }
public ShadingState getRadiance(float rx, float ry, float time, int i, int d, Ray r, IntersectionState istate, ShadingCache cache) { istate.time = time; scene.trace(r, istate); if (istate.hit()) { ShadingState state = ShadingState.createState(istate, rx, ry, time, r, i, d, this); state.getInstance().prepareShadingState(state); IShader shader = getShader(state); if (shader == null) { state.setResult(Color.BLACK); return state; } if (cache != null) { Color c = cache.lookup(state, shader); if (c != null) { state.setResult(c); return state; } } state.setResult(shader.GetRadiance(state)); if (cache != null) cache.add(state, shader, state.getResult()); checkNanInf(state.getResult()); return state; } else return null; }
public void intersectPrimitive(Ray r, int primID, IntersectionState state) { float intervalMin = float.NegativeInfinity; float intervalMax = float.PositiveInfinity; float orgX = r.ox; float invDirX = 1 / r.dx; float t1, t2; t1 = (minX - orgX) * invDirX; t2 = (maxX - orgX) * invDirX; int sideIn = -1, sideOut = -1; if (invDirX > 0) { if (t1 > intervalMin) { intervalMin = t1; sideIn = 0; } if (t2 < intervalMax) { intervalMax = t2; sideOut = 1; } } else { if (t2 > intervalMin) { intervalMin = t2; sideIn = 1; } if (t1 < intervalMax) { intervalMax = t1; sideOut = 0; } } if (intervalMin > intervalMax) return; float orgY = r.oy; float invDirY = 1 / r.dy; t1 = (minY - orgY) * invDirY; t2 = (maxY - orgY) * invDirY; if (invDirY > 0) { if (t1 > intervalMin) { intervalMin = t1; sideIn = 2; } if (t2 < intervalMax) { intervalMax = t2; sideOut = 3; } } else { if (t2 > intervalMin) { intervalMin = t2; sideIn = 3; } if (t1 < intervalMax) { intervalMax = t1; sideOut = 2; } } if (intervalMin > intervalMax) return; float orgZ = r.oz; float invDirZ = 1 / r.dz; t1 = (minZ - orgZ) * invDirZ; // no front wall t2 = (maxZ - orgZ) * invDirZ; if (invDirZ > 0) { if (t1 > intervalMin) { intervalMin = t1; sideIn = 4; } if (t2 < intervalMax) { intervalMax = t2; sideOut = 5; } } else { if (t2 > intervalMin) { intervalMin = t2; sideIn = 5; } if (t1 < intervalMax) { intervalMax = t1; sideOut = 4; } } if (intervalMin > intervalMax) return; if (r.isInside(intervalMin)) { r.setMax(intervalMin); state.setIntersection(sideIn, 0, 0); } else if (r.isInside(intervalMax)) { r.setMax(intervalMax); state.setIntersection(sideOut, 0, 0); } }
private void renderBucket(IDisplay display, int bx, int by, int threadID, IntersectionState istate) { // pixel sized extents int x0 = bx * bucketSize; int y0 = by * bucketSize; int bw = Math.Min(bucketSize, imageWidth - x0); int bh = Math.Min(bucketSize, imageHeight - y0); // prepare bucket display.imagePrepare(x0, y0, bw, bh, threadID); Color[] bucketRGB = new Color[bw * bh]; float[] bucketAlpha = new float[bw * bh]; // subpixel extents int sx0 = x0 * subPixelSize - fs; int sy0 = y0 * subPixelSize - fs; int sbw = bw * subPixelSize + fs * 2; int sbh = bh * subPixelSize + fs * 2; // round up to align with maximum step size sbw = (sbw + (maxStepSize - 1)) & (~(maxStepSize - 1)); sbh = (sbh + (maxStepSize - 1)) & (~(maxStepSize - 1)); // extra padding as needed if (maxStepSize > 1) { sbw++; sbh++; } // allocate bucket memory ImageSample[] samples = new ImageSample[sbw * sbh]; // allocate samples and compute jitter offsets float invSubPixelSize = 1.0f / subPixelSize; for (int y = 0, index = 0; y < sbh; y++) { for (int x = 0; x < sbw; x++, index++) { int sx = sx0 + x; int sy = sy0 + y; int j = sx & (sigmaLength - 1); int k = sy & (sigmaLength - 1); int i = (j << sigmaOrder) + QMC.sigma(k, sigmaOrder); float dx = useJitter ? (float) QMC.halton(0, k) : 0.5f; float dy = useJitter ? (float) QMC.halton(0, j) : 0.5f; float rx = (sx + dx) * invSubPixelSize; float ry = (sy + dy) * invSubPixelSize; ry = imageHeight - ry; samples[index] = new ImageSample(rx, ry, i); } } for (int x = 0; x < sbw - 1; x += maxStepSize) for (int y = 0; y < sbh - 1; y += maxStepSize) refineSamples(samples, sbw, x, y, maxStepSize, thresh, istate); if (dumpBuckets) { UI.printInfo(UI.Module.BCKT, "Dumping bucket [{0}, {1}] to file ...", bx, by); GenericBitmap bitmap = new GenericBitmap(sbw, sbh); for (int y = sbh - 1, index = 0; y >= 0; y--) for (int x = 0; x < sbw; x++, index++) bitmap.writePixel(x, y, samples[index].c, samples[index].alpha); bitmap.save(string.Format("bucket_{0}_{1}.png", bx, by)); } if (displayAA) { // color coded image of what is visible float invArea = invSubPixelSize * invSubPixelSize; for (int y = 0, index = 0; y < bh; y++) { for (int x = 0; x < bw; x++, index++) { int sampled = 0; for (int i = 0; i < subPixelSize; i++) { for (int j = 0; j < subPixelSize; j++) { int sx = x * subPixelSize + fs + i; int sy = y * subPixelSize + fs + j; int s = sx + sy * sbw; sampled += samples[s].sampled() ? 1 : 0; } } bucketRGB[index] = new Color(sampled * invArea); bucketAlpha[index] = 1.0f; } } } else { // filter samples into pixels float cy = imageHeight - (y0 + 0.5f); for (int y = 0, index = 0; y < bh; y++, cy--) { float cx = x0 + 0.5f; for (int x = 0; x < bw; x++, index++, cx++) { Color c = Color.black(); float a = 0.0f; float weight = 0.0f; for (int j = -fs, sy = y * subPixelSize; j <= fs; j++, sy++) { for (int i = -fs, sx = x * subPixelSize, s = sx + sy * sbw; i <= fs; i++, sx++, s++) { float dx = samples[s].rx - cx; if (Math.Abs(dx) > fhs) continue; float dy = samples[s].ry - cy; if (Math.Abs(dy) > fhs) continue; float f = filter.get(dx, dy); c.madd(f, samples[s].c); a += f * samples[s].alpha; weight += f; } } float invWeight = 1.0f / weight; c.mul(invWeight); a *= invWeight; bucketRGB[index] = c; bucketAlpha[index] = a; } } } // update pixels display.imageUpdate(x0, y0, bw, bh, bucketRGB, bucketAlpha); }
public Color traceShadow(Ray r, IntersectionState state) { state.numShadowRays++; trace(r, state); return(state.hit() ? Color.WHITE : Color.BLACK); }
public void intersectPrimitive(Ray r, int primID, IntersectionState state) { if (r.getMax() == float.PositiveInfinity) state.setIntersection(0, 0, 0); }
private void computeSubPixel(ImageSample sample, IntersectionState istate) { float x = sample.rx; float y = sample.ry; double q0 = QMC.halton(1, sample.i); double q1 = QMC.halton(2, sample.i); double q2 = QMC.halton(3, sample.i); if (superSampling > 1) { // multiple sampling sample.add(scene.getRadiance(istate, x, y, q1, q2, q0, sample.i, 4, null)); for (int i = 1; i < superSampling; i++) { double time = QMC.mod1(q0 + i * invSuperSampling); double lensU = QMC.mod1(q1 + QMC.halton(0, i)); double lensV = QMC.mod1(q2 + QMC.halton(1, i)); sample.add(scene.getRadiance(istate, x, y, lensU, lensV, time, sample.i + i, 4, null)); } sample.scale((float)invSuperSampling); } else { // single sample sample.set(scene.getRadiance(istate, x, y, q1, q2, q0, sample.i, 4, null)); } }
public void Run() { ByteUtil.InitByteUtil(); IntersectionState istate = new IntersectionState(); for (int i = start; i < end; i++) { lock (lockObj) { UI.taskUpdate(server.photonCounter); server.photonCounter++; if (UI.taskCanceled()) return; } int qmcI = i + seed; double rand = QMC.halton(0, qmcI) * histogram[histogram.Length - 1]; int j = 0; while (rand >= histogram[j] && j < histogram.Length) j++; // make sure we didn't pick a zero-probability light if (j == histogram.Length) continue; double randX1 = (j == 0) ? rand / histogram[0] : (rand - histogram[j]) / (histogram[j] - histogram[j - 1]); double randY1 = QMC.halton(1, qmcI); double randX2 = QMC.halton(2, qmcI); double randY2 = QMC.halton(3, qmcI); Point3 pt = new Point3(); Vector3 dir = new Vector3(); Color power = new Color(); server.lights[j].getPhoton(randX1, randY1, randX2, randY2, pt, dir, power); power.mul(scale); Ray r = new Ray(pt, dir); server.scene.trace(r, istate); if (istate.hit()) server.shadePhoton(ShadingState.createPhotonState(r, istate, qmcI, map, server), power); } }
private void refineSamples(ImageSample[] samples, int sbw, int x, int y, int stepSize, float thresh, IntersectionState istate) { int dx = stepSize; int dy = stepSize * sbw; int i00 = x + y * sbw; ImageSample s00 = samples[i00]; ImageSample s01 = samples[i00 + dy]; ImageSample s10 = samples[i00 + dx]; ImageSample s11 = samples[i00 + dx + dy]; if (!s00.sampled()) computeSubPixel(s00, istate); if (!s01.sampled()) computeSubPixel(s01, istate); if (!s10.sampled()) computeSubPixel(s10, istate); if (!s11.sampled()) computeSubPixel(s11, istate); if (stepSize > minStepSize) { if (s00.isDifferent(s01, thresh) || s00.isDifferent(s10, thresh) || s00.isDifferent(s11, thresh) || s01.isDifferent(s11, thresh) || s10.isDifferent(s11, thresh) || s01.isDifferent(s10, thresh)) { stepSize >>= 1; thresh *= 2; refineSamples(samples, sbw, x, y, stepSize, thresh, istate); refineSamples(samples, sbw, x + stepSize, y, stepSize, thresh, istate); refineSamples(samples, sbw, x, y + stepSize, stepSize, thresh, istate); refineSamples(samples, sbw, x + stepSize, y + stepSize, stepSize, thresh, istate); return; } } // interpolate remaining samples float ds = 1.0f / stepSize; for (int i = 0; i <= stepSize; i++) for (int j = 0; j <= stepSize; j++) if (!samples[x + i + (y + j) * sbw].processed()) ImageSample.bilerp(samples[x + i + (y + j) * sbw], s00, s01, s10, s11, i * ds, j * ds); }