Giter VIP home page Giter VIP logo

Comments (4)

greggman avatar greggman commented on June 10, 2024

This is not a bad idea. Unfortunately POINTS in OpenGL/OpenGL ES/WebGL have incompatibilities across GPUs.

See the bottom of this article

If you're curious, here's an example of how to emulate POINTS using instancing. This emulation doesn't have the issues that POINTS has.

There's no article for WebGL1 on instanced drawing but there is for WebGL2 since it's not an extension there.

from webgl-fundamentals.

 avatar commented on June 10, 2024

TL;DR: You can also use a transformfeedback with gl.INTERLEAVED_ATTRIBS to emit multiple vertices at a time, which is good for drawing small particles like quads.

Hi Greg, Thanks for the reply.

These past few weeks I've taken a look at the various methods of drawing quads to the screen with WebGL2/OpenGLES3. I've also run into those same issues with point sprites- namely the size limit.

I've also become quite familiar with the instanced rendering method (thanks in large part to webgl2fundamentals.org). However, there are a couple problems with instanced rendering I'd like to discuss in further detail, but I'll skip to my main point:

Yesterday I came up with a (new?) method of drawing small groups of primatives like quads and whatnot faster using transform feedbacks with gl.INTERLEAVED_ATTRIBS. Well, I have not benchmarked it yet, but it should be faster and more versatile than an equivalent instanced render, assuming you are already using transform feedbacks to write to per-instance (per-quad) data like to interpolate the quad's position or texture-coordinates.

I can send you some of the code I've been working on if you are interested, but it goes something like this:

  1. You have a particle shader program that uses a vertex shader with transform feedbacks, it takes in stuff like the position and outputs one vertex for each vertex the shape needs (for example a quad drawn with GL_TRIANGLES would need 6). you use transformfeedbackvaryings with gl.INTERLEAVED_ATTRIBS so they're packed back-to-back in the same output buffer after you do the transform feedback on a draw call like gl.drawArrays(gl.POINTS,0,<num_quads>);

  2. You configure the transformFeedbackVaryings of the particle shader program and the vertexAttribPointers (using stride and offset) of the quad-drawing shader program such that the inputs line up with the outputs properly.

  3. What you end up with is a single buffer with all 6*<num_quads> verticies lined up nicely, so you can draw them with another shader program in one fell gl.drawArrays(gl.TRIANGLES,0, 6*<num_quads>)

It gets more complicated than that if you want the particle shader to output multiple per-vertex attributes, like position and color at the same time, because you need to interleave them, but that is the basic gist of it.

It might be a bit better than instanced rendering. I've heard that instanced rendering adds an additional CPU overhead in terms of draw calls or something, and that it's really for larger models as opposed to quads. The other problem with instanced rendering is that you have to do a little more per-vertex processing (to draw a 2D quad at least). This was my motivation for using this method in the first place (for example, instead of transforming texture co-ordinates by a per-instance matrix or something, you can just put those in a static draw buffer). You can just generally make it faster by optimizing stuff that should only be calculated once per quad.

I guess the only downside is that you can't use GL_TRIANGLE_STRIP to draw a single quad like you could with instanced rendering.

Point Sprites have their advantages too, because you can run the vertex shader once per-quad without doing all the transform feedbacks calls. But they really don't outweigh the limitiations. Also, I'm told that many OpenGL implementations just process GL_POINTS as two triangles in their backend.

Sorry if this is was too wordy.

from webgl-fundamentals.

 avatar commented on June 10, 2024

Oh, I should mention that the GL_TRIANGLE_STRIP with instanced rendering trick is just to prevent you from running the vertex shader an extra two more times per quad instance.
But using this method you still only run those same per-vertex calculatons four times in the particle shader, and then copy two of them to get a total of 6 output verts.

from webgl-fundamentals.

greggman avatar greggman commented on June 10, 2024

Yea, you can do particles without instancing. An example is covered in this article though it may or may not be faster than instancing.

TRIANGLE_STRIP is generally slower than TRIANGLES because on several implementations it has to be emulated.

Also, you can easily do the particle calculations in the shaders for more speed though of course likely without any collisions and other limitations. That's often fine depending on your needs. The same article above shows a simple example of moving particles based on time. This article shows moving particles in the GPU.

This example shows a single shader that does time based particles where every particle has these inputs

  'attribute vec4 uvLifeTimeFrameStart; // uv, lifeTime, frameStart\n' +
  'attribute vec4 positionStartTime;    // position.xyz, startTime\n' +
  'attribute vec4 velocityStartSize;    // velocity.xyz, startSize\n' +
  'attribute vec4 accelerationEndSize;  // acceleration.xyz, endSize\n' +
  'attribute vec4 spinStartSpinSpeed;   // spinStart.x, spinSpeed.y\n' +
  'attribute vec4 orientation;          // orientation quaternion\n' +
  'attribute vec4 colorMult;            // multiplies color and ramp textures\n' +

copied from here

And things are computed based on time as in

// pp = per particle
localTime = currentTime - pp.startTime;   
lerp = localTime / pp.lifeTime;
position = pp.startPosition + (pp.velocity + pp.acceleration * localTime) * localTime;
color = mix(pp.startColor, pp.endColor, lerp)

etc.....

from webgl-fundamentals.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.