Как нарисовать только определенные части массива, заполненные данными вершин - PullRequest
0 голосов
/ 18 января 2019

КОНТЕКСТ:

Я пытаюсь создать в openGL естественную сцену с открытым миром. Массив terrainVertices длины 3*NUM_OF_VERTICES содержит данные вершин для ландшафта, которые представляют собой карту высот, генерируемую шумом. Каждая вершина имеет x,y,z координаты, и на основе значения y определенному цвету присваивается вершина, что обеспечивает несколько плавный переход между глубокими водами и горными вершинами.

ПРОБЛЕМА:

Озера образуются, когда окрестность вершин имеет значение y, такое что y<0. Раскраска выполняется должным образом, однако результат нереалистичен. Это похоже на голубую яму:

enter image description here

Я решил решить эту проблему, создав слой вершин, которые появляются над озером, имеют y=0 и светло-синий цвет с низким значением альфа, создавая иллюзию поверхности, под которой лежит фактическое озеро.

Массив terrainVertices индексируется массивом элементов elements[NUM_OF_ELEMENTS]. Я перебираю массив элементов и пытаюсь найти триплеты индексов, которые соответствуют вершинам с y<0. Я собираю каждый триплет, который соответствует этому условию, в векторе, затем создаю новый объект массива вершин с теми же данными вершин, что и у ландшафта, но с новым буферным объектом элемента, который я только что описал. У «подводных» вершин значение y заменено на 0, чтобы прилипать к поверхности озера.

Вот код, который я использовал для этого:

std::vector<GLuint> waterElementsV;

//iterating over every triangle
for (int i = 0; i < NUM_OF_ELEMENTS / 3; i++) {

    //accessing each vertex based on its index from the element array
    //checking if its height is lower than zero
    //elements[3*i+0, +1, +2] represents the indices for a triangle
    //terrainVertices[index + 1] represents the height of the vertex
    if (terrainVertices[3 * (elements[3 * i]) + 1] < 0 &&
        terrainVertices[3 * (elements[3 * i + 1]) + 1] < 0 &&
        terrainVertices[3 * (elements[3 * i + 2]) + 1] < 0) {


        //since its a valid triangle, add its indices in the elements array.
        waterElementsV.push_back(elements[3 * i]);
        waterElementsV.push_back(elements[3 * i + 1]);
        waterElementsV.push_back(elements[3 * i + 2]);

    }

}


//iterating through the terrain vertices, and setting
//each appropriate vertex's y value to water surface level y = 0
for (unsigned int i = 0; i < waterElementsV.size(); i++) {

    currentIndex = waterElementsV[i];

    terrainVertices[3 * currentIndex + 1] = 0;

}

//get the vector's underlying array
waterElements = waterElementsV.data();


glGenVertexArrays(1, &waterVAO);
glBindVertexArray(waterVAO);

glGenBuffers(1, &waterVerticesVBO);
glBindBuffer(GL_ARRAY_BUFFER, waterVerticesVBO);
glBufferData(GL_ARRAY_BUFFER, NUM_OF_VERTICES, terrainVertices, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);


glGenBuffers(1, &waterEBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, waterEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(waterElements), waterElements, GL_STATIC_DRAW);

Шейдеры очень просты, так как мне нужно только назначить позицию и цвет. Матрицы проекции мировоззрения не используются, потому что каждый объект рисуется относительно местности в любом случае.

Вершинный шейдер:

#version 330 core

layout (location = 0) in vec3 pos;

void main()
{
    gl_Position = vec4(pos, 1.0);
}  

Фрагмент шейдера:

#version 330 core

out vec4 fragColor;

void main()
{
    fragColor = vec4(0, 0, 0, 1);
}  

Результат точно такой же, как на картинке выше. Я размышлял о том, что происходит, но, похоже, не могу понять ... Обратите внимание, что озера расположены в случайных местах и ​​не обязательно соседствуют друг с другом.

Любая помощь или советы с благодарностью:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...