繁体   English   中英

地形将单独绘制,但不会与场景 OpenGL 中的其他对象一起渲染

[英]Terrain will draw alone, but won't render with other objects in scene OpenGL

编辑:想通了,但如果有人对我的代码有一些指示,将不胜感激! 太疯狂了,这么小的错误会花费你几天的时间。

在 OpenGL 中创建地形后,我注意到当场景中有其他对象时它会拒绝渲染,但如果我自己渲染,它渲染得很好。 我有一个单独的 VAO、VBO、IBO,所以我不确定为什么会这样。

这是我的地形课

#include "Terrain.h"
#include <stb_image.h>

unsigned int terrainTexture;
Texture texture(terrainTexture);

Terrain::Terrain(const char* imagePath) {
    this->imagePath = imagePath;
    this->TERRAIN_WIDTH = 20.0f;
    this->TERRAIN_LENGTH = 20.0f;
    this->shader = new Shader("..\\..\\src\\shaders\\terrVert.glsl", 
    "..\\..\\src\\shaders\\terrFrag.glsl");
    terrainTexture = texture.loadTexture("..\\..\\res\\rock.jpg");
}

void Terrain::setUniforms(glm::mat4 model, glm::mat4 view, glm::mat4 projection) {
    GLint modelLoc = glGetUniformLocation(shader->Program, "model");
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
    GLint viewLoc = glGetUniformLocation(shader->Program, "view");
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
    GLint projLoc = glGetUniformLocation(shader->Program, "projection");
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
}

void Terrain::setupTerrain() {
    createVertexData();
    createIndexData();
    checkHeightMapLoaded();
    //generate & bind vao
    glGenVertexArrays(1, &terrVao);
    glBindVertexArray(terrVao);
    //specify vertex buffer
    glGenBuffers(1, &vbufferid);
    glBindBuffer(GL_ARRAY_BUFFER, vbufferid);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices.front(), 
    GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    //specify index buffer
    glGenBuffers(1, &ibufferid);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibufferid);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(short), &indices.front(),              
    GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

void Terrain::draw() {
    glBindBuffer(GL_ARRAY_BUFFER, vbufferid);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (GLvoid*)0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibufferid);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, terrainTexture);
    glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, 0);
    glDrawArrays(GL_TRIANGLES, 0, vertices.size());
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glDisableVertexAttribArray(0);
}

void Terrain::createVertexData() {
    unsigned char* image = stbi_load(imagePath, &heightMapWidth, &heightMapHeight, 
    &numOfChannels, 0);
    cout << "\033[31mHeight Map width: \033[0m" << heightMapWidth << "\033[31m Height Map 
    height: \033[0m" << heightMapHeight << endl << endl;
    for (int row = 0; row < heightMapHeight; row++) {
        for (int col = 0; col < heightMapWidth; col++) {
            unsigned char* pixelOffset = image + (row + heightMapHeight * col) * 
            numOfChannels;
            unsigned char red = pixelOffset[0];
            float x = ((float)col / (float)(heightMapWidth - 1)) /*- 0.5f*/;
            float y = (float)red / 255.0;
            float z = ((float)row / (float)(heightMapHeight - 1)) /*- 0.5f*/;

            vertices.push_back(glm::vec3(x, y, z));
        }
    }
    delete image;
}

void Terrain::createIndexData() {
    for (int row = 0; row < heightMapHeight - 1; row++) {
        for (int col = 0; col < heightMapWidth - 1; col++) {
            int TL = (int)(row * heightMapWidth + col);
            int TR = (int)(row * heightMapWidth + col + 1);
            int BL = (int)((row + 1) * heightMapWidth + col);
            int BR = (int)((row + 1) * heightMapWidth + col + 1);
            indices.push_back(TL);
            indices.push_back(BL);
            indices.push_back(TR);
            indices.push_back(TR);
            indices.push_back(BL);
            indices.push_back(BR);
        }
    }
}

void Terrain::checkHeightMapLoaded() {
    if (heightMapWidth == 0 || heightMapHeight == 0) {
        cout << "\033[31mHeight Map failed to load\033[0m\n";
        return;
    }
    else if (heightMapWidth > 255 || heightMapHeight > 255) {
        cout << "\033[31mHEIGHT MAP SIZE GREATER THAN 255x255! RESIZE DOWN!!\033[0m" << endl;
    }
    else {
        cout << "\033[32mHeight Map loaded successfully\033[0m\n";
    }
}

glm::mat4 Terrain::getModelMatrix() {
    glm::mat4 terrModel = glm::scale(glm::mat4(1.0f), glm::vec3(this->TERRAIN_WIDTH, 1.0f, 
    this->TERRAIN_LENGTH));
    return  terrModel;
}

Shader* Terrain::getShader() {
    return shader;
}

Terrain::~Terrain()
{
    glDeleteBuffers(1, &vbufferid);
    glDeleteBuffers(1, &ibufferid);
    delete shader;
}

就在我的主循环之前,我调用了terrain.setupTerrain(); 并在循环中生病了

terrain.getShader()->use();
terrain.setUniforms(terrain.getModelMatrix(), view, projection);
terrain.draw();

我认为我设置 VAO、VBO 和 IBO 的方式有问题,但经过几天的尝试,我完全不知道是什么原因造成的。

发帖5分钟后搞定

对于遇到同样问题的人来说,我在设置地形时绑定了 vao,但我没有在每个绘制调用中绑定它。

添加

glBindVertexArray(terrVao);

在 draw 方法中修复了问题!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM