WebGL中使用JS改变点位

说明

在下面的代码中,我们要实现的是在一个canvas画布中鼠标点击哪里则WebGL将点位绘制在哪里。

代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #canvas {
            background-color: antiquewhite;
        }
    </style>
</head>
<body>
    <canvas id="canvas"></canvas>

    <!-- 顶点着色器 -->
    <script id="vertexShader" type="x-shader/x-vertex">
        attribute vec4 a_Position;  // 定义一个四维向量,后面我们用js改变这个变量的值,从而实现点位变化
        void main() {
            // 设置点位
            gl_Position = a_Position;
            // 设置点的尺寸
            gl_PointSize = 100.0;

        }
    </script>

    <!-- 片元着色器 -->
    <script id="fragmentShader" type="x-sahder/x-fragment">
        void main() {
            gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);  // 设置颜色
        }
    </script>

    <script>
        const canvas = document.querySelector("#canvas");
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;

        // 获取着色器文本
        const vsSource = document.querySelector("#vertexShader").innerText;
        const fsSource = document.querySelector("#fragmentShader").innerText;

        const gl = canvas.getContext("webgl");  // 获取三维画笔

        // 初始化着色器
        initShaders(gl, vsSource, fsSource);

        // 获取着色器暴露的变量
        const a_Position = gl.getAttribLocation(gl.program, 'a_Position');

        // 设置attribute变量
        gl.vertexAttrib3f(a_Position, 0.0, 0.5, 0.0);

        gl.clearColor(0, 0, 0, 1);   // 声明颜色  rgba
        gl.clear(gl.COLOR_BUFFER_BIT);  // 刷底色

        // 绘制顶点
        gl.drawArrays(gl.POINTS, 0, 1);

        // 鼠标点击事件
        canvas.addEventListener('click',  ({clientX, clientY}) => {
            const {left, top, width, height} = canvas.getBoundingClientRect();

            const [cssX, cssY] = [clientX - left, clientY - top];

            // 解决坐标原点位置的差异
            const [halfWidth, halfHeight] = [width / 2, height / 2];  // canvas画布中心点的位置

            // 计算鼠标点击位置到canvas画布中心点的位置
            const [xBaseCenter, yBaseCenter] = [cssX - halfWidth, cssY - halfHeight];

            // 解决y方向上的差异
            // 因为WebGL里的y轴和canvas 2d里的y轴相反,所以咱们对yBaseCenter取反即可
            const yBaseCenterTop = -yBaseCenter;

            // 将canvas中的宽高大小转为WebGL中的宽高大小(即将canvas中的鼠标点位转为WebGL中的鼠标点位)
            const [x, y] = [xBaseCenter/halfWidth, yBaseCenterTop/halfHeight];

            // 跟新WebGL中坐标位置
            gl.vertexAttrib2f(a_Position, x, y);

            gl.clear(gl.COLOR_BUFFER_BIT);
            // 绘图
            gl.drawArrays(gl.POINTS, 0, 1);

        })


        // 初始化着色器
        function initShaders(gl, vsSource, fsSource) {
            // 创建程序对象
            const program = gl.createProgram();

            // 建立着色器对象
            const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
            const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);

            // 把顶点着色对象装进程序对象中
            gl.attachShader(program, vertexShader);
            // 把片元着色对象装进程序对象中
            gl.attachShader(program, fragmentShader);

            // 连接webgl上下文对象和程序对象
            gl.linkProgram(program);

            // 启动程序对象
            gl.useProgram(program);

            gl.program = program;

            return true;
        }

        function loadShader(gl, type, source) {
            // 根据着色类型,建立着色器对象
            const shader = gl.createShader(type);

            // 将着色器源文件传入着色器对象中
            gl.shaderSource(shader, source);

            // 编译着色器对象
            gl.compileShader(shader);

            // 返回着色器对象
            return shader;
        }
    </script>
</body>
</html>

测试效果

相关推荐
littleplayer几秒前
iOS 单元测试详细讲解-DeepSeek
前端
littleplayer1 分钟前
iOS 单元测试与 UI 测试详解-DeepSeek
前端·单元测试·测试
夜熵4 分钟前
Vue中nextTick()用法
前端·面试
小桥风满袖4 分钟前
Three.js-硬要自学系列15 (圆弧顶点、几何体方法、曲线简介、圆、椭圆、样条曲线、贝塞尔曲线)
前端·css·three.js
洋流5 分钟前
JavaScript事件流机制详解:捕获、冒泡与阻止传播
前端·javascript
啊花是条龙5 分钟前
在 Angular 中使用 ECharts 并处理 xAxis 标签的点击事件
前端·angular.js
凌冰_10 分钟前
CSS3 基础(背景-文本效果)
前端·css·css3
tjh000112 分钟前
vue3+TS 手动实现表格滚动
前端·javascript·vue.js
SimonKing12 分钟前
惊!未实现Serializable竟让第三方接口回调全军覆没
前端·程序员·架构
凯哥197015 分钟前
如何将你写的 js 模块发布到 npmjs 给大家使用
前端