搭建WebGL开发环境

前言

本篇文章介绍如何搭建WebGL开发环境

WebGL

WebGL的技术规范继承自免费和开源的OpenGL ES标准,从某种意义上说,WebGL就是Web版的OpenGL ES,而OpenGL ES是从OpenGL中派生出来的。他们的应用环境有区别,一般来说:

  • OpenGL:一般应用于桌面级别的三维图形渲染,同类的还有微软的DirectX和苹果公司的Metal技术
  • OpenGL ES:OpenGL的子集,删除了很多用处不大的接口和特性,但仍然能进行三维渲染,应用于智能手机、嵌入式计算机、家用游戏机等
  • WebGL:从OpenGL ES派生出来的。需要浏览器内核的支持。WebGL广泛应用于所有的网页渲染。因为需要运行在浏览器上,所以浏览器在背后做了很多工作,包括跨平台的特性。

版本

既然OpenGL、OpenGL ES和WebGL存在继承关系,那必然涉及到版本信息
先看一下OpenGL的版本信息:

  • OpenGL 1.5:这个版本的OpenGL不支持着色器编程,采用固定渲染管线
  • OpenGL 2.0:这个版本加入GLSL着色器编程语言
  • OpenGL 3.3:2010年发布
  • OpenGL 4.3:2013年发布

看一下OpenGL ES的版本信息:

  • OpenGL ES 1.1:OpenGL 1.5的子集,应用范围有限
  • OpenGL ES 2.0:OpenGL 2.0的子集,应用最广泛的版本
  • OpenGL ES 3.0:OpenGL 3.3的子集,增加了很多新功能,包括:
    • 遮挡查询
    • 变缓反馈(Transform Feedback)
    • 实例渲染(Instanced Rendering)
    • 四个或更多渲染目标支持
    • 着色语言全面支持整数和32位浮点操作
    • 纹理功能大幅增强,支持浮点纹理、3D纹理、深度纹理、顶点纹理、NPOT纹理、R/RG单双通道纹理、不可变纹理、2D阵列纹理、无二次幂限制纹理、阴影对比、调配(swizzle)、LOD与mip level clamps、无缝立方体贴图、采样对象、纹理MSAA抗锯齿渲染器
    • 一系列广泛的精确尺寸纹理和渲染缓冲格式

看一下WebGL的版本信息:

  • WebGL 1.0:基于OpenGL ES 2.0,并提供了3D图形的API,它使用HTML5Canvas并允许利用文档对象模型接口。
  • WebGL 2.0:WebGL 2.0基于OpenGL ES 3.0,确保了提供许多选择性的WebGL 1.0扩展,并引入新的API。可利用部分Javascript实现自动存储器管理

WebGL程序组成

一个最简单的WebGL程序之需要一个html文件和几个js文件就可以了,下面详细介绍

html部分

html主要是为了放置canvas元素,因为WebGL的渲染都是在canvas进行的。
下面是一个html部分:

<!DOCTYPE html>
<html lang="cn">
<head><meta charset="utf-8"><title>wgl render ins</title>
</head>
<body onload="main()"><canvas id="wglCanvas" width="960" height="540">当前浏览器不支持canvas</canvas><script src="sk_init.js"></script><script src="sk_shader.js"></script><script src="sk_utils.js"></script>
</body>
</html>

这个简单的不能再简单的html就已经够用了。

上面的html我们命名为main.html。从上面的html中,可以发现我们需要一个main函数,这个函数一般来说在js中实现,这也是我们WebGL程序正式开始的入口函数,我们添加一个js文件sk_init.js,并实现该函数,当然我们也需要在html中加入引用js的代码,为了保持代码的简洁,已经在上面的html中加入了该代码。

js部分

下面是sk_init.js的代码:

var gl;
function main()
{var canvas = document.getElementById("wglCanvas");gl = create3DContext(canvas);if(!gl){console.log("获取webgl渲染上下文失败");return;}gl.clearColor(0.0,0.0,0.0,1.0);gl.clear(gl.COLOR_BUFFER_BIT);
}var create3DContext = function(canvas) {var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];var context = null;for (var ii = 0; ii < names.length; ++ii) {try {context = canvas.getContext(names[ii]);} catch(e) {}if (context) {break;}}return context;
}

上面这个代码分为几部分:

  • 获取canvas对象
  • 获取webgl上下文
  • 设置canvas画布背景色
  • 使用背景色清空绘图区

虽然代码很简单,但是这几步是所有webgl程序都需要做的事情,当前main.html已经可以运行了。不过只会显示一个黑色背景。下面我们开始加入些东西

shader

想编写一个真正可以使用的webgl程序,首先需要写shader,由于本篇文章我们着重介绍WebGL框架,所以我们只是简单说明一下,关于shader语法,会有专门文章介绍。

  • WebGL程序的shader一般有两个,顶点着色器片元着色器
  • 着色器是以字符串的形式嵌入到js文件中的

下面是两个简单的着色器代码,我们创建一个sk_shader.js存放这部分代码:
顶点着色器:

var VERTEX_SHADER=`
attribute vec4 a_Position;
uniform float u_PointSize;
void main() {gl_Position = a_Position;gl_PointSize = u_PointSize;
}`;

片元着色器:

var FRAG_SHADER=`
void main() {gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}`;

初始化着色器

创建好了着色器以后,下一步就要初始化着色器了

加载着色器代码

我们新建一个sk_util.js文件,里面封装一些公共的方法,首先我们要添加的方法就是加载着色器代码的方法:

// gl: webgl上下文
// type: 着色器类型
// source: 着色器代码
function loadShader(gl, type, source) {var shader = gl.createShader(type);if (shader == null) {console.log('unable to create shader');return null;}gl.shaderSource(shader, source);gl.compileShader(shader);var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);if (!compiled) {var error = gl.getShaderInfoLog(shader);console.log('Failed to compile shader: ' + error);gl.deleteShader(shader);return null;}return shader;
}

加载一个着色器需要以下步骤:

  • 创建着色器对象:使用gl.createShader接口,参数为着色器类型,着色器类型一般有两类:
    • gl.VERTEX_SHADER:顶点着色器
    • gl.FRAGMENT_SHADER:片元着色器
  • 加载着色器代码:使用gl.shaderSource接口,第一个参数为第一步创建的着色器对象,第二个参数为着色器的字符串表示
  • 编译着色器代码:使用gl.compileShader接口,参数为第一步创建的着色器对象
  • 获取着色器编译状态,如果编译失败,获取错误信息

创建着色器程序

下面是创建着色器程序的代码:

function createProgram(gl, vshader, fshader) {var vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshader);var fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshader);if (!vertexShader || !fragmentShader) {return null;}var program = gl.createProgram();if (!program) {return null;}gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);var linked = gl.getProgramParameter(program, gl.LINK_STATUS);if (!linked) {var error = gl.getProgramInfoLog(program);console.log('Failed to link program: ' + error);gl.deleteProgram(program);gl.deleteShader(fragmentShader);gl.deleteShader(vertexShader);return null;}return program;
}

创建着色器程序的步骤如下:

  • 创建着色器程序:使用gl.createProgram接口,返回着色器程序对象
  • 关联着色器对象:使用gl.attachShader接口,第一个参数是第一步创建的着色器程序对象,第二个参数是关联的着色器对象
  • 链接着色器程序:使用gl.linkProgram接口链接程序,参数是第一步创建的着色器程序对象
  • 获取着色器程序链接状态,如果链接失败,获取错误信息

使用着色器对象

  • 使用gl.useProgram接口使用我们上一步创建的着色器程序对象。
  • 将着色器程序对象赋给gl.program,方便我们后面传递数据的时候使用

代码如下:

function initShaders(gl, vshader, fshader) {var program = createProgram(gl, vshader, fshader);if (!program) {console.log('Failed to create program');return false;}gl.useProgram(program);gl.program = program;return true;
}

经过这三步以后,着色器程序已经初始化完成了,接下来就是向着色器传递数据

传递数据

所谓的传递数据就是将内存的数据传递给显存
一般情况下shader中使用的数据有三种:

  • 使用attribute标记的数据,这个也叫做顶点数据,就是每个顶点都会有自己的数值
  • 使用uniform标记的数据,这个也叫做统一数据,就是所有顶点共用的数据
  • 使用varying标记的数据,这个是在着色器之间传递的数据

获取shader的数据标记

  • 使用gl.getAttribLocation接口获取attribute数据的标记,第一个参数是着色器程序对象,第二个参数是数据在shader中的名称的字符串表示
  • 使用gl.getUniformLocation接口获取uniform数据的标记,第一个参数是着色器程序对象,第二个参数是数据在shader中的名称的字符串表示

下面我们获取前面着色器程序的a_Position和u_PointSize的标记:

var u_PointSize = gl.getUniformLocation(gl.program, "u_PointSize");
if (u_PointSize < 0) {console.log('Failed to get the storage location of u_PointSize');return -1;
}
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {console.log('Failed to get the storage location of a_Position');return -1;
}

从内存传递attribute数据到显存

  • 创建缓冲区,使用gl.createBuffer()创建缓冲区
  • 绑定缓冲区,使用gl.bindBuffer接口绑定缓冲区,第一个参数是缓冲区类型,这里我们使用gl.ARRAY_BUFFER,第二个参数是上一步创建的缓冲区
  • 传递数据,使用gl.bufferData接口传递数据,第一参数是缓冲区类型,这里我们使用gl.ARRAY_BUFFER,第二个参数是内存数据指针,第三个参数是数据的使用方式,这里我们使用gl.STATIC_DRAW
    代码如下:
var verticesTexCoords = new Float32Array([-0.5, 0.5, 0.0, 1.0,-0.5, -0.5, 0.0, 1.0,0.5, 0.5, 0.0, 1.0,0.5, -0.5, 0.0, 1.0,    ]);
var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;
var vertexTexCoordBuffer = gl.createBuffer();
if (!vertexTexCoordBuffer) {console.log('Failed to create the buffer object');return -1;
}
gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);

传递uniform数据到显存

使用gl.uniform1f接口传递单个float数值到显存,在当前程序中用来传递u_PointSize的值
代码如下:

gl.uniform1f(u_PointSize, 10);

绑定缓冲区与attribute顶点属性

  • 使用gl.vertexAttribPointer接口绑定缓冲区与attribute顶点属性
  • 使用gl.enableVertexAttribArray接口开启顶点属性数组,如果不开启的话,默认会使用静态属性,就是所有顶点数据都使用一个默认的值
    代码如下:
gl.vertexAttribPointer(a_Position, 4, gl.FLOAT, false, FSIZE * 4, 0);
gl.enableVertexAttribArray(a_Position);

绘制

当前程序使用gl.drawArrays来开始绘制操作
gl.drawArrays的第一个参数是绘制的类型,我们当前程序就使用gl.POINTS方式
gl.drawArrays的第二个参数是绘制顶点的偏移,当前为0
gl.drawArrays的第三个参数是绘制顶点的数量,当前为4
代码如下:

gl.clearColor(0.0,0.0,0.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.POINTS, 0, 4);

代码结构调整

  • 我们把创建WebGL上下文和初始化着色器的方法放进sk_utils.js
  • 我们把shader字符串放进sk_shader.js
  • 我们把传递数据的部分放进sk_init.js
  • main.html中需要添加对这3个js的引用,我们已经添加好了

完整的代码已经上传gitlab:
https://gitlab.com/lingyanTools/sk_webgl.git
该例子绘制了四个顶点
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++:第十四讲动态规划初步

每日C知识 想要在做C小游戏里实现等待效果&#xff0c;可以用Sleep。 Sleep函数可以使计算机程序&#xff08;进程&#xff0c;任务或线程&#xff09;进入休眠&#xff0c;使其在一段时间内处于非活动状态。 一般需要头文件windows.h。 注意"Sleep"首字母要大写…

ppt背景图片怎么设置?让你的演示更加出彩!

PowerPoint是一款广泛应用于演示文稿制作的软件&#xff0c;而背景图片是演示文稿中不可或缺的一部分。一个好的背景图片能够提升演示文稿的整体效果&#xff0c;使观众更加关注你的演示内容。可是ppt背景图片怎么设置呢&#xff1f;本文将介绍ppt背景图片设置的三个方法&#…

Spring-boot项目+Rancher6.3部署+Nacos配置中心+Rureka注册中心+Harbor镜像仓库+NFS存储

目录 一、项目概述二、环境三、部署流程3.1 Harbor部署3.1.1 docker安装3.1.2 docker-compose安装3.1.3 安装证书3.1.4 Harbor下载配置安装 3.2 NFS存储搭建3.3 Rancher平台配置3.3.1 NFS存储相关配置3.3.2 Harbor相关配置3.3.3 Nacos部署及相关配置3.3.4 工作负载deployment配…

ubuntu20.04 安装ROS2 记录

主要参考B站古月居的ROS2入门21讲 和 以下链接&#xff08;基本和视频上一致&#xff09; ubuntu20.04安装ROS2 详细教程_ubuntu20.04 ros2-CSDN博客 但是中间有些需要注意的地方&#xff0c; 1&#xff0c;添加源 步骤中提到 sudo curl -sSL https://raw.githubuserconten…

Redis冲冲冲——缓存三兄弟:缓存击穿、穿透、雪崩

目录 引出缓存击穿缓存穿透缓存雪崩 总结 引出 谈谈redis的击穿、穿透、雪崩。 缓存击穿 缓存击穿&#xff1a;redis中没有&#xff0c;但是数据库有 顺序&#xff1a;先查缓存&#xff0c;判断缓存是否存在&#xff1b;如果缓存存在&#xff0c;直接返回数据&#xff1b;如果…

【前端素材】bootstrap3 实现地产置业公司source网页设计

一、需求分析 地产置业公司的网页通常是该公司的官方网站&#xff0c;旨在向访问者提供相关信息和服务。这些网页通常具有以下功能&#xff1a; 公司介绍&#xff1a;网页通常包含有关公司背景、历史、核心价值观和使命等方面的信息。此部分帮助访问者了解公司的身份和目标。 …

人工视觉仍然需要图像采集卡

最初&#xff0c;图像采集卡被用作模拟视频数字转换器和图像缓冲器&#xff0c;但如今它们能够执行复杂的任务&#xff0c;例如图像处理。图像采集卡的设计不断发展&#xff0c;旨在提高系统性能并减少计算机处理需求。 除了图像采集之外&#xff0c;图像采集卡还执行机器视觉…

芯片跨时钟域设计(二)

芯片培训(真实项目)介绍&#xff1a; 低功耗景芯SoC前端、中端、后端全流程实战培训(火爆订购中) DDR4/3项目实战培训 ARM Cortex-A72处理器12nm PR实战培训 ARM Cortex-A72处理器12nm DFT实战培训 ARM Cortex-A7处理器28nm PR实战培训(火爆价格战) RISC-V MCU 40nm全芯片…

抽象类(Java)、模板方法设计模式

一、概念 在Java中有abstract关键字&#xff0c;就是抽象的意思&#xff0c;可用来修饰类和成员方法。 用abstract来修饰类&#xff0c;那这个类就是抽象类&#xff1b;修饰方法&#xff0c;那这个方法就是抽象方法。 修饰符 abstract class 类名{修饰符 abstract 返回值类型…

走进水稻种植教学基地可视化:科技与农业知识的完美结合

随着科技的不断发展&#xff0c;农业领域也在不断创新和进步。水稻种植教学基地可视化系统是一种基于现代信息技术手段的教学方式&#xff0c;通过虚拟现实、3D建模等技术&#xff0c;将水稻种植的全过程进行模拟和展示。这种教学方式打破了传统农业教学的局限性&#xff0c;使…

Springboot+vue的健身房管理系统(有报告)。Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的健身房管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的健身房管理系统&#xff0c;采用M&#xff08;model&#xf…

知识点积累系列(一)golang语言篇【持续更新】

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 知识点积累 系列文章的第一篇&#xff0c;记录golang语言相关的知识点 1.结构体的mapstructure是什么 mapstructure:"default" mapstructure是一个Go语言的库&#xff0c;用于将一个map中的值映射到…

STM32读取MPU6050数据并通过角度值控制舵机运动(STM32、GY-521 MPU6050、SG90舵机、MG946舵机)

通过STM32F103C8T6读取MPU6050数据控制舵机运动&#xff08;STM32、GY-521 MPU6050、SG90舵机、MG946舵机&#xff09; 最终现象一、MPU6050数据读取二、舵机控制原理①什么是PWM&#xff1f;②STM32F103C8T6如何生成PWM&#xff1f;③控制舵机需要什么样的PWM波&#xff1f; 三…

【Go】Channel底层实现 ②

文章目录 channel底层实现channel发送、接收数据有缓冲 channelchannel 先写再读channel 先读再写(when the receiver comes first) 无缓冲channelchannel存在3种状态&#xff1a; channel底层实现 // channel 类型定义 type hchan struct {// channel 中的元素数量, lenqcoun…

【排序算法】C语言实现随机快排,巨详细讲解

文章目录 &#x1f680;前言&#x1f680;快排的核心过程partition&#xff08;划分过程&#xff09;&#x1f680;快排1.0&#x1f680;随机快速排序&#x1f680;稳定性 &#x1f680;前言 铁子们好啊&#xff01;继续我们排序算法今天要讲的是快排&#xff0c;通常大家所说…

房产信息网源码,房产系统,二手房小程序源码,租房小程序系统楼盘系统房产经纪人系统

房产门户系统、多城市房产网、房产小程序 房产网系统、地方房产门户信息网 带im即时通讯聊天 二手房 租房 楼盘 置业顾问 经纪人 腾房云房产网 分为单城市版本 和多城市版本 多城市 自动定位当前城市 每个分站对应独立管理员分站管理 thinkphpuniapp 独立开源

微信开发者工具 git 拉取 failed invalid authentication scheme

微信开发者工具 git 拉取 failed invalid authentication scheme 拉取代码时报错,无效身份认证 解决方案: 1.检查git地址是否正常 2.检查git用户名密码是否正确

uniapp多格式文件选择(APP,H5)

uniapp多格式文件选择&#xff08;APP&#xff0c;H5&#xff09; 背景实现代码实现运行结果注意事项 尾巴 背景 从手机选择文件进行上传是移动端很常见的需求&#xff0c;在原生开发时由于平台专一性很容易实现。但是用uniapp开发官方提供的API在APP平台只能选择图片和视频&a…

使用visual studio写一个简单的c语言程序

官网下载visual studio&#xff0c;社区版免费的 https://visualstudio.microsoft.com/zh-hans/ 下载好以后选择自己的需求进行安装&#xff0c;我选择了两个&#xff0c;剩下的是默认。 创建文件&#xff1a;

K8s 安装部署-Master和Minion(Node)

K8s 安装部署-Master和Minion(Node) 操作系统版本&#xff1a;CentOS 7.4 Master &#xff1a;172.20.26.167 Minion-1&#xff1a;172.20.26.198 Minion-2&#xff1a;172.20.26.210&#xff08;后增加节点&#xff09; ETCD&#xff1a;172.20.27.218 先安装部署ETCD y…