• Advertisement
Sign in to follow this  

OpenGL Vertex Shader Iteration

This topic is 1050 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm working with OpenGL 3.3 and I got a question about the possibility of updating multiple vertices through the Vertex Shader.
I know you can update a single vertex in a Vertex Shader using transform feedback, but I was wondering could you update multiple vertices at a single time?
 
Something like:
 

//Vertex Shader Code
 
in float vertexType;
in vec3 position;
 
out float vertexType;
out vec3 positionOUT;
 
unifomr float modCount;
 
void main()
{
      //Do the following for the next 5 vertex
      if(vertexType == 0)
      {
           vertexTypeOUT = vertexType;
           positionOUT = position;
 
           //Mod the next X number of vertex; X is based on modCount uniform
           for(int i = 0; i < modCount; ++i)
           {
                  //Something like this?
                  vertexTypeOUT[i] = vertexType[i];
                  positionOUT[i] = position[i];
           }
       }
       else
       {
            vertexTypeOUT = vertexType;
            positionOUT = position;
       }
    }
 
}
 
Edited by noodleBowl

Share this post


Link to post
Share on other sites
Advertisement

Each vertex shader corresponds to only one vertex. It's not possible to update multiple vertices in a single shader.

 

What is it you're trying to do exactly?

Share this post


Link to post
Share on other sites

What is it you're trying to do exactly?

 

So I'm in the midst of trying to create a particle emitter and it is working (particles update and show up on screen) biggrin.png

It works by using transform feedback, where the each particle (GL_POINTS) is updated through the vertex shader and the results of the update get written to a buffer object. This buffer object is then bound at render time as a Texture Buffer, so I can expand my points into a quads without the use of Geometry Shader.

I now I want to add in the ability to spawn X particles every Y seconds

I was thinking that on the first run of the vertex shader I could run through X number of vertices, reactivate them (basically resetting their life time), and then finish this first run by updating the first vertex. After (next and subsequent runs) I could continue on like normal and just update the particle

 

Edited by noodleBowl

Share this post


Link to post
Share on other sites

Could you do something like that with a Compute Shader?

 

I don't think I can use a Compute Shader here, because I need to target OpenGL 3.3

 

So is there absolutely no way I can do this?

Share this post


Link to post
Share on other sites

 

I would really like to stick to OpenGL only

 

I have been thinking of ways that I could achieve what I'm trying to do and I wanted to know everyone's thoughts on them

Now, I'm strictly talking about the update side of things here as the rendering part is taken care of.

 

Conditions

1. Ability to generate X particles every Y seconds

2. Lots and lots of particles. Have as many as I can

3. Particles have textures and attributes like position, lifetime, size, etc
 

Idea 1

Use a pass through Vertex Shader with a Geometry Shader. Where the Geometry Shader takes in GL_POINTS and spits back out GL_POINTS. In this case the Geometry Shader would be the one responsible for updating the particles. (Might be faster to update in Vertex Shader and then check if I need to discard in the Geometry Shader. Thoughts?) In addition it only generates new particles through the EmitVertex and EndPrimative calls when the generation time has been hit

 

Pros:

Should be able to allow me to do what I want

Particles "die" and "are created" on the fly

 

Cons:

Have to use a Geometry shader sad.png

Only can emit out MAX_GEOMETRY_OUTPUT_VERTICES (For me this is 1024, lowest it must be is 32)

[Might be able to get past above. Could do multiple updates. If I need to use more than the MAX_GEOMETRY_OUTPUT_VERTICES just write into another part of the buffer or a different buffer all together]

 

Idea 2

Create all the particles that I would ever need and keep a copy of my particles on the CPU side.

When it comes time to "generate" particles, check which particles are "dead" and reset there lifetime using glBufferSubData on the whole buffer (since I dont think multiple glBufferSubData for "dead" particles only would be good). Then afterwards, my buffer gets sent to the Vertex Shader where they get updated. After the update in the Vertex Shader, I save the results back into my CPU's particle copy

 

Pros:

Should be able to allow me to do what I want

Should be able to have as many particles as my hardware can handle

 

Cons:

Might be super slow since I'm pretty sure I need to read back / save the transform feedback buffer

The more particles I have the slower it gets

 

Idea 3

Keep everything as it is and have a global counter to reset the lifetimes of dead particles. When the Vertex Shader runs, check if the "generate particles" flag has been set to true. If so, then revive the particles that are dead and repeat this until counter has met the "number to revive count". Continue on updating the particles

 

Pros:

Should be able to allow me to do what I want

Should be able to have as many particles as my hardware can handle

 

Cons:

I don't think this (a global counter) is possible with the current version of OpenGL I am targeting?

Edited by noodleBowl

Share this post


Link to post
Share on other sites
Why not move the updating code to a fragment shader which renders to a texture, then use vertex texture fetch for the positions.
Then next frame you bind the previous frame's particle framebuffer as a texture and render the data to a second framebuffer, then use vertex texture fetch and draw,
then next frame bind second framebuffer as the texture and use the first as the render target and repeat. Basically, ping-pong the particle data between the two framebuffers.

This post describes what I mean in detail, as you can see, the performance isn't too bad either http://www.hackbarth-gfx.com/2013/03/17/making-of-1-million-particles/

Share this post


Link to post
Share on other sites

 

Might be super slow since I'm pretty sure I need to read back / save the transform feedback buffer

The more particles I have the slower it gets

if you create particle's vertex buffer as not static (dynamic), it will couse it to render not that fast, but per frame updates to it (not realocating its size of course), should come totaly acceptable. Try it out, it is no big hit at all to render a dynamic render buffer, and batched subdata calls to it are of no big issue as well.

a hint:

update the buffer while it is still yet bound after the draw call that has used it (being a frame back thus), move on next gpu issue

Share this post


Link to post
Share on other sites

if you create particle's vertex buffer as not static (dynamic), it will couse it to render not that fast, but per frame updates to it (not realocating its size of course), should come totaly acceptable. Try it out, it is no big hit at all to render a dynamic render buffer, and batched subdata calls to it are of no big issue as well.
a hint:
update the buffer while it is still yet bound after the draw call that has used it (being a frame back thus), move on next gpu issue

 

I went back and tried this out (the idea you were referencing) and its super slow

I did a minor test with 10k particles (each particle has 6 attribute each) and its the actual particle update portion that makes the hit to performance. Having to read back from the GPU every frame to keep particles in sync is really rough. At best, on a good, run I'd get a DT of 0.00105 (~950 FPS)

I changed it up to use a pass through Geometry Shader along with a bind to the previous TBO used (done to get psudo random values to use when particles are to be revived) and the performance sky rocketed! I was getting a DT of 0.000606 (~1650 FPS)

Share this post


Link to post
Share on other sites


and its the actual particle update portion that makes the hit to performance. Having to read back from the GPU every frame to keep particles in sync is really rough

You read the particles from gpu? Try not to do that, also, I doubt too that dynamic buffer will outperform geometry shader.

Share this post


Link to post
Share on other sites

http://www.slideshare.net/icastano/cascades-demo-secrets

From page 119.

Nvidia Cascades demo where they are running full gpu particle system. Particle updating happen on vertex shader, emitting/killing particle happen on geometry shader. They use double buffered vbo and stream out. Super simple stuff and general enough for most thing. Speed should not be problem with those particle counts.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
  • Advertisement
  • Popular Tags

  • Advertisement
  • Popular Now

  • Similar Content

    • By LifeArtist
      Good Evening,
      I want to make a 2D game which involves displaying some debug information. Especially for collision, enemy sights and so on ...
      First of I was thinking about all those shapes which I need will need for debugging purposes: circles, rectangles, lines, polygons.
      I am really stucked right now because of the fundamental question:
      Where do I store my vertices positions for each line (object)? Currently I am not using a model matrix because I am using orthographic projection and set the final position within the VBO. That means that if I add a new line I would have to expand the "points" array and re-upload (recall glBufferData) it every time. The other method would be to use a model matrix and a fixed vbo for a line but it would be also messy to exactly create a line from (0,0) to (100,20) calculating the rotation and scale to make it fit.
      If I proceed with option 1 "updating the array each frame" I was thinking of having 4 draw calls every frame for the lines vao, polygons vao and so on. 
      In addition to that I am planning to use some sort of ECS based architecture. So the other question would be:
      Should I treat those debug objects as entities/components?
      For me it would make sense to treat them as entities but that's creates a new issue with the previous array approach because it would have for example a transform and render component. A special render component for debug objects (no texture etc) ... For me the transform component is also just a matrix but how would I then define a line?
      Treating them as components would'nt be a good idea in my eyes because then I would always need an entity. Well entity is just an id !? So maybe its a component?
      Regards,
      LifeArtist
    • By QQemka
      Hello. I am coding a small thingy in my spare time. All i want to achieve is to load a heightmap (as the lowest possible walking terrain), some static meshes (elements of the environment) and a dynamic character (meaning i can move, collide with heightmap/static meshes and hold a varying item in a hand ). Got a bunch of questions, or rather problems i can't find solution to myself. Nearly all are deal with graphics/gpu, not the coding part. My c++ is on high enough level.
      Let's go:
      Heightmap - i obviously want it to be textured, size is hardcoded to 256x256 squares. I can't have one huge texture stretched over entire terrain cause every pixel would be enormous. Thats why i decided to use 2 specified textures. First will be a tileset consisting of 16 square tiles (u v range from 0 to 0.25 for first tile and so on) and second a 256x256 buffer with 0-15 value representing index of the tile from tileset for every heigtmap square. Problem is, how do i blend the edges nicely and make some computationally cheap changes so its not obvious there are only 16 tiles? Is it possible to generate such terrain with some existing program?
      Collisions - i want to use bounding sphere and aabb. But should i store them for a model or entity instance? Meaning i have 20 same trees spawned using the same tree model, but every entity got its own transformation (position, scale etc). Storing collision component per instance grats faster access + is precalculated and transformed (takes additional memory, but who cares?), so i stick with this, right? What should i do if object is dynamically rotated? The aabb is no longer aligned and calculating per vertex min/max everytime object rotates/scales is pretty expensive, right?
      Drawing aabb - problem similar to above (storing aabb data per instance or model). This time in my opinion per model is enough since every instance also does not have own vertex buffer but uses the shared one (so 20 trees share reference to one tree model). So rendering aabb is about taking the model's aabb, transforming with instance matrix and voila. What about aabb vertex buffer (this is more of a cosmetic question, just curious, bumped onto it in time of writing this). Is it better to make it as 8 points and index buffer (12 lines), or only 2 vertices with min/max x/y/z and having the shaders dynamically generate 6 other vertices and draw the box? Or maybe there should be just ONE 1x1x1 cube box template moved/scaled per entity?
      What if one model got a diffuse texture and a normal map, and other has only diffuse? Should i pass some bool flag to shader with that info, or just assume that my game supports only diffuse maps without fancy stuff?
      There were several more but i forgot/solved them at time of writing
      Thanks in advance
    • By RenanRR
      Hi All,
      I'm reading the tutorials from learnOpengl site (nice site) and I'm having a question on the camera (https://learnopengl.com/Getting-started/Camera).
      I always saw the camera being manipulated with the lookat, but in tutorial I saw the camera being changed through the MVP arrays, which do not seem to be camera, but rather the scene that changes:
      Vertex Shader:
      #version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec2 aTexCoord; out vec2 TexCoord; uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { gl_Position = projection * view * model * vec4(aPos, 1.0f); TexCoord = vec2(aTexCoord.x, aTexCoord.y); } then, the matrix manipulated:
      ..... glm::mat4 projection = glm::perspective(glm::radians(fov), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); ourShader.setMat4("projection", projection); .... glm::mat4 view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp); ourShader.setMat4("view", view); .... model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f)); ourShader.setMat4("model", model);  
      So, some doubts:
      - Why use it like that?
      - Is it okay to manipulate the camera that way?
      -in this way, are not the vertex's positions that changes instead of the camera?
      - I need to pass MVP to all shaders of object in my scenes ?
       
      What it seems, is that the camera stands still and the scenery that changes...
      it's right?
       
       
      Thank you
       
    • By dpadam450
      Sampling a floating point texture where the alpha channel holds 4-bytes of packed data into the float. I don't know how to cast the raw memory to treat it as an integer so I can perform bit-shifting operations.

      int rgbValue = int(textureSample.w);//4 bytes of data packed as color
      // algorithm might not be correct and endianness might need switching.
      vec3 extractedData = vec3(  rgbValue & 0xFF000000,  (rgbValue << 8) & 0xFF000000, (rgbValue << 16) & 0xFF000000);
      extractedData /= 255.0f;
    • By Devashish Khandelwal
      While writing a simple renderer using OpenGL, I faced an issue with the glGetUniformLocation function. For some reason, the location is coming to be -1.
      Anyone has any idea .. what should I do?
  • Advertisement