WebGL——绘制水平移动的点、通过鼠标控制绘制、绘制不同颜色的点

04-01 阅读 0评论

个人简介

WebGL——绘制水平移动的点、通过鼠标控制绘制、绘制不同颜色的点,WebGL——绘制水平移动的点、通过鼠标控制绘制、绘制不同颜色的点,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,我们,设置,第1张
(图片来源网络,侵删)

👀个人主页: 前端杂货铺

🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展

📃个人状态: 研发工程师,现效力于中国工业软件事业

🚀人生格言: 积跬步至千里,积小流成江海

🥇推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js🍒Three.js🍖数据结构与算法体系教程

🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧

WebGL——绘制水平移动的点、通过鼠标控制绘制、绘制不同颜色的点,WebGL——绘制水平移动的点、通过鼠标控制绘制、绘制不同颜色的点,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,我们,设置,第2张
(图片来源网络,侵删)
内容参考链接
WebGL+Three.js入门与实战(一)给画布换颜色、绘制一个点、三维坐标系
WebGL+Three.js入门与实战(二)绘制水平移动的点、通过鼠标控制绘制

文章目录

    • 前言
    • 一、绘制一个水平移动的点(attribute)
    • 二、通过鼠标控制绘制
      • 1、鼠标点击绘制点
      • 2、鼠标移动绘制点
      • 3、模拟画笔
      • 三、绘制不同颜色的点(uniform)
      • 总结

        前言

        大家好,这里是前端杂货铺。

        上一篇文章,我们学习了如何给画布换颜色、如何绘制一个点并且了解了三维坐标系…

        接下来,继续我们 WebGL 内容的学习!

        鼠标绘制的三种效果

        绘制不同的颜色


        一、绘制一个水平移动的点(attribute)

        我们在着色器源程序中声明 attribute 变量,js 可以给这个变量传值,再绘制出来,从而就可以实现动态修改点的位置。

        WebGL——绘制水平移动的点、通过鼠标控制绘制、绘制不同颜色的点,WebGL——绘制水平移动的点、通过鼠标控制绘制、绘制不同颜色的点,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,我们,设置,第3张
        (图片来源网络,侵删)

        以下是 声明 attribute 变量,需要注意的是,attribute 只能在顶点着色器中使用,不能在片元着色器中使用。

        // attribute: 存储限定符; vec4: 类型; aPosition: 变量名;
        attribute vec4 aPosition;
        

        以下是 获取 attribute 变量,需要注意的是 获取 attribute 变量需要在 initShader 函数之后,因为会用到 program 这个程序对象。获取之后返回变量的存储地址。

        // program: 程序对象; 'aPosition': 指定想要获取存储地址的 attribute 变量的名称
        const aPositon = gl.getAttribLocation(program, 'aPosition');
        

        以下是 给 attribute 变量赋值,可以传递 1/2/3 个分量的值,没有传递的值为 0.0。

        // location: 指定 attribute 变量的存储位置; v0, v1, v2, v3: 传入的分量值; 
        gl.vertexAttrib1f(location, v0);
        gl.vertexAttrib2f(location, v0, v1);
        gl.vertexAttrib3f(location, v0, v1, v2);
        gl.vertexAttrib4f(location, v0, v1, v2, v3);
        

        绘制流程如下:

        WebGL——绘制水平移动的点、通过鼠标控制绘制、绘制不同颜色的点

        基于以上知识点,我们使用 attribute 变量绘制一个水平移动的点

        
        
            
            
            
            Document
            
        
        
            
                此浏览器不支持canvas
            
            
                const ctx = document.getElementById('canvas');
                const gl = ctx.getContext('webgl');
                // 着色器
                // 创建着色器源码
                // 顶点着色器
                const VERTEX_SHADER_SOURCE = `
                    // 存储限定符 类型 变量名 分号 (注: attribute 只传递顶点数据)
                    attribute vec4 aPosition;
                    void main() {
                        gl_Position = aPosition; // vec4(0.0,0.0,0.0,1.0)
                        gl_PointSize = 30.0;
                    }
                `;
                // 片元着色器
                const FRAGMENT_SHADER_SOURCE = `
                    void main() {
                        // r g b a
                        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
                    }
                `
                const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE);
                // 获取 attribute 变量,返回变量的存储地址
                const aPosition = gl.getAttribLocation(program, 'aPosition');
                let x = 0;
                setInterval(() => {
                    x += 0.1;
                    if (x > 1.0) {
                        x = 0;
                    }
                    // 给 attribute 变量赋值
                    gl.vertexAttrib1f(aPosition, x);
                    // 执行绘制
                    gl.drawArrays(gl.POINTS, 0, 1);
                }, 200)
            
        
        
        

        attribute绘制一个水平移动的点


        二、通过鼠标控制绘制

        1、鼠标点击绘制点

        接下来,我们通过鼠标来控制在画布上绘制点。

        • 屏幕坐标通过 event.clickX 和 event.clickY 来获取
        • 画布边距通过 event.target.getBoundingClientRect() 来获取,其 .left 和 .right 等同于 ctx.offsetWidth 和 ctx.offsetHeight
        • 画布的坐标通过 屏幕坐标 - 画布边距 获取
        • 转为 ndc 坐标:设画布的长和宽均为 400px,那么原点为 0,最左为 -200px,最右为 200px。想要转为原点为 0,最左为 -1,最右为 1,就可以均除以 200。最上和最下同理。

          WebGL——绘制水平移动的点、通过鼠标控制绘制、绘制不同颜色的点

          示例:我们点击画布的左上角的位置,查看控制台输出的坐标,如下

          WebGL——绘制水平移动的点、通过鼠标控制绘制、绘制不同颜色的点

          WebGL——绘制水平移动的点、通过鼠标控制绘制、绘制不同颜色的点

          
          
              
              
              
              Document
              
              
                  * {
                      margin: 0;
                      padding: 0;
                  }
                  canvas {
                      margin: 50px auto 0;
                      display: block;
                      background: yellow;
                  }
              
          
          
              
                  此浏览器不支持canvas
              
              
                  const ctx = document.getElementById('canvas');
                  const gl = ctx.getContext('webgl');
                  // 着色器
                  // 创建着色器源码
                  // 顶点着色器
                  const VERTEX_SHADER_SOURCE = `
                      // 存储限定符 类型 变量名 分号 (注: attribute 只传递顶点数据)
                      attribute vec4 aPosition;
                      void main() {
                          gl_Position = aPosition; // vec4(0.0,0.0,0.0,1.0)
                          gl_PointSize = 10.0; // 点的大小
                      }
                  `;
                  // 片元着色器
                  const FRAGMENT_SHADER_SOURCE = `
                      void main() {
                          // r g b a 绘制颜色
                          gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
                      }
                  `
                  const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE);
                  // 获取 attribute 变量,返回变量的存储地址
                  const aPosition = gl.getAttribLocation(program, 'aPosition');
                  ctx.onclick = function (event) {
                      // 坐标
                      const x = event.clientX;
                      const y = event.clientY;
                      console.log("鼠标点击的屏幕坐标:", x, y);
                      // 获取边距 (上边距和左边距) domPosition.left 等同于 ctx.offsetLeft 的值
                      const domPosition = event.target.getBoundingClientRect();
                      console.log("画布边距:", domPosition.left, domPosition.top);
                      // 点击的点位于画布上方 、 左侧的距离 (domPosition.left: 568(基于我显示屏的长度), domPosition.top: 50)
                      const domx = x - domPosition.left;
                      const domy = y - domPosition.top;
                      console.log("画布的坐标:", domx, domy);
                      // 固定值,画布长和宽的一半,均为200
                      const halfWidth = ctx.offsetWidth / 2;
                      const halfHeight = ctx.offsetHeight / 2;
                      console.log("画布长和宽的一半:", halfWidth, halfHeight);
                      // 转为 ndc坐标 (-1, 1)
                      const clickX = (domx - halfWidth) / halfWidth;
                      const clickY = (halfHeight - domy) / halfHeight;
                      console.log("转为ndc的坐标:", clickX, clickY);
                      // 给 attribute 变量赋值
                      gl.vertexAttrib2f(aPosition, clickX, clickY);
                      // 执行绘制
                      gl.drawArrays(gl.POINTS, 0, 1);
                  }
              
          
          
          

          通过鼠标点击绘制点


          2、鼠标移动绘制点

          改为 ctx.onmousemove 实现鼠标移动:

          绘制点跟随鼠标


          3、模拟画笔

          改为 ctx.onmousemove 的基础上,在 ctx.onmousemove 之前定义一个存储点的数组 points

          const points = [];
          

          把以下内容替换掉,从而实现画笔效果:

              // 给 attribute 变量赋值
              // gl.vertexAttrib2f(aPosition, clickX, clickY);
              // 执行绘制
              // gl.drawArrays(gl.POINTS, 0, 1);
              for (let i = 0; i  
           
           
            
           

          画笔


          三、绘制不同颜色的点(uniform)

          通过点击不同位置来控制绘制不同颜色的点,我们可以通过使用 uniform 变量来实现。

          • 我们在片元着色器源码中声明 uColor,在 main 函数中进行相应设置。(没有的分量补全即可)
          • 我们需要设置片元着色器的精度,它决定了 GPU 在计算 float 时使用的精度(highp、mediump、lowp,分别代表 高、中、低 精度)
          • 通过 getUniformLocation 可以获取 uniform 变量的内存地址
          • 通过鼠标点击的位置,控制绘制的点的颜色 gl.uniform2f(uColor, points[i].clickX, points[i].clickY)
            
            
                
                
                
                Document
                
            
            
                
                    此浏览器不支持canvas
                
                
                    const ctx = document.getElementById('canvas');
                    const gl = ctx.getContext('webgl');
                    // 着色器
                    // 创建着色器源码
                    // 顶点着色器
                    const VERTEX_SHADER_SOURCE = `
                        // 存储限定符 类型 变量名 分号 (注: attribute 只传递顶点数据)
                        attribute vec4 aPosition;
                        void main() {
                            gl_Position = aPosition; // vec4(0.0, 0.0, 0.0, 1.0)
                            gl_PointSize = 10.0;
                        }
                    `;
                    // 片元着色器
                    const FRAGMENT_SHADER_SOURCE = `
                        // 设置精度为中精度,高精度为 highp,低精度为lowp
                        precision mediump float;
                        uniform vec2 uColor;
                        void main() {
                            // r g b a
                            gl_FragColor = vec4(uColor.r, uColor.g, 0.0, 1.0);
                        }
                    `
                    const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE);
                    // 获取 attribute 变量,返回变量的存储地址
                    const aPosition = gl.getAttribLocation(program, 'aPosition');
                    // 获取 uniform 变量,返回变量的存储地址(包含顶点和片元着色器的程序对象,uniform变量名称)
                    const uColor = gl.getUniformLocation(program, 'uColor');
                    // 指定 uniform 的存储地址,四个分量
                    gl.uniform4f(uColor, 1.0, 0.0, 0.0, 1.0);
                    let points = [];
                    
                    ctx.onclick = function (event) {
                        // 坐标
                        const x = event.clientX;
                        const y = event.clientY;
                        // 获取边距 (上边距和左边距) domPosition.left 等同于 ctx.offsetLeft 的值
                        const domPosition = event.target.getBoundingClientRect();
                        // 点击的点位于画布上方、 左侧的距离 (domPosition.left: 568(基于我显示屏的长度), domPosition.top: 50)
                        const domx = x - domPosition.left;
                        const domy = y - domPosition.top;
                        // 固定值,画布长和宽的一半,均为200
                        const halfWidth = ctx.offsetWidth / 2;
                        const halfHeight = ctx.offsetHeight / 2;
                        // 转为 ndc坐标 (-1, 1)
                        const clickX = (domx - halfWidth) / halfWidth;
                        const clickY = (halfHeight - domy) / halfHeight;
                        points.push({ clickX, clickY });
                        for (let i = 0; i  
             
             
              
             

            绘制不同的颜色

            总结

            本文,我们首先实现了绘制水平移动的点,之后通过坐标的转移,认识了 ndc 坐标的求解,从而实现了鼠标控制绘制,(包括点击绘制、移动绘制和模拟画布)的效果。此外,我们通过 uniform 实现了绘制不同颜色的点。

            更多 WebGL 和 Three.js 内容正在更新中…

            好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!


            参考资料:

            1. 百度百科 · WebGL
            2. WebGL + Three.js入门与实战【作者:yancy_慕课网】

            WebGL——绘制水平移动的点、通过鼠标控制绘制、绘制不同颜色的点



免责声明
本网站所收集的部分公开资料来源于AI生成和互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,人围观)

还没有评论,来说两句吧...

目录[+]