📄 cornellbox.java
字号:
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;
assert sideIn != -1;
assert sideOut != -1;
// can't hit minY wall, there is none
if (sideIn != 2 && r.isInside(intervalMin)) {
r.setMax(intervalMin);
state.setIntersection(sideIn, 0, 0);
} else if (sideOut != 2 && r.isInside(intervalMax)) {
r.setMax(intervalMax);
state.setIntersection(sideOut, 0, 0);
}
}
public Color getRadiance(ShadingState state) {
int side = state.getPrimitiveID();
Color kd = null;
switch (side) {
case 0:
kd = left;
break;
case 1:
kd = right;
break;
case 3:
kd = back;
break;
case 4:
kd = bottom;
break;
case 5:
float lx = state.getPoint().x;
float ly = state.getPoint().y;
if (lx >= lxmin && lx < lxmax && ly >= lymin && ly < lymax && state.getRay().dz > 0)
return state.includeLights() ? radiance : Color.BLACK;
kd = top;
break;
default:
assert false;
}
// make sure we are on the right side of the material
state.faceforward();
// setup lighting
state.initLightSamples();
state.initCausticSamples();
return state.diffuse(kd);
}
public void scatterPhoton(ShadingState state, Color power) {
int side = state.getPrimitiveID();
Color kd = null;
switch (side) {
case 0:
kd = left;
break;
case 1:
kd = right;
break;
case 3:
kd = back;
break;
case 4:
kd = bottom;
break;
case 5:
float lx = state.getPoint().x;
float ly = state.getPoint().y;
if (lx >= lxmin && lx < lxmax && ly >= lymin && ly < lymax && state.getRay().dz > 0)
return;
kd = top;
break;
default:
assert false;
}
// make sure we are on the right side of the material
if (Vector3.dot(state.getNormal(), state.getRay().getDirection()) > 0) {
state.getNormal().negate();
state.getGeoNormal().negate();
}
state.storePhoton(state.getRay().getDirection(), power, kd);
double avg = kd.getAverage();
double rnd = state.getRandom(0, 0, 1);
if (rnd < avg) {
// photon is scattered
power.mul(kd).mul(1 / (float) avg);
OrthoNormalBasis onb = OrthoNormalBasis.makeFromW(state.getNormal());
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 int getNumSamples() {
return samples;
}
public void getSamples(ShadingState state) {
if (lightBounds.contains(state.getPoint()) && state.getPoint().z < maxZ) {
int n = state.getDiffuseDepth() > 0 ? 1 : samples;
float a = area / n;
for (int i = 0; i < n; i++) {
// random offset on unit square, we use the infinite version of
// getRandom
// because the light sampling is adaptive
double randX = state.getRandom(i, 0);
double randY = state.getRandom(i, 1);
Point3 p = new Point3();
p.x = (float) (lxmin * (1 - randX) + lxmax * randX);
p.y = (float) (lymin * (1 - randY) + lymax * randY);
p.z = maxZ - 0.001f;
LightSample dest = new LightSample();
// prepare shadow ray to sampled point
dest.setShadowRay(new Ray(state.getPoint(), p));
// check that the direction of the sample is the same as the
// normal
float cosNx = dest.dot(state.getNormal());
if (cosNx <= 0)
return;
// light source facing point ?
// (need to check with light source's normal)
float cosNy = dest.getShadowRay().dz;
if (cosNy > 0) {
// compute geometric attenuation and probability scale
// factor
float r = dest.getShadowRay().getMax();
float g = cosNy / (r * r);
float scale = g * a;
// set final sample radiance
dest.setRadiance(radiance, radiance);
dest.getDiffuseRadiance().mul(scale);
dest.getSpecularRadiance().mul(scale);
dest.traceShadow(state);
state.addSample(dest);
}
}
}
}
public void getPhoton(double randX1, double randY1, double randX2, double randY2, Point3 p, Vector3 dir, Color power) {
p.x = (float) (lxmin * (1 - randX2) + lxmax * randX2);
p.y = (float) (lymin * (1 - randY2) + lymax * randY2);
p.z = maxZ - 0.001f;
double u = 2 * Math.PI * randX1;
double s = Math.sqrt(randY1);
dir.set((float) (Math.cos(u) * s), (float) (Math.sin(u) * s), (float) -Math.sqrt(1.0f - randY1));
Color.mul((float) Math.PI * area, radiance, power);
}
public float getPower() {
return radiance.copy().mul((float) Math.PI * area).getLuminance();
}
public int getNumPrimitives() {
return 1;
}
public float getPrimitiveBound(int primID, int i) {
switch (i) {
case 0:
return minX;
case 1:
return maxX;
case 2:
return minY;
case 3:
return maxY;
case 4:
return minZ;
case 5:
return maxZ;
default:
return 0;
}
}
public BoundingBox getWorldBounds(Matrix4 o2w) {
BoundingBox bounds = new BoundingBox(minX, minY, minZ);
bounds.include(maxX, maxY, maxZ);
if (o2w == null)
return bounds;
return o2w.transform(bounds);
}
public PrimitiveList getBakingPrimitives() {
return null;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -