OpenGL Point Functionality in WebGL

前端 未结 2 1532
天涯浪人
天涯浪人 2021-02-10 15:17

In OpenGL you can draw define points like this:

glBegin(GL_POINTS);
for(float theta=0, radius=60.0; radius>1.0; theta+=0.1, radius-=0.3){
            


        
相关标签:
2条回答
  • 2021-02-10 15:33

    The code you wrote really doesn't do much except define some points. To do that in WebGL could do it like this

    var colors = [];
    var verts = [];
    var theta=0 
    for(var radius=60.0; radius>1.0; radius-=0.3) {
      colors.push(radius/60.0, 0.3, 1-(radius/60.0));
      verts.push(200+radius*Math.cos(theta),200+radius*Math.sin(theta));
      theta+=0.1;
    }
    var numPoints = colors.length / 3;
    

    That would make 2 JavaScript arrays. You'd then need to put them to WebGLBuffers

    var colorBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
    
    var vertBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);
    

    After that though you need to write a shader and set it up. Shaders are a huge topic. For your particular data I'm guessing these shader would do

    A vertex shader

    uniform mat4 u_matrix;
    attribute vec4 a_vertex;
    attribute vec4 a_color;
    varying vec4 v_color;
    
    void main() {
      // Set the size of the point
      gl_PointSize = 3.0;
    
      // multiply each vertex by a matrix.
      gl_Position = u_matrix * a_vertex;
    
      // pass the color to the fragment shader
      v_color = a_color;
    }
    

    A fragment shader

    precision mediump float;
    varying vec4 v_color;
    void main() {
      gl_FragColor = v_color;
    }
    

    Next you need to initialize the shaders and parameters. I'm going to assume I put the shaders in script tags with ids "vshader" and "fshader" and use this boilerplate code to load them.

    var program = createProgramFromScriptTags(gl, "vshader", "fshader");
    gl.useProgram(program);
    
    // look up the locations for the inputs to our shaders.
    var u_matLoc = gl.getUniformLocation(program, "u_matrix");
    var colorLoc = gl.getAttribLocation(program, "a_color");
    var vertLoc = gl.getAttribLocation(program, "a_vertex");
    
    // Set the matrix to some that makes 1 unit 1 pixel.
    gl.uniformMatrix4fv(u_matLoc, false, [
      2 / width, 0, 0, 0,
      0, 2 / height, 0, 0,
      0, 0, 1, 0,
      0, 0, 0, 1
    ]);
    
    // Tell the shader how to get data out of the buffers.
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    gl.vertexAttribPointer(colorLoc, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(colorLoc);
    gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
    gl.vertexAttribPointer(vertLoc, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(vertLoc);
    

    and finally draw the points

    gl.drawArrays(gl.POINTS, 0, numPoints);
    

    Here's a snippet

    var canvas = document.getElementById("c");
    var gl = canvas.getContext("webgl");
    if (!gl) {
        alert("no WebGL");
        //return;
    }
    
    var colors = [];
    var verts = [];
    var theta=0 
    for(var radius=160.0; radius>1.0; radius-=0.3) {
        colors.push(radius/160.0, 0.3, 1-(radius/160.0));
        verts.push(radius*Math.cos(theta),radius*Math.sin(theta));
        theta+=0.1;
    }
    var numPoints = colors.length / 3;
    
    var colorBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
    
    var vertBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);
    
    var program = twgl.createProgramFromScripts(gl, ["vshader", "fshader"]);
    gl.useProgram(program);
    
    // look up the locations for the inputs to our shaders.
    var u_matLoc = gl.getUniformLocation(program, "u_matrix");
    var colorLoc = gl.getAttribLocation(program, "a_color");
    var vertLoc = gl.getAttribLocation(program, "a_vertex");
    
    function draw() {
        gl.clear(gl.COLOR_BUFFER_BIT);
        gl.clearColor(1.0, 1.0, 1.0, 1.0);
        
     // Set the matrix to some that makes 1 unit 1 pixel.
    gl.uniformMatrix4fv(u_matLoc, false, [
        2 / canvas.width, 0, 0, 0,
        0, -2 / canvas.height, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
    ]);
        
        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
        gl.vertexAttribPointer(colorLoc, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(colorLoc);
        gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
        gl.vertexAttribPointer(vertLoc, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(vertLoc);
        
        gl.drawArrays(gl.POINTS, 0, numPoints);
        
        requestAnimationFrame(draw, canvas);
    }
    
    draw();
    canvas { border: 1px solid black; }
    <script src="https://twgljs.org/dist/3.x/twgl.min.js"></script>
    <script id="vshader" type="whatever">
        uniform mat4 u_matrix;
        attribute vec4 a_vertex;
        attribute vec4 a_color;
        varying vec4 v_color;
    
        void main() {
          // Set the size of the point
          gl_PointSize = length(a_vertex) * 0.1;
        
          // multiply each vertex by a matrix.
          gl_Position = u_matrix * a_vertex;
    
          // pass the color to the fragment shader
          v_color = a_color;
        }    
    </script>
    <script id="fshader" type="whatever">
    precision mediump float;
    varying vec4 v_color;
    void main() {
        gl_FragColor = v_color;
    }
    </script>
    <canvas id="c" width="400" height="400"></canvas>

    you might find these WebGL tutorials helpful.

    0 讨论(0)
  • 2021-02-10 15:47

    WebGL is based on OpenGL ES 2.0 (see here), which dropped immediate-mode support.

    This specification describes an additional rendering context and support objects for the HTML 5 canvas element [CANVAS]. This context allows rendering using an API that conforms closely to the OpenGL ES 2.0 API.

    You'll need to use vertex buffers to store vertex data. See here1 for a good explanation of how things work in retained mode. And there for a nice small example to get you started.

    1: Kudos to whoever posted this here.

    0 讨论(0)
提交回复
热议问题