Search

Categories

WebGL: How It Works

This post has moved to webglfundamentals.org

  • kurt

    Hey.
    These are really useful tutorials.
    I chose not to set my origin to top-left corner, but to leave it at the bottom left.
    But, what happens is, that the x and y coordinates are getting interchanged.

    In the setGeometry function, I just verified that the vertices are as they are supposed to be. But when drawn, I find that x and y vertices are interchanged.
    (e.g., I pass [-10, -5, -10, 5, 10, 5, 10, -5] as vertices, to draw a flat rectangle with a long resting base, only to find that what is drawn is a tall rectangle.

    Can you please tell me what could be wrong?
    Again, I assure you, the vertices going into setGeometry are perfectly correct.
    So they should be going to the buffer correctly.

  • http://greggman.com greggman

    Can you post your code on http://jsfiddle.net or some place else that I can take a look?

  • kurt

    http://jsfiddle.net/DwB7P/1/

    I put just the portion that is enough to draw a rectangle on the screen.
    I’ve removed the animation there was, so it can be looked into easily.
    The same problem exists.

    Thanks a lot!

    p.s. : There is nothing shown on jsFiddle by the way, probably because of the missing webgl-utils.js. Anyway, my code is there.

  • http://greggman.com greggman

    The problem is you had sin and cos reversed.
    http://jsfiddle.net/greggman/LYXE5/1/

  • kurt

    Oh :( Sorry about that. Thank you greggman!

  • kurt

    Can you suggest a good way to draw more than 1 shape in different places in an animation based WebGL page?

    My animation occurs via the requestAnimFrame function.
    What I could think of is to hold an array of objects corresponding to my different distinct hapes.

    In every call of my “refresh” function, I first clear the canvas.
    Then, I loop over all the elements of that array and
    call “initBuffers” (the same one in my JSFiddle page), which has bindBuffer and setGeometry calls. Then I call the drawScene function which has a drawArrays call after setting the rotation and translations in the shader program.
    Then happens my objects’ parameters updating and the same cycle repeats.

    So, I reset the buffers every time for each object and redraw every single frame

    I notice that my animation is quite slow at times, and gives a discontinuous appearance. Could you please tell me how it should be actually done?

  • http://greggman.com greggman

    It really depends on what you are trying to do.

    Most GL programs (ie, games) try to create all of their shapes when a start up (or when they start a level). After that they don’t change the shapes. Other apps have different needs so it really depends on your app but ideally you’d try to change the buffers as little as possible.

    Generally you need some kind of class or object that represents your shape (the buffers). You need some kind of object that represent a shader program. You need some kind of object that represents the uniform settings for that shader program (what color for example). And you need some kind of object that represents a specific collection of those to actually draw. Shape X + ShaderProgram Y + Settings Z = ?? VisualObject? Model?

    So for example you might make an object called a Shape

    Shape = function(positions) {
      this.buffer = gl.createBuffer(); 
      gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
      gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
    }
    
    
    Shape.prototype.setup = function() {
      gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
      gl.enableVertexAttribArray(positionLocation);
      gl.vertexAttribPointer(positionLocation, ..);
    };
    

    And similar objects for programs and uniform settings.

    Then at init time you can do things like

       var shape1 = new Shape([data for shape1]);
       var shape2 = new Shape([data for shape2]);
    

    and at draw time you can do things like

    function render() {
       ...
       shape1.setup();
       program1.setup();
       uniforms2.setup();
       draw();
       shape2.setup();
       program2.setup();
       uniforms2.setup();
       draw();
    }
    

    I’m sorry if that’s not very detailed but the question you’re asking seems like a general programming question and so would require a really long answer.

    I’d suggest looking at some of the existing WebGL frameworks as examples
    http://www.khronos.org/webgl/wiki/User_Contributions#Frameworks

  • kurt

    Thanks! :)

    So we’re saving those “bufferData” calls by keeping separate buffers for each shape and calling “createBuffer”, “bindBuffer”, “bufferData” only once during init.

    Everytime we have refresh the screen,
    we only have to call “enableVertexAttribArray” and “vertexAttribPointer” after binding the required shape’s buffer(using “bindBuffer”).

    My shapes don’t change with time.
    There are just a variety of them (like polygons, circles, triangles) that stay from beginning to end.

    So this is the best way to do it I suppose. Hope I got it right. Did I ?

  • http://greggman.com greggman

    Yes, that’s the normal way to do it.

  • Geo877

    This tutorial is brilliant, everything has been so clearly explained, and I love the interactive demos throughout, thanks very much! :)