簡體   English   中英

無法在OpenGL上使用不同的VAO渲染不同的網格

[英]Can't render different meshes with different VAO on OpenGL

由於某些奇怪的原因,我似乎無法渲染不同的生成的網格。 我有一個為每個實例生成適當的緩沖區和值的類。 類的想法是讓我生成基元。 我分別向BoxGeometry和SphereGeometry添加此類的成員。 如果僅渲染1種類型,就沒有問題,但是如果渲染兩種不同的類型,則它僅渲染1種基本類型,並且不正確。

這是基本幾何圖形生成器:

#pragma once

// GLAD
#include <vector>
#include <glad/glad.h>
#include <cstddef>
#include <cstdint>

class GeometryGenerator {

public:
    GeometryGenerator() : buffer(64), ibuffer(192) {
        buffer.clear();
        ibuffer.clear();
        generated = false;
    }

    void emitVertex() {
        buffer.push_back(currentVertex);
    }

    void emitTriangle() {
        ibuffer.push_back(currentTriangle[0]);
        ibuffer.push_back(currentTriangle[1]);
        ibuffer.push_back(currentTriangle[2]);
    }

    void declareVertexPosition(float x, float y, float z) {
        currentVertex.position[0] = x;
        currentVertex.position[1] = y;
        currentVertex.position[2] = z;
    }

    void declareVertexNormal(float x, float y, float z) {
        currentVertex.normal[0] = x;
        currentVertex.normal[1] = y;
        currentVertex.normal[2] = z;
    }

    void declareTriangle(std::uint32_t x, std::uint32_t y, std::uint32_t z) {
        currentTriangle[0] = x;
        currentTriangle[1] = y;
        currentTriangle[2] = z;
        emitTriangle();
    }

    void generate() {
        glGenVertexArrays(1, &VAO);
        glGenBuffers(1, &VBO);
        glGenBuffers(1, &EBO);

        glBindVertexArray(VAO);

        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * buffer.size(), buffer.data(),
                     GL_STATIC_DRAW);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(std::uint32_t) * ibuffer.size(), ibuffer.data(),
                     GL_STATIC_DRAW);

        // position attribute
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);

        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
                              (void*)offsetof(Vertex, normal));

        glBindVertexArray(0);
        generated = true;
    }

    void draw() {
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, ibuffer.size(), GL_UNSIGNED_INT, 0);
        glBindVertexArray(0);
    }

private:
    struct alignas(1) Vertex {
        float position[3];
        float normal[3];
    };

    Vertex currentVertex;
    std::uint32_t currentTriangle[3];
    std::vector<struct Vertex> buffer;
    std::vector<std::uint32_t> ibuffer;
    bool generated;
    unsigned int VAO, VBO, EBO;
};

這是我的BoxClass:#pragma

#include <memory>
#include "GeometryGenerator.h"
#include "shader.h"
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/string_cast.hpp>
#include "Light.h"

class BoxGeometry {
public:
    static BoxGeometry& getInstance() {
        static BoxGeometry instance;
        return instance;
    }

    void render(const glm::mat4& projection, const glm::mat4& view, const Light& light,
                const Kepler3D::Matrix44& modelMatrix, const Kepler3D::Matrix44& shapeMatrix,
                float length, float width, float height, const glm::vec4& baseColor) {
        glm::mat4 mv;
        std::memcpy(glm::value_ptr(mv), &modelMatrix, sizeof(float)*4*4);
        glm::mat4 sv;
        std::memcpy(glm::value_ptr(sv), &shapeMatrix, sizeof(float)*4*4);
        mainShader->setFloat("boxLength", length);
        mainShader->setFloat("boxWidth", width);
        mainShader->setFloat("boxHeight", height);
        mainShader->setVec3("light.direction", light.direction);
        mainShader->setVec3("light.ambient", light.ambient);
        mainShader->setVec3("light.diffuse", light.diffuse);
        mainShader->setVec3("light.specular", light.specular);
        mainShader->setMat4("ProjectionMatrix", projection);
        mainShader->setMat4("ViewMatrix", view);
        mainShader->setMat4("ModelMatrix", glm::transpose(mv));
        mainShader->setMat4("ShapeMatrix", glm::transpose(sv));
        mainShader->setVec4("baseColor", baseColor);
        mainShader->use();
        geometry.draw();
    }

    BoxGeometry(BoxGeometry const&) = delete;
    void operator=(BoxGeometry const&) = delete;

private:
    void generateGeometry() {
        geometry.declareVertexPosition(0.5f, 0.5f, 0.5f);
        geometry.declareVertexNormal(0.0f, 1.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(0.5f, 0.5f, -0.5f);
        geometry.declareVertexNormal(0.0f, 1.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(-0.5f, 0.5f, -0.5f);
        geometry.declareVertexNormal(0.0f, 1.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(-0.5f, 0.5f, 0.5f);
        geometry.declareVertexNormal(0.0f, 1.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareTriangle(0, 1, 2);
        geometry.declareTriangle(2, 3, 0);

        // bottom

        geometry.declareVertexPosition(0.5f, -0.5f, 0.5f);
        geometry.declareVertexNormal(0.0f, -1.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(0.5f, -0.5f, -0.5f);
        geometry.declareVertexNormal(0.0f, -1.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(-0.5f, -0.5f, -0.5f);
        geometry.declareVertexNormal(0.0f, -1.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(-0.5f, -0.5f, 0.5f);
        geometry.declareVertexNormal(0.0f, -1.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareTriangle(4, 5, 6);
        geometry.declareTriangle(6, 7, 4);

        //left

        geometry.declareVertexPosition(0.5f, -0.5f, 0.5f);
        geometry.declareVertexNormal(1.0f, 0.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(0.5f, -0.5f, -0.5f);
        geometry.declareVertexNormal(1.0f, 0.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(0.5f, 0.5f, -0.5f);
        geometry.declareVertexNormal(1.0f, 0.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(0.5f, 0.5f, 0.5f);
        geometry.declareVertexNormal(1.0f, 0.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareTriangle(8, 9, 10);
        geometry.declareTriangle(10, 11, 8);

        //Right

        geometry.declareVertexPosition(-0.5f, -0.5f, 0.5f);
        geometry.declareVertexNormal(-1.0f, 0.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(-0.5f, -0.5f, -0.5f);
        geometry.declareVertexNormal(-1.0f, 0.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(-0.5f, 0.5f, -0.5f);
        geometry.declareVertexNormal(-1.0f, 0.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(-0.5f, 0.5f, 0.5f);
        geometry.declareVertexNormal(-1.0f, 0.0f, 0.0f);
        geometry.emitVertex();

        geometry.declareTriangle(12, 13, 14);
        geometry.declareTriangle(14, 15, 12);

        //Front

        geometry.declareVertexPosition(0.5f, -0.5f, 0.5f);
        geometry.declareVertexNormal(0.0f, 0.0f, 1.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(-0.5f, -0.5f, 0.5f);
        geometry.declareVertexNormal(0.0f, 0.0f, 1.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(-0.5f, 0.5f, 0.5f);
        geometry.declareVertexNormal(0.0f, 0.0f, 1.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(0.5f, 0.5f, 0.5f);
        geometry.declareVertexNormal(0.0f, 0.0f, 1.0f);
        geometry.emitVertex();

        geometry.declareTriangle(16, 17, 18);
        geometry.declareTriangle(18, 19, 16);

        //Back

        geometry.declareVertexPosition(0.5f, -0.5f, -0.5f);
        geometry.declareVertexNormal(0.0f, 0.0f, 1.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(-0.5f, -0.5f, -0.5f);
        geometry.declareVertexNormal(0.0f, 0.0f, 1.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(-0.5f, 0.5f, -0.5f);
        geometry.declareVertexNormal(0.0f, 0.0f, 1.0f);
        geometry.emitVertex();

        geometry.declareVertexPosition(0.5f, 0.5f, -0.5f);
        geometry.declareVertexNormal(0.0f, 0.0f, 1.0f);
        geometry.emitVertex();

        geometry.declareTriangle(20, 21, 22);
        geometry.declareTriangle(22, 23, 20);

        geometry.generate();
    }
    void initShader() {
        mainShader = std::make_unique<Shader>("shaders/VSBox.glsl", "shaders/PSPhong.glsl");
    }
    BoxGeometry() : geometry() {
        generateGeometry();
        initShader();
    }
    std::unique_ptr<Shader> mainShader;
    GeometryGenerator geometry;
};

和sphere類:#pragma一次

#include <memory>
#include "GeometryGenerator.h"
#include "shader.h"
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/string_cast.hpp>
#include "Light.h"
#include <math.h>

class SphereGeometry {
public:
    static SphereGeometry& getInstance() {
        static SphereGeometry instance;
        return instance;
    }

    void render(const glm::mat4& projection, const glm::mat4& view, const Light& light,
                const Kepler3D::Matrix44& modelMatrix, const Kepler3D::Matrix44& shapeMatrix,
                float radius, const glm::vec4& baseColor) {
        glm::mat4 mv;
        std::memcpy(glm::value_ptr(mv), &modelMatrix, sizeof(float)*4*4);
        glm::mat4 sv;
        std::memcpy(glm::value_ptr(sv), &shapeMatrix, sizeof(float)*4*4);
        mainShader->setFloat("radius", radius);
        mainShader->setVec3("light.direction", light.direction);
        mainShader->setVec3("light.ambient", light.ambient);
        mainShader->setVec3("light.diffuse", light.diffuse);
        mainShader->setVec3("light.specular", light.specular);
        mainShader->setMat4("ProjectionMatrix", projection);
        mainShader->setMat4("ViewMatrix", view);
        mainShader->setMat4("ModelMatrix", glm::transpose(mv));
        mainShader->setMat4("ShapeMatrix", glm::transpose(sv));
        mainShader->setVec4("baseColor", baseColor);
        mainShader->use();
        geometry.draw();
    }

    SphereGeometry(SphereGeometry const&) = delete;
    void operator=(SphereGeometry const&) = delete;

private:
    void generateGeometry() {
        glm::vec3 top(0.0f, 0.5f, 0.0f);
        glm::vec3 bottom(0.0f, -0.5f, 0.0f);
        float radius = 0.5f;
        float angleA = 0.f;
        const float pi = 3.14159265f;
        float angleB = pi * 0.5f;
        unsigned int sides = 16;
        unsigned int laterals = 16;
        float advanceX = 2.f*pi / sides;
        float advanceY = pi / laterals;

        unsigned int faceIndex = 0;

        angleB -= advanceY;
        laterals--;
        // Top
        for (unsigned int i = 0; i < sides; i++) {
            geometry.declareVertexPosition(top.x, top.y, top.z);
            geometry.declareVertexNormal(0.0f, 1.0f, 0.0f);
            geometry.emitVertex();

            geometry.declareVertexPosition(cos(angleA)*cos(angleB)*radius, sin(angleB)*radius, sin(angleA)*cos(angleB)*radius);
            geometry.declareVertexNormal(cos(angleA)*cos(angleB), sin(angleB), sin(angleA)*cos(angleB));
            geometry.emitVertex();

            angleA += advanceX;

            geometry.declareVertexPosition(cos(angleA)*cos(angleB)*radius, sin(angleB)*radius, sin(angleA)*cos(angleB)*radius);
            geometry.declareVertexNormal(cos(angleA)*cos(angleB), sin(angleB), sin(angleA)*cos(angleB));
            geometry.emitVertex();

            geometry.declareTriangle(faceIndex, faceIndex+1, faceIndex+2);
            faceIndex += 3;
        }

        for(; laterals > 1; laterals--) {
            float cachedB = angleB;
            angleB -= advanceY;
            angleA = 0.f;
            for (unsigned int i = 0; i < sides; i++) {

                geometry.declareVertexPosition(cos(angleA)*cos(cachedB)*radius, sin(cachedB)*radius, sin(angleA)*cos(cachedB)*radius);
                geometry.declareVertexNormal(cos(angleA)*cos(cachedB), sin(cachedB), sin(angleA)*cos(cachedB));
                geometry.emitVertex();

                geometry.declareVertexPosition(cos(angleA)*cos(angleB)*radius, sin(angleB)*radius, sin(angleA)*cos(angleB)*radius);
                geometry.declareVertexNormal(cos(angleA)*cos(angleB), sin(angleB), sin(angleA)*cos(angleB));
                geometry.emitVertex();

                angleA += advanceX;

                geometry.declareVertexPosition(cos(angleA)*cos(cachedB)*radius, sin(cachedB)*radius, sin(angleA)*cos(cachedB)*radius);
                geometry.declareVertexNormal(cos(angleA)*cos(cachedB), sin(cachedB), sin(angleA)*cos(cachedB));
                geometry.emitVertex();

                geometry.declareVertexPosition(cos(angleA)*cos(angleB)*radius, sin(angleB)*radius, sin(angleA)*cos(angleB)*radius);
                geometry.declareVertexNormal(cos(angleA)*cos(angleB), sin(angleB), sin(angleA)*cos(angleB));
                geometry.emitVertex();

                geometry.declareTriangle(faceIndex, faceIndex+1, faceIndex+2);
                geometry.declareTriangle(faceIndex+1, faceIndex+3, faceIndex+2);
                faceIndex += 4;
            }
        }

        angleA = 0.f;
        // Bottom
        for (unsigned int i = 0; i < sides; i++) {

            geometry.declareVertexPosition(cos(angleA)*cos(angleB)*radius, sin(angleB)*radius, sin(angleA)*cos(angleB)*radius);
            geometry.declareVertexNormal(cos(angleA)*cos(angleB), sin(angleB), sin(angleA)*cos(angleB));
            geometry.emitVertex();

            angleA += advanceX;

            geometry.declareVertexPosition(cos(angleA)*cos(angleB)*radius, sin(angleB)*radius, sin(angleA)*cos(angleB)*radius);
            geometry.declareVertexNormal(cos(angleA)*cos(angleB), sin(angleB), sin(angleA)*cos(angleB));
            geometry.emitVertex();

            geometry.declareVertexPosition(bottom.x, bottom.y, bottom.z);
            geometry.declareVertexNormal(0.0f, -1.0f, 0.0f);
            geometry.emitVertex();

            geometry.declareTriangle(faceIndex, faceIndex+2, faceIndex+1);
            faceIndex += 3;
        }

        geometry.generate();
    }
    void initShader() {
        mainShader = std::make_unique<Shader>("shaders/VSSphere.glsl", "shaders/PSPhong.glsl");
    }
    SphereGeometry() : geometry() {
        generateGeometry();
        initShader();
    }
    std::unique_ptr<Shader> mainShader;
    GeometryGenerator geometry;
};

現在,我不確定我是否忘記正確設置,但是從理論上講,我應該能夠渲染每個基元的實例而不會遇到任何麻煩,但VAO似乎存在問題。 我正在使用OpenGL 3.3,glfw,glm和我嘗試測試的物理引擎。 我不是ogl的業余愛好者,我對此感到有些驚訝,但是我一無是處編寫了這段代碼,所以我不確定自己忘記了什么。

編輯:圖像: 顯示不同實例的圖像專輯

我檢查了一下,沒有內存損壞問題,這似乎表明ogl存在問題。

我看不到所有代碼,但是對我來說這似乎很可疑:

mainShader->setFloat("boxLength", length);
mainShader->...;
mainShader->use();

在不同的着色器程序中,統一的位置不是唯一的。 如果setFloat只是glUniform1f或類似內容的包裝,並且useglUseProgram ,則意味着代碼在錯誤的程序上設置了制服!

glUniform —為當前程序對象指定統一變量的值

這是OpenGL有狀態API困擾您的另一種情況,這種問題是通過直接狀態訪問,其他各種無綁定功能以及更新的API(如Vulkan)解決的。

簡易解決方案

只需將use放在頂部:

mainShader->use();
mainShader->setFloat("boxLength", length);
mainShader->...;

替代解決方案

如果可以選擇OpenGL 4.1,則可以使用glProgramUniform操作,該操作不受當前綁定程序的影響。 這來自GL_ARB_separate_shader_objects擴展。

調試和檢測問題

您可能未使用KHR_debug或未調用glGetError 不正確的統一訪問生成INVALID_OPERATION錯誤。 看到這些錯誤的最佳方法是創建調試上下文並啟用KHR_debug擴展。 這需要執行一些工作,並且不能在所有地方都可以使用(嗯,它不能在macOS上使用,對於猜對的人也沒有獎品),但是它確實為您節省了很多調試時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM