【问题标题】:ZBuffer issues with homebrew rendering engine自制渲染引擎的 ZBuffer 问题
【发布时间】:2016-03-16 23:16:52
【问题描述】:

我的渲染引擎中的 zbuffer 出现问题。我从头开始编写它,没有太多关于 3D 图形的先验知识。转换工作完美,在没有 zbuffer 的情况下进行了测试。但是,启用缓冲区时,它不会以正确的顺序绘制。

这是它的实现方式。

Scene 类有一个 render 方法,它在需要更新时由 JFrame 调用。渲染清除 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

【问题讨论】:

  • 为什么Triangle3D 绘制一个新图像,它在必要时着色,然后绘制到g2,而不是仅接收它在必要时着色的图像 - 然后渲染循环吸引到g2?当您可以分配 1 张图像并绘制一次时,似乎没有必要继续分配图像和绘画。
  • 我不清楚z 计算是如何工作的。它似乎是用旋转来写的(我猜getFirst()getSecond() 等是 3x​​3 旋转矩阵的元素) - 翻译在哪里考虑? (我不知道您是否遇到过这样一个事实,即 OpenGL 使用 4x4 矩阵,它允许一起传递旋转和平移 - 称为 homogeneous notation,因为两者不被认为是不同的)
  • 将参数从 g2 更​​改为缓冲图像应该有助于提高效率。谢谢推荐!
  • Triangle3D 和 Point3D 扩展了一个 Triplet 类,它只包含 3 个数据并允许访问和变异。我发现这样做比为每个类编写 getX()、getY()、getZ() 等更容易。这就是 getFirst-Third 的来源。 Z计算来自平面方程:ax + by + cz = d。简单的 3D 几何。翻译尚未实施。我打算平移坐标点,而不是 4x4 倾斜。
  • 如果您在完整代码链接中运行 JAR,您会看到轮换有效。我担心的是 z 缓冲区不起作用。

标签: java swing graphics 3d rendering


【解决方案1】:

getZ() 返回未旋转三角形的 Z 值。改为rotated.getZ()

【讨论】:

    猜你喜欢
    • 2012-11-04
    • 1970-01-01
    • 1970-01-01
    • 2012-09-23
    • 2023-04-03
    • 2011-05-05
    • 2013-06-08
    • 2015-04-03
    • 1970-01-01
    相关资源
    最近更新 更多