【发布时间】:2019-01-20 11:46:10
【问题描述】:
由于某种奇怪的原因,我似乎无法渲染不同的生成网格。我有一个类可以为每个实例生成适当的缓冲区和 vaos。这个类的想法是让我生成原语。我将这个类的一个成员添加到 BoxGeometry 和 SphereGeometry 中。如果我只渲染一种类型,那没有问题,但如果我渲染两种不同的类型,它只会渲染一种原始类型并且不正确。
这是基本几何生成器:
#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 的业余爱好者,但我无中生有地写了这段代码,所以我不确定我忘记了什么。
编辑: 图片: Album of images showing different instances
我查了一下,没有内存损坏的问题,好像是ogl的问题。
【问题讨论】:
-
你有截图吗?您的程序的行为是什么,它与您的期望/期望有何不同?
-
编辑并添加了显示问题的图片相册。
-
所有对象都使用相同的着色器吗?但主要问题是,函数背后隐藏了太多代码。例如,哪个着色器方法会调用
glUseProgram?我怀疑use这意味着着色器在 设置unforms 之后被绑定。由于统一设置始终适用于当前着色器,因此您可能将统一设置在错误的着色器中。 -
你的硬件平台是什么?英特尔?英伟达? AMD ?
-
NVIDIA,毕竟制服像其他人提到的那样被损坏了,而不是真正的驱动问题。