2014-09-23 23 views
0

现在它似乎对我来说,我交错的VBO是严格'只读',但我想每帧更新它(最好从GLSL)。动态VBO在GLSL中读/写?

我有一颗行星在轨道上移动,下面的代码是用于渲染轨道点。

问题提纲: 我要上轨道每个点都有自己的“一生”,逻辑:

    当行星经过每个连续点
  • ?将寿命更新到1.0并随着时间减少!

这将用于创建每个移动物体的衰落轨道。现在我只是想找到方法来操纵vbo ...

如何读取和写入GLSL内和从VBO?任何人都可以发布示例吗?


更新:我修改上面的代码转换反馈工作(由用户的Andon M.科尔曼建议),但我想我可能会做一些错误(我得到glError):

设置:

// Initialize and upload to graphics card 
glGenVertexArrays(1, &_vaoID); 
glGenBuffers(1, &_vBufferID); 
glGenBuffers(1, &_iBufferID); 
glGenBuffers(1, &_tboID); 

// First VAO setup 
glBindVertexArray(_vaoID); 
glBindBuffer(GL_ARRAY_BUFFER, _vBufferID); 
glBufferData(GL_ARRAY_BUFFER, _vsize * sizeof(Vertex), _varray, GL_DYNAMIC_DRAW); 

// TRANSFORM FEEDBACK 
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, _tboID); // Specify buffer 
// Allocate space without specifying data 
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 
      _vsize*sizeof(Vertex), NULL, GL_DYNAMIC_COPY); 
// Tell OGL which object to store the results of transform feedback 
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, _vBufferID); //correct? 

glEnableVertexAttribArray(0); 
glEnableVertexAttribArray(1); 
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 
       sizeof(Vertex), reinterpret_cast<const GLvoid*>(offsetof(Vertex, location))); 
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 
       sizeof(Vertex), reinterpret_cast<const GLvoid*>(offsetof(Vertex, velocity))); 

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _isize * sizeof(int), _iarray, GL_STREAM_DRAW); 

渲染()的方法:

//disable fragment, so that we do a first run with feedback 
glEnable(GL_RASTERIZER_DISCARD); 

glBindVertexArray(_vaoID); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID); 
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, _tboID); 
glBeginTransformFeedback(_mode); 
glDrawElements(_mode, _isize, GL_UNSIGNED_INT, 0); 
glEndTransformFeedback(); 
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); 
glBindVertexArray(0); 

glDisable(GL_RASTERIZER_DISCARD); 

// then i attempt to do the actual draw 
glBindVertexArray(_vaoID); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID); 
glDrawElements(_mode, _isize, GL_UNSIGNED_INT, 0); 
glBindVertexArray(0); 

而且 - 右联前:

const GLchar* feedbackVaryings[] = { "point_position" }; 
glTransformFeedbackVaryings(_ephemerisProgram->getProgramID(), 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS); 
+1

我建议你阅读[变换反馈](http://www.opengl。组织/维基/ Transform_Feedback)。从GLSL内部使用它没有什么特别的需要。 – 2014-09-23 20:32:22

+0

@ AndonM.Coleman - Ive无意中发现了变换反馈,还有: glMapBufferRange,glBufferSubData,double缓冲区和计算着色器,如user42813所示。它很难知道哪一个给了我最大的灵活性(每个轨道的数学运算,即距离,点积计算等等都是一样的,但是我想稍后为每个线段添加一个几何着色器到实例四边形 - 粗线)。 – mike 2014-09-23 21:10:26

+0

我很难确定哪种方法是最好的。我在某处添加了一个geom。着色器会影响变换反馈的捕获(一旦有1个点,现在每个四角的角点都有4个点)。 glBufferSubData似乎没事,但我无法找到如何“重新上传”数据的例子,它似乎应该与glMapBufferRange一起使用?这仍然需要我在CPU上进行计算,然后上传到设备... – mike 2014-09-23 21:29:37

回答

1

你不能改变你的VBO从的OpenGL渲染pipline的内容,但可以使用招数它们取决于时间,如果你还更新正在使用Opengl 4.4,你可以使用ComputeShaders,但在这里解释它有点复杂,因此谷歌为它,祝你好运。

0

如何在GLSL内读写VBO?

你不行。 VBO严格从常规渲染着色器中只读。修改是完全不可能的(因为这会打开深不可测的深度蠕虫),但使用变换反馈,着色器阶段的结果可以写入缓冲区。

或者您使用计算着色器。

问题提纲:我希望轨道上的每个点都有自己的“生命”逻辑:当行星经过每个连续点时?将寿命更新到1.0并随着时间减少!

听起来像计算着色器的任务。但说实话,我认为在GPU上处理这个并没有太大的收获。

+0

那么你建议在CPU上做更好,还是我正确地使用转换反馈?如果你看到我修改我的帖子来使用它,但我得到'无效操作'glError - 我以前没有使用过这种技术。另一方面,如果有可能在CPU上做我想做的所有事情,那会让我的生活变得更轻松,但是当我拥有VBO时,我没有看到这种可能性。 – mike 2014-09-24 01:31:05

+0

我在上面的代码中做了什么似乎是教科书。我认为这个问题可能有索引缓冲区存在?也许改变反馈不起作用在这种情况下... – mike 2014-09-24 02:23:29