有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在OpenGL中对半透明三角形排序?

我正在用OpenGL写一个3D游戏。渲染半透明三角形时出现排序问题。我知道它们需要分类,但如何分类呢?我不想使用BSP树(如果我想更改对象的位置,那么我需要重建树。)和OIT算法(性能昂贵)。我想按“覆盖率”对它们进行分类

我有两个半透明的三角形,我用透视相机把它们投射到屏幕上

视口:0、0、1280、720

例如

[正确排序]黑色三角形覆盖绿色三角形

enter image description here

[排序不正确]绿色三角形覆盖黑色三角形

enter image description here

为了清楚地看到排序瑕疵,图像中的三角形是不透明的


我对这个问题的解决方案

将这些三角形的顶点转换为屏幕空间坐标,并通过插值z坐标进行比较,但在我的图像中,你可以看到黑色三角形的一个坐标在视口之外,因此这个坐标很奇怪(类似于:-2896;1423;1.169),我无法在黑色三角形上插值z坐标

如何转换为屏幕空间坐标

  1. 用MVP矩阵变换三角形顶点
  2. 执行透视图分割
  3. 转换到屏幕空间

MVP矩阵变换

public Vector4f transform(Vector4f vector) {
    float x = m00 * vector.x + m10 * vector.y + m20 * vector.z + m30 * vector.w;
    float y = m01 * vector.x + m11 * vector.y + m21 * vector.z + m31 * vector.w;
    float z = m02 * vector.x + m12 * vector.y + m22 * vector.z + m32 * vector.w;
    float w = m03 * vector.x + m13 * vector.y + m23 * vector.z + m33 * vector.w;

    return new Vector4f(x, y, z, w);
}

观点分歧

public Vector3f perspectiveDivide() {
    float wInverse = 1.0f / w;
    return new Vector3f(x * wInverse, y * wInverse, z * wInverse);
}

转换到屏幕空间

public void toScreenCoords(int width, int height) {
    x = (x * 0.5f + 0.5f) * width;
    y = (y * 0.5f + 0.5f) * height;
    z = (z + 1.0f) * 0.5f;
}

我是怎么做到的

Vector4f clipspace = mvp.transform(triangle_vertex);
Vector3f ndc = clipspace.perspectiveDivide();
Vector3f screenspace = ndc.toScreenCoords(1280, 720);

我做错了什么?为什么在视口外进行坐标变换会很奇怪?如何获得视口外的正确坐标


---编辑---

我发现如果三角形的一个坐标在视口外,那么三角形必须被分成两个

但是如何使用剪辑空间坐标和剪辑平面将三角形一分为二呢


共 (1) 个答案

  1. # 1 楼答案

    正确排序(半透明)三角形的快速简便解决方案

    我称之为“假投影排序”。 如果可以假设三角形不会相交,那么只需检查三角形(黑色或绿色)是否与四面体相交(从绿色三角形的黑色到相机位置的坐标)


    一个例子

    第一个三角形坐标:

    0.0, 0.0, 5.0
    0.0, 5.0, 5.0
    5.0, 5.0, 5.0
    

    第二个三角形坐标:

    0.0, 0.0, 5.0
    5.0, 0.0, 5.0
    5.0, 0.0, 5.0
    

    摄像机位置

    1.15, 5.8, 5.5
    

    然后,四面体坐标将是来自三角形(例如,第一个)和相机位置的坐标

    0.0,  0.0, 5.0  // First coordinate from the first triangle
    0.0,  5.0, 5.0  // Second coordinate from the first triangle
    5.0,  5.0, 5.0  // Third coordinate from the first triangle
    1.15, 5.8, 5.5  // Camera position
    

    最后一件事是检查第二个三角形是否与四面体相交。如果第二个三角形相交,则它覆盖第一个三角形。如果使用第二个三角形的坐标创建四面体,则需要检查第一个三角形的交点,而不是第二个三角形


    注释

    不要使用Java中的TreeSet或TreeMap来比较使用“伪投影排序”的三角形,这可能会产生不正确的排序