📄 bucketrenderer.java
字号:
for (int x = 0; x < sbw; x++, index++) {
int sx = sx0 + x;
int sy = sy0 + y;
int j = sx & (sigma.length - 1);
int k = sy & (sigma.length - 1);
int i = j * sigma.length + sigma[k];
float dx = useJitter ? (float) sigma[k] / (float) sigma.length : 0.5f;
float dy = useJitter ? (float) sigma[j] / (float) sigma.length : 0.5f;
float rx = (sx + dx) * invSubPixelSize;
float ry = (sy + dy) * invSubPixelSize;
ry = imageHeight - ry - 1;
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(Module.BCKT, "Dumping bucket [%d, %d] to file ...", bx, by);
Bitmap bitmap = new Bitmap(sbw, sbh, true);
for (int y = sbh - 1, index = 0; y >= 0; y--)
for (int x = 0; x < sbw; x++, index++)
bitmap.setPixel(x, y, samples[index].c.copy().toNonLinear());
bitmap.save(String.format("bucket_%04d_%04d.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);
}
}
} else {
// filter samples into pixels
float cy = imageHeight - 1 - (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 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);
weight += f;
}
}
c.mul(1.0f / weight);
bucketRGB[index] = c;
}
}
}
// update pixels
display.imageUpdate(x0, y0, bw, bh, bucketRGB);
}
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));
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));
}
sample.scale((float) invSuperSampling);
} else {
// single sample
sample.set(scene.getRadiance(istate, x, y, q1, q2, q0, sample.i));
}
}
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);
}
private static final class ImageSample {
float rx, ry;
int i, n;
Color c;
Instance instance;
Shader shader;
float nx, ny, nz;
ImageSample(float rx, float ry, int i) {
this.rx = rx;
this.ry = ry;
this.i = i;
n = 0;
c = null;
instance = null;
shader = null;
nx = ny = nz = 1;
}
final void set(ShadingState state) {
if (state == null)
c = Color.BLACK;
else {
c = state.getResult();
checkNanInf();
shader = state.getShader();
instance = state.getInstance();
if (state.getNormal() != null) {
nx = state.getNormal().x;
ny = state.getNormal().y;
nz = state.getNormal().z;
}
}
n = 1;
}
final void add(ShadingState state) {
if (n == 0)
c = Color.black();
if (state != null) {
c.add(state.getResult());
checkNanInf();
}
n++;
}
final void checkNanInf() {
if (c.isNan())
UI.printError(Module.BCKT, "NaN shading sample!");
else if (c.isInf())
UI.printError(Module.BCKT, "Inf shading sample!");
}
final void scale(float s) {
c.mul(s);
}
final boolean processed() {
return c != null;
}
final boolean sampled() {
return n > 0;
}
final boolean isDifferent(ImageSample sample, float thresh) {
if (instance != sample.instance)
return true;
if (shader != sample.shader)
return true;
if (Color.hasContrast(c, sample.c, thresh))
return true;
// only compare normals if this pixel has not been averaged
float dot = (nx * sample.nx + ny * sample.ny + nz * sample.nz);
return dot < 0.9f;
}
static final ImageSample bilerp(ImageSample result, ImageSample i00, ImageSample i01, ImageSample i10, ImageSample i11, float dx, float dy) {
float k00 = (1.0f - dx) * (1.0f - dy);
float k01 = (1.0f - dx) * dy;
float k10 = dx * (1.0f - dy);
float k11 = dx * dy;
Color c00 = i00.c;
Color c01 = i01.c;
Color c10 = i10.c;
Color c11 = i11.c;
Color c = Color.mul(k00, c00);
c.madd(k01, c01);
c.madd(k10, c10);
c.madd(k11, c11);
result.c = c;
return result;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -