当前位置: 首页 > news >正文

WebGL系列教程二(环境搭建及初始化Shader)

目录

  • 1 前言
  • 2 新建html页面
  • 3 着色器介绍
    • 3.1 顶点着色器、片元着色器与光栅化的概念
    • 3.2 声明顶点着色器
    • 3.3 声明片元着色器
  • 4 坐标系(右手系)介绍
  • 5 着色器初始化
    • 5.1 给一个画布canvas
    • 5.2 获取WebGL对象
    • 5.3 创建着色器对象
    • 5.4 获取着色器对象的源
    • 5.5 绑定着色器的源
    • 5.6 编译着色器
    • 5.7 创建并关联项目
  • 6 绘制
    • 6.1 声明点的位置、大小和颜色
    • 6.2 绘制
    • 6.3 完整代码
  • 7 总结

1 前言

  上一篇中我们对WebGL进行了简单的介绍,从本篇开始,正式进入实战。那么我们第一步需要做什么呢?当然是环境的搭建,以及Shader的初始化。废话不多说,咱们直接开整。

2 新建html页面

  其实搭建WebGL的环境十分简单,因为WebGL在在浏览里运行的,因此只需要新建一个html页面就行了。

3 着色器介绍

3.1 顶点着色器、片元着色器与光栅化的概念

  那么什么是顶点着色器?什么是片元着色器?什么叫做光栅化?这三个概念对我们学习WebGL还是很重要的,在学习WebGL的过程中,我曾经常困惑于片元、光栅化的概念,现在我们就用一张图来解释下。假设我们要在屏幕上画一个三角形。
在这里插入图片描述
  如图所示,v1 v2 v3 就叫做顶点,三角形内部的一个个红色的点,就叫做片元,也叫片段,其实它的意思就是一个个像素。注意像素应该是密密麻麻占满了整个三角形,这里为了示意只画出来了少部分。屏幕是什么?屏幕是一种光栅设备,因此把任何一种图形,不论是二维三维的,画在屏幕上,就叫做光栅化。光栅化的概念就这么简单。看过很多其他教程,只说光栅化,不说光栅化是什么意思,很令人困惑。

3.2 声明顶点着色器

  声明顶点着色器很简单,只需要写一个script标签,注意type

<script id="vertex-shader" type="x-shader/x-vertex"></script>

3.3 声明片元着色器

  声明片元着色器也很简单,只需要写一个script标签,同样注意type

<script id="vertex-shader" type="x-shader/x-fragment"></script>

4 坐标系(右手系)介绍

  现在我们来做一个最简单的例子,画一个点,这个点的坐标分别是x=0.5,y=0.5,z=0。在此之前我们先明确一下WebGL中的坐标系:X轴向右,Y轴向上,Z轴向外。右手握拳,四指从XY转动,大拇指的方向就是Z轴的方向。很明显,WebGL中默认是右手系。因为z=0,因此这个点在xy所形成的平面内。
在这里插入图片描述

5 着色器初始化

  初始化着色也很简单,我们先给出步骤,然后一步步来说明

  1. 创建着色器对象
  2. 获取着色器对象的源代码
  3. 绑定着色器的源
  4. 编译着色器
  5. 创建并关联项目

5.1 给一个画布canvas

<canvas id="canvas" width="1080" height="720"></canvas>

5.2 获取WebGL对象

const canvas = document.getElementById("canvas");
const gl = canvas.getContext("webgl");

5.3 创建着色器对象

//创建着色器对象
let vertexShader = gl.createShader(gl.VERTEX_SHADER);
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

5.4 获取着色器对象的源

//获取着色器对象的源
let vertexSource = document.getElementById("vertex-shader").innerText;
let fragmentSource = document.getElementById("fragment-shader").innerText;

因为这里我们要用的innerText,也就是script标签里的文本,因此也可以不把文本写在script标签里,而是直接手写字符串,这样的不好处就是没有智能提示,比如:
let vertexSource = “…”
let fragmentSource = “…”

5.5 绑定着色器的源

//绑定着色器的源
gl.shaderSource(vertexShader,vertexSource);
gl.shaderSource(fragmentShader,fragmentSource);

5.6 编译着色器

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

5.7 创建并关联项目

//创建并关联项目
let program = gl.createProgram();
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

6 绘制

  现在我们的准备工作已经完事了,可以开始绘制了。首先需要补齐script标签的内容

6.1 声明点的位置、大小和颜色

<script id="vertex-shader" type="x-shader/x-vertex">//声明一个点,vec2表示2维向量attribute vec2 aPos;void main(){//点的大小10像素gl_PointSize = 10.0;//点的位置,将vec2补齐为vec4gl_Position = vec4(aPos,0.0,1.0);   }
</script>
<script id="fragment-shader" type="x-shader/x-fragment">void main(){//点的颜色,rgba形式,红色gl_FragColor = vec4(1.0,0.0,0.0,1.0);}
</script>

6.2 绘制

//绘制
let aPos = gl.getAttribLocation(program,"aPos");
//设置顶点的值,该顶点是用二维坐标表示的,vertexAttrib2f表示vertex中的attribute属性,2个float值
gl.vertexAttrib2f(aPos,0.5,0.5);
//绘制点,从第0个点开始,绘制两个
gl.drawArrays(gl.POINTS,0,2);

在这里插入图片描述
改为x=0,y=0看看效果,点回到了正中间。
在这里插入图片描述

6.3 完整代码

<!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{border: 1px solid #ccc;}</style>
</head><body><canvas id="canvas" width="1080" height="720"></canvas><script id="vertex-shader" type="x-shader/x-vertex">attribute vec2 aPos;void main(){gl_PointSize = 10.0;gl_Position = vec4(aPos,0.0,1.0);   //gl_Position = aPos;   }</script><script id="fragment-shader" type="x-shader/x-fragment">void main(){gl_FragColor = vec4(1.0,0.0,0.0,1.0);}</script><script>const canvas = document.getElementById("canvas");const gl = canvas.getContext("webgl");//创建着色器对象let vertexShader = gl.createShader(gl.VERTEX_SHADER);let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);//获取着色器对象的源let vertexSource = document.getElementById("vertex-shader").innerText;let fragmentSource = document.getElementById("fragment-shader").innerText;//绑定着色器的源gl.shaderSource(vertexShader,vertexSource);gl.shaderSource(fragmentShader,fragmentSource);//编译着色器gl.compileShader(vertexShader);gl.compileShader(fragmentShader);console.log(gl.getShaderInfoLog(vertexShader));//创建并关联项目let program = gl.createProgram();gl.attachShader(program,vertexShader);gl.attachShader(program,fragmentShader);gl.linkProgram(program);gl.useProgram(program);//绘制let aPos = gl.getAttribLocation(program,"aPos");//设置顶点的值,该顶点是用二维坐标表示的gl.vertexAttrib2f(aPos,0.0,0.0);gl.drawArrays(gl.POINTS,0,2);</script>
</body></html>

7 总结

  本篇博文中我们梳理了WebGL中整个的绘制流程,右手坐标系的指向,顶点着色器、片元着色器、光栅化等概念的含义,并以一个最简单的示例,点绘制来演示Shader的初始化过程,代码并不复杂,希望读者仔细体会,回见~

相关文章:

WebGL系列教程二(环境搭建及初始化Shader)

目录 1 前言2 新建html页面3 着色器介绍3.1 顶点着色器、片元着色器与光栅化的概念3.2 声明顶点着色器3.3 声明片元着色器 4 坐标系(右手系)介绍5 着色器初始化5.1 给一个画布canvas5.2 获取WebGL对象5.3 创建着色器对象5.4 获取着色器对象的源5.5 绑定着色器的源5.6 编译着色器…...

keepalive和nginx高可用集群

keepalived 和 nginx 高可用集群搭建 主备模式 zyj86主机和zyj87主机安装nginx和keepalived yum install nginx keepalived -y systemctl enable --now nginx.service keepalived.service主调度器配置 编辑zyj86主机&#xff08;主&#xff09;配置文件 vi /etc/keepalived…...

二分查找题总结

二分查找题总结 hot100搜索插入位置搜索二维矩阵在排序数组中查找元素的第一个和最后一个位置搜索旋转排序数组寻找旋转排序数组中的最小值寻找两个正序数组的中位数 hot100 搜索插入位置 题目链接&#xff1a; 35.搜索插入位置 代码&#xff1a; class Solution {public in…...

仕考网:公务员面试流程介绍

通知进面信息——资格审查——面试签到——抽签候考 面试形式&#xff1a; 面试分为结构化和无领导小组两种形式 1.在结构化面试中&#xff0c;当轮到某位考生时&#xff0c;引导员将在候考室宣布其编号&#xff0c;随后考生跟随引导人员前往考场入口。考生在开始考试时需回…...

(十五)SpringCloudAlibaba-Sentinel持久化到Nacos

前言 在前面我们已经将Sentinel配置的规则持久化到系统的文件中。本章节我们将Sentinel持久化到Nacos中; 传送门(Sentinel数据持久化到文件)https://blog.csdn.net/weixin_45876411/article/details/140742963 默认情况下 Sentinel 只能接收到 Nacos 推送的消息&#xff0c;但…...

GitHub图床

GitHub图床 文章目录 GitHub图床图床介绍Github访问GitHub手动修改hostsgithub520 加速器创建账户创建仓库创建token PicGoTypora 图床介绍 图床 存放图片的地方 为什么设置图床呢 在我认识图床之前, 有一个问题 [^放在typora上面的图片, 其实是一个链接, 并且将图片存放在本地…...

记一次高版本view-design的组件迁移到自身项目的低版本

背景 npm i -S view-design当前老项目使用view-design这个组件库&#xff0c;但是当我们去官网查看该组件库最新版本&#xff0c;竟然发现没有博主想用的image/ImagePreivew这两个基础组件 说实话&#xff0c;有点离谱了哈&#xff01;&#xff01; 自己造轮子&#xff1f; …...

QT运行ROS工程

文章目录 使用QT创建ROS工程项目配置修改cmake环境配置运行设置 运行 使用QT创建ROS工程 工程名字和路径 下一步(直接选择默认选项就可以&#xff09;->完成 完成之后 是这样的 接下来在工作空间里面创建功能包 鼠标选中src点击右键->添加新文件 name::功能包的名字…...

电脑技巧:如何在Win11电脑上调整设置,让屏幕更加护眼?

目录 一、调整屏幕亮度 二、启用夜间模式 三、调整色彩设置 四、使用第三方护眼软件 五、保持良好的用眼习惯 总结 随着长时间使用电脑的人越来越多,护眼问题也变得越来越重要。Win11作为更新的操作系统,提供了更多的设置选项来帮助我们保护眼睛。本文将详细介绍如何在…...

【数据结构】排序算法篇二

【数据结构】排序算法篇二 1. 快速排序&#xff08;hoare版本&#xff09;&#xff08;1&#xff09;基本思想&#xff1a;&#xff08;2&#xff09;动态图解&#xff1a;&#xff08;3&#xff09;代码实现&#xff1a;&#xff08;4&#xff09;特性总结&#xff1a; 2. 快速…...

python进阶篇-day09-数据结构与算法(非线性结构与排序算法)

非线性结构(树状结构) 特点: 每个节点都可以有n个子节点(后继节点) 和 n个父节点(前驱节点) 代表: 树, 图...... 概述 属于数据结构之 非线性结构的一种, 父节点可以有多个子节点(后续节点) 特点 有且只有1个根节点 每个节点都可以有1个父节点及任意个子节点, 前提: 根节点除…...

线性代数基础

Base 对于矩阵 A&#xff0c;对齐做 SVD 分解&#xff0c;即 U Σ V s v d ( A ) U\Sigma V svd(A) UΣVsvd(A). 其中 U 为 A A T AA^T AAT的特征向量&#xff0c;V 为 A T A A^TA ATA的特征向量。 Σ \Sigma Σ 的对角元素为降序排序的特征值。显然&#xff0c;U、V矩阵…...

LCR 021

题目&#xff1a;LCR 021 解法一&#xff1a;计算链表长度 遍历两次&#xff0c;第一次获取链表长度 L&#xff08;包括虚拟节点&#xff09;&#xff0c;第二次遍历到第 L-n 个节点&#xff08;从虚拟节点遍历&#xff09; public ListNode removeNthFromEnd(ListNode head, …...

【阿雄不会写代码】全国职业院校技能大赛GZ036第四套

也不说那么多了&#xff0c;要用到这篇博客&#xff0c;肯定也知道他是干嘛的&#xff0c;给博主点点关注点点赞&#xff01;&#xff01;&#xff01;这样博主才能更新更多免费的教程&#xff0c;不然就直接丢付费专栏里了&#xff0c;需要相关文件请私聊...

Vue组件:使用$emit()方法监听子组件事件

1、监听自定义事件 父组件通过使用 Prop 为子组件传递数据&#xff0c;但如果子组件要把数据传递回去&#xff0c;就需要使用自定义事件来实现。父组件可以通过 v-on 指令&#xff08;简写形式“”&#xff09;监听子组件实例的自定义事件&#xff0c;而子组件可以通过调用内建…...

数据分析-埋点

1、数据埋点的定义 针对特定用户行为或事件进行捕获、处理何发送的相关技术及其实施过程。 2、数据埋点的原理 埋点是数据采集的重要方式。通过在页面上植入代码&#xff0c;监控用户行为(例:页面加载、按钮点击等)。用户一旦触发了该事件&#xff0c;就会根据埋点信息将相关数…...

【文心智能体】通过工作流使用知识库来实现信息查询输出,一键查看旅游相关信息,让出行多一份信心

欢迎来到《小5讲堂》 这是《文心智能体平台》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 创建灵感基本配置头像名称和简介人物设定角色与目标思考路…...

服务器监控工具都是监控服务器的哪些性能和指标

服务器监控工具通常用于确保服务器及其相关服务的正常运行。这些工具可以帮助管理员快速识别并解决问题&#xff0c;从而减少停机时间和性能下降的风险。以下是服务器监控工具通常会监控的一些主要内容&#xff1a; 系统健康状态&#xff1a; CPU使用率 内存&#xff08;RAM&…...

不小心删除丢失了所有短信?如何在 iPhone 上查找和恢复误删除的短信

不小心删除了一条短信&#xff0c;或者丢失了所有短信&#xff1f;希望还未破灭&#xff0c;下面介绍如何在 iPhone 上查找和恢复已删除的短信。 短信通常都是非正式和无关紧要的&#xff0c;但短信中可能包含非常重要的信息。因此&#xff0c;如果您删除了一些短信以清理 iPh…...

【skyvern 快速上手】一句话让AI帮你实现爬虫+自动化

目录 skyvern介绍主要特点工作流程 部署&#xff08;重点介绍源码部署&#xff09;源码部署docker快速部署 运行&#xff08;基于源码&#xff09;后端前端 快速使用示例总结 skyvern介绍 Skyvern 是一款利用大语言模型&#xff08;LLM&#xff09;和计算机视觉技术来自动化浏…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...