最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • WebGL第八课:搞一搞 vertex shader(2)

    正文概述 掘金(庖丁解牛)   2021-07-19   775
    本文标题:WebGL第八课:搞一搞 vertex shader(2)
    

    上次课,我们一开始画了一个周期的sin函数,然后画了两个周期的sin函数。
    不过,我们是直接改的 vertex shader 代码。
    如果我们在网页里,能通过一个滑竿(slider)来拖动改变,然后反应到图形里就好了。

    根据上面的需求,我们先在网页里加一个,slider input 控件,
    整个代码改动如下:

    
    <!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);
              gl_Position.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>
    

    我们在前面,加了一个 slider input 控件,在最后将这个控件绑定了一个事件,也就是
    这个控件的值改变的时候,我们可以在 sliderfunc 函数中做一些事情。

    var sliderDom = document.getElementById("slider");
    function sliderfunc() {
        // 应该在这里来改变图形的绘制
    }
    sliderDom.addEventListener("change", sliderfunc);
    
    重点新概念:uniform 变量
    • uniform 变量是可以写在 vertex shaderfragment shader 中的变量
    • 随时都可以通过glapi,改变uniform变量的值

    我们改动我们的 vertex shader, 如下:

        <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);
              gl_Position.y = sin(gl_Position.x * 3.14 * u_x_offset);
              gl_PointSize = 3.0;
            }
        </script>
    
    • 注意,声明了一个 float 类型的 uniform 变量 u_x_offset;
    • 注意,sin 的传入参数,变成了 gl_Position.x * 3.14 * u_x_offset
    • 也就是说,我们可以把 u_x_offset 当做一个调节因子.

    光这些还没用,我们要在 sliderfunc 里写一些代码,来从外面改变 vertex shader 中的 u_x_offset变量。

    最后的代码改动如下:

        <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>
    
    

    详解:

    • gl.getUniformLocation , 用于得到 vertex shader 中的 uniform 变量的位置
    • gl.uniform1f 改变 vertex shader中的 uniform变量的值
    • gl.clear(gl.COLOR_BUFFER_BIT) 清空整个图像 ,否则会重复绘制,越来越乱
    • gl.drawArrays(gl.POINTS, 0, pointCount) 重新绘制

    效果如下:

    WebGL第八课:搞一搞 vertex shader(2)

    WebGL第八课:搞一搞 vertex shader(2)

    随着我们拖动滑竿,不同周期的sin图像会被绘制到页面上。




    正文结束,下面是答疑
    
    小鸭鸭说:既然可以在 js 代码改变 uniform 变量的值,那么我搞个定时器,是不是就是动画了?
    • 答:完全正确✔️!!!!!下课~

    起源地下载网 » WebGL第八课:搞一搞 vertex shader(2)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元