Java Opengl地形纹理着色
我目前正在用java开发一个OpenGL(JOGL)项目。 目标是创建具有纹理和着色的地形 我正在创建一个随机单纯形噪波,使用这些值作为高度贴图。 高度映射到1D纹理,以模拟基于高度的着色。 然后使用材质(环境光/漫反射/镜面反射/反光)模拟着色 但是,;向地形添加着色后,“条纹”出现在地形的每个“列”(Y方向)上 然后应用以下材料:Java Opengl地形纹理着色,java,opengl,opengl-es,Java,Opengl,Opengl Es,我目前正在用java开发一个OpenGL(JOGL)项目。 目标是创建具有纹理和着色的地形 我正在创建一个随机单纯形噪波,使用这些值作为高度贴图。 高度映射到1D纹理,以模拟基于高度的着色。 然后使用材质(环境光/漫反射/镜面反射/反光)模拟着色 但是,;向地形添加着色后,“条纹”出现在地形的每个“列”(Y方向)上 然后应用以下材料: TERRAIN( new float[]{0.5f, 0.5f, 0.5f, 1.0f}, new float[]{0.7f, 0
TERRAIN(
new float[]{0.5f, 0.5f, 0.5f, 1.0f},
new float[]{0.7f, 0.7f, 0.7f, 1.0f},
new float[]{0.2f, 0.2f, 0.2f, 1.0f},
new float[]{100f})
材质枚举构造函数:
Material(float[] ambient, float[] diffuse, float[] specular, float[] shininess) {
this.ambient = ambient;
this.diffuse = diffuse;
this.specular = specular;
this.shininess = shininess;
}
我使用以下方法应用材料:
public void use(GL2 gl) {
// set the material properties
gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GLLightingFunc.GL_AMBIENT, ambient, 0);
gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GLLightingFunc.GL_DIFFUSE, diffuse, 0);
gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GLLightingFunc.GL_SPECULAR, specular, 0);
gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GLLightingFunc.GL_SHININESS, shininess, 0);
}
在创建一个0-1值一致的2D“noisearray”后,将创建一个2D矢量数组,该数组由X*Y矢量组成,其中每个矢量表示平面/地形中的一个点
以下是在这些点之间绘制三角形的方法,您可以看到我绘制了每列的平面(Y方向):
public void draw(GL2 gl、GLU GLU、GLUT GLU、抽屉){
材料、地形、用途(gl);
纹理绑定(gl);
如果(显示网格)
gl.glPolygonMode(gl.gl\u前部和后部,gl.gl\u线);
ArrayList法线=新的ArrayList();
对于(inti=1;我感谢@Spektre对我的帮助
在正确计算顶点上所有周围面的平均法线并将此法线用于glNormal
之后,着色是正确的。您需要重新计算每个顶点的法线,以便它们匹配请参见@Spektre谢谢您的评论,我刚刚计算完平均法线,我现在确实有一个平滑的地形,但是e灯光看起来有点暗(没有深度)有什么建议吗?我打赌你的法线指向另一个方向,试着否定它们normal=-normal
或者没有正常化或者是错误的computed@Spektre我也这么认为,我尝试将它们反转,但没有效果。此外,这意味着地形另一侧的照明将是正确的,但事实并非如此-(在CW/CCW之间更改CULL_FACE之前,您不会看到它。无论如何,请尝试绘制法向量,以查看它们是否正确,是否与第一张图像中的相同(从中,您应该估计法向量方向和大小的正确性)。
public void draw(GL2 gl, GLU glu, GLUT glut, Drawer drawer) {
Material.TERRAIN.use(gl);
texture.bind(gl);
if (showGrid)
gl.glPolygonMode( gl.GL_FRONT_AND_BACK, gl.GL_LINE );
ArrayList<Vector[]> normals = new ArrayList<>();
for(int i=1;i<vectors.length;i++) {
gl.glBegin(gl.GL_TRIANGLE_STRIP);
for (int j = 0; j < vectors[i].length; j++) {
Vector normalTopRight, normalBottomLeft;
//Calculate normals top right
Vector v1, v2, triangleCenterTR;
if (j < vectors[i].length - 1)
{
v1 = vectors[i-1][j].subtract(vectors[i][j]);
v2 = vectors[i][j+1].subtract(vectors[i][j]);
normalTopRight = v2.cross(v1).normalized();
// Get center (a+b+c)*(1/3)
triangleCenterTR = (vectors[i][j].add(vectors[i - 1][j]).add(vectors[i][j + 1])).scale(1.0 / 3);
} else {
v1 = vectors[i-1][j].subtract(vectors[i][j]);
v2 = vectors[i][j-1].subtract(vectors[i][j]);
normalTopRight = v1.cross(v2).normalized();
// Get center (a+b+c)*(1/3)
triangleCenterTR = (vectors[i][j].add(vectors[i-1][j]).add(vectors[i][j-1])).scale(1.0/3);
}
normals.add(new Vector[] {triangleCenterTR, triangleCenterTR.add(normalTopRight)});
if (j != 0)
{
v1 = vectors[i][j].subtract(vectors[i-1][j]);
v2 = vectors[i-1][j-1].subtract(vectors[i-1][j]);
normalBottomLeft = v2.cross(v1).normalized();
// Get center (a+b+c)*(1/3)
Vector triangleCenterBL = (vectors[i - 1][j].add(vectors[i][j]).add(vectors[i - 1][j - 1])).scale(1.0 / 3);
normals.add(new Vector[]{triangleCenterBL, triangleCenterBL.add(normalBottomLeft)});
} else {
normalBottomLeft = null; // If j==0, there is no bottom left triangle above
}
/**
* We have everything to start drawing
*/
// Set some color
if (j == 0) {
// Initialization vector
gl.glTexCoord1d(mapTextureToHeight(vectors[i][j].z));
drawer.glVertexV(vectors[i][j]);
} else {
drawer.glNormalV(normalBottomLeft);
}
// Shift left
gl.glTexCoord1d(mapTextureToHeight(vectors[i - 1][j].z));
drawer.glVertexV(vectors[i - 1][j]);
// Right down diagonally
if (j < vectors[i].length - 1) { // Skip if we are reached the end
gl.glTexCoord1d(mapTextureToHeight(vectors[i][j + 1].z));
drawer.glNormalV(normalTopRight);
drawer.glVertexV(vectors[i][j + 1]);
}
}
gl.glEnd();
}
if (showGrid)
gl.glPolygonMode( gl.GL_FRONT_AND_BACK, gl.GL_FILL );
if (drawNormals) {
for (Vector[] arrow : normals) {
if (yellowNormals)
Material.YELLOW.use(gl);
else
gl.glTexCoord1d(mapTextureToHeight(arrow[0].z));
drawer.drawArrow(arrow[0], arrow[1], 0.05);
}
}
texture.unbind(gl);
}
public void draw() {
if (showGrid)
gl.glPolygonMode( gl.GL_FRONT_AND_BACK, gl.GL_LINE);
texture.bind(gl);
Material.TERRAIN.use(gl);
for(int i=1;i<vectors.length;i++) {
gl.glBegin(gl.GL_TRIANGLE_STRIP);
for (int j = 0; j < vectors[i].length; j++) {
// Initialization vector
gl.glTexCoord1d(mapTextureToHeight(vectors[i][j].z));
drawer.glNormalV(normals.get(vectors[i][j]));
drawer.glVertexV(vectors[i][j]);
// Shift left
gl.glTexCoord1d(mapTextureToHeight(vectors[i - 1][j].z));
drawer.glNormalV(normals.get(vectors[i - 1][j]));
drawer.glVertexV(vectors[i - 1][j]);
}
gl.glEnd();
}
if (showGrid)
gl.glPolygonMode( gl.GL_FRONT_AND_BACK, gl.GL_FILL );
if (drawNormals)
drawFaceNormals();
texture.unbind(gl);
}