OpenGL VBO绘图问题
OpenGL VBO drawing problems
目前我正在制作的粒子引擎有问题。使用引擎,你可以在引擎中添加多个发射器,其想法是每个粒子系统可以发射自己的粒子。
然而,我遇到的问题是,当我添加第二个粒子系统时,第一个粒子系统的图像似乎受到了影响,我的意思是它根本没有被绘制出来。每个粒子系统的绘制调用都被正确调用。
我认为问题是,尽管创建了多个vbo,但实际上只使用了一个。
我将展示影响vbo的函数的重要部分。我的着色器使用一个统一的位置来存储WVP矩阵。我还应该提到每个粒子系统应该使用自己的着色器程序。
下面是我在创建粒子系统时调用的initializeBuffers函数:
void ParticleSystem::InitializeBuffers()
{
glGenVertexArrays(1, &VaoId);
glBindVertexArray(VaoId);
//glGenBuffers(1, &VboId);
glGenBuffers(1, &PositionBufferId);
glGenBuffers(1, &IndexBufferId);
glGenBuffers(1, &WVPId);
std::list<Particle>::iterator iterator = particles.begin();
//positions.reserve(5);
for (std::list<Particle>::iterator iterator = particles.begin(), end = particles.end(); iterator != end; ++iterator)
{
positions.push_back(iterator->GetPosition());
//verticesToDraw.insert(verticesToDraw.end(), iterator->GetVertices()->begin(), iterator->GetVertices()->end());
indicesToDraw.insert(indicesToDraw.end(), iterator->GetIndices()->begin(), iterator->GetIndices()->end());
}
//glBindBuffer(GL_ARRAY_BUFFER, VboId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicesToDraw[0]) * indicesToDraw.size(), &indicesToDraw[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, WVPId);
for (unsigned int i = 0; i < 4 ; i++) {
glEnableVertexAttribArray(WVP_LOCATION + i);
glVertexAttribPointer(WVP_LOCATION + i, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4f), (const GLvoid*)(sizeof(GLfloat) * i * 4));
glVertexAttribDivisor(WVP_LOCATION + i, 1);
}
for(std::list<BaseBuildingBlock*>::iterator iterator = buildingBlocks.begin(), end = buildingBlocks.end(); iterator != end; ++iterator)
{
(*iterator)->InitializeBuffer(programId);
}
/*
glBindBuffer(GL_ARRAY_BUFFER, WorldId);
for (unsigned int i = 0; i < 4 ; i++) {
glEnableVertexAttribArray(WORLD_LOCATION + i);
glVertexAttribPointer(WORLD_LOCATION + i, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4f), (const GLvoid*)(sizeof(GLfloat) * i * 4));
glVertexAttribDivisor(WORLD_LOCATION + i, 1);
}
*/
//return GLCheckError();
}
这是绘制函数和实际绘制实例元素的代码,wvp矩阵由函数前面的粒子系统形成。
void ParticleSystem::Draw(Matrix4f perspectiveCameraMatrix)
{
// scale TEST
//GLint gScaleLocation = glGetUniformLocation(program, "gScale");
//assert(gScaleLocation != 0xFFFFFFFF);
//glUniform1f(gScaleLocation, scale);
//Pipeline p;
//Matrix4f* WVPMatrices = new Matrix4f[particles.size()];
//Matrix4f* WorldMatrices = new Matrix4f[particles.size()];
WVPMatrices.clear();
WorldMatrices.clear();
glUseProgram(0);
glUseProgram(programId);
//Matrix4f perspectiveMatrix;
//perspectiveMatrix.BuildPerspProjMat(90,1, 0.01, 200, 100 - 0 /*getWidth() / 32*/, 100 - 0 /*getHeight() / 32*/);
//********************************************************************************************************
// Method 1
// Think I need to next define a camera position.
if(particles.size() == 0)
{
return;
}
verticesToDraw.clear();
Matrix4f scaleMatrix;
Matrix4f worldMatrix;
Matrix4f rotateMatrix;
Matrix4f finalMatrix;
//ColourId = glGetUniformLocation(programId, "UniformColour");
int i = 0;
for (std::list<Particle>::iterator iterator = particles.begin(), end = particles.end(); iterator != end; ++iterator)
{
verticesToDraw = *iterator->GetVertices();
indicesToDraw = *iterator->GetIndices();
//positions.push_back(iterator->GetPosition());
worldMatrix.InitTranslationTransform(iterator->GetPosition().x, iterator->GetPosition().y, iterator->GetPosition().z);
rotateMatrix.InitRotateTransform(iterator->GetRotation().x, iterator->GetRotation().y, iterator->GetRotation().z);
scaleMatrix.InitScaleTransform(iterator->GetScale().x, iterator->GetScale().y, iterator->GetScale().z);
finalMatrix = perspectiveCameraMatrix * worldMatrix * rotateMatrix * scaleMatrix;
//p.WorldPos(iterator->GetPosition());
//p.Rotate(iterator->GetRotation());
WVPMatrices.push_back(finalMatrix.Transpose());
/*glUniform4f(ColourId, iterator->GetColour().r, iterator->GetColour().g, iterator->GetColour().b,
iterator->GetColour().a);*/
//WorldMatrices[i] = p.GetWorldTrans();
i++;
//iterator->Draw();
}
//glEnableVertexAttribArray(0);
if(colourOverLifeBuildingBlock != NULL)
{
colourOverLifeBuildingBlock->Test();
}
glBindBuffer(GL_ARRAY_BUFFER, VboId);
glBufferData(GL_ARRAY_BUFFER, verticesToDraw.size() * sizeof(verticesToDraw[0]), &verticesToDraw.front(), GL_STATIC_DRAW);
glEnableVertexAttribArray(POSITION_LOCATION);
glVertexAttribPointer(POSITION_LOCATION, 3, GL_FLOAT, GL_FALSE, 0, 0);
int size = particles.size();
glBindBuffer(GL_ARRAY_BUFFER, WVPId);
glBufferData(GL_ARRAY_BUFFER, sizeof(Matrix4f) * size, &WVPMatrices.front(), GL_DYNAMIC_DRAW);
glDrawElementsInstanced(GL_TRIANGLES, indicesToDraw.size(), GL_UNSIGNED_BYTE, 0, particles.size());
glBindBuffer(GL_ARRAY_BUFFER, 0);
//glDisableVertexAttribArray(0);
//glFlush();
}
粒子系统的整个头部在下面:
#include <glglew.h>
#include <array>
#include <vector>
class ParticleSystem
{
public:
ParticleSystem(Vector3 pos, Quaternion rot, float spawnRate, int particlesToSpawn); // Constructs a particle system.
~ParticleSystem(); // Destructor.
void Update(float elapsedTime); // Updates the particle system.
void Draw(Matrix4f perspectiveMatrix); // Draw the particle system
void CreateShaders();
void InitializeBuffers();
// Long amount of get sets.
/*float* GetMinLifeTime();
void SetMinLifeTime(float lt);
float* GetMaxLifeTime();
void SetMaxLifeTime(float lt);*/
int* GetParticlesToSpawnAtATime();
void SetParticlesToSpawnAtATime(int particlesToSpawn);
float* GetSpawnRate();
void SetSpawnRate(float spawnRate);
Vector3* GetPosition();
void SetPosition(Vector3 newPosition);
Quaternion* GetRotation();
void SetRotation(Quaternion rotation);
std::list<BaseBuildingBlock*> GetBuildingBlocks();
VelocityBuildingBlock* GetVelocityBuilding();
ColourOverLifeBuildingBlock* GetColourOverLifeBuildingBlock();
LifeTimeBuildingBlock* GetLifeTimeBuildingBlock();
UniformColourBuildingBlock* GetUniformColourBuildingBlock();
ScaleBuildingBlock* GetScaleBuildingBlock();
/*Vector3* GetMinVelocity();
void SetMinVelocity(Vector3 min);
Vector3* GetMaxVelocity();
void SetMaxVelocity(Vector3 maxVelocity);*/
Vector3 GetMinParticleStartPoint();
void SetMinParticleStartPoint(Vector3 minParticleStartPoint);
Vector3 GetMaxParticleStartPoint();
void SetMaxParticleStartPoint(Vector3 maxParticleStartPoint);
bool CreateColourOverLifeBuildingBlock();
bool DeleteColourOverLifeBuildingBlock();
bool CreateUniformColourBuildingBlock();
bool DeleteUniformColourBuildingBlock();
bool CreateScaleBuildingBlock();
bool DeleteScaleBuildingBlock();
/*Colour GetStartColour();
void SetStartColour(Colour startColour);
Colour GetEndColour();
void SetEndColour(Colour endColour);*/
Vector3* GetMinParticleRotationAmountPerFrame();
void SetMinParticleRotationAmountPerFrame(Vector3 minParticleRotationAmount);
Vector3* GetMaxParticleRotationAmountPerFrame();
void SetMaxParticleRotationAmountPerFrame(Vector3 maxParticleRotationAmount);
void Save(TiXmlElement* element);
private:
// Spawns a particle.
void SpawnParticle();
GLuint VaoId;
GLuint VboId;
GLuint IndexBufferId;
GLuint PositionBufferId;
GLuint WVPId;
GLenum programId;
std::vector<GLfloat> verticesToDraw;
std::vector<GLubyte> indicesToDraw;
std::vector<Vector3> positions;
std::vector<Matrix4f> WVPMatrices;
std::vector<Matrix4f> WorldMatrices;
std::list<Particle> particles; // List of particles
Vector3 position; // position of the emitter
Quaternion rotation; // rotation of the emitter.
float spawnRate; // spawnrate of the emitter.
int particlesToSpawnAtATime; // The amount of particles to spawn at a time.
float minLifeTime; // The minimum time a particle can live for.
float maxLifeTime; // The maximum time a particle can live for.
float timer; // Timer
ShaderCreator* shaderCreator;
//Vector3 minVelocity; // The minimum velocity a particle can have.
//Vector3 maxVelocity; // The maximum velocity a particle can have/
//std::list<BaseBuildingBlock> buildingBlocks;
// I'm thinking of eventually making a list of baseBuildingBlocks.
std::list<BaseBuildingBlock*> buildingBlocks;
VelocityBuildingBlock* velocityBuildingBlock;
ColourOverLifeBuildingBlock* colourOverLifeBuildingBlock;
LifeTimeBuildingBlock* lifeTimeBuildingBlock;
UniformColourBuildingBlock* uniformColourBuildingBlock;
ScaleBuildingBlock* scaleBuildingBlock;
Vector3 minParticleStartPoint; // The minimum position a particle can start at.
Vector3 maxParticleStartPoint; // The maximum position a particle can start at.
Vector3 minParticleRotationAmountPerFrame; // The minimum amount of rotation that a particle can rotate every frame.
Vector3 maxParticleRotationAmountPerFrame; // The maximum amount of rotation that a particle can rotate every frame.
Colour startColour; // StartColour is the colour that a particle will start with.
Colour endColour; // EndColour is the colour that a particle will end with.
//TEST
float scale;
};
#endif
现在我在想,有没有办法我必须切换活动VBO?还是我完全走错了方向我使用了一个着色器调试器,两个vbo都存在。
你需要在每次绘制调用之前正确设置你的顶点属性-即,你必须调用glBindBuffer然后是glEnableVertexArray &glVertexAttribPointer为你的每个属性在每次绘制调用之前。在你发布的代码中,这只发生在粒子位置,而不是'WVP_LOCATION'属性,它显然包含你的变换矩阵(你通过glBufferData将数据上传到GPU,但不要设置属性)-这意味着一旦你有多个粒子系统,只有你的第二个粒子系统的变换矩阵将被访问渲染。
一个边不,你在这里尝试做的似乎是相当低效的-你本质上是为每帧的每个粒子向GPU推送一个变换矩阵。这取决于你想要多少粒子,这将会破坏你的性能——你应该考虑更新粒子的位置等与转换反馈。
编辑:刚刚意识到opengl wiki链接并没有真正解释很多。转换反馈是记录顶点着色器输出的一种方式(或者,如果存在几何/镶嵌着色器,则将记录输出)。输出变量被写入到VBO中——之后,它们可以像任何其他顶点属性一样用于渲染。整个概念非常类似于使用framebuffer对象来记录片段着色器输出;它允许粒子系统完全存在于GPU上,用顶点着色器计算更新的位置,生命时间和;每帧中的其他属性。一个非常好的教程,展示了这种转换反馈的基本设置,可以在这里找到
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 如何解决多线程绘图的问题不流畅
- 绘图程序的问题
- 使用gdi的免费绘图-alpha颜色问题
- 为什么我的非所有者绘制的列表框在添加字符串后会出现绘图问题
- 现代OpenGL 2D和3D绘图问题
- Cinder & C++:镜像纹理和高效绘图问题
- OpenGL VBO绘图问题
- OpenGL 3.1 使用索引绘图渲染纹理时出现问题