OpenGL顶点在着色器存储缓冲区中 [英] OpenGL vertices in shader storage buffer

查看:866
本文介绍了OpenGL顶点在着色器存储缓冲区中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用计算着色器的粒子系统。我把所有的粒子在着色器存储缓冲区。一个粒子包含两个顶点,即当前位置和上一个位置。

  struct Particle {
glm :: vec4 _currPosition ;
glm :: vec4 _prevPosition;
};

在我分派我的计算着色器之后,我想直接从shader-storage-buffer 。所以这是我做的:

  glBindBufferBase(GL_SHADER_STORAGE_BUFFER,0,shaderStorageBufferID); 
_shaderManager-> useProgram(computeProg);
glDispatchCompute((_ numParticles / WORK_GROUP_SIZE)+1,1,1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
_shaderManager-> useProgram(shaderProg);
glBindBuffer(GL_ARRAY_BUFFER,shaderStorageBufferID);
glVertexPointer(4,GL_FLOAT,sizeof(glm :: vec4),(GLvoid *)0);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_POINTS,0,_numParticles);
glDisableClientState(GL_VERTEX_ARRAY);问题是,我在屏幕上看到_numParticles,但是一半是用我的_prevPosition属性渲染的粒子结构。这意味着一个粒子被解释为在屏幕上绘制的两个顶点。但我想让他跳过每个粒子结构中的_prevPosition属性。我的错误在哪里?



也许我初始化我的着色器存储缓冲区的方式很重要:

  GLuint shaderStorageBufferID; 

glGenBuffers(1,& shaderStorageBufferID);
glBindBuffer(GL_SHADER_STORAGE_BUFFER,shaderStorageBufferID);
glBufferData(GL_SHADER_STORAGE_BUFFER,numParticles * sizeof(Particle),NULL,GL_STATIC_DRAW);
struct Particle * particles =(struct Particle *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER,0,numParticles * sizeof(Particle),GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
for(int i = 0; i particles [i] ._ currPosition = glm :: vec4(i,0,0.0,1.0f)
particles [i] ._ prevPosition = glm :: vec4(i,0,1.0,1.0f);
}


解决方案

您的 Particle struct包含两个 vec4 的。您的计算着色器每个数组元素写入两个 vec4

但是这行:

  glVertexPointer(4,GL_FLOAT,sizeof :: vec4),(GLvoid *)0); 

告诉OpenGL你传递的数组 vec4 s。你不是。你传递一个数组,其中每个元素都是两个 vec4



所以告诉OpenGL,通过提供一个适当的步幅:

  glVertexPointer(4,GL_FLOAT,sizeof(Particle),(GLvoid *)0); 

哦,和BTW:你还是使用错误的障碍。只是因为你的代码碰巧运行并不意味着它的保证。不同步的加载/存储操作可能很棘手,除非你正确地做了一切。


I'm working on a particle system using the compute shader right now. I put all my particles in a shader-storage-buffer. A particle contains two vertices, the current position and the previous position.

struct Particle{
    glm::vec4   _currPosition;
    glm::vec4   _prevPosition;
};

After I dispatch my compute shader I want to draw all the particles directly from the shader-storage-buffer. So this is what I do:

glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBufferID);
_shaderManager->useProgram("computeProg");
glDispatchCompute((_numParticles/WORK_GROUP_SIZE)+1, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
_shaderManager->useProgram("shaderProg");
glBindBuffer(GL_ARRAY_BUFFER, shaderStorageBufferID);
glVertexPointer(4,GL_FLOAT, sizeof(glm::vec4), (GLvoid*)0);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_POINTS, 0, _numParticles);
glDisableClientState(GL_VERTEX_ARRAY);

The problem is that I see _numParticles on the screen but one half is rendered with the _prevPosition attribute of my particle structure. That means one particle is interpreted as two vertices which are drawn on the screen. But I want him to skip the _prevPosition attribute in every particle structure. Where's my mistake?

Maybe the way I initialize my shader-storage-buffer is important:

GLuint shaderStorageBufferID;

glGenBuffers(1, &shaderStorageBufferID);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBufferID);
glBufferData(GL_SHADER_STORAGE_BUFFER, numParticles*sizeof(Particle), NULL ,GL_STATIC_DRAW);
struct Particle* particles = (struct Particle*) glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, numParticles*sizeof(Particle), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
for(int i = 0; i < numParticles; ++i){
    particles[i]._currPosition = glm::vec4(i, 0, 0.0, 1.0f);
    particles[i]._prevPosition = glm::vec4(i, 0, 1.0, 1.0f);
}

解决方案

Your Particle struct contains two vec4's. Your compute shader writes two vec4s per array element.

Yet this line:

glVertexPointer(4,GL_FLOAT, sizeof(glm::vec4), (GLvoid*)0);

Tells OpenGL that you're passing an array of vec4s. You're not. You're passing an array, where every element is two vec4s. And you want to skip the second one.

So tell OpenGL that, by providing a proper stride:

glVertexPointer(4, GL_FLOAT, sizeof(Particle), (GLvoid*)0);

Oh, and BTW: you're still using the wrong barrier. Just because your code happens to function doesn't mean that it's guaranteed. Unsynchronized load/store operations can be tricky unless you're doing everything correctly.

这篇关于OpenGL顶点在着色器存储缓冲区中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆