自制渲染引擎的 ZBuffer 问题
ZBuffer issues with homebrew rendering engine
我的渲染引擎中的 zbuffer 有问题。我是从头开始写的,没有太多关于 3D 图形的先验知识。转换工作完美,在没有 zbuffer 的情况下进行了测试。但是,启用缓冲区后,它不会以正确的顺序绘制。
这是它的实现方式。
场景 class 有一个 render 方法,当 JFrame 需要更新时调用它。 Render 清除 zbuffer,然后将命令传递给场景的形状。 Renderable是一个接口。代码如下:
public void render(Graphics2D g2, int pitch, int yaw, int roll)
{
for(double[] d : buffer)
Arrays.fill(d, Double.NEGATIVE_INFINITY);
for(Renderable shape : shapes)
shape.render(image, pitch, yaw, roll, buffer);
g2.drawImage(image, null, null);
for(int x = 0; x < 512; x++)
for(int y = 0; y < 512; y++)
image.setRGB(x, y, 0); //Clear buffered image
}
private Renderable[] shapes;
private double[][] buffer = new double[512][512];
private BufferedImage image = new BufferedImage(512, 512, BufferedImage.TYPE_INT_ARGB);
这是 Triangle3D 中 Render 方法的代码(实现 Renderable)。
public void render(BufferedImage image, int pitch, int yaw, int roll, double[][] buffer, boolean showBorders)
{
Triangle3D rotated = (Triangle3D) getRotated(pitch, yaw, roll);
rotated.translate(256, 256, 0);
Polygon path = new Polygon();
path.addPoint(rotated.getFirst().getFirst().intValue(), rotated.getFirst().getSecond().intValue());
path.addPoint(rotated.getSecond().getFirst().intValue(), rotated.getSecond().getSecond().intValue());
path.addPoint(rotated.getThird().getFirst().intValue(), rotated.getThird().getSecond().intValue());
Rectangle bounds = path.getBounds();
int minY = Math.max(Math.min(bounds.y, 511), 0);
int maxY = Math.max(Math.min(bounds.y + bounds.height, 511), 0);
int minX = Math.max(Math.min(bounds.x, 511), 0);
int maxX = Math.max(Math.min(bounds.x + bounds.width, 511), 0);
for (int y = minY; y <= maxY; y++)
for (int x = minX; x <= maxX; x++)
if(path.contains(x, y) && buffer[x][y] < getZ(x, y))
{
image.setRGB(x, y, color.getRGB());
buffer[x][y] = getZ(x, y);
}
}
public double getZ(int x, int y)
{
double a = getFirst().getFirst();
double b = getFirst().getSecond();
double c = getFirst().getThird();
double d = getSecond().getFirst();
double e = getSecond().getSecond();
double f = getSecond().getThird();
double g = getThird().getFirst();
double h = getThird().getSecond();
double w = getThird().getThird();
double v1a = d - a;
double v1b = e - b;
double v1c = f - c;
double v2a = g - a;
double v2b = h - b;
double v2c = w - c;
double i = v1b * v2c - v1c * v2b;
double j = v1c * v2a - v1a * v2c;
double k = v1a * v2b - v1b * v2a;
double o = (a * i) + (b * j) + (c * k);
return ((o - (x * i) - (y * j)) / k);
}
我注意到最后渲染的 Triangle3D(场景形状 [] 中的最后一项)永远不可见,即使它应该绘制在前面也是如此。
知道为什么它不起作用吗?
完整代码:
https://drive.google.com/folderview?id=0Bw-Cg4sUAOWvS3BTazgyeTRRUjg&usp=sharing
getZ() returns 未旋转三角形的 Z 值。改为 rotated.getZ()
我的渲染引擎中的 zbuffer 有问题。我是从头开始写的,没有太多关于 3D 图形的先验知识。转换工作完美,在没有 zbuffer 的情况下进行了测试。但是,启用缓冲区后,它不会以正确的顺序绘制。
这是它的实现方式。
场景 class 有一个 render 方法,当 JFrame 需要更新时调用它。 Render 清除 zbuffer,然后将命令传递给场景的形状。 Renderable是一个接口。代码如下:
public void render(Graphics2D g2, int pitch, int yaw, int roll)
{
for(double[] d : buffer)
Arrays.fill(d, Double.NEGATIVE_INFINITY);
for(Renderable shape : shapes)
shape.render(image, pitch, yaw, roll, buffer);
g2.drawImage(image, null, null);
for(int x = 0; x < 512; x++)
for(int y = 0; y < 512; y++)
image.setRGB(x, y, 0); //Clear buffered image
}
private Renderable[] shapes;
private double[][] buffer = new double[512][512];
private BufferedImage image = new BufferedImage(512, 512, BufferedImage.TYPE_INT_ARGB);
这是 Triangle3D 中 Render 方法的代码(实现 Renderable)。
public void render(BufferedImage image, int pitch, int yaw, int roll, double[][] buffer, boolean showBorders)
{
Triangle3D rotated = (Triangle3D) getRotated(pitch, yaw, roll);
rotated.translate(256, 256, 0);
Polygon path = new Polygon();
path.addPoint(rotated.getFirst().getFirst().intValue(), rotated.getFirst().getSecond().intValue());
path.addPoint(rotated.getSecond().getFirst().intValue(), rotated.getSecond().getSecond().intValue());
path.addPoint(rotated.getThird().getFirst().intValue(), rotated.getThird().getSecond().intValue());
Rectangle bounds = path.getBounds();
int minY = Math.max(Math.min(bounds.y, 511), 0);
int maxY = Math.max(Math.min(bounds.y + bounds.height, 511), 0);
int minX = Math.max(Math.min(bounds.x, 511), 0);
int maxX = Math.max(Math.min(bounds.x + bounds.width, 511), 0);
for (int y = minY; y <= maxY; y++)
for (int x = minX; x <= maxX; x++)
if(path.contains(x, y) && buffer[x][y] < getZ(x, y))
{
image.setRGB(x, y, color.getRGB());
buffer[x][y] = getZ(x, y);
}
}
public double getZ(int x, int y)
{
double a = getFirst().getFirst();
double b = getFirst().getSecond();
double c = getFirst().getThird();
double d = getSecond().getFirst();
double e = getSecond().getSecond();
double f = getSecond().getThird();
double g = getThird().getFirst();
double h = getThird().getSecond();
double w = getThird().getThird();
double v1a = d - a;
double v1b = e - b;
double v1c = f - c;
double v2a = g - a;
double v2b = h - b;
double v2c = w - c;
double i = v1b * v2c - v1c * v2b;
double j = v1c * v2a - v1a * v2c;
double k = v1a * v2b - v1b * v2a;
double o = (a * i) + (b * j) + (c * k);
return ((o - (x * i) - (y * j)) / k);
}
我注意到最后渲染的 Triangle3D(场景形状 [] 中的最后一项)永远不可见,即使它应该绘制在前面也是如此。
知道为什么它不起作用吗?
完整代码: https://drive.google.com/folderview?id=0Bw-Cg4sUAOWvS3BTazgyeTRRUjg&usp=sharing
getZ() returns 未旋转三角形的 Z 值。改为 rotated.getZ()