public void scatterPhoton(ShadingState state, Color power) { Color diffuse, specular; // make sure we are on the right side of the material state.faceforward(); diffuse = getDiffuse(state); specular = getSpecular(state); state.storePhoton(state.getRay().getDirection(), power, diffuse); float d = diffuse.getAverage(); float r = specular.getAverage(); double rnd = state.getRandom(0, 0, 1); if (rnd < d) { // photon is scattered power.mul(diffuse).mul(1.0f / d); OrthoNormalBasis onb = state.getBasis(); double u = 2 * Math.PI * rnd / d; double v = state.getRandom(0, 1, 1); float s = (float)Math.Sqrt(v); float s1 = (float)Math.Sqrt(1.0 - v); Vector3 w = new Vector3((float)Math.Cos(u) * s, (float)Math.Sin(u) * s, s1); w = onb.transform(w, new Vector3()); state.traceDiffusePhoton(new Ray(state.getPoint(), w), power); } else if (rnd < d + r) { if (glossyness == 0) { float cos = -Vector3.dot(state.getNormal(), state.getRay().getDirection()); power.mul(diffuse).mul(1.0f / d); // photon is reflected float dn = 2 * cos; Vector3 dir = new Vector3(); dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x; dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y; dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z; state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power); } else { float dn = 2.0f * state.getCosND(); // reflected direction Vector3 refDir = new Vector3(); refDir.x = (dn * state.getNormal().x) + state.getRay().dx; refDir.y = (dn * state.getNormal().y) + state.getRay().dy; refDir.z = (dn * state.getNormal().z) + state.getRay().dz; power.mul(spec).mul(1.0f / r); OrthoNormalBasis onb = state.getBasis(); double u = 2 * Math.PI * (rnd - r) / r; double v = state.getRandom(0, 1, 1); float s = (float)Math.Pow(v, 1 / ((1.0f / glossyness) + 1)); float s1 = (float)Math.Sqrt(1 - s * s); Vector3 w = new Vector3((float)Math.Cos(u) * s1, (float)Math.Sin(u) * s1, s); w = onb.transform(w, new Vector3()); state.traceReflectionPhoton(new Ray(state.getPoint(), w), power); } } }
public void prepareShadingState(ShadingState state) { state.init(); Instance i = state.getInstance(); state.getRay().getPoint(state.getPoint()); Ray r = state.getRay(); IShader s = i.getShader(0); state.setShader(s != null ? s : this); int primID = state.getPrimitiveID(); int hair = primID / numSegments; int line = primID % numSegments; int vRoot = hair * 3 * (numSegments + 1); int v0 = vRoot + line * 3; // tangent vector Vector3 v = getTangent(line, v0, state.getV()); v = state.transformVectorObjectToWorld(v); state.setBasis(OrthoNormalBasis.makeFromWV(v, new Vector3(-r.dx, -r.dy, -r.dz))); state.getBasis().swapVW(); // normal state.getNormal().set(0, 0, 1); state.getBasis().transform(state.getNormal()); state.getGeoNormal().set(state.getNormal()); state.getUV().set(0, (line + state.getV()) / numSegments); }
public void scatterPhoton(ShadingState state, Color power) { Color diffuse; // make sure we are on the right side of the material if (Vector3.dot(state.getNormal(), state.getRay().getDirection()) > 0.0) { state.getNormal().negate(); state.getGeoNormal().negate(); } diffuse = getDiffuse(state); state.storePhoton(state.getRay().getDirection(), power, diffuse); float avg = diffuse.getAverage(); double rnd = state.getRandom(0, 0, 1); if (rnd < avg) { // photon is scattered power.mul(diffuse).mul(1.0f / avg); OrthoNormalBasis onb = state.getBasis(); double u = 2 * Math.PI * rnd / avg; double v = state.getRandom(0, 1, 1); float s = (float)Math.Sqrt(v); float s1 = (float)Math.Sqrt(1.0 - v); Vector3 w = new Vector3((float)Math.Cos(u) * s, (float)Math.Sin(u) * s, s1); w = onb.transform(w, new Vector3()); state.traceDiffusePhoton(new Ray(state.getPoint(), w), power); } }
public Color getIrradiance(ShadingState state, Color diffuseReflectance) { if (samples <= 0) return Color.BLACK; // compute new sample Color irr = Color.black(); OrthoNormalBasis onb = state.getBasis(); Vector3 w = new Vector3(); int n = state.getDiffuseDepth() == 0 ? samples : 1; for (int i = 0; i < n; i++) { float xi = (float)state.getRandom(i, 0, n); float xj = (float)state.getRandom(i, 1, n); float phi = (float)(xi * 2 * Math.PI); float cosPhi = (float)Math.Cos(phi); float sinPhi = (float)Math.Sin(phi); float sinTheta = (float)Math.Sqrt(xj); float cosTheta = (float)Math.Sqrt(1.0f - xj); w.x = cosPhi * sinTheta; w.y = sinPhi * sinTheta; w.z = cosTheta; onb.transform(w); ShadingState temp = state.traceFinalGather(new Ray(state.getPoint(), w), i); if (temp != null) { temp.getInstance().prepareShadingState(temp); if (temp.getShader() != null) irr.add(temp.getShader().getRadiance(temp)); } } irr.mul((float)Math.PI / n); return irr; }
public Color GetRadiance(ShadingState state) { // don't use these - gather lights for sphere of directions // gather lights state.initLightSamples(); state.initCausticSamples(); Vector3 v = state.getRay().getDirection(); v.negate(); Vector3 h = new Vector3(); Vector3 t = state.getBasis().transform(new Vector3(0, 1, 0)); Color diff = Color.black(); Color spec = Color.black(); foreach (LightSample ls in state) { Vector3 l = ls.getShadowRay().getDirection(); float dotTL = Vector3.dot(t, l); float sinTL = (float)Math.Sqrt(1 - dotTL * dotTL); // float dotVL = Vector3.dot(v, l); diff.madd(sinTL, ls.getDiffuseRadiance()); Vector3.add(v, l, h); h.normalize(); float dotTH = Vector3.dot(t, h); float sinTH = (float)Math.Sqrt(1 - dotTH * dotTH); float s = (float)Math.Pow(sinTH, 10.0f); spec.madd(s, ls.getSpecularRadiance()); } Color c = Color.add(diff, spec, new Color()); // transparency return(Color.blend(c, state.traceTransparency(), state.getV(), new Color())); }
public Color getRadiance(ShadingState state) { // don't use these - gather lights for sphere of directions // gather lights state.initLightSamples(); state.initCausticSamples(); Vector3 v = state.getRay().getDirection(); v.negate(); Vector3 h = new Vector3(); Vector3 t = state.getBasis().transform(new Vector3(0, 1, 0)); Color diff = Color.black(); Color spec = Color.black(); foreach (LightSample ls in state) { Vector3 l = ls.getShadowRay().getDirection(); float dotTL = Vector3.dot(t, l); float sinTL = (float)Math.Sqrt(1 - dotTL * dotTL); // float dotVL = Vector3.dot(v, l); diff.madd(sinTL, ls.getDiffuseRadiance()); Vector3.add(v, l, h); h.normalize(); float dotTH = Vector3.dot(t, h); float sinTH = (float)Math.Sqrt(1 - dotTH * dotTH); float s = (float)Math.Pow(sinTH, 10.0f); spec.madd(s, ls.getSpecularRadiance()); } Color c = Color.add(diff, spec, new Color()); // transparency return Color.blend(c, state.traceTransparency(), state.getV(), new Color()); }
public Color getIrradiance(ShadingState state, Color diffuseReflectance) { OrthoNormalBasis onb = state.getBasis(); Vector3 w = new Vector3(); Color result = Color.black(); for (int i = 0; i < samples; i++) { float xi = (float)state.getRandom(i, 0, samples); float xj = (float)state.getRandom(i, 1, samples); float phi = (float)(2 * Math.PI * xi); float cosPhi = (float)Math.Cos(phi); float sinPhi = (float)Math.Sin(phi); float sinTheta = (float)Math.Sqrt(xj); float cosTheta = (float)Math.Sqrt(1.0f - xj); w.x = cosPhi * sinTheta; w.y = sinPhi * sinTheta; w.z = cosTheta; onb.transform(w); Ray r = new Ray(state.getPoint(), w); r.setMax(maxDist); result.add(Color.blend(bright, dark, state.traceShadow(r))); } return(result.mul((float)Math.PI / samples)); }
public void ScatterPhoton(ShadingState state, Color power) { Color diffuse; // make sure we are on the right side of the material if (Vector3.dot(state.getNormal(), state.getRay().getDirection()) > 0.0) { state.getNormal().negate(); state.getGeoNormal().negate(); } diffuse = Color.GRAY; state.storePhoton(state.getRay().getDirection(), power, diffuse); float avg = diffuse.getAverage(); double rnd = state.getRandom(0, 0, 1); if (rnd < avg) { // photon is scattered power.mul(diffuse).mul(1.0f / avg); OrthoNormalBasis onb = state.getBasis(); double u = 2 * Math.PI * rnd / avg; double v = state.getRandom(0, 1, 1); float s = (float)Math.Sqrt(v); float s1 = (float)Math.Sqrt(1.0 - v); Vector3 w = new Vector3((float)Math.Cos(u) * s, (float)Math.Sin(u) * s, s1); w = onb.transform(w, new Vector3()); state.traceDiffusePhoton(new Ray(state.getPoint(), w), power); } }
public void scatterPhoton(ShadingState state, Color power) { // make sure we are on the right side of the material state.faceforward(); Color d = getDiffuse(state); state.storePhoton(state.getRay().getDirection(), power, d); float avgD = d.getAverage(); float avgS = spec.getAverage(); double rnd = state.getRandom(0, 0, 1); if (rnd < avgD) { // photon is scattered diffusely power.mul(d).mul(1.0f / avgD); OrthoNormalBasis onb = state.getBasis(); double u = 2 * Math.PI * rnd / avgD; double v = state.getRandom(0, 1, 1); float s = (float)Math.Sqrt(v); float s1 = (float)Math.Sqrt(1.0f - v); Vector3 w = new Vector3((float)Math.Cos(u) * s, (float)Math.Sin(u) * s, s1); w = onb.transform(w, new Vector3()); state.traceDiffusePhoton(new Ray(state.getPoint(), w), power); } else if (rnd < avgD + avgS) { // photon is scattered specularly float dn = 2.0f * state.getCosND(); // reflected direction Vector3 refDir = new Vector3(); refDir.x = (dn * state.getNormal().x) + state.getRay().dx; refDir.y = (dn * state.getNormal().y) + state.getRay().dy; refDir.z = (dn * state.getNormal().z) + state.getRay().dz; power.mul(spec).mul(1.0f / avgS); OrthoNormalBasis onb = state.getBasis(); double u = 2 * Math.PI * (rnd - avgD) / avgS; double v = state.getRandom(0, 1, 1); float s = (float)Math.Pow(v, 1 / (this.power + 1)); float s1 = (float)Math.Sqrt(1 - s * s); Vector3 w = new Vector3((float)Math.Cos(u) * s1, (float)Math.Sin(u) * s1, s); w = onb.transform(w, new Vector3()); state.traceReflectionPhoton(new Ray(state.getPoint(), w), power); } }
public Color getIrradiance(ShadingState state, Color diffuseReflectance) { if (samples <= 0) { return(Color.BLACK); } // compute new sample Color irr = Color.black(); OrthoNormalBasis onb = state.getBasis(); Vector3 w = new Vector3(); int n = state.getDiffuseDepth() == 0 ? samples : 1; for (int i = 0; i < n; i++) { float xi = (float)state.getRandom(i, 0, n); float xj = (float)state.getRandom(i, 1, n); float phi = (float)(xi * 2 * Math.PI); float cosPhi = (float)Math.Cos(phi); float sinPhi = (float)Math.Sin(phi); float sinTheta = (float)Math.Sqrt(xj); float cosTheta = (float)Math.Sqrt(1.0f - xj); w.x = cosPhi * sinTheta; w.y = sinPhi * sinTheta; w.z = cosTheta; onb.transform(w); ShadingState temp = state.traceFinalGather(new Ray(state.getPoint(), w), i); if (temp != null) { temp.getInstance().prepareShadingState(temp); if (temp.getShader() != null) { irr.add(temp.getShader().getRadiance(temp)); } } } irr.mul((float)Math.PI / n); return(irr); }
public void scatterPhoton(ShadingState state, Color power) { Color diffuse; // make sure we are on the right side of the material state.faceforward(); diffuse = getDiffuse(state); state.storePhoton(state.getRay().getDirection(), power, diffuse); float d = diffuse.getAverage(); float r = d * refl; double rnd = state.getRandom(0, 0, 1); if (rnd < d) { // photon is scattered power.mul(diffuse).mul(1.0f / d); OrthoNormalBasis onb = state.getBasis(); double u = 2 * Math.PI * rnd / d; double v = state.getRandom(0, 1, 1); float s = (float)Math.Sqrt(v); float s1 = (float)Math.Sqrt(1.0 - v); Vector3 w = new Vector3((float)Math.Cos(u) * s, (float)Math.Sin(u) * s, s1); w = onb.transform(w, new Vector3()); state.traceDiffusePhoton(new Ray(state.getPoint(), w), power); } else if (rnd < d + r) { float cos = -Vector3.dot(state.getNormal(), state.getRay().getDirection()); power.mul(diffuse).mul(1.0f / d); // photon is reflected float dn = 2 * cos; Vector3 dir = new Vector3(); dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x; dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y; dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z; state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power); } }
public Color getIrradiance(ShadingState state, Color diffuseReflectance) { OrthoNormalBasis onb = state.getBasis(); Vector3 w = new Vector3(); Color result = Color.black(); for (int i = 0; i < samples; i++) { float xi = (float)state.getRandom(i, 0, samples); float xj = (float)state.getRandom(i, 1, samples); float phi = (float)(2 * Math.PI * xi); float cosPhi = (float)Math.Cos(phi); float sinPhi = (float)Math.Sin(phi); float sinTheta = (float)Math.Sqrt(xj); float cosTheta = (float)Math.Sqrt(1.0f - xj); w.x = cosPhi * sinTheta; w.y = sinPhi * sinTheta; w.z = cosTheta; onb.transform(w); Ray r = new Ray(state.getPoint(), w); r.setMax(maxDist); result.add(Color.blend(bright, dark, state.traceShadow(r))); } return result.mul((float)Math.PI / samples); }
public void ScatterPhoton(ShadingState state, Color power) { Color diffuse; // make sure we are on the right side of the material state.faceforward(); diffuse = getDiffuse(state); state.storePhoton(state.getRay().getDirection(), power, diffuse); float d = diffuse.getAverage(); float r = d * refl; double rnd = state.getRandom(0, 0, 1); if (rnd < d) { // photon is scattered power.mul(diffuse).mul(1.0f / d); OrthoNormalBasis onb = state.getBasis(); double u = 2 * Math.PI * rnd / d; double v = state.getRandom(0, 1, 1); float s = (float)Math.Sqrt(v); float s1 = (float)Math.Sqrt(1.0 - v); Vector3 w = new Vector3((float)Math.Cos(u) * s, (float)Math.Sin(u) * s, s1); w = onb.transform(w, new Vector3()); state.traceDiffusePhoton(new Ray(state.getPoint(), w), power); } else if (rnd < d + r) { float cos = -Vector3.dot(state.getNormal(), state.getRay().getDirection()); power.mul(diffuse).mul(1.0f / d); // photon is reflected float dn = 2 * cos; Vector3 dir = new Vector3(); dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x; dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y; dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z; state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power); } }
public void modify(ShadingState state) { // apply bump state.getNormal().set(bumpTexture.getBump(state.getUV().x, state.getUV().y, state.getBasis(), scale)); state.setBasis(OrthoNormalBasis.makeFromW(state.getNormal())); }
public void ScatterPhoton(ShadingState state, Color power) { // make sure we are on the right side of the material state.faceforward(); Color d = getDiffuse(state); state.storePhoton(state.getRay().getDirection(), power, d); float avgD = d.getAverage(); float avgS = rhoS.getAverage(); double rnd = state.getRandom(0, 0, 1); if (rnd < avgD) { // photon is scattered diffusely power.mul(d).mul(1.0f / avgD); OrthoNormalBasis onb = state.getBasis(); double u = 2 * Math.PI * rnd / avgD; double v = state.getRandom(0, 1, 1); float s = (float)Math.Sqrt(v); float s1 = (float)Math.Sqrt(1.0f - v); Vector3 w = new Vector3((float)Math.Cos(u) * s, (float)Math.Sin(u) * s, s1); w = onb.transform(w, new Vector3()); state.traceDiffusePhoton(new Ray(state.getPoint(), w), power); } else if (rnd < avgD + avgS) { // photon is scattered specularly power.mul(rhoS).mul(1 / avgS); OrthoNormalBasis basis = state.getBasis(); Vector3 inv = state.getRay().getDirection().negate(new Vector3()); double r1 = rnd / avgS; double r2 = state.getRandom(0, 1, 1); float alphaRatio = alphaY / alphaX; float phi = 0; if (r1 < 0.25) { double val = 4 * r1; phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); } else if (r1 < 0.5) { double val = 1 - 4 * (0.5 - r1); phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); phi = (float)Math.PI - phi; } else if (r1 < 0.75) { double val = 4 * (r1 - 0.5); phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); phi += (float)Math.PI; } else { double val = 1 - 4 * (1 - r1); phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); phi = 2 * (float)Math.PI - phi; } float cosPhi = (float)Math.Cos(phi); float sinPhi = (float)Math.Sin(phi); float denom = (cosPhi * cosPhi) / (alphaX * alphaX) + (sinPhi * sinPhi) / (alphaY * alphaY); float theta = (float)Math.Atan(Math.Sqrt(-Math.Log(1 - r2) / denom)); float sinTheta = (float)Math.Sin(theta); float cosTheta = (float)Math.Cos(theta); Vector3 h = new Vector3(); h.x = sinTheta * cosPhi; h.y = sinTheta * sinPhi; h.z = cosTheta; basis.transform(h); Vector3 o = new Vector3(); float ih = Vector3.dot(h, inv); o.x = 2 * ih * h.x - inv.x; o.y = 2 * ih * h.y - inv.y; o.z = 2 * ih * h.z - inv.z; Ray r = new Ray(state.getPoint(), o); state.traceReflectionPhoton(r, power); } }
public void prepareShadingState(ShadingState state) { state.init(); Instance i = state.getInstance(); state.getRay().getPoint(state.getPoint()); Ray r = state.getRay(); IShader s = i.getShader(0); state.setShader(s != null ? s : this); int primID = state.getPrimitiveID(); int hair = primID / numSegments; int line = primID % numSegments; int vRoot = hair * 3 * (numSegments + 1); int v0 = vRoot + line * 3; // tangent vector Vector3 v = getTangent(line, v0, state.getV()); v = i.transformVectorObjectToWorld(v); state.setBasis(OrthoNormalBasis.makeFromWV(v, new Vector3(-r.dx, -r.dy, -r.dz))); state.getBasis().swapVW(); // normal state.getNormal().set(0, 0, 1); state.getBasis().transform(state.getNormal()); state.getGeoNormal().set(state.getNormal()); state.getUV().set(0, (line + state.getV()) / numSegments); }
public void ScatterPhoton(ShadingState state, Color power) { Color diffuse, specular; // make sure we are on the right side of the material state.faceforward(); diffuse = getDiffuse(state); specular = getSpecular(state); state.storePhoton(state.getRay().getDirection(), power, diffuse); float d = diffuse.getAverage(); float r = specular.getAverage(); double rnd = state.getRandom(0, 0, 1); if (rnd < d) { // photon is scattered power.mul(diffuse).mul(1.0f / d); OrthoNormalBasis onb = state.getBasis(); double u = 2 * Math.PI * rnd / d; double v = state.getRandom(0, 1, 1); float s = (float)Math.Sqrt(v); float s1 = (float)Math.Sqrt(1.0 - v); Vector3 w = new Vector3((float)Math.Cos(u) * s, (float)Math.Sin(u) * s, s1); w = onb.transform(w, new Vector3()); state.traceDiffusePhoton(new Ray(state.getPoint(), w), power); } else if (rnd < d + r) { if (glossyness == 0) { float cos = -Vector3.dot(state.getNormal(), state.getRay().getDirection()); power.mul(diffuse).mul(1.0f / d); // photon is reflected float dn = 2 * cos; Vector3 dir = new Vector3(); dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x; dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y; dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z; state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power); } else { float dn = 2.0f * state.getCosND(); // reflected direction Vector3 refDir = new Vector3(); refDir.x = (dn * state.getNormal().x) + state.getRay().dx; refDir.y = (dn * state.getNormal().y) + state.getRay().dy; refDir.z = (dn * state.getNormal().z) + state.getRay().dz; power.mul(spec).mul(1.0f / r); OrthoNormalBasis onb = state.getBasis(); double u = 2 * Math.PI * (rnd - r) / r; double v = state.getRandom(0, 1, 1); float s = (float)Math.Pow(v, 1 / ((1.0f / glossyness) + 1)); float s1 = (float)Math.Sqrt(1 - s * s); Vector3 w = new Vector3((float)Math.Cos(u) * s1, (float)Math.Sin(u) * s1, s); w = onb.transform(w, new Vector3()); state.traceReflectionPhoton(new Ray(state.getPoint(), w), power); } } }
public Color GetRadiance(ShadingState state) { // make sure we are on the right side of the material state.faceforward(); OrthoNormalBasis onb = state.getBasis(); // direct lighting and caustics state.initLightSamples(); state.initCausticSamples(); Color lr = Color.black(); // compute specular contribution if (state.includeSpecular) { Vector3 inv = state.getRay().getDirection().negate(new Vector3()); foreach (LightSample sample in state) { float cosNL = sample.dot(state.getNormal()); float fr = brdf(inv, sample.getShadowRay().getDirection(), onb); lr.madd(cosNL * fr, sample.getSpecularRadiance()); } // indirect lighting - specular if (numRays > 0) { int n = state.getDepth() == 0 ? numRays : 1; for (int i = 0; i < n; i++) { // specular indirect lighting double r1 = state.getRandom(i, 0, n); double r2 = state.getRandom(i, 1, n); float alphaRatio = alphaY / alphaX; float phi = 0; if (r1 < 0.25) { double val = 4 * r1; phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); } else if (r1 < 0.5) { double val = 1 - 4 * (0.5 - r1); phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); phi = (float)Math.PI - phi; } else if (r1 < 0.75) { double val = 4 * (r1 - 0.5); phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); phi += (float)Math.PI; } else { double val = 1 - 4 * (1 - r1); phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); phi = 2 * (float)Math.PI - phi; } float cosPhi = (float)Math.Cos(phi); float sinPhi = (float)Math.Sin(phi); float denom = (cosPhi * cosPhi) / (alphaX * alphaX) + (sinPhi * sinPhi) / (alphaY * alphaY); float theta = (float)Math.Atan(Math.Sqrt(-Math.Log(1 - r2) / denom)); float sinTheta = (float)Math.Sin(theta); float cosTheta = (float)Math.Cos(theta); Vector3 h = new Vector3(); h.x = sinTheta * cosPhi; h.y = sinTheta * sinPhi; h.z = cosTheta; onb.transform(h); Vector3 o = new Vector3(); float ih = Vector3.dot(h, inv); o.x = 2 * ih * h.x - inv.x; o.y = 2 * ih * h.y - inv.y; o.z = 2 * ih * h.z - inv.z; float no = onb.untransformZ(o); float ni = onb.untransformZ(inv); float w = ih * cosTheta * cosTheta * cosTheta * (float)Math.Sqrt(Math.Abs(no / ni)); Ray r = new Ray(state.getPoint(), o); lr.madd(w / n, state.traceGlossy(r, i)); } } lr.mul(rhoS); } // add diffuse contribution lr.add(state.diffuse(getDiffuse(state))); return(lr); }
public void modify(ShadingState state) { // apply normal map state.getNormal().set(normalMap.getNormal(state.getUV().x, state.getUV().y, state.getBasis())); state.setBasis(OrthoNormalBasis.makeFromW(state.getNormal())); }
public Color getIrradiance(ShadingState state, Color diffuseReflectance) { float b = (float)Math.PI * c / diffuseReflectance.getMax(); Color irr = Color.black(); Point3 p = state.getPoint(); Vector3 n = state.getNormal(); int set = (int)(state.getRandom(0, 1, 1) * numSets); foreach (PointLight vpl in virtualLights[set]) { Ray r = new Ray(p, vpl.p); float dotNlD = -(r.dx * vpl.n.x + r.dy * vpl.n.y + r.dz * vpl.n.z); float dotND = r.dx * n.x + r.dy * n.y + r.dz * n.z; if (dotNlD > 0 && dotND > 0) { float r2 = r.getMax() * r.getMax(); Color opacity = state.traceShadow(r); Color power = Color.blend(vpl.power, Color.BLACK, opacity); float g = (dotND * dotNlD) / r2; irr.madd(0.25f * Math.Min(g, b), power); } } // bias compensation int nb = (state.getDiffuseDepth() == 0 || numBias <= 0) ? numBias : 1; if (nb <= 0) { return(irr); } OrthoNormalBasis onb = state.getBasis(); Vector3 w = new Vector3(); float scale = (float)Math.PI / nb; for (int i = 0; i < nb; i++) { float xi = (float)state.getRandom(i, 0, nb); float xj = (float)state.getRandom(i, 1, nb); float phi = (float)(xi * 2 * Math.PI); float cosPhi = (float)Math.Cos(phi); float sinPhi = (float)Math.Sin(phi); float sinTheta = (float)Math.Sqrt(xj); float cosTheta = (float)Math.Sqrt(1.0f - xj); w.x = cosPhi * sinTheta; w.y = sinPhi * sinTheta; w.z = cosTheta; onb.transform(w); Ray r = new Ray(state.getPoint(), w); r.setMax((float)Math.Sqrt(cosTheta / b)); ShadingState temp = state.traceFinalGather(r, i); if (temp != null) { temp.getInstance().prepareShadingState(temp); if (temp.getShader() != null) { float dist = temp.getRay().getMax(); float r2 = dist * dist; float cosThetaY = -Vector3.dot(w, temp.getNormal()); if (cosThetaY > 0) { float g = (cosTheta * cosThetaY) / r2; // was this path accounted for yet? if (g > b) { irr.madd(scale * (g - b) / g, temp.getShader().GetRadiance(temp)); } } } } } return(irr); }
public Color getIrradiance(ShadingState state, Color diffuseReflectance) { float b = (float)Math.PI * c / diffuseReflectance.getMax(); Color irr = Color.black(); Point3 p = state.getPoint(); Vector3 n = state.getNormal(); int set = (int)(state.getRandom(0, 1, 1) * numSets); foreach (PointLight vpl in virtualLights[set]) { Ray r = new Ray(p, vpl.p); float dotNlD = -(r.dx * vpl.n.x + r.dy * vpl.n.y + r.dz * vpl.n.z); float dotND = r.dx * n.x + r.dy * n.y + r.dz * n.z; if (dotNlD > 0 && dotND > 0) { float r2 = r.getMax() * r.getMax(); Color opacity = state.traceShadow(r); Color power = Color.blend(vpl.power, Color.BLACK, opacity); float g = (dotND * dotNlD) / r2; irr.madd(0.25f * Math.Min(g, b), power); } } // bias compensation int nb = (state.getDiffuseDepth() == 0 || numBias <= 0) ? numBias : 1; if (nb <= 0) return irr; OrthoNormalBasis onb = state.getBasis(); Vector3 w = new Vector3(); float scale = (float)Math.PI / nb; for (int i = 0; i < nb; i++) { float xi = (float)state.getRandom(i, 0, nb); float xj = (float)state.getRandom(i, 1, nb); float phi = (float)(xi * 2 * Math.PI); float cosPhi = (float)Math.Cos(phi); float sinPhi = (float)Math.Sin(phi); float sinTheta = (float)Math.Sqrt(xj); float cosTheta = (float)Math.Sqrt(1.0f - xj); w.x = cosPhi * sinTheta; w.y = sinPhi * sinTheta; w.z = cosTheta; onb.transform(w); Ray r = new Ray(state.getPoint(), w); r.setMax((float)Math.Sqrt(cosTheta / b)); ShadingState temp = state.traceFinalGather(r, i); if (temp != null) { temp.getInstance().prepareShadingState(temp); if (temp.getShader() != null) { float dist = temp.getRay().getMax(); float r2 = dist * dist; float cosThetaY = -Vector3.dot(w, temp.getNormal()); if (cosThetaY > 0) { float g = (cosTheta * cosThetaY) / r2; // was this path accounted for yet? if (g > b) irr.madd(scale * (g - b) / g, temp.getShader().getRadiance(temp)); } } } } return irr; }
public Color getIrradiance(ShadingState state, Color diffuseReflectance) { if (samples <= 0) return Color.BLACK; if (state.getDiffuseDepth() > 0) { // do simple path tracing for additional bounces (single ray) float xi = (float)state.getRandom(0, 0, 1); float xj = (float)state.getRandom(0, 1, 1); float phi = (float)(xi * 2 * Math.PI); float cosPhi = (float)Math.Cos(phi); float sinPhi = (float)Math.Sin(phi); float sinTheta = (float)Math.Sqrt(xj); float cosTheta = (float)Math.Sqrt(1.0f - xj); Vector3 w = new Vector3(); w.x = cosPhi * sinTheta; w.y = sinPhi * sinTheta; w.z = cosTheta; OrthoNormalBasis onb = state.getBasis(); onb.transform(w); Ray r = new Ray(state.getPoint(), w); ShadingState temp = state.traceFinalGather(r, 0); return temp != null ? getGlobalRadiance(temp).copy().mul((float)Math.PI) : Color.BLACK; } //rwl.readLock().lockwoot();//fixme Color irr; lock(lockObj) irr = getIrradiance(state.getPoint(), state.getNormal()); //rwl.readLock().unlock(); if (irr == null) { // compute new sample irr = Color.black(); OrthoNormalBasis onb = state.getBasis(); float invR = 0; float minR = float.PositiveInfinity; Vector3 w = new Vector3(); for (int i = 0; i < samples; i++) { float xi = (float)state.getRandom(i, 0, samples); float xj = (float)state.getRandom(i, 1, samples); float phi = (float)(xi * 2 * Math.PI); float cosPhi = (float)Math.Cos(phi); float sinPhi = (float)Math.Sin(phi); float sinTheta = (float)Math.Sqrt(xj); float cosTheta = (float)Math.Sqrt(1.0f - xj); w.x = cosPhi * sinTheta; w.y = sinPhi * sinTheta; w.z = cosTheta; onb.transform(w); Ray r = new Ray(state.getPoint(), w); ShadingState temp = state.traceFinalGather(r, i); if (temp != null) { minR = Math.Min(r.getMax(), minR); invR += 1.0f / r.getMax(); temp.getInstance().prepareShadingState(temp); irr.add(getGlobalRadiance(temp)); } } irr.mul((float)Math.PI / samples); invR = samples / invR; //rwl.writeLock().lockwoot();//fixme lock(lockObj) insert(state.getPoint(), state.getNormal(), invR, irr); //rwl.writeLock().unlock(); // view irr-cache points // irr = Color.YELLOW.copy().mul(1e6f); } return irr; }
public Color getRadiance(ShadingState state) { // make sure we are on the right side of the material state.faceforward(); OrthoNormalBasis onb = state.getBasis(); // direct lighting and caustics state.initLightSamples(); state.initCausticSamples(); Color lr = Color.black(); // compute specular contribution if (state.includeSpecular) { Vector3 inv = state.getRay().getDirection().negate(new Vector3()); foreach (LightSample sample in state) { float cosNL = sample.dot(state.getNormal()); float fr = brdf(inv, sample.getShadowRay().getDirection(), onb); lr.madd(cosNL * fr, sample.getSpecularRadiance()); } // indirect lighting - specular if (numRays > 0) { int n = state.getDepth() == 0 ? numRays : 1; for (int i = 0; i < n; i++) { // specular indirect lighting double r1 = state.getRandom(i, 0, n); double r2 = state.getRandom(i, 1, n); float alphaRatio = alphaY / alphaX; float phi = 0; if (r1 < 0.25) { double val = 4 * r1; phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); } else if (r1 < 0.5) { double val = 1 - 4 * (0.5 - r1); phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); phi = (float)Math.PI - phi; } else if (r1 < 0.75) { double val = 4 * (r1 - 0.5); phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); phi += (float)Math.PI; } else { double val = 1 - 4 * (1 - r1); phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); phi = 2 * (float)Math.PI - phi; } float cosPhi = (float)Math.Cos(phi); float sinPhi = (float)Math.Sin(phi); float denom = (cosPhi * cosPhi) / (alphaX * alphaX) + (sinPhi * sinPhi) / (alphaY * alphaY); float theta = (float)Math.Atan(Math.Sqrt(-Math.Log(1 - r2) / denom)); float sinTheta = (float)Math.Sin(theta); float cosTheta = (float)Math.Cos(theta); Vector3 h = new Vector3(); h.x = sinTheta * cosPhi; h.y = sinTheta * sinPhi; h.z = cosTheta; onb.transform(h); Vector3 o = new Vector3(); float ih = Vector3.dot(h, inv); o.x = 2 * ih * h.x - inv.x; o.y = 2 * ih * h.y - inv.y; o.z = 2 * ih * h.z - inv.z; float no = onb.untransformZ(o); float ni = onb.untransformZ(inv); float w = ih * cosTheta * cosTheta * cosTheta * (float)Math.Sqrt(Math.Abs(no / ni)); Ray r = new Ray(state.getPoint(), o); lr.madd(w / n, state.traceGlossy(r, i)); } } lr.mul(rhoS); } // add diffuse contribution lr.add(state.diffuse(getDiffuse(state))); return lr; }
public void scatterPhoton(ShadingState state, Color power) { // make sure we are on the right side of the material state.faceforward(); Color d = getDiffuse(state); state.storePhoton(state.getRay().getDirection(), power, d); float avgD = d.getAverage(); float avgS = rhoS.getAverage(); double rnd = state.getRandom(0, 0, 1); if (rnd < avgD) { // photon is scattered diffusely power.mul(d).mul(1.0f / avgD); OrthoNormalBasis onb = state.getBasis(); double u = 2 * Math.PI * rnd / avgD; double v = state.getRandom(0, 1, 1); float s = (float)Math.Sqrt(v); float s1 = (float)Math.Sqrt(1.0f - v); Vector3 w = new Vector3((float)Math.Cos(u) * s, (float)Math.Sin(u) * s, s1); w = onb.transform(w, new Vector3()); state.traceDiffusePhoton(new Ray(state.getPoint(), w), power); } else if (rnd < avgD + avgS) { // photon is scattered specularly power.mul(rhoS).mul(1 / avgS); OrthoNormalBasis basis = state.getBasis(); Vector3 inv = state.getRay().getDirection().negate(new Vector3()); double r1 = rnd / avgS; double r2 = state.getRandom(0, 1, 1); float alphaRatio = alphaY / alphaX; float phi = 0; if (r1 < 0.25) { double val = 4 * r1; phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); } else if (r1 < 0.5) { double val = 1 - 4 * (0.5 - r1); phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); phi = (float)Math.PI - phi; } else if (r1 < 0.75) { double val = 4 * (r1 - 0.5); phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); phi += (float)Math.PI; } else { double val = 1 - 4 * (1 - r1); phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val)); phi = 2 * (float)Math.PI - phi; } float cosPhi = (float)Math.Cos(phi); float sinPhi = (float)Math.Sin(phi); float denom = (cosPhi * cosPhi) / (alphaX * alphaX) + (sinPhi * sinPhi) / (alphaY * alphaY); float theta = (float)Math.Atan(Math.Sqrt(-Math.Log(1 - r2) / denom)); float sinTheta = (float)Math.Sin(theta); float cosTheta = (float)Math.Cos(theta); Vector3 h = new Vector3(); h.x = sinTheta * cosPhi; h.y = sinTheta * sinPhi; h.z = cosTheta; basis.transform(h); Vector3 o = new Vector3(); float ih = Vector3.dot(h, inv); o.x = 2 * ih * h.x - inv.x; o.y = 2 * ih * h.y - inv.y; o.z = 2 * ih * h.z - inv.z; Ray r = new Ray(state.getPoint(), o); state.traceReflectionPhoton(r, power); } }
public Color getIrradiance(ShadingState state, Color diffuseReflectance) { if (samples <= 0) { return(Color.BLACK); } if (state.getDiffuseDepth() > 0) { // do simple path tracing for additional bounces (single ray) float xi = (float)state.getRandom(0, 0, 1); float xj = (float)state.getRandom(0, 1, 1); float phi = (float)(xi * 2 * Math.PI); float cosPhi = (float)Math.Cos(phi); float sinPhi = (float)Math.Sin(phi); float sinTheta = (float)Math.Sqrt(xj); float cosTheta = (float)Math.Sqrt(1.0f - xj); Vector3 w = new Vector3(); w.x = cosPhi * sinTheta; w.y = sinPhi * sinTheta; w.z = cosTheta; OrthoNormalBasis onb = state.getBasis(); onb.transform(w); Ray r = new Ray(state.getPoint(), w); ShadingState temp = state.traceFinalGather(r, 0); return(temp != null?getGlobalRadiance(temp).copy().mul((float)Math.PI) : Color.BLACK); } //rwl.readLock().lockwoot();//fixme Color irr; lock (lockObj) irr = getIrradiance(state.getPoint(), state.getNormal()); //rwl.readLock().unlock(); if (irr == null) { // compute new sample irr = Color.black(); OrthoNormalBasis onb = state.getBasis(); float invR = 0; float minR = float.PositiveInfinity; Vector3 w = new Vector3(); for (int i = 0; i < samples; i++) { float xi = (float)state.getRandom(i, 0, samples); float xj = (float)state.getRandom(i, 1, samples); float phi = (float)(xi * 2 * Math.PI); float cosPhi = (float)Math.Cos(phi); float sinPhi = (float)Math.Sin(phi); float sinTheta = (float)Math.Sqrt(xj); float cosTheta = (float)Math.Sqrt(1.0f - xj); w.x = cosPhi * sinTheta; w.y = sinPhi * sinTheta; w.z = cosTheta; onb.transform(w); Ray r = new Ray(state.getPoint(), w); ShadingState temp = state.traceFinalGather(r, i); if (temp != null) { minR = Math.Min(r.getMax(), minR); invR += 1.0f / r.getMax(); temp.getInstance().prepareShadingState(temp); irr.add(getGlobalRadiance(temp)); } } irr.mul((float)Math.PI / samples); invR = samples / invR; //rwl.writeLock().lockwoot();//fixme lock (lockObj) insert(state.getPoint(), state.getNormal(), invR, irr); //rwl.writeLock().unlock(); // view irr-cache points // irr = Color.YELLOW.copy().mul(1e6f); } return(irr); }