WebGL: WebGL: Vertex ShaderCopy the code

Last time, we started with the sine of theta over one period, and then we drew the sine of theta over two periods. However, we changed the Vertex Shader code directly. It would be nice if we had a slider on the page that we could use to drag the changes and reflect them on the graph.

Based on the above requirements, we first added a slider Input control to the page, and the whole code changes are as follows:

<! doctype html> <html> <head> <style> canvas { border: 1px solid #000000; </style> </head> <body> <input ID ="slider" type="range" min="0" Max ="100" value="50" step="1" οnchange=" sliderFunc ()" /> <canvas id="point" style="width:300px; height:300px"> </canvas> <script id="vertex_shader" type="myshader"> // Vertex Shader precision mediump int; precision mediump float; attribute vec2 a_PointVertex; Void main() {gl_Position = vec4(a_PointVertex, 0.0, 1.0); Y = sin(gl_position. x * 3.14); Gl_PointSize = 3.0; } </script> <script id="fragment_shader" type="myshader"> // Fragment shader precision mediump int; precision mediump float; Void main() {gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); } </script> <script type="text/javascript"> var pointCanvas = document.getElementById('point'); Var gl = pointCanvas. GetContext ('webgl', {preserveDrawingBuffer: true}); Var pointCount = 0; var pointData = []; for (var idx = -500; idx <= 500; idx++) { pointCount++; pointData.push(idx / 500); pointData.push(0); } // var pointArray = new Float32Array(pointData); var buffer_id; buffer_id = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer_id); gl.bufferData(gl.ARRAY_BUFFER, pointArray, gl.STATIC_DRAW); // var vertex_shader_code = document.getElementById('vertex_shader').textContent; console.log(vertex_shader_code); var vertex_shader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertex_shader, vertex_shader_code); gl.compileShader(vertex_shader); // var fragment_shader_code = document.getElementById('fragment_shader').textContent; var fragment_shader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragment_shader, fragment_shader_code); gl.compileShader(fragment_shader); // var program = gl.createProgram(); gl.attachShader(program, vertex_shader); gl.attachShader(program, fragment_shader); gl.linkProgram(program); gl.useProgram(program); // var a_PointVertex = gl.getAttribLocation(program, 'a_PointVertex'); gl.vertexAttribPointer(a_PointVertex, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(a_PointVertex); // // gl.drawArrays(gl.POINTS, 0, pointCount); </script> <script> var sliderDom = document.getElementById("slider"); function sliderfunc() { } sliderDom.addEventListener("change", sliderfunc); </script> </script> </body> </html>Copy the code

We added a slider Input control in the first place, and at the end we bound the control to an event. When the value of the control changes, we can do something in the sliderFunc function.

var sliderDom = document.getElementById("slider"); Function sliderfunc () {/ / should be here to change the drawings of} sliderDom. AddEventListener (" change ", sliderfunc);Copy the code
Key new concept: uniform variables
  • uniformThe variables can be written invertex shaderfragment shaderThe variables in the
  • You can go through at any timegltheapiChange,uniformThe value of the variable

We changed our Vertex shader as follows:

<script id="vertex_shader" type="myshader"> // Vertex Shader precision mediump int; precision mediump float; uniform float u_x_offset; attribute vec2 a_PointVertex; Void main() {gl_Position = vec4(a_PointVertex, 0.0, 1.0); Y = sin(gl_position. x * 3.14 * u_x_offset); Gl_PointSize = 3.0; } </script>Copy the code
  • Notice that one is declaredfloatThe type ofuniformvariableu_x_offset;
  • Notice that the parameter that we pass in to sine theta, theta, becomes thetaX * 3.14 * u_x_offset
  • In other words, we can takeu_x_offsetAs a regulator.

That’s not enough. We need to write some code in SliderFunc to change the u_X_offset variable in the Vertex Shader from the outside.

The final code changes are as follows:

    <script>
        var u_x_offset_loc = gl.getUniformLocation(program, "u_x_offset");

        var sliderDom = document.getElementById("slider");
        function sliderfunc() {
            gl.uniform1f(u_x_offset_loc, parseFloat(sliderDom.value) / 10);
            gl.clearColor(0, 0, 0, 0);
            gl.clear(gl.COLOR_BUFFER_BIT);
            gl.drawArrays(gl.POINTS, 0, pointCount);
        }
        sliderDom.addEventListener("change", sliderfunc);
    </script>

Copy the code

A:

  • Gl. getUniformLocation: used to obtainvertex shaderThe location of the uniform variable in
  • Gl. Uniform1f changevertex shaderThe uniform variable value in
  • Gl.clear (gl.color_buffer_bit) Clears the entire image, otherwise it will be drawn repeatedly and become more and more messy
  • Gl.drawarrays (gl.points, 0, pointCount) are redrawn

The effect is as follows:

As we drag the slider, sin images of different periods will be drawn on the page.




At the end of the text, questions are answeredCopy the code
Duck duck said: since you can change the value of the uniform variable in THE JS code, so I make a timer, is it animation?
  • A: Exactly ✔️!!!!! Class is over ~