В настоящее время я работаю над проектом OpenGL (JOGL) в java. Целью является создание ландшафта с текстурами и затенением.Окантовка текстуры ландшафта
Я создаю случайный симплекс-шум, используя эти значения в качестве карты высот. Высота сопоставляется с 1D текстурой для имитации окраски по высоте. Затем для имитации затенения используется материал (окружающий/рассеянный/зеркальный/блеск).
Однако; после добавления затенения к рельефу, «полосы» появляются на каждом «столбце» (направление Y) местности.
Следующий материал затем применяется:
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);
}
После создания 2D «noisearray», совпадающий с значениями 0-1, создается 2D-векторный символ, содержащий X * Y vec tors, где каждый вектор представляет собой точку в плоскости/местности.
Вот метод, который рисует треугольники между теми точками, где вы можете увидеть, я рисую плоскость для каждого столбца (Y-направление):
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);
}
Наиболее очевидной причиной полос является тот факт, я рисую треугольники на столбец, в результате чего OpenGL не сможет сгладить затенение на многоугольниках (GL_SMOOTH). Есть ли способ исправить это?
[Edit1] скопированные с комментарием по Spektre
Я только что закончил вычисления средних нормалей, я действительно имеют гладкую местность в настоящее время, но освещение выглядит вид (глубина)
Вот новый код, который рисует рельеф местности:
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);
}
Я очистил его, я уверен, что нормалей указывает правильный путь, используя функцию drawnormals и убедились, что OpenGL видит в верхней части местности, как FRONT использует (gl.GL_FRONT -> рисует только над рельефом, а не ниже).
Вот полный класс: PasteBin
вам нужно пересчитать нормали на вершину, чтобы они соответствовали [Как достичь гладких касательных пространственных нормалей?] (http://stackoverflow.com/a/21930058/2521214) – Spektre
@Spektre Спасибо за ваш комментарий, я только что закончил вычислять средние нормали, у меня действительно есть гладкая местность сейчас, но освещение выглядит вроде скучно (без глубины) [image] (http://i.imgur.com/EbtqLAK.png) Любые предложения? –
Моя ставка заключается в том, что ваши нормали указывают на другой способ попытаться свести их на нет «normal = -normal» или не нормализуются или ошибочно вычисляются – Spektre