分享webgl魔幻星球

界面截图

d87235398463404eac2b25e28face0f5.png

webgl 是在网页上绘制和渲染三维图形的技术,可以让用户与其进行交互。div+css、canvas 2d 专注于二维图形。

对公司而言,webgl 可以解决他们在三维模型的显示和交互上的问题;对开发者而言,webgl 可以让我们是实现更多、更炫酷的效果,让我们即使工作,也可以乐在其中,并且还会有一份不错的薪资。

色相偏移动画

!(function animation() {

    color.offsetHSL(0.005, 0, 0);

    gl.clearColor(color.r, color.g, color.b, 1);

    gl.clear(gl.COLOR_BUFFER_BIT);

    requestAnimationFrame(animation);

})();

webgl画布和着色器

webgl画布的建立和获取,和canvas 2d是一样的。一旦我们使用canvas.getContext()方法获取了webgl 类型的上下文对象,那这张画布就不再是以前的canvas 2d 画布。

canvas 2d 画布和webgl 画布使用的坐标系都是二维直角坐标系,只不过它们坐标原点、y 轴的坐标方向,坐标基底都不一样了。

canvas 2d 坐标系的原点在左上角。

canvas 2d 坐标系的y 轴方向是朝下的。

canvas 2d 坐标系的坐标基底有两个分量,分别是一个像素的宽和一个像素的高,即1个单位的宽便是1个像素的宽,1个单位的高便是一个像素的高。

webgl坐标系的坐标原点在画布中心。

webgl坐标系的y 轴方向是朝上的。

webgl坐标基底中的两个分量分别是半个canvas的宽和canvas的高,即1个单位的宽便是半个个canvas的宽,1个单位的高便是半个canvas的高。

webgl 的绘图逻辑和canvas 2d 的绘图逻辑有一个本质的差别。

浏览器有三大线程: js 引擎线程、GUI 渲染线程、浏览器事件触发线程。

其中GUI 渲染线程就是用于渲图的,在这个渲染线程里,有负责不同渲染工作的工人。比如有负责渲染HTML+css的工人,有负责渲染二维图形的工人,有负责渲染三维图形的工人。

渲染二维图形的工人和渲染三维图形的工人不是一个国家的,他们说的语言不一样。

渲染二维图形的工人说的是js语言。

渲染三维图形的工人说的是GLSL ES 语言。

而我们在做web项目时,业务逻辑、交互操作都是用js 写的。

我们在用js 绘制canvas 2d 图形的时候,渲染二维图形的工人认识js 语言,所以它可以正常渲图。

但我们在用js 绘制webgl图形时,渲染三维图形的工人就不认识这个js 语言了,因为它只认识GLSL ES 语言。

就像手绘板,在webgl 里叫“程序对象”。手绘板 - 程序对象,承载GLSL ES语言,翻译GLSL ES语言和js语言,使两者可以相互通信。

webgl 的着色器语言是GLSL ES语言,webgl 绘图需要两种着色器:

顶点着色器(Vertex shader):描述顶点的特征,如位置、颜色等。

片元着色器(Fragment shader):进行逐片元处理,如光照。

在js中获取顶点着色器和片元着色器的文本

const vsSource = document.getElementById('vertexShader').innerText;
const fsSource = document.getElementById('fragmentShader').innerText;

初始化着色器

initShaders(gl, vsSource, fsSource);

指定将要用来清空绘图区的颜色

gl.clearColor(0,0,0,1);

使用之前指定的颜色,清空绘图区

gl.clear(gl.COLOR_BUFFER_BIT);

绘制顶点

gl.drawArrays(gl.POINTS, 0, 1);
//顶点着色器
<script id="vertexShader" type="x-shader/x-vertex">void main() {gl_Position = vec4(0.0, 0.0, 0.0, 1.0);gl_PointSize = 100.0;}
</script>
//片元着色器
<script id="fragmentShader" type="x-shader/x-fragment">void main() {gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);}
</script>
const canvas = document.createElement("canvas")
const gl = canvas.getContext("webgl2")document.title = "??"
document.body.innerHTML = ""
document.body.appendChild(canvas)
document.body.style = "margin:0;touch-action:none;overflow:hidden;"
canvas.style.width = "100%"
canvas.style.height = "auto"
canvas.style.userSelect = "none"const dpr = Math.max(1, .5*window.devicePixelRatio)function resize() {const {innerWidth: width,innerHeight: height} = windowcanvas.width = width * dprcanvas.height = height * dprgl.viewport(0, 0, width * dpr, height * dpr)
}
window.onresize = resizeconst vertexSource = `#version 300 es#ifdef GL_FRAGMENT_PRECISION_HIGHprecision highp float;#elseprecision mediump float;#endifin vec4 position;void main(void) {gl_Position = position;}`const fragmentSource = `#version 300 es/********** made by Matthias Hurrle (@atzedent) * * Adaptation of "Quasar" by @kishimisu * Source: https://www.shadertoy.com/view/msGyzc*/#ifdef GL_FRAGMENT_PRECISION_HIGHprecision highp float;#elseprecision mediump float;#endifout vec4 fragColor;uniform vec2 resolution;uniform float time;uniform vec2 touch;uniform int pointerCount;#define mouse (touch/resolution)#define P pointerCount#define T (10.+time*.5)#define S smoothstep#define hue(a) (.6+.6*cos(6.3*(a)+vec3(0,23,21)))mat2 rot(float a) {float c = cos(a), s = sin(a);return mat2(c, -s, s, c);}float orbit(vec2 p, float s) {return floor(atan(p.x, p.y)*s+.5)/s;}void cam(inout vec3 p) {if (P > 0) {p.yz *= rot(mouse.y*acos(-1.)+acos(.0));p.xz *= rot(-mouse.x*acos(-1.)*2.);}}void main(void) {vec2 uv = (gl_FragCoord.xy-.5*resolution)/min(resolution.x, resolution.y);vec3 col = vec3(0), p = vec3(0),rd = normalize(vec3(uv, 1));cam(p);cam(rd);const float steps = 30.;float dd = .0;for (float i=.0; i<steps; i++) {p.z  -= 4.;p.xz *= rot(T*.2);p.yz *= rot(sin(T*.2)*.5); p.zx *= rot(orbit(p.zx, 12.));float a = p.x;p.yx *= rot(orbit(p.yx, 2.));float b = p.x-T;p.x = fract(b-.5)-.5;float d = length(p)-(a-S(b+.05,b,T)*30.)*(cos(T)*5e-2+1e-1)*1e-1;dd += d;col += (hue(dd)*.04)/(1.+abs(d)*40.);p = rd * dd;}fragColor = vec4(col, 1);}`function compile(shader, source) {gl.shaderSource(shader, source)gl.compileShader(shader);if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {console.error(gl.getShaderInfoLog(shader))}
}let programfunction setup() {const vs = gl.createShader(gl.VERTEX_SHADER)const fs = gl.createShader(gl.FRAGMENT_SHADER)compile(vs, vertexSource)compile(fs, fragmentSource)program = gl.createProgram()gl.attachShader(program, vs)gl.attachShader(program, fs)gl.linkProgram(program)if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {console.error(gl.getProgramInfoLog(program))}
}let vertices, bufferfunction init() {vertices = [-1., -1., 1.,-1., -1., 1.,-1., 1., 1.,-1., 1., 1.,]buffer = gl.createBuffer()gl.bindBuffer(gl.ARRAY_BUFFER, buffer)gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW)const position = gl.getAttribLocation(program, "position")gl.enableVertexAttribArray(position)gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0)program.resolution = gl.getUniformLocation(program, "resolution")program.time = gl.getUniformLocation(program, "time")program.touch = gl.getUniformLocation(program, "touch")program.pointerCount = gl.getUniformLocation(program, "pointerCount")
}const mouse = {x: 0,y: 0,touches: new Set(),update: function(x, y, pointerId) {this.x = x * dpr;this.y = (innerHeight - y) * dpr;this.touches.add(pointerId)},remove: function(pointerId) { this.touches.delete(pointerId) }
}function loop(now) {gl.clearColor(0, 0, 0, 1)gl.clear(gl.COLOR_BUFFER_BIT)gl.useProgram(program)gl.bindBuffer(gl.ARRAY_BUFFER, buffer)gl.uniform2f(program.resolution, canvas.width, canvas.height)gl.uniform1f(program.time, now * 1e-3)gl.uniform2f(program.touch, mouse.x, mouse.y)gl.uniform1i(program.pointerCount, mouse.touches.size)gl.drawArrays(gl.TRIANGLES, 0, vertices.length * .5)requestAnimationFrame(loop)
}setup()
init()
resize()
loop(0)window.addEventListener("pointerdown", e => mouse.update(e.clientX, e.clientY, e.pointerId))
window.addEventListener("pointerup", e => mouse.remove(e.pointerId))
window.addEventListener("pointermove", e => {if (mouse.touches.has(e.pointerId))mouse.update(e.clientX, e.clientY, e.pointerId)
})

参见:

jQuery插件库-收集最全最新最好的jQuery插件

 

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

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

相关文章

UE4 C++获取Niagara变量值

UE4 获取Niagara变量值 Niagara有一堆Get方法&#xff0c;但是是基于数据的&#xff0c;单独的Set方法是有的&#xff0c;因此&#xff0c;我们这参考Set源码去Get 源代码如下&#xff1a; 我们的实现&#xff08;当然要返回其他类型值&#xff0c;修改一下对应传参就行了…

在线考试|基于Springboot的在线考试管理系统设计与实现(源码+数据库+文档)

在线考试管理系统目录 目录 基于Springboot的在线考试管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1、前台&#xff1a; 2、后台 管理员功能 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主…

[问题记录] oracle问题汇总记录

plsql问题 1、oracle-initialization error could not locate OCI.dll 下载plsql客户端后&#xff0c;登录显示如图所示的错误 解决方法&#xff0c;点击下方链接&#xff0c;下载64位客户端 Instant Client for Microsoft Windows (x64) 64-bit (oracle.com) 2、显示中文乱…

MongoDB 启动异常

Failed to start up WiredTiger under any compatibility version. 解决方案: 删除WiredTiger.lock 和 mongod.lock两个文件&#xff0c;在重新启动。回重新生成新的文件。

72小时内报告!美国发布关键基础设施网络攻击通报新规草案

美国网络安全和基础设施安全局(CISA)本周四发布了关键基础设施企业如何向政府报告网络攻击的规定草案。 新规基于拜登2022年3月15日签署的美国《关键基础设施网络事件报告法案》(简称CIRCIA)。这是美国联邦政府首次提出一套跨关键基础设施部门的全面网络安全规则。CISA正在就规…

的C++奇迹之旅:值和引用的本质效率与性能比较

文章目录 请添加图片描述 [TOC](文章目录) &#x1f4dd;引用# &#x1f320;引用概念**引用**不是新定义一个变量&#xff0c;而是给**已存在变量取了一个别名**&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。>定义&#…

软件杯 深度学习乳腺癌分类

文章目录 1 前言2 前言3 数据集3.1 良性样本3.2 病变样本 4 开发环境5 代码实现5.1 实现流程5.2 部分代码实现5.2.1 导入库5.2.2 图像加载5.2.3 标记5.2.4 分组5.2.5 构建模型训练 6 分析指标6.1 精度&#xff0c;召回率和F1度量6.2 混淆矩阵 7 结果和结论8 最后 1 前言 &…

07 - D触发器

---- 整理自B站UP主 踌躇月光 的视频 1. 电路实现 将 D 接到 S 端&#xff0c;D 取反接到 R 端&#xff0c;两个输入合成一个输入&#xff0c;R 和 S 总是相反的&#xff0c;就构成了 D 触发器。再添加一个EN&#xff0c;作为锁存功能&#xff0c;EN0 时&#xff0c;R 和 S 都…

Pygame基础10-物理模拟

PyMunk PyMunk是一个模拟物理的库。 注意&#xff0c;PyMunk只是进行物理模拟&#xff0c;不包含可视化的功能。如果需要可视化&#xff0c;可使用pygame等库。 可用pip安装pymunk pip install pymunk pymunk中的概念&#xff1a; space&#xff1a; 物理空间。 包含gravity 模…

Kubernetes(k8s):精通 Pod 操作的关键命令

Kubernetes&#xff08;k8s&#xff09;&#xff1a;精通 Pod 操作的关键命令 1、查看 Pod 列表2、 查看 Pod 的详细信息3、创建 Pod4、删除 Pod5、获取 Pod 日志6、进入 Pod 执行命令7、暂停和启动 Pod8、改变 Pod 副本数量9、查看当前部署中使用的镜像版本10、滚动更新 Pod11…

【网站项目】少儿编程管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

JVM专题——类文件加载

本文部分内容节选自Java Guide和《深入理解Java虚拟机》, Java Guide地址: https://javaguide.cn/java/jvm/class-loading-process.html &#x1f680; 基础&#xff08;上&#xff09; → &#x1f680; 基础&#xff08;中&#xff09; → &#x1f680;基础&#xff08;下&a…