WebGL简介

2023-11-10

前言

HTML的<canvas>元素为JavaScript提供了动态创建图形的API。这些图形需要使用特定上下文绘制,主要有两种:

  • 第一种是Canvas,一般只能做2d操作,用canvas.getContext(“2d”)来建立一个CanvasRenderingContext2D二维渲染上下文。
  • 第二种是WebGL,通过canvas.getContext(‘webgl’)就能获取WebGL的3d上下文,进行3D的渲染。

1. WebGL简介

1.1 WebGL概述

WebGL,是一项用来在网页上绘制和渲染复杂三维图形,并允许用户与之进行交互的技术。WebGL通过JavaScript操作OpenGL接口的标准,把三维空间图像显示在二维的屏幕上。

1.2 WebGL程序的结构

相对于传统网页,支持WebGL的浏览器底层接入了OpenGL/OpenGL ES标准,WebGL通过实现标准支持着色器语言编程语言GLSL ES,在我们实际开发过程中,GLSL ES通常是以字符串的形式存在JavaScript中,我们可以通过JavaScript修改GLSL ES字符串来改变着色器程序。
在这里插入图片描述

1.3 WebGL和OpenGL

  • OpenGL是一种用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口,是在个人计算机上使用最广泛的两种三维图形渲染技术之一,另一种是Direct3D。在某种意义上,WebGL就是“Web版的OpenGL”。
  • OpenGL ES在添加新特性的同时从OpenGL中移除了许多陈旧无用的就特性,使得在保持轻量级的同时,仍然具有足够的能力来渲染出精美的三维图形。
  • WebGL的技术规范继承自OpenGL ES,从2.0版本开始,OpenGL支持可编程着色器方法,这个支持可以让我们通过着色器语言编写着色器程序。
    在这里插入图片描述

2. 着色器语言

着色器是WebGL依赖的实现图像渲染的一种绘图机制。WebGL在GPU中运行,因此需要使用能够在GPU上运行的代码,这样的代码需要提供成对的方法,他们分别是顶点着色器和片元着色器,可以简单理解为一个定位置一个添颜色。

2.1 顶点着色器

顶点着色器的作用是计算顶点的位置。根据计算出的一系列顶点位置,WebGL可以对点, 线和三角形在内的一些图元进行光栅化处理。

//顶点着色器
const VERTEX_SHADER_SOURCE = `
	// 所有着色器都有一个main方法
	void main() {
	  gl_Position = vec4(0.0, 0.0, 0.0, 1.0);//设置坐标
	  gl_PointSize = 10.0;//设置尺寸
	}  
`

其中,gl_Position和gl_PointSize是着色器的内置变量,分别代表顶点的位置和大小,因此这段代码的作用是设置顶点的位置和大小。
在着色器内,一般命名以gl_开头的变量是着色器的内置变量。

2.2 片元着色器

片段着色器的作用是计算出当前绘制图元中每个像素的颜色值,逐片元控制片元的颜色和纹理等渲染。

//片元着色器
const FRAGMENT_SHADER_SOURCE = `
	void main() {
	  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);//设置颜色
	}   
`

内置变量gl_FragColor来确定顶点像素颜色,vec4是一个四维向量,用来表示一个 RGBA 颜色值,它与 CSS 的颜色区别是,CSS 的 RGB 值是 0 到 255,Alpha 值是 0 到 1,但是在着色器里面,RGBA 的值都是从 0 到 1。

3. webGL绘制一个点

webgl会有大量的重复性前置工作,也就是创建着色器 -> 传入着色器代码 -> 编译着色器 -> 创建着色器程序 -> 绑定、连接、启用着色器 -> 进行绘制。
创建着色器的代码一般封装好了直接调用就行,如下所示:

//gl代表渲染上下文,VERTEX_SHADER_SOURCE代表顶点着色器代码,FRAGMENT_SHADER_SOURCE代表片元着色器代码
function initShader (gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE) {
	// 创建着色器
    const vertexShader = gl.createShader(gl.VERTEX_SHADER);
    const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
	// 指定着色器对象的代码
    gl.shaderSource(vertexShader, VERTEX_SHADER_SOURCE);
    gl.shaderSource(fragmentShader, FRAGMENT_SHADER_SOURCE);
    //编译着色器
    gl.compileShader(vertexShader);
    gl.compileShader(fragmentShader);
    //创建程序对象
    const program = gl.createProgram();
	// 为程序对象分配顶点着色器和片元着色器
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
	// 连接program指定的程序对象中的着色器
    gl.linkProgram(program);
    //告知WebGL系统绘制时使用program指定的程序对象
    gl.useProgram(program);

    return program;
}

绘制点的完整代码

<!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="./initShader.js"></script>
</head>

<body>
  <canvas id="canvas" width="400" height="400">
    不支持canvas
  </canvas>
</body>

<script>
  //获取<canvas>元素
  const ctx = document.getElementById('canvas')
  //获取WebGL绘图上下文
  const gl = ctx.getContext('webgl')

  //顶点着色器
  const VERTEX_SHADER_SOURCE = `
    void main() {
      gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
      gl_PointSize = 10.0;
    }  
  `
  //片元着色器
  const FRAGMENT_SHADER_SOURCE = `
    void main() {
      gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }   
  `
  //创建着色器
  const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)

  //执行绘制
  gl.drawArrays(gl.POINTS, 0, 1)

</script>

</html>

效果
在这里插入图片描述

  • 整个绘制流程如下所示:

在这里插入图片描述

  • 程序的执行流程如下:

在这里插入图片描述
首先运行JavaScript程序,调用WebGL相关方法,然后顶点着色器和片元着色器就会执行,在颜色缓冲区内进行绘制,并且清空绘图区,最后颜色缓冲区的内容会自动在浏览器的canvas上显示出来。

4. webGL渲染过程

webGL渲染管线,其实就是图形的渲染过程。
渲染管线主要包括两个功能:一是将物体 3D 坐标转变为屏幕空间 2D 坐标,二是为屏幕每个像素点进行着色,渲染管线的一般流程如下图所示,分别是:顶点处理、裁剪和图元组装、光栅化、片元处理。

  • 1.顶点处理

顶点处理是针对存储于顶点缓冲区的各个输入顶点进行操作,此阶段为可编程状态。主要的操作是对顶点进行坐标转换,把对象由其所定义的坐标系下的表示,转化为照相机下的坐标系。
在这里插入图片描述

  • 2.裁剪和图元组装

在顶点处理完之后,就需要将顶点组合成一个个单元,这个单元就是我们的图元。这一步就是组装,将顶点组合成一个个单元,如点,线,三角形。
裁剪则是指将视口以外的片元进行裁剪。
在这里插入图片描述

  • 3.光栅化

完成图元组装和裁剪后,下一步是光栅化。
光栅化是将几何图元转化为图像的过程。光栅化主要目的是为了将图元组装和裁剪之后的图元数据转化生成帧缓存中的像素。但是光栅化处理完之后,我们并没有直接得到像素,而是得到了片元。片元是一个像素大小的基本单位,但是它并非像素,而是像素的前身。片元相比于像素,除了 RGBA 之外,还会包含如深度值,法线,纹理坐标等信息。
在这里插入图片描述

  • 4.片元处理

片元处理,主要是通过片元着色器,计算片元的最终颜色和深度。
光栅化后,程序调用片元着色器,假定光栅化后有10个片元,那么片元着色器将执行10次,每次调用处理一个片元,片元着色器计算该片元的颜色并写入颜色缓冲区,当最后一个片元被处理完成,浏览器就会显示出最终的结果。
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WebGL简介 的相关文章

  • 在Three.JS中通过鼠标点击选择Collada对象

    我需要通过鼠标单击在 Three JS 中选择 Collada 对象 我知道我可以根据对象的 id 选择对象 并且我看到了一些用户可以与几何定义的对象交互的示例 here http mrdoob github com three js ex
  • 在 Chrome 中调试 webgl

    我有一个在 chrome 中运行的 webgl 页面 chrome 时不时会报如下错误 WebGLRenderingContext GL 错误 GL INVALID OPERATION glDrawElements 尝试在没有附加到启用属性
  • 使用 ShaderMaterial 复制 MeshLambertMaterial 会忽略纹理

    我注意到 THREE js 在内部使用着色器来创建核心材质 例如 MeshLambertMaterial 因此我决定将 Three js 代码中的兰伯特着色器复制到新的着色器中并在其上进行构建 这是我得到的代码 忠实地从 Three js
  • 是否可以使用 WebGL 运行 #version 120 着色器

    我有许多 GLSL 片段着色器 我几乎可以保证它们符合 version 120它们使用标准的 不符合 ES 的值 并且没有任何 ES 特定的编译指示 我真的很想使用 WebGL 为他们制作一个网页预览器 预览器不会在移动设备上使用 这可行吗
  • WebGL / Three.js - 移动相机时,纹理着色的粒子不规则地闪烁

    这是一个jsfiddle http jsfiddle net vko8hzzs 4 我将粒子在使用纹理着色时以及相机移动时 闪烁 的问题放在一起展示 更新 粒子上不应该发生动画或运动 如果当您在视口上单击并拖动并且粒子闪烁或完全改变颜色时
  • 背面剔除的法线变换

    从本课开始 WebGL 3D 透视 https webglfundamentals org webgl lessons webgl 3d perspective html我正在尝试实现没有魔法的背面剔除 我正在动态计算对象空间中的面法线 之
  • 未捕获的类型错误:无法解析模块说明符“三/示例/jsm/loaders/GLTFLoader.js”

    我很难理解为什么我的程序由于这个错误而崩溃 未捕获的类型错误 无法解析模块说明符 三 示例 jsm loaders GLTFLoader js 相对引用必须以 或 开头 我正在尝试使我的 html 文件与我创建的 serial js 文件进
  • 三.js:纹理到数据纹理

    我正在尝试在 JavaScript 中实现延迟网络摄像头查看器 使用 Three js 实现 WebGL 功能 我需要存储从网络摄像头抓取的帧 以便在一段时间 几毫秒到几秒 后显示它们 我可以在没有 Three js 的情况下使用canva
  • 将颜色从 Javascript 传递到片段着色器

    我目前正在学习webgl 有一个问题 我正在尝试制作一个三角形并将颜色信息从 js 文件传递 到片段着色器中 以下是我的js代码 var VSHADER SOURCE attribute vec4 a Position n attribut
  • 如何编写基于网络的音乐可视化工具?

    我正在尝试找到构建音乐可视化工具以在网络浏览器中运行的最佳方法 Unity 是一个选项 但我需要构建一个自定义音频导入 分析插件来获取最终用户的声音输出 Quartz 可以满足我的需要 但只能在 Mac Safari 上运行 WebGL 似
  • 以到最近边缘的距离为函数的着色矩形会在对角线上产生奇怪的结果

    I m trying to color a rectangle in ShaderToy GLSL in function of each pixel s distance to the nearest rectangle edge How
  • Webgl使用视口+剪刀更新区域

    我一直在尝试创建一个多视口 webgl 应用程序 对于每个视图 我使用视口 剪刀将所有内容渲染得非常好 但现在我想改进渲染并只渲染更新的视图 因此跳过过度绘制 我做了一个小演示来展示这个想法 http kile stravaganza or
  • Three.js中是否有一个容器类型对象来转换一组孩子?

    Three js 中是否有一个容器或节点对象 可以将多个网格添加为子对象 以便它们可以一起转换 一个不可见的容器 允许对组中的所有子对象执行转换 thanks Example http mrdoob github com three js
  • WebGL 绘制图像

    我是 WebGL 新手 之前在 Java 中使用过 OpenGL 我一直在尝试编写一个简单的函数 该函数以特定的大小和旋转在特定位置绘制图像 但在网上搜索了一段时间后 我的代码仍然无法运行 目前 我已经成功绘制了图像 但是该图像距离正确的位
  • WebGL 渲染抗锯齿

    我正在使用 webgl 和 javascript 有没有一种方法可以在不使用抗锯齿的情况下进行渲染 我需要每个像素都是纯色的 我当前的片段着色器非常简单 precision mediump float varying highp vec3
  • 如何在 WebGL 中创建合适的圆角矩形?

    我试图实现答案这个问题 https stackoverflow com questions 43970170 bordered rounded rectangle in glsl但似乎有点问题 如果您打开他们的 ShaderToys 并尝试
  • 在 Fabric.js 中真正旋转等边三角形的中心

    使用 Fabric js 我无法真正围绕其中心点旋转三角形 或者至少我认为应该是中心点 我创建了一个jsFiddle http jsfiddle net UW8Be 这表明 三角形很简单 我用了originX center 原点Y 也是如此
  • 如何在 Ubuntu 的 headless chrome 中启用 WebGL?

    如何在 Ubuntu 14 的 headless chrome 中启用 webgl 或安装 webgl 我尝试安装 libosmesa6 但这没有帮助 有人可以指出我正确的方向吗 我想使用 webgl 来处理无头 chrome 和 sele
  • 在 Three.js 中渲染具有大量对象的多个场景的最佳方式

    想象一下 您想要绘制两个场景 每个场景都有数百个球体 并提供在这些场景之间切换的功能 做到这一点的最佳方法是什么 目前 一个开关大约需要 4 到 5 秒 因为我要删除 创建和绘制每个开关上的所有球体 下面是在场景切换上运行的代码示例 cle
  • 开始使用 Three.js 中的行进立方体

    我是 Three js 的新手 正在寻找教程来帮助我开始了解如何在 Three js 中使用 Marching Cubes 到目前为止 我在 Three js 中看到的一些使用它的项目对我来说有点复杂 所以一个简单的教程会很好 谢谢 像您一

随机推荐

  • Bug:Unable to determine application id: com.android.tools.idea.run.ApkProvisionException: No outputs

    问题描述 Android Studio 3 6 3版本 运行之前项目时 项目可正常编译出apk文件 但无法自动安装到设备 手动通过命令行将apk安装到设备 也存在无法调试的问题 问题展示 解决方法 1 对Android Studio进行降级
  • M - Marbles Lucky Distribution(贪心)

    M Marbles Lucky Distributionhttps vjudge csgrandeur cn problem Gym 101845M Juan have N red marbles M blue marbles and K
  • 用定时器设计门铃,按下按键时蜂鸣器发出叮咚的门铃声

    叮咚 产生的方式 仿真 程序代码 include
  • 作为一个江苏人,我眼中的苏宁

    江苏人 人人都在苏宁电器的地面商店里买过东西 我也不例外 听说张近东要转让苏宁易购的股份给一家疑似国企或国有基金 作为一个地道的江苏人 感慨良多 中国有4个电商平台 天猫 京东 拼多多和苏宁易购 还有大商 国美什么 已经彻底掉队 暂且不提
  • 推荐你个软件 TDengine

    推荐你个软件 https github com taosdata TDengine 时序数据库 效率非常高 https constd com 2019 07 26 tdengine doc https www taosdata com cn
  • Linux 桌面虚拟化技术 KVM

    KVM 是 Kernel based Virtual Machine 的简称 是一个开源的系统虚拟化模块 自Linux 2 6 20之后集成在Linux的各个主要发行版本中 它使用Linux自身的调度器进行管理 所以相对于Xen 其核心源码
  • Easylogging介绍和简单使用

    一 Easylogging简介 Easyloggingpp是一个C 开源log库 其在github的地址 https github com muflihun easyloggingpp Easyloggingpp最大的特点是只需一个头文件
  • 最全面计算机英语单词列表(四)

    作为一名开发者 不管是自己写代码还是阅读英文文档 英语水平对于开发进度有很大的影响 业余时间简单整理了计算机开发中常见的英语单词 不限于前端开发 再此和朋友们分享 单词较多 为了阅读体验良好分成几个部分 下面是其他部分的链接 最全面计算机英
  • go get 与git clone的区别

    一直对go get 和git clone 区别不开 go get 的参数说明 d 只下载不安装 f 只有在你包含了 u参数的时候才有效 不让 u去验证import中的每一个都已经获取了 这对于本地fork的包特别有用 fix 在获取源码之后
  • 布局优化之ViewStub原理

    1 概述 在进行Android程序开发时 除了要实现基本功能外 还要关注应用的性能 内存占用少 程序稳定 响应速度快等 懒加载 就是为了让程序尽可能快地启动而提出的一个优化策略 即让那些对用户不重要或者不需要立即显示的布局控件做延迟加载 只
  • Linux下进程与多线程之间的共享资源

    在Linux 下 程序或可执行文件是一个静态的实体 它只是一组指令的集合 没有执行的含义 进程是一个动态的实体 有自己的生命周期 线程是操作系统进城调度器可以执行的最小执行单元 同一个进程中的各个线程都有自己独立的线程ID 用来标识线程 如
  • 使用jsPlumb制作流程图设计器

    jsPlumb是一个比较强大的绘图组件 它提供了一种方法 主要用于连接网页上的元素 在现代浏览器中 它使用SVG或者Canvas技术 而对于IE8以下 含IE8 的古董浏览器 则使用VML技术 项目主页 http jsplumbtoolki
  • PCL 常用小知识

    目录 零 保存点云 一 时间计算 二 已知需要保存点的索引 从原点云中拷贝点到新点云 三 删除无效点 四 pcl PointCloud Ptr和pcl PointCloud的两个类相互转换 五 计算点云中心点 六 将vector型索引转换成
  • scikit-learn 逻辑回归--调参

    代码笔记 from sklearn linear model import LogisticRegression as LR from sklearn datasets import load breast cancer import nu
  • CTFshow web15

    ctf show 萌新模块 web15关 这一关是代码执行漏洞 需要灵活的运用PHP的命令执行函数 在上一关的基础上又过滤了 gt 关键字 看起来已经没啥思路了 但仔细一看 它居然取消了对分号 的过滤 这样一来就好办了 继续上一关的曲线救国
  • IDEA中打jar包的方式

    在讲这两种方式之前 我们先来说明一下什么是java中的jar文件 jar Java Archive File 翻译过来就是java的档案文件 它其实也类似于我们windows下的zip文件 唯一的区别就是在 JAR 文件的内容中 包含了一个
  • opencv学习--图像处理基础

    将图片处理为灰度图 import os import re import cv2 from PIL import Image import numpy as np import matplotlib pylab as pylab img c
  • css公共样式总结(持续总结)

    flex display flex align center align items center justify between justify content space between justify center justify c
  • java基础(一)-虚拟机和第一个命令

    虚拟机 用 Java 语言编写的程序由 Java 虚拟机 JVM 来执行 JVM 是一个特殊的程序 它知道如何执行用 Java 语言编写的程序 并且它的命令列表涵盖范围很大 比如 System out println 你以为我会说虚拟机是由
  • WebGL简介

    WebGL简介 前言 1 WebGL简介 1 1 WebGL概述 1 2 WebGL程序的结构 1 3 WebGL和OpenGL 2 着色器语言 2 1 顶点着色器 2 2 片元着色器 3 webGL绘制一个点 4 webGL渲染过程 前言