OpenGL: Ландшафт не рисует (карта высот)

РЕДАКТИРОВАТЬ: я думаю, что проблема может быть, когда я загружаю вершины и индексы. Может быть, сосредоточиться на этом разделе 🙂

Я пытаюсь загрузить карту высот из файла BMP и отображать ее в OpenGL. Как и во многих других попытках, все компилируется и работает без ошибок, но на экране ничего не отображается. Кажется, я не могу так сильно изолировать проблему, поскольку весь код работает сам по себе, но в сочетании для рисования ландшафта ничего не работает.

Класс местности

У меня есть класс местности. Он имеет 2 VBO, 1 IBO и 1 VAO. Он также хранит вершины, индексы, цвета вершин и высоты. Загружается из файла bmp.

Погрузка местности:

Terrain* Terrain::loadTerrain(const std::string& filename, float height)
{
BitMap* bmp = BitMap::load(filename);
Terrain* t = new Terrain(bmp->width, bmp->length);
for(unsigned y = 0; y < bmp->length; y++)
{
for(unsigned x = 0; x < bmp->width; x++)
{
unsigned char color =
(unsigned char)bmp->pixels[3 * (y * bmp->width + x)];
float h = height * ((color / 255.0f) - 0.5f);
t->setHeight(x, y, h);
}
}
delete bmp;
t->initGL();
return t;
}

Инициализация буферов:

void Terrain::initGL()
{
// load vertices from heights data
vertices = new Vector4f[w * l];
int vertIndex = 0;
for(unsigned y = 0; y < l; y++)
{
for(unsigned x = 0; x < w; x++)
{
vertices[vertIndex++] = Vector4f((float)x, (float)y, heights[y][x], 1.0f);
}
}

// generate indices for indexed drawing
indices = new GLshort[(w - 1) * (l - 1) * 6]; // patch count * 6 (2 triangles per terrain patch)
int indicesIndex = 0;
for(unsigned y = 0; y < (l - 1); ++y)
{
for(unsigned x = 0; x < (w - 1); ++x)
{
int start = y * w + x;
indices[indicesIndex++] = (GLshort)start;
indices[indicesIndex++] = (GLshort)(start + 1);
indices[indicesIndex++] = (GLshort)(start + w);

indices[indicesIndex++] = (GLshort)(start + 1);
indices[indicesIndex++] = (GLshort)(start + 1 + w);
indices[indicesIndex++] = (GLshort)(start + w);
}
}

// generate colours for the vertices
colours = new Vector4f[w * l];
for(unsigned i = 0; i < w * l; i++)
{
colours[i] = Vector4f(0.0f, 1.0f, 0.0f, 1.0f); // let's make the entire terrain green
}

// THIS CODE WORKS FOR CUBES (BEGIN)

// vertex buffer object
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

// index buffer object
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

// colours vertex buffer object
glGenBuffers(1, &colour_vbo);
glBindBuffer(GL_ARRAY_BUFFER, colour_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(colours), colours, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

// create vertex array object
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, colour_vbo);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

glBindVertexArray(0);

// THIS CODE WORKS FOR CUBES (END)
}

Часть, в которой я создаю VBO, IBO и VAO, отлично работает для кубов, они хорошо прорисованы.

Рендеринг местности:

void Terrain::render()
{
glUseProgram(shaderProgram);

glBindVertexArray(vao);
int indices_length = (w - 1) * (l - 1) * 6;
glDrawElements(GL_TRIANGLES, indices_length, GL_UNSIGNED_SHORT, 0);
}

шейдеры

Это вершинные и фрагментные шейдеры.

Vertex:

#version 330

layout (location = 0) in vec4 position;
layout (location = 1) in vec4 vertexColour;

out vec4 fragmentColour;

uniform vec3 offset;
uniform mat4 perspectiveMatrix;

void main()
{
vec4 cameraPos = position + vec4(offset.x, offset.y, offset.z, 0.0);

gl_Position = perspectiveMatrix * cameraPos;

fragmentColour = vertexColour;
}

Фрагмент:

#version 330

in vec4 fragmentColour;

out vec4 outputColour;

void main()
{
outputColour = fragmentColour;
}

Перспективная матрица

Вот настройки для «камеры»:

struct CameraSettings
{
static const float FRUSTUM_SCALE = 1.0f;
static const float Z_NEAR = 0.5f;
static const float Z_FAR = 3.0f;

static float perspective_matrix[16];
};

float CameraSettings::perspective_matrix[16] = {
FRUSTUM_SCALE,
0, 0, 0, 0,
FRUSTUM_SCALE,
0, 0, 0, 0,
(Z_FAR + Z_NEAR) / (Z_NEAR - Z_FAR),
-1.0f,
0, 0,
(2 * Z_FAR * Z_NEAR) / (Z_NEAR - Z_FAR),
0
};

Форма заполняется после initGL() называется:

// get offset uniform
offsetUniform = ShaderManager::getUniformLocation(shaderProgram, "offset");
perspectiveMatrixUniform = ShaderManager::getUniformLocation(shaderProgram, "perspectiveMatrix");

// set standard uniform data
glUseProgram(shaderProgram);
glUniform3f(offsetUniform, xOffset, yOffset, zOffset);
glUniformMatrix4fv(perspectiveMatrixUniform, 1, GL_FALSE, CameraSettings::perspective_matrix);
glUseProgram(0);

Может ли кто-нибудь проверить мой код и дать предложения?

3

Решение

Я уверен, что когда вы говорите:

    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

Вы действительно хотите сказать:

    glBufferData(GL_ARRAY_BUFFER, sizeof (Vector4f) * w * l, vertices, GL_STATIC_DRAW);

(то же самое для цветного буфера и т. д.)

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]