出于某些奇怪的原因,我似乎无法渲染不同的生成网格。我有一个为每个实例生成适当的缓冲区和值的类。类的想法是让我生成基元。我分别向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的业余爱好者,对此我感到有些惊讶,但是我一无是处编写了这段代码,所以我不确定自己忘记了什么。
编辑: 图片: Album of images showing different instances
我检查了一下,没有内存损坏问题,这似乎表明ogl有问题。
答案 0 :(得分:2)
我看不到所有代码,但这对我来说可疑:
mainShader->setFloat("boxLength", length);
mainShader->...;
mainShader->use();
在不同的着色器程序中,统一的位置并不是唯一的。如果setFloat
只是glUniform1f
或类似名称的包装,而use
是glUseProgram
,则意味着代码在错误的程序上设置了统一的样式!
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上运行,对于猜对了的人来说没有任何奖励),但是它确实为您节省了很多调试时间。