LibGDX中的平面着色

时间:2014-07-25 15:41:58

标签: 3d libgdx

我目前正在制作一款简单的游戏,我希望我的地形是平面阴影。我的地形目前如下所示: my terrain

正如您所看到的,颜色根据顶点颜色混合在一起。

我希望我的最终产品类似于以下内容: Goal

所以我想知道如何实现这一目标?从gouraud阴影到平面阴影的步骤是什么?

以下是我如何创建我给网格的顶点:

public TerrainChunk() {
    buildHeightmap();
    buildIndices();
    buildVertices();
    calcNormals(indices, vertices);

}   

public void buildHeightmap() {...}

private void buildIndices() {
    int idx = 0;
    short pitch = (short) (width + 1);
    short i1 = 0;
    short i2 = 1;
    short i3 = (short) (1 + pitch);
    short i4 = pitch;

    short row = 0;

    for (int z = 0; z < height; z++) {
        for (int x = 0; x < width; x++) {
            indices[idx++] = i1;
            indices[idx++] = i2;
            indices[idx++] = i3;

            indices[idx++] = i3;
            indices[idx++] = i4;
            indices[idx++] = i1;

            i1++;
            i2++;
            i3++;
            i4++;
        }

        row += pitch;
        i1 = row;
        i2 = (short) (row + 1);
        i3 = (short) (i2 + pitch);
        i4 = (short) (row + pitch);
    }
}

public void buildVertices() {
    int heightPitch = height + 1;
    int widthPitch = width + 1;
    int idx = 0;

    for (int x = 0; x < widthPitch; x++) {
        for (int z = 0; z < heightPitch; z++) {

            // POSITION
            vertices[idx++] = scale * x;
            vertices[idx++] = (float)Math.pow(1 + chunkDepths[x][z], strength));
            vertices[idx++] = scale * z;

            // NORMAL, skip these for now
            idx += 3;

            // COLOR
            vertices[idx++] = getColor(;

            // TEXTURE
            vertices[idx++] = (x / (float) width);
            vertices[idx++] = (z / (float) height);

        }
    }
}

/*
 * Calculates the normals
 */
private void calcNormals(short[] indices, float[] verts) {

    for (int i = 0; i < indices.length; i += 3) {
        int i1 = getPositionStart(indices[i]);
        int i2 = getPositionStart(indices[i + 1]);
        int i3 = getPositionStart(indices[i + 2]);

        // p1
        float x1 = verts[i1];
        float y1 = verts[i1 + 1];
        float z1 = verts[i1 + 2];

        // p2
        float x2 = verts[i2];
        float y2 = verts[i2 + 1];
        float z2 = verts[i2 + 2];

        // p3
        float x3 = verts[i3];
        float y3 = verts[i3 + 1];
        float z3 = verts[i3 + 2];

        // u = p3 - p1
        float ux = x3 - x1;
        float uy = y3 - y1;
        float uz = z3 - z1;

        // v = p2 - p1
        float vx = x2 - x1;
        float vy = y2 - y1;
        float vz = z2 - z1;

        // n = cross(v, u)
        float nx = ((vy * uz) - (vz * uy));
        float ny = ((vz * ux) - (vx * uz));
        float nz = ((vx * uy) - (vy * ux));

        // normalize(n)
        float num2 = ((nx * nx) + (ny * ny)) + (nz * nz);
        float num = 1f / (float) Math.sqrt(num2);
        nx *= num;
        ny *= num;
        nz *= num;

        addNormal(indices[i], verts, nx,ny, nz);
        addNormal(indices[i + 1], verts, nx, ny, nz);
        addNormal(indices[i + 2], verts, nx, ny, nz);
    }

    for (int i = 0; i < (verts.length / VERTEX_SIZE); i++) {
        normalizeNormal(i, verts);
    }
}

// Adds the provided value to the normal
private void addNormal(int vertIndex, float[] verts, float x, float y,
        float z) {

    int i = getNormalStart(vertIndex);

    float rx = (float) ((x * Math.cos(180)) - (y * Math.sin(180)));
    float ry = (float) ((x * Math.sin(180)) + (y * Math.cos(180)));
    x = rx;
    y = ry;
    verts[i] += x;
    verts[i + 1] += y;
    verts[i + 2] += z;
}

/*
 * Normalizes normals
 */
private void normalizeNormal(int vertIndex, float[] verts) {

    int i = getNormalStart(vertIndex);

    float x = verts[i];
    float y = verts[i+1];
    float z = verts[i+2];

    float num2 = ((x * x) + (z * z)) + (y * y);
    float num = (float) Math.sqrt(num2);
    x *= num;
    y *= num;
    z *= num;

    verts[i] = x;
    verts[i + 1] = y;
    verts[i + 2] = z;
}


// Gets the index of the first float of a normal for a specific vertex
private int getNormalStart(int vertIndex) {
    return vertIndex * VERTEX_SIZE + 3;
}

// Gets the index of the first float of a specific vertex
private int getPositionStart(int vertIndex) {
    return vertIndex * VERTEX_SIZE;
}

1 个答案:

答案 0 :(得分:1)

最后,我改变了完全构建Mesh的方式。现在我用三角形构建网格。现在看来是这样的:image。 它还不完美,因为没有对角色,但我对整体外观感到满意。

我是这样做的。 我创建了一个新类来保存我的变量

private Vector3 corner1;
private Vector3 corner2;
private Vector3 corner3;
private Vector3 corner4;
private Vector3 leftNormal;
private Vector3 rightNormal;
private Color color1;
private Color color2;
private Color color3;
private Color color4;
private Vector2 texturePos;

并像这样绘制它们:

// left triangle
VertexInfo v1 = new VertexInfo();
VertexInfo v2 = new VertexInfo();
VertexInfo v3 = new VertexInfo();

// right triangle
VertexInfo v4 = new VertexInfo();
VertexInfo v5 = new VertexInfo();
VertexInfo v6 = new VertexInfo();

v1.setPos(cell.getCorner1()).setNor(cell.getLeftNormal()).setCol(cell.getColor1()).setUV(cell.getTexturePos());
v2.setPos(cell.getCorner4()).setNor(cell.getLeftNormal()).setCol(cell.getColor1()).setUV(cell.getTexturePos());
v3.setPos(cell.getCorner2()).setNor(cell.getLeftNormal()).setCol(cell.getColor1()).setUV(cell.getTexturePos());

v4.setPos(cell.getCorner3()).setNor(cell.getRightNormal()).setCol(cell.getColor3()).setUV(cell.getTexturePos());
v5.setPos(cell.getCorner2()).setNor(cell.getRightNormal()).setCol(cell.getColor3()).setUV(cell.getTexturePos());
v6.setPos(cell.getCorner4()).setNor(cell.getRightNormal()).setCol(cell.getColor3()).setUV(cell.getTexturePos());

meshBuilder.triangle(v1, v2, v3);
meshBuilder.triangle(v4, v5, v6);

我计算三角形的面法线如下:

private Vector3 calcNormal(Vector3 p1, Vector3 p2, Vector3 p3) {

    // u = p3 - p1
    float ux = p3.x - p1.x;
    float uy = p3.y - p1.y;
    float uz = p3.z - p1.z;

    // v = p2 - p1
    float vx = p2.x - p1.x;
    float vy = p2.y - p1.y;
    float vz = p2.z - p1.z;

    // n = cross(v, u)
    float nx = ((vy * uz) - (vz * uy));
    float ny = ((vz * ux) - (vx * uz));
    float nz = ((vx * uy) - (vy * ux));

    // // normalize(n)
    float num2 = ((nx * nx) + (ny * ny)) + (nz * nz);
    float num = 1f / (float) Math.sqrt(num2);
    nx *= num;
    ny *= num;
    nz *= num;

    return new Vector3(nx, ny, nz);
}