WebGL+Three.js入门与实战——给画布换颜色、绘制一个点、三维坐标系

news2024/12/24 11:47:03

个人简介

👀个人主页: 前端杂货铺
🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js🍒Three.js🍖数据结构与算法体系教程

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

文章目录

    • 前言
    • 一、canvas 和 webgl
      • 1、给画布换颜色-Canvas实现
      • 2、给画布换颜色-WebGL实现
    • 二、使用 WebGL 绘制一个点
    • 三、WebGL三维坐标系
    • 总结

前言

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

前端分为多种方向,其中 图形学方向 变得越来越火热,那么说到图形学在前端的使用,就不得不提起 WebGL

WebGL(全写Web Graphics Library)是一种3D绘图协议,这种绘图技术标准允许把 JavaScript 和 OpenGL ES 2.0 结合在一起,通过 增加 OpenGL ES 2.0 的一个 JavaScript 绑定,WebGL 可以为 HTML5 Canvas 提供硬件 3D加速渲染,这样 Web开发人员 就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。

接下来,我们来系统的学习 WebGL 及其框架 Three.js,进而完成 前端图形学方向 的入门!

一、canvas 和 webgl

Canvas API 提供 二维 绘图的方式,用于显示 二维三维 的图像。
图像的绘制主要通过 CanvasRenderingContext2D 接口完成。

WebGL API 提供 三维 绘图的方式。
图像的绘制主要通过 WebGLRenderingContext 接口完成。

1、给画布换颜色-Canvas实现

Canvas 实现:首先获取 canvas 画布,之后填充颜色为红色,最后使用 fillRect() 方法绘制"已填充"的矩形。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <canvas id="canvas" width="400" height="400">
        此浏览器不支持canvas
    </canvas>

    <script>
        const ctx = document.getElementById('canvas');
        const c = ctx.getContext('2d');
        c.fillStyle = 'red';
        // 矩形左上角的x坐标,矩形左上角的y坐标,矩形的宽度(px),矩形的高度(px)
        c.fillRect(0, 0, 400, 400);
    </script>
</body>
</html>

在这里插入图片描述

2、给画布换颜色-WebGL实现

WebGL 实现:首先依旧是获取 canvas 画布,之后指定清空 canvas 的颜色,并接受四个参数(red、green、blue、alpha),最后清空颜色缓存(即在绘制新的图像前,先把旧的图像清除,保证每次绘制的图像都是干净的)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <canvas id="canvas" width="400" height="400">
        此浏览器不支持canvas
    </canvas>
    <script>
        const ctx = document.getElementById('canvas');
        const gl = ctx.getContext('webgl');
        // 指定清空<canvas>的颜色,接受四个参数(rgba)
        gl.clearColor(1.0, 0.0, 0.0, 1.0);
        // 清空颜色缓存
        gl.clear(gl.COLOR_BUFFER_BIT);
    </script>
</body>
</html>

在这里插入图片描述


二、使用 WebGL 绘制一个点

着色器:着色器就是让开发者自己去编写一段程序,用来代替固定渲染管线,来处理图像的渲染。

顶点着色器:用来描述顶点的特性,通过计算来获取位置信息。 顶点 是指二维三维空间中的一个点,可以理解为一个个坐标。

片元着色器: 进行逐片源处理程序,通过计算来获取颜色信息片源 可以理解为一个个像素。

绘制一个点:创建顶点着色器源码和片元着色器源码,通过 initShader() gl 上下文顶点着色器片元着色器 连接起来。initShader() 是封装的一个方法,用于初始化片元着色器源程序。

具体流程及源码如下:

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./index.js"></script>
</head>
<body>
    <canvas id="canvas" width="400" height="400" style="background: gray;">
        此浏览器不支持canvas
    </canvas>
    <script>
        const ctx = document.getElementById('canvas');
        const gl = ctx.getContext('webgl');
        
        // 着色器
        // 创建着色器源码

        // 顶点着色器
        const VERTEX_SHADER_SOURCE = `
            void main() {
                // 要绘制的点的坐标 x, y, z, w
                gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
                // 点的大小(px)
                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);
            }
        `

        initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE);

        // 执行绘制
        gl.drawArrays(gl.POINTS, 0 , 1);
    </script>
</body>
</html>

初始化片元着色器源程序:

index.js

function initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE) {
    // 创建着色器
    const vertexShader = gl.createShader(gl.VERTEX_SHADER);
    const fragmentSharder = gl.createShader(gl.FRAGMENT_SHADER);

    gl.shaderSource(vertexShader, VERTEX_SHADER_SOURCE) // 指定顶点着色器的源码
    gl.shaderSource(fragmentSharder, FRAGMENT_SHADER_SOURCE) // 指定片元着色器的源码

    // 编译着色器
    gl.compileShader(vertexShader);
    gl.compileShader(fragmentSharder);

    // 创建一个程序对象,用于关联JavaScript和WebGL
    const program = gl.createProgram();

    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentSharder);

    gl.linkProgram(program);
    gl.useProgram(program);

    return program;
}

图形绘制出来了,请大家思考一个问题,在(0.0, 0.0, 0.0)坐标绘制的点为什么在画布的正中间呢??

在这里插入图片描述


三、WebGL三维坐标系

三维坐标系概览

在这里插入图片描述

绘图区域(NDC坐标:归一化设备坐标)

在WebGL中,坐标系是以绘制画布的中心点为原点,正常的笛卡尔坐标系。而浏览器和Canvas 2D的坐标系统是以左上角为坐标原点,y轴向下,x轴向右,坐标值相对于原点。

在这里插入图片描述

通过两个伪元素 ::before::after,在canvas中绘制两条线,充当 x 和 y 坐标。此时,我们修改顶点着色器的 gl_Position = vec4(0.5, 0.5, 0.0, 1.0);,观察此时点的位置可以发现,确实符合 NDC 坐标的位置

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./index.js"></script>
    <style>
        * {
            margin:0;
            padding: 0;
        }
        #canvas {
            background: gray;
        }
        body::after {
            content: ' ';
            display: block;
            width: 1px;
            height: 400px;
            background: red;
            position: absolute;
            top: 0;
            left: 200px;
        }
        body::before {
            content: ' ';
            display: block;
            width: 400px;
            height: 1px;
            background: red;
            position: absolute;
            top: 200px;
            left: 0;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="400" height="400">
        此浏览器不支持canvas
    </canvas>
    <script>
        const ctx = document.getElementById('canvas');
        const gl = ctx.getContext('webgl');
        
        // 着色器
        // 创建着色器源码

        // 顶点着色器
        const VERTEX_SHADER_SOURCE = `
            void main() {
                // 要绘制的点的坐标 x, y, z, w
                gl_Position = vec4(0.5, 0.5, 0.0, 1.0);
                // 点的大小(px)
                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);
            }
        `

        initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE);

        // 执行绘制
        gl.drawArrays(gl.POINTS, 0 , 1);
    </script>
</body>
</html>

在这里插入图片描述


总结

本文我们主要介绍了 WebGL,它是一种3D绘图协议,允许我们通过 JavaScript 代码在 Canvas 画布上绘制和渲染三维图像。

此外,我们通过使用 canvas 和 webgl 给画布换背景颜色。通过着色器源程序绘制出了一个点。通过伪元素在画布上绘制出来两条线,感受到了 NDC 坐标的独特魅力。

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

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


参考资料:

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

在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1314896.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

国产浪潮服务器:风扇免手动调节脚本

简介&#xff1a;浪潮集团&#xff0c;是中国本土顶尖的大型IT企业之一&#xff0c;中国领先的云计算、大数据服务商。浪潮集团旗下拥有浪潮信息、浪潮软件、浪潮国际&#xff0c;业务涵盖云计算、大数据、工业互联网等新一代信息技术产业领域&#xff0c;为全球120多个国家和地…

20.Java程序设计-基于SSM框架的安卓掌上校园生活系统的设计与实现

摘要&#xff1a; 随着移动互联网技术的快速发展&#xff0c;校园生活信息化成为提高学校管理效率、方便学生生活的关键。本研究以基于SSM&#xff08;Spring Spring MVC MyBatis&#xff09;框架的技术体系为基础&#xff0c;致力于设计与实现一款功能强大、高效稳定的安卓…

软件测试经典面试题(答案解析+视频讲解)

前言 &#xff08;第一个就刷掉一大批人&#xff09; 有很多“会自动化”的同学来咨询技术问题&#xff0c;他总会问到我一些元素定位的问题。元素定位其实都不算自动化面试的问题。 一般我都会问&#xff1a;你是定位不到吗&#xff1f;通常结果都是说确实定位不到。 做自…

【云原生kubernets】Pod详解

一、Pod介绍 1.1.概念 Pod是kubernetes中最小的资源管理组件&#xff0c;Pod也是最小化运行容器化应用的资源对象。一个Pod代表着集群中运行的一个进程。kubernetes中其他大多数组件都是围绕着Pod来进行支撑和扩展Pod功能的&#xff0c;例如&#xff0c;用于管理Pod运行的State…

详细教程 - 从零开发 鸿蒙harmonyOS应用 第四节 (鸿蒙Stage模型 登录页面 ArkTS版 推荐使用)

在鸿蒙OS中&#xff0c;Ability是应用程序提供的抽象功能&#xff0c;可以理解为一种功能。在应用程序中&#xff0c;一个页面即一种能力&#xff0c;如登录页面&#xff0c;即具有登录功能的能力。以下是对鸿蒙新建项目的登录代码功能的详细解读和工作流程的描述&#xff1a; …

WINCC8.0脚本调试方法

前言 WINCC是西门子推出的过程可视化系统&#xff08;SCADA&#xff09;&#xff0c;是基于PC的HMI系统&#xff0c;兼容WINDOWS各种系统&#xff0c;除了强大的图形系统之外&#xff0c;WINCC还具有在线历史趋势、报警记录、用户管理、用户归档等高级功能&#xff0c;而且WINC…

信息安全和网络安全的区别

信息安全与网络安全都属于安全领域&#xff0c;但它们的范围和重点不同。 信息安全主要关注数据的保护&#xff0c;包括对敏感数据进行加密、防止数据丢失或泄露等措施。信息安全通常与数据存储、传输和处理相关。 而网络安全更侧重于保护计算机系统和网络免受攻击、病毒、蠕…

UE5 动画 Sequencer-学习笔记

P2. 课程介绍 资料&#xff1a;https://www.bilibili.com/video/BV1Ag411873f?p2&vd_source707ec8983cc32e6e065d5496a7f79ee6 Sequencer不仅可以做互动动画&#xff0c;还可以导出视频与序列帧 P3-4. 界面介绍 https://www.bilibili.com/video/BV1Ag411873f?p3&spm_…

Certbot实现 HTTPS 免费证书(Let‘s Encrypt)自动续期

Certbot实现 HTTPS 自动续期 以前阿里云支持申请一年的免费https证书&#xff0c;那每年我们手动更新证书并没什么大问题&#xff0c;但现在阿里云的免费证书仅支持3个月&#xff0c;这意味着每三个月都要要申请一下证书显得非常麻烦。 下面我们使用Certbot实现ssl证书的自动…

C++相关闲碎记录(14)

1、数值算法 &#xff08;1&#xff09;运算后产生结果accumulate() #include "algostuff.hpp"using namespace std;int main() {vector<int> coll;INSERT_ELEMENTS(coll, 1, 9);PRINT_ELEMENTS(coll);cout << "sum: " << accumulate(…

C# WPF上位机开发(crc校验)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 为了验证数据传输的过程中有没有发生翻转&#xff0c;我们在传输报文的同时一般还会添加一个crc校验。对于modbus协议也是一样&#xff0c;它在数据…

帆软FCRP模拟题

制作步骤可见此博主&#xff1a;https://blog.csdn.net/Ipkiss_Yongheng/article/details/125594366 完成文件下载&#xff1a;【免费】帆软FCRP官网模拟题代码资源-CSDN文库

css的元素显示模式(有单行文字垂直居中,侧边栏等案例)

目录 1. 什么是元素的显示模式 2. 元素显示模式的类型 块元素 行内元素 行内块元素 3. 元素显示模式的转换 4.文字垂直居中 5.具体实现案例 1. 什么是元素的显示模式 定义&#xff1a;元素显示模式就是元素&#xff08;标签&#xff09;以什么方式进行显示&#xff0c;…

基于ssm居家养老系统论文

居家养老系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了居家养老系统的开发全过程。通过分析高校学生综合素质评价管理方面的不足&#xff0c;创建了一个计算机管理居家养老系统的方案。文章介绍了居家…

springboot升级到3.2导致mybatis-plus启动报错

在springboot升级到3.2时&#xff0c;服务启动报错 java.lang.IllegalArgumentException: Invalid value type for attribute ‘factoryBeanObjectType’: java.lang.String&#xff1a; java.lang.IllegalArgumentException: Invalid value type for attribute factoryBeanOb…

系统安全-WAF入侵防御系统测评指标

WAF&#xff08;Web Application Firewall&#xff09;是一种部署在web应用程序前面的安全系统&#xff0c;其作用是在用户请求到达web服务器之前对用户请求进行扫描和过滤&#xff0c;分析并校验每个用户请求的网络包&#xff0c;确保每个用户请求有效且安全&#xff0c;对无效…

maven工程中读取resources中的资源文件

maven工程的代码布局如下&#xff1a;在resources下面有一个资源文件test.properties&#xff0c;现在的目标要在Java代码中读取该资源文件中的内容。 test.properties资源文件的内容如下&#xff1a; Java代码如下&#xff1a; package com.thb;import java.io.BufferedR…

(c语言)输出一个十进制整数的二进制序列

#include<stdio.h> int main() {int x;scanf("%d",&x);for (int i 31; i >0; i--)//从前向后输出{if (((x >> i) ^ 0) 0) //当移位后全都是0时&#xff0c;进入下一个循环{continue; //需要输出完整二进制数时该判断语句删去}if (…

【SpringBoot】之Mybatis=Plus集成及使用(入门级)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringBoot开发之Mybatis-Plus系列》。&#x1…

​【EI会议征稿中】#先投稿,先送审#第三届网络安全、人工智能与数字经济国际学术会议(CSAIDE 2024)​

#先投稿&#xff0c;先送审# 第三届网络安全、人工智能与数字经济国际学术会议&#xff08;CSAIDE 2024&#xff09; 2024 3rd International Conference on Cyber Security, Artificial Intelligence and Digital Economy 2024年3月1日-3日 | 中国南京 会议官网&#xff1a…