在LibGDX平面着色 [英] Flat shading in LibGDX
问题描述
我目前工作的一个简单的游戏,我想我的地势要平坦着色。我目前的地形如下所示:
正如你所看到的颜色混合toghether根据顶点的颜色。
我会为我的最终产品类似于以下喜爱:
所以我想知道我怎样才能做到这一点?有哪些步骤,从洛德着色去平阴影?
下面是我如何去创造我给我的网格顶点:
公共TerrainChunk(){
buildHeightmap();
buildIndices();
buildVertices();
calcNormals(指数,顶点);
}
公共无效buildHeightmap(){...}
私人无效buildIndices(){
INT IDX = 0;
短节距=(短)(宽度+ 1);
短的i1 = 0;
短I2 = 1;
短I3 =(短)(1 +间距);
短I4 =间距;
短行= 0;
对于(INT Z = 0; Z<高度; Z ++){
为(中间体X = 0 X - 其中;宽度; X ++){
指数[IDX +] = I1;
指数[IDX +] = I2;
指数[IDX +] = I3;
指数[IDX +] = I3;
指数[IDX +] = 6-14;
指数[IDX +] = I1;
I1 ++;
I2 ++;
I3 ++;
I4 ++;
}
行+ =间距;
I1 =行;
I2 =(短)(行+ 1);
I3 =(短)(I2 +间距);
I4 =(短)(行+间距);
}
}
公共无效buildVertices(){
INT heightPitch =身高+ 1;
INT widthPitch =宽度+ 1;
INT IDX = 0;
为(中间体X = 0 X - 其中; widthPitch; X ++){
对于(INT Z = 0; Z< heightPitch; Z ++){
// 位置
顶点[IDX +] =规模* X;
顶点[IDX +] =(浮点)Math.pow(1 + chunkDepths [X] [Z],强度));
顶点[IDX +] =规模* Z;
//师范大学,跳过这些现在
IDX + = 3;
// 颜色
顶点[IDX +] =的getColor(;
// 质地
顶点[IDX +] =(X /(浮点)宽);
顶点[IDX +] =(Z /(浮点)高度);
}
}
}
/ *
*计算法线
* /
私人无效calcNormals(简称[]指数,浮动[]绿党){
的for(int i = 0; I< indices.length; I + = 3){
INT I1 = getPositionStart(指数[I]);
INT I2 = getPositionStart(指数为[I + 1]);
INT的i3 = getPositionStart(指数为[I + 2]);
// P1
浮X1 =绿党[I1]
浮Y1 =绿党[I1 + 1];
浮Z1 =绿党[I1 + 2];
// P2
浮X2 =绿党[12];
浮Y2 =绿党[I2 + 1];
浮Z2 =绿党[I2 + 2];
// P3
浮X3 =绿党[I3]
浮Y3 =绿党[酷睿i3 + 1];
浮Z3 =绿党[酷睿i3 + 2];
// U = P3 - P1
浮UX = X3 - X1;
浮UY = Y3 - Y1;
浮UZ = Z3 - Z1;
// V = P2 - P1
浮VX = X2 - X1;
浮VY = Y2 - Y1;
浮VZ = Z2 - Z1;
// N =交(V,U)
浮动NX =((VY * UZ) - (VZ * UY));
浮动NY =((VZ * UX) - (VX * UZ));
浮动NZ =((VX * UY) - (VY * UX));
//正常化(N)
浮动NUM2 =((NX * NX)+(纽约州*纽约州))+(NZ * NZ);
浮NUM = 1F /(浮动)的Math.sqrt(NUM2);
NX * = NUM;
纽约* = NUM;
新西兰* = NUM;
addNormal(指数为[I]中,绿党,NX,NY,NZ);
addNormal(指数为[I + 1],绿党,NX,NY,NZ);
addNormal(指数为[1 + 2],绿党,NX,NY,NZ);
}
的for(int i = 0;我≤(verts.length / VERTEX_SIZE);我++){
normalizeNormal(我,绿党);
}
}
//将提供的值正常
私人无效addNormal(INT vertIndex,浮法[]绿党,浮动的x,浮Y,
浮Z){
INT I = getNormalStart(vertIndex);
浮RX =(浮子)((X * Math.cos(180)) - (γ* Math.sin(180)));
浮RY =(浮子)((X * Math.sin(180))+(γ* Math.cos(180)));
X = RX;
Y = RY;
绿党[I] + = X;
绿党[I + 1] + = Y;
绿党[I + 2] + = Z;
}
/ *
*正常化法线
* /
私人无效normalizeNormal(INT vertIndex,浮法[]绿党){
INT I = getNormalStart(vertIndex);
浮法X =绿党[I]
浮动Y =绿党[I + 1];
浮Z =绿党[I + 2];
浮动NUM2 =((X * X)+(Z * Z))+(Y * Y);
浮NUM =(浮动)的Math.sqrt(NUM2);
X * = NUM;
Y * = NUM;
Z * = NUM;
绿党[I] = X;
绿党[I + 1] = Y;
绿党[1 + 2] = Z;
}
//获取一个正常的第一条浮法的指数为特定的顶点
私人诠释getNormalStart(INT vertIndex){
返回vertIndex * VERTEX_SIZE + 3;
}
//获取特定顶点的第一个浮动的索引
私人诠释getPositionStart(INT vertIndex){
返回vertIndex * VERTEX_SIZE;
}
在最后,我改变了我的建网完全的方式。现在我建网了三角形。下面是它看起来像现在:。 这还不是很完善,因为没有对角的颜色,但我很高兴与一般的样子。
下面是我做到了。 我做了一个新的类来保存我的变量
私人Vector3类型corner1;
私人Vector3类型corner2;
私人Vector3类型corner3;
私人Vector3类型corner4;
私人Vector3类型leftNormal;
私人Vector3类型rightNormal;
私人色颜色1;
私人色颜色2;
私人色彩COLOR3;
私人色彩color4;
私人Vector2 texturePos;
和吸引他们,像这样:
//左三角
VertexInfo V1 =新VertexInfo();
VertexInfo V2 =新VertexInfo();
VertexInfo V3 =新VertexInfo();
// 直角三角形
VertexInfo V4 =新VertexInfo();
VertexInfo V5 =新VertexInfo();
VertexInfo V6 =新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);
我计算三角形的面法线像这样:
私人Vector3类型calcNormal(Vector3类型P1,P2 Vector3类型,Vector3类型P3){
// U = P3 - P1
浮UX = p3.x - p1.x;
浮UY = p3.y - p1.y;
浮UZ = p3.z - p1.z;
// V = P2 - P1
浮VX = p2.x - p1.x;
浮VY = p2.y - p1.y;
浮VZ = p2.z - p1.z;
// N =交(V,U)
浮动NX =((VY * UZ) - (VZ * UY));
浮动NY =((VZ * UX) - (VX * UZ));
浮动NZ =((VX * UY) - (VY * UX));
// //正常化(N)
浮动NUM2 =((NX * NX)+(纽约州*纽约州))+(NZ * NZ);
浮NUM = 1F /(浮动)的Math.sqrt(NUM2);
NX * = NUM;
纽约* = NUM;
新西兰* = NUM;
返回新的Vector3类型(NX,NY,NZ);
}
I am currently working on a simple game and I would like to my terrain to be flat shaded. My terrain currently looks like the following:
As you can see the colours blend toghether depending on the vertice colours.
I would love for my end product to resemble the following:
So I was wondering how can I achieve this? What are the steps to go from gouraud shading to flat shading?
Here is how I go about creating the vertices I give to my mesh:
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;
}
In the end I changed the way I build the Mesh entirely. Now I build the mesh out of triangles. Here's what it looks like now: . it's not yet perfect as there are no diagonal colours but I'm happy with the general look.
Here is how I did it. I made a new class to hold my variables
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;
and draw them like so:
// 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);
I calculate the face normals of the triangles like so:
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);
}
这篇关于在LibGDX平面着色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!