2

Java で LWJGL エンジンに照明を追加しようとしています。地球の高さマップを使用して地形をレンダリングし、太陽/光源を追加したいのですが、何らかの理由で、おそらく何かを台無しにしたため、照明が適切に機能しません。

これがマップの画像です。現在、海を削除して、照明がより明確になるようにしています。(画像を投稿するには評判が10必要と書いてあるのでimgurです)
http://imgur.com/A0e4gIi
黄色いのが光源です。ご覧のとおり、側面から 2 本の「影」の線が出ていますが、その理由はわかりません。私の推測では、法線は正しくありません。

タイルに近い別の画像を次に示します。2 つの三角形を使用して、高さマップ上の 1 つのピクセルをレンダリングします。 http://imgur.com/v3VSnBP
三角形の 1 つが「適切に」レンダリングされていることがわかりますが、他の三角形はレンダリングされていません。それらはすべて同じ灰色/緑色です。

ハイトマップをロードして tiles[][] と normal[][] を作成するコード:

public void createMap(File heightmap) {

    try {
        BufferedImage image = ImageIO.read(heightmap);
        tiles = new float[image.getWidth()][image.getHeight()];
        normals = new Vector3f[image.getWidth()][image.getHeight()];
        int rgb;

        for(int x = 0; x < image.getWidth(); x++) {
            for(int y = 0; y < image.getHeight(); y++) {
                rgb = image.getRGB(x, y);
                tiles[x][y] = (rgb >> 16) & 0xff;

            }
        }
    } catch(Exception e) {
        e.printStackTrace();
    }

    for(int x = 0; x < tiles.length - 1; x++) {
        for(int z = 0; z < tiles[x].length - 1; z++) {
            try {
                Vector3f p1 = new Vector3f(x, tiles[x][z] * MODIFIER, z);
                Vector3f p2 = new Vector3f(x, tiles[x][z+1] * MODIFIER, z+1);
                Vector3f p3 = new Vector3f(x+1, tiles[x+1][z] * MODIFIER, z);
                normals[x][z] = UtilMath.getNormal(p1, p2, p3);
            } catch(Exception e) { e.printStackTrace(); }
            try {
                Vector3f p1 = new Vector3f(x+1, tiles[x+1][z+1] * MODIFIER, z+1);
                Vector3f p2 = new Vector3f(x, tiles[x][z+1] * MODIFIER, z+1);
                Vector3f p3 = new Vector3f(x+1, tiles[x+1][z] * MODIFIER, z);
                normals[x+1][z+1] = UtilMath.getNormal(p1, p2, p3);
            } catch(Exception e) { e.printStackTrace(); }
        }
    }
}

マップをレンダリングする表示リストを作成するメソッド:

public void createDisplayList() {
    Random rand = new Random();

    int mapDisplayList = glGenLists(1);
    glNewList(mapDisplayList, GL_COMPILE);

    glPushMatrix();
    {

        for(int x = 0; x < tiles.length - 1; x++) {
            for(int z = 0; z < tiles[x].length - 1; z++) {
                glColor3f(0, 0.75f, 0);
                try {
                    glBegin(GL_TRIANGLES);
                    glNormal3f(normals[x][z].x, normals[x][z].y, normals[x][z].z);
                    glVertex3f(x, tiles[x][z] * MODIFIER, z);
                    glVertex3f(x, tiles[x][z+1] * MODIFIER, z+1);
                    glVertex3f(x+1, tiles[x+1][z] * MODIFIER, z);
                    glEnd();
                } catch(Exception e) { e.printStackTrace(); }
                try {
                    glBegin(GL_TRIANGLES);
                    glNormal3f(normals[x+1][z+1].x, normals[x+1][z+1].y, normals[x+1][z+1].z);
                    glVertex3f(x+1, tiles[x+1][z+1] * MODIFIER, z+1);
                    glVertex3f(x, tiles[x][z+1] * MODIFIER, z+1);
                    glVertex3f(x+1, tiles[x+1][z] * MODIFIER, z);
                    glEnd();
                } catch(Exception e) { e.printStackTrace(); }
            }
        }

    }
    glPopMatrix();

    glEndList();
}

そして最後に、法線の計算に使用する方法は次のとおりです。

public static Vector3f getNormal(Vector3f p1, Vector3f p2, Vector3f p3) {
    try {
        Vector3f normal = new Vector3f();

        Vector3f calU = new Vector3f(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
        Vector3f calV = new Vector3f(p3.x - p1.x, p3.y - p1.y, p3.z - p1.z);

        normal.setX(calU.y*calV.z - calU.z-calV.y);
        normal.setY(calU.z*calV.x - calU.x-calV.z);
        normal.setZ(calU.x*calV.y - calU.y-calV.x);

        return (Vector3f) normal.normalise();
    } catch(Exception e) {
        e.printStackTrace();
    }
    return null;
}

私はおそらく法線で間違いを犯したことを知っています。

私が間違っていたことと、これら 2 つの問題を解決する方法を知っている方がいらっしゃることを願っています。

4

0 に答える 0