2024年全网最新最详细《WebGL教程》
2024年全网最新最详细《WebGL教程》
https://www.bilibili.com/video/BV1AS411A74T/
1 2
02-canvas的基础知识
https://bx2eq6ulg18.feishu.cn/docx/I4hTdO95qozPBOxauPlcbDfInVd
2.1 获取渲染上下文
HTMLCanvasElement.getContext()方法用于返回绘图上下文对象,绘图上下文对象是2D上下文还是3D上下文取决于传入的参数。
getContext('2d'):创建一个CanvasRenderingContext2D 二维的渲染上下文对象getContext('webgl'):创建一个 WebGLRenderingContext 三维的渲染上下文对象
css图片会拉伸 标签属性width不会
03-了解类型化数组
作用:常用在处理图像数据、音频数据、视频数据这些方向。对应的API有:WebGL、Canvas API、WebRTC、File
04-着色器基础语法
GLSL(OpenGL Shading Language)是一种用于编写图形着色器的编程语言。着色器是用于在图形处理单元
(GPU)上执行特定图形处理任务的程序。通俗讲,着色器是画点的工具,一个图形是由无数个点组成的,每个点都有其自己的颜色。
变量修饰符:
用于指定变量的作用域、生命周期和用途。不同的修饰符在顶点着色器和片段着色器中起到不同的作用。
attribute:用于顶点着色器,定义从顶点缓冲区传入的变量(仅在顶点着色器中使用)。
uniform:定义在整个渲染过程中保持不变的变量,常用于传递变换矩阵、光照参数等。
varying:用于在顶点着色器和片段着色器之间传递插值数据。
内罟变量:
05-webGL接口api
06-第一个WebGL程序
另类script 需要加;才行
<!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 class="canvas" width="500" height="500"></canvas>
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
void main(){
gl_PointSize=10.0;
gl_Position=vec4(0.0,0.0,0.0,1.0);
}
</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 vertexSource=`
// void main(){
// gl_PointSize=10.0;
// gl_Position=vec4(0.0,0.0,0.0,1.0)
// }
// `
const canvas=document.querySelector('.canvas')
const gl=canvas.getContext("webgl")
//创建顶点着色器和片元着色器
const vertexShader=gl.createShader(gl.VERTEX_SHADER)
const fragmentShader=gl.createShader(gl.FRAGMENT_SHADER)
//获取着色器源码
const vertexSource=document.getElementById('vertex-shader').innerText
const fragmentSource=document.getElementById('fragment-shader').innerText
//绑定着色器源码
gl.shaderSource(vertexShader, vertexSource)
gl.shaderSource(fragmentShader, fragmentSource)
//编译着色器源码
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
//创建程序对象
const program=gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program);
gl.drawArrays(gl.POINTS, 0, 1);
</script>
</body>
</html>
07-attribute动态传递点数据
<!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 class="canvas" width="500" height="500"></canvas>
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec2 aPos;
attribute vec2 aPos1;
void main(){
gl_PointSize=10.0;
vec2 newPos=aPos+aPos1;
gl_Position=vec4(newPos,0.0,1.0);
}
</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 vertexSource=`
// void main(){
// gl_PointSize=10.0;
// gl_Position=vec4(0.0,0.0,0.0,1.0)
// }
// `
const canvas=document.querySelector('.canvas')
const gl=canvas.getContext("webgl")
//创建顶点着色器和片元着色器
const vertexShader=gl.createShader(gl.VERTEX_SHADER)
const fragmentShader=gl.createShader(gl.FRAGMENT_SHADER)
//获取着色器源码
const vertexSource=document.getElementById('vertex-shader').innerText
const fragmentSource=document.getElementById('fragment-shader').innerText
//绑定着色器源码
gl.shaderSource(vertexShader, vertexSource)
gl.shaderSource(fragmentShader, fragmentSource)
//编译着色器源码
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
//创建程序对象
const program=gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program);
//动态传数据 坐标
const posLocation=gl.getAttribLocation(program, 'aPos')
const posLocation1=gl.getAttribLocation(program, 'aPos1')
const offset=[0.5,0.5]
const offset1=[-0.1,-0.2]
gl.vertexAttrib2f(posLocation,...offset)
gl.vertexAttrib2f(posLocation1,...offset1)
gl.drawArrays(gl.POINTS, 0, 1);
</script>
</body>
</html>
08-使用缓冲区数据绘制线段
<!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 class="canvas" width="500" height="500"></canvas>
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec2 aPosition;
void main(){
gl_Position=vec4(aPosition,0.0,1.0);
}
</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.querySelector('.canvas')
const gl=canvas.getContext("webgl")
//创建顶点着色器和片元着色器
const vertexShader=gl.createShader(gl.VERTEX_SHADER)
const fragmentShader=gl.createShader(gl.FRAGMENT_SHADER)
//获取着色器源码
const vertexSource=document.getElementById('vertex-shader').innerText
const fragmentSource=document.getElementById('fragment-shader').innerText
//绑定着色器源码
gl.shaderSource(vertexShader, vertexSource)
gl.shaderSource(fragmentShader, fragmentSource)
//编译着色器源码
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
//创建程序对象
const program=gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program);
const vertices=new Float32Array([
-0.5,-0.5, //第一个点的x轴和y轴坐标
0.5,0.5, //第二个点的xy轴坐标
])
const buffer=gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
const posLocation=gl.getAttribLocation(program, 'aPosition')
gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false, 2*Float32Array.BYTES_PER_ELEMENT, 0)
gl.enableVertexAttribArray(posLocation)
gl.drawArrays(gl.LINES, 0, 2);
</script>
</body>
</html>
09-varying实现彩色线段
<!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 class="canvas" width="500" height="500"></canvas>
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec2 aPosition;
attribute vec4 aColor;
varying vec4 vColor;
void main(){
gl_Position=vec4(aPosition,0.0,1.0);
vColor=aColor;
}
</script>
<!-- 片段着色器 -->
<script id="fragment-shader" type="x-shader/x-fragment">
precision highp float;
varying vec4 vColor;
void main(){
gl_FragColor=vColor;
}
</script>
<script>
const canvas=document.querySelector('.canvas')
const gl=canvas.getContext("webgl")
//创建顶点着色器和片元着色器
const vertexShader=gl.createShader(gl.VERTEX_SHADER)
const fragmentShader=gl.createShader(gl.FRAGMENT_SHADER)
//获取着色器源码
const vertexSource=document.getElementById('vertex-shader').innerText
const fragmentSource=document.getElementById('fragment-shader').innerText
//绑定着色器源码
gl.shaderSource(vertexShader, vertexSource)
gl.shaderSource(fragmentShader, fragmentSource)
//编译着色器源码
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
//创建程序对象
const program=gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program);
const vertices=new Float32Array([
-0.5,-0.5, //第一个点的x轴和y轴坐标
0.5,0.5, //第二个点的xy轴坐标
])
const colors=new Float32Array([
0.0,0.0,0.0,1.0,
1.0,0.0,0.0,0.0,
])
const buffer=gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
const posLocation=gl.getAttribLocation(program, 'aPosition')
gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false, 2*Float32Array.BYTES_PER_ELEMENT, 0)
gl.enableVertexAttribArray(posLocation)
const colorBuffer=gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)
gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW)
const colorLocation=gl.getAttribLocation(program, 'aColor')
gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 2*Float32Array.BYTES_PER_ELEMENT, 0)
gl.enableVertexAttribArray(colorLocation)
gl.drawArrays(gl.LINES, 0, 2);
</script>
</body>
</html>
10-如何使用单个buffer解析数据
<!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 class="canvas" width="500" height="500"></canvas>
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec2 aPosition;
attribute vec4 aColor;
varying vec4 vColor;
void main(){
gl_Position=vec4(aPosition,0.0,1.0);
vColor=aColor;
}
</script>
<!-- 片段着色器 -->
<script id="fragment-shader" type="x-shader/x-fragment">
precision highp float;
varying vec4 vColor;
void main(){
gl_FragColor=vColor;
}
</script>
<script>
const canvas=document.querySelector('.canvas')
const gl=canvas.getContext("webgl")
//创建顶点着色器和片元着色器
const vertexShader=gl.createShader(gl.VERTEX_SHADER)
const fragmentShader=gl.createShader(gl.FRAGMENT_SHADER)
//获取着色器源码
const vertexSource=document.getElementById('vertex-shader').innerText
const fragmentSource=document.getElementById('fragment-shader').innerText
//绑定着色器源码
gl.shaderSource(vertexShader, vertexSource)
gl.shaderSource(fragmentShader, fragmentSource)
//编译着色器源码
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
//创建程序对象
const program=gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program);
const vertices=new Float32Array([
-0.5,-0.5, 0.0,0.0,0.0,1.0, //第一个点的x轴和y轴坐标
0.5,0.5, 1.0,0.0,0.0,0.0, //第二个点的xy轴坐标
])
// const colors=new Float32Array([
// 0.0,0.0,0.0,1.0,
// 1.0,0.0,0.0,0.0,
// ])
const buffer=gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
const posLocation=gl.getAttribLocation(program, 'aPosition')
gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false, 6*Float32Array.BYTES_PER_ELEMENT, 0)
gl.enableVertexAttribArray(posLocation)
// const colorBuffer=gl.createBuffer()
// gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)
// gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW)
const colorLocation=gl.getAttribLocation(program, 'aColor')
gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 6*Float32Array.BYTES_PER_ELEMENT, 2*Float32Array.BYTES_PER_ELEMENT)
gl.enableVertexAttribArray(colorLocation)
gl.drawArrays(gl.LINES, 0, 2);
</script>
</body>
</html>
11-绘制三角形案例
<!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 class="canvas" width="500" height="500"></canvas>
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec2 aPosition;
attribute vec4 aColor;
varying vec4 vColor;
void main(){
gl_Position=vec4(aPosition,0.0,1.0);
vColor=aColor;
}
</script>
<!-- 片段着色器 -->
<script id="fragment-shader" type="x-shader/x-fragment">
precision highp float;
varying vec4 vColor;
void main(){
gl_FragColor=vColor;
}
</script>
<script>
const canvas=document.querySelector('.canvas')
const gl=canvas.getContext("webgl")
//创建顶点着色器和片元着色器
const vertexShader=gl.createShader(gl.VERTEX_SHADER)
const fragmentShader=gl.createShader(gl.FRAGMENT_SHADER)
//获取着色器源码
const vertexSource=document.getElementById('vertex-shader').innerText
const fragmentSource=document.getElementById('fragment-shader').innerText
//绑定着色器源码
gl.shaderSource(vertexShader, vertexSource)
gl.shaderSource(fragmentShader, fragmentSource)
//编译着色器源码
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
//创建程序对象
const program=gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program);
const vertices=new Float32Array([
-0.5,-0.5, 0.0,0.0,0.0,1.0, //第一个点的x轴和y轴坐标 前2坐标 后4颜色
0.5,-0.5, 1.0,0.0,0.0,0.0, //第二个点的xy轴坐标
0.0,0.5, 0.0,0.0,1.0,0.0, //3 point
])
// const colors=new Float32Array([
// 0.0,0.0,0.0,1.0,
// 1.0,0.0,0.0,0.0,
// ])
const buffer=gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
const posLocation=gl.getAttribLocation(program, 'aPosition')
gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false, 6*Float32Array.BYTES_PER_ELEMENT, 0)
gl.enableVertexAttribArray(posLocation)
// const colorBuffer=gl.createBuffer()
// gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)
// gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW)
const colorLocation=gl.getAttribLocation(program, 'aColor')
gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 6*Float32Array.BYTES_PER_ELEMENT, 2*Float32Array.BYTES_PER_ELEMENT)
gl.enableVertexAttribArray(colorLocation)
gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>
</body>
</html>
12-图元绘制类型详解
<!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 class="canvas" width="500" height="500"></canvas>
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec2 aPosition;
attribute vec4 aColor;
varying vec4 vColor;
void main(){
gl_Position=vec4(aPosition,0.0,1.0);
gl_PointSize=10.0;
vColor=aColor;
}
</script>
<!-- 片段着色器 -->
<script id="fragment-shader" type="x-shader/x-fragment">
precision highp float;
varying vec4 vColor;
void main(){
gl_FragColor=vColor;
}
</script>
<script>
const canvas=document.querySelector('.canvas')
const gl=canvas.getContext("webgl")
//创建顶点着色器和片元着色器
const vertexShader=gl.createShader(gl.VERTEX_SHADER)
const fragmentShader=gl.createShader(gl.FRAGMENT_SHADER)
//获取着色器源码
const vertexSource=document.getElementById('vertex-shader').innerText
const fragmentSource=document.getElementById('fragment-shader').innerText
//绑定着色器源码
gl.shaderSource(vertexShader, vertexSource)
gl.shaderSource(fragmentShader, fragmentSource)
//编译着色器源码
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
//创建程序对象
const program=gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program);
const vertices=new Float32Array([
-1.0,1.0, 0.0,0.0,0.0,1.0, //第一个点的x轴和y轴坐标 前2坐标 后4颜色
-0.5,-1.0, 1.0,0.0,0.0,0.0, //第二个点的xy轴坐标
-0.5,1.0, 0.0,0.0,1.0,0.0, //3 point
0.0,-1.0, 0.0,0.0,1.0,0.0, //3 point
0.0,1.0, 0.0,0.0,1.0,0.0, //3 point
0.5,-1.0, 0.0,0.0,1.0,0.0, //3 point
])
// const colors=new Float32Array([
// 0.0,0.0,0.0,1.0,
// 1.0,0.0,0.0,0.0,
// ])
const buffer=gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
const posLocation=gl.getAttribLocation(program, 'aPosition')
gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false, 6*Float32Array.BYTES_PER_ELEMENT, 0)
gl.enableVertexAttribArray(posLocation)
// const colorBuffer=gl.createBuffer()
// gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)
// gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW)
const colorLocation=gl.getAttribLocation(program, 'aColor')
gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 6*Float32Array.BYTES_PER_ELEMENT, 2*Float32Array.BYTES_PER_ELEMENT)
gl.enableVertexAttribArray(colorLocation)
gl.drawArrays(gl.POINTS, 0, 6);
gl.drawArrays(gl.LINE_LOOP, 0, 6);
gl.drawArrays(gl.TRIANGLES, 0, 6);
</script>
</body>
</html>
13-uniform传递矩阵变换数据
<!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 class="canvas" width="500" height="500"></canvas>
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec2 aPosition;
uniform vec2 uTranslate;
void main(){
vec2 newPos=uTranslate+aPosition;
gl_Position=vec4(newPos,0.0,1.0);
gl_PointSize=10.0;
}
</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.querySelector('.canvas')
const gl=canvas.getContext("webgl")
//创建顶点着色器和片元着色器
const vertexShader=gl.createShader(gl.VERTEX_SHADER)
const fragmentShader=gl.createShader(gl.FRAGMENT_SHADER)
//获取着色器源码
const vertexSource=document.getElementById('vertex-shader').innerText
const fragmentSource=document.getElementById('fragment-shader').innerText
//绑定着色器源码
gl.shaderSource(vertexShader, vertexSource)
gl.shaderSource(fragmentShader, fragmentSource)
//编译着色器源码
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
//创建程序对象
const program=gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program);
const vertices=new Float32Array([
-0.5,0.5,
-0.5,-0.5,
0.5,-0.5,
0.5,0.5,
])
const buffer=gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
const posLocation=gl.getAttribLocation(program, 'aPosition')
gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false, 2*Float32Array.BYTES_PER_ELEMENT, 0)
gl.enableVertexAttribArray(posLocation)
const translationLocation=gl.getUniformLocation(program,'uTranslate')
const translation=[0.2,0.2]
gl.uniform2fv(translationLocation,translation)
gl.drawArrays(gl.POINTS, 0, 4);
gl.drawArrays(gl.LINE_LOOP, 0, 4);
</script>
</body>
</html>
14-推导旋转矩阵
scale *
一行 矩阵 行向量
三角形 cos sin tan 等知识换算
<!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 class="canvas" width="500" height="500"></canvas>
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec2 aPosition;
void main(){
float radian=radians(45.0);
float sin=sin(radian);
float cos=cos(radian);
mat4 roatate=mat4(
cos,-sin,0,0,
sin,cos,0,0,
0,0,1,0,
0,0,0,1
);
gl_Position=roatate * vec4(aPosition,0.0,1.0);
gl_PointSize=10.0;
}
</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.querySelector('.canvas')
const gl=canvas.getContext("webgl")
//创建顶点着色器和片元着色器
const vertexShader=gl.createShader(gl.VERTEX_SHADER)
const fragmentShader=gl.createShader(gl.FRAGMENT_SHADER)
//获取着色器源码
const vertexSource=document.getElementById('vertex-shader').innerText
const fragmentSource=document.getElementById('fragment-shader').innerText
//绑定着色器源码
gl.shaderSource(vertexShader, vertexSource)
gl.shaderSource(fragmentShader, fragmentSource)
//编译着色器源码
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
//创建程序对象
const program=gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program);
const vertices=new Float32Array([
-0.5,0.5,
-0.5,-0.5,
0.5,-0.5,
0.5,0.5,
])
const buffer=gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
const posLocation=gl.getAttribLocation(program, 'aPosition')
gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false, 2*Float32Array.BYTES_PER_ELEMENT, 0)
gl.enableVertexAttribArray(posLocation)
gl.drawArrays(gl.POINTS, 0, 4);
gl.drawArrays(gl.LINE_LOOP, 0, 4);
</script>
</body>
</html>
15-绘制线框立方体
也有旋转公式
<!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 class="canvas" width="500" height="500"></canvas>
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 aPosition;
void main(){
float radian=radians(10.0);
float sin=sin(radian);
float cos=cos(radian);
mat4 mx=mat4(
1,0,0,0,
0,cos,-sin,0,
0,sin,cos,0,
0,0,0,1
);
mat4 my=mat4(
cos,0,-sin,0,
0,1,0,0,
sin,0,cos,0,
0,0,0,1
);
gl_Position= mx * my * aPosition;
gl_PointSize=10.0;
}
</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.querySelector('.canvas')
const gl=canvas.getContext("webgl")
//创建顶点着色器和片元着色器
const vertexShader=gl.createShader(gl.VERTEX_SHADER)
const fragmentShader=gl.createShader(gl.FRAGMENT_SHADER)
//获取着色器源码
const vertexSource=document.getElementById('vertex-shader').innerText
const fragmentSource=document.getElementById('fragment-shader').innerText
//绑定着色器源码
gl.shaderSource(vertexShader, vertexSource)
gl.shaderSource(fragmentShader, fragmentSource)
//编译着色器源码
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
//创建程序对象
const program=gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program);
const vertices=new Float32Array([
0.5,0.5,0.5,
-0.5,0.5,0.5,
-0.5,-0.5,0.5,
0.5,-0.5,0.5,
0.5,0.5,-0.5,
-0.5,0.5,-0.5,
-0.5,-0.5,-0.5,
0.5,-0.5,-0.5,
0.5,0.5,0.5,
0.5,0.5,-0.5,
-0.5,0.5,0.5,
-0.5,0.5,-0.5,
-0.5,-0.5,0.5,
-0.5,-0.5,-0.5,
0.5,-0.5,0.5,
0.5,-0.5,-0.5,
])
const buffer=gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
const posLocation=gl.getAttribLocation(program, 'aPosition')
gl.vertexAttribPointer(posLocation, 3, gl.FLOAT, false, 3*Float32Array.BYTES_PER_ELEMENT, 0)
gl.enableVertexAttribArray(posLocation)
gl.drawArrays(gl.POINTS, 0, 4);
gl.drawArrays(gl.LINE_LOOP, 0, 4);
gl.drawArrays(gl.POINTS, 4, 4);
gl.drawArrays(gl.LINE_LOOP, 4, 4);
gl.drawArrays(gl.LINES, 8, 8);
</script>
</body>
</html>
16-顶点索引绘制立方体
<!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 class="canvas" width="500" height="500"></canvas>
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 aPosition;
void main(){
float radian=radians(10.0);
float sin=sin(radian);
float cos=cos(radian);
mat4 mx=mat4(
1,0,0,0,
0,cos,-sin,0,
0,sin,cos,0,
0,0,0,1
);
mat4 my=mat4(
cos,0,-sin,0,
0,1,0,0,
sin,0,cos,0,
0,0,0,1
);
gl_Position= mx * my * aPosition;
gl_PointSize=10.0;
}
</script>
<!-- 片段着色器 -->
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 uColor;
void main(){
gl_FragColor=uColor;
}
</script>
<script>
const canvas=document.querySelector('.canvas')
const gl=canvas.getContext("webgl")
//创建顶点着色器和片元着色器
const vertexShader=gl.createShader(gl.VERTEX_SHADER)
const fragmentShader=gl.createShader(gl.FRAGMENT_SHADER)
//获取着色器源码
const vertexSource=document.getElementById('vertex-shader').innerText
const fragmentSource=document.getElementById('fragment-shader').innerText
//绑定着色器源码
gl.shaderSource(vertexShader, vertexSource)
gl.shaderSource(fragmentShader, fragmentSource)
//编译着色器源码
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
//创建程序对象
const program=gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program);
const vertices=new Float32Array([
//前面
-0.5,-0.5,0.5,
0.5,-0.5,0.5,
0.5,0.5,0.5,
-0.5,0.5,0.5,
//后面
-0.5,-0.5,-0.5,
-0.5,0.5,-0.5,
0.5,0.5,-0.5,
0.5,-0.5,-0.5,
//上面
-0.5,0.5,-0.5,
-0.5,0.5,0.5,
0.5,0.5,0.5,
0.5,0.5,-0.5,
//下面
-0.5,-0.5,-0.5,
0.5,-0.5,-0.5,
0.5,-0.5,0.5,
-0.5,-0.5,0.5,
//右边
0.5,-0.5,-0.5,
0.5,0.5,-0.5,
0.5,0.5,0.5,
0.5,-0.5,0.5,
//左边
-0.5,-0.5,-0.5,
-0.5,-0.5,0.5,
-0.5,0.5,0.5,
-0.5,0.5,-0.5,
])
const buffer=gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
const indices=new Uint16Array([
0,1,2, 0,2,3,
4,5,6, 4,6,7,
8,9,10, 8,10,11,
12,13,14, 12,14,15,
16,17,18, 16,18,19,
20,21,22, 20,22,23
])
const indexBuffer=gl.createBuffer()
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW)
const posLocation=gl.getAttribLocation(program, 'aPosition')
gl.vertexAttribPointer(posLocation, 3, gl.FLOAT, false, 3*Float32Array.BYTES_PER_ELEMENT, 0)
gl.enableVertexAttribArray(posLocation)
// gl.drawElements(gl.TRIANGLES,indices.length,gl.UNSIGNED_SHORT,0)
const faceColors=[
[1.0,0.0,0.0,1.0],//前面
[0.0,1.0,0.0,1.0],
[1.0,0.0,1.0,1.0],
[0.0,0.0,0.0,1.0],
[1.0,0.0,1.0,1.0],
[1.0,0.0,0.0,1.0],
];
const colorLocation=gl.getUniformLocation(program,'uColor')
for(let i=0;i<6;i++){
gl.uniform4fv(colorLocation,faceColors[i])
gl.drawElements(gl.TRIANGLES,6,gl.UNSIGNED_SHORT,i*6*Uint16Array.BYTES_PER_ELEMENT)
}
</script>
</body>
</html>
17-实现webgl动画
requestAnimationFrmae(callback)
每秒钟60次
20 = 360
Π = 180
弧度 = 角度*(n/180)
<!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 class="canvas" width="500" height="500"></canvas>
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 aPosition;
uniform mat4 u_x_matrix;
uniform mat4 u_y_matrix;
void main(){
gl_Position= u_x_matrix * u_y_matrix * aPosition;
gl_PointSize=10.0;
}
</script>
<!-- 片段着色器 -->
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 uColor;
void main(){
gl_FragColor=uColor;
}
</script>
<script>
const canvas=document.querySelector('.canvas')
const gl=canvas.getContext("webgl")
//创建顶点着色器和片元着色器
const vertexShader=gl.createShader(gl.VERTEX_SHADER)
const fragmentShader=gl.createShader(gl.FRAGMENT_SHADER)
//获取着色器源码
const vertexSource=document.getElementById('vertex-shader').innerText
const fragmentSource=document.getElementById('fragment-shader').innerText
//绑定着色器源码
gl.shaderSource(vertexShader, vertexSource)
gl.shaderSource(fragmentShader, fragmentSource)
//编译着色器源码
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
//创建程序对象
const program=gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program);
const vertices=new Float32Array([
//前面
-0.5,-0.5,0.5,
0.5,-0.5,0.5,
0.5,0.5,0.5,
-0.5,0.5,0.5,
//后面
-0.5,-0.5,-0.5,
-0.5,0.5,-0.5,
0.5,0.5,-0.5,
0.5,-0.5,-0.5,
//上面
-0.5,0.5,-0.5,
-0.5,0.5,0.5,
0.5,0.5,0.5,
0.5,0.5,-0.5,
//下面
-0.5,-0.5,-0.5,
0.5,-0.5,-0.5,
0.5,-0.5,0.5,
-0.5,-0.5,0.5,
//右边
0.5,-0.5,-0.5,
0.5,0.5,-0.5,
0.5,0.5,0.5,
0.5,-0.5,0.5,
//左边
-0.5,-0.5,-0.5,
-0.5,-0.5,0.5,
-0.5,0.5,0.5,
-0.5,0.5,-0.5,
])
const buffer=gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
const indices=new Uint16Array([
0,1,2, 0,2,3,
4,5,6, 4,6,7,
8,9,10, 8,10,11,
12,13,14, 12,14,15,
16,17,18, 16,18,19,
20,21,22, 20,22,23
])
const indexBuffer=gl.createBuffer()
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW)
const posLocation=gl.getAttribLocation(program, 'aPosition')
gl.vertexAttribPointer(posLocation, 3, gl.FLOAT, false, 3*Float32Array.BYTES_PER_ELEMENT, 0)
gl.enableVertexAttribArray(posLocation)
// gl.drawElements(gl.TRIANGLES,indices.length,gl.UNSIGNED_SHORT,0)
const faceColors=[
[1.0,0.0,1.0,1.0],//前面
[0.0,1.0,0.0,1.0],
[1.0,0.0,1.0,1.0],
[0.0,1.0,1.0,1.0],
[1.0,0.0,1.0,1.0],
[1.0,1.0,0.0,1.0],
];
const colorLocation=gl.getUniformLocation(program,'uColor')
gl.enable(gl.DEPTH_TEST)
const u_x_matrix=gl.getUniformLocation(program,'u_x_matrix')
const u_y_matrix=gl.getUniformLocation(program,'u_y_matrix')
let deg=30
function render(){
deg+=0.1
const cosB=Math.cos(deg*Math.PI/180)
const sinB=Math.sin(deg*Math.PI/180)
gl.uniformMatrix4fv(u_x_matrix,false,new Float32Array([
1,0,0,0,
0,cosB,-sinB,0,
0,sinB,cosB,0,
0,0,0,1
]))
gl.uniformMatrix4fv(u_y_matrix,false,new Float32Array([
cosB,0,-sinB,0,
0,1,0,0,
sinB,0,cosB,0,
0,0,0,1
]))
for(let i=0;i<6;i++){
gl.uniform4fv(colorLocation,faceColors[i])
gl.drawElements(gl.TRIANGLES,6,gl.UNSIGNED_SHORT,i*6*Uint16Array.BYTES_PER_ELEMENT)
}
window.requestAnimationFrame(render)
}
window.requestAnimationFrame(render)
</script>
</body>
</html>
18-glmatrix矩阵库的使用
gl-matrix矩阵库
glmatrix.net/docs/
<!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 class="canvas" width="500" height="500"></canvas>
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 aPosition;
unifrom mat4 mTranslate;
void main(){
gl_Position=mTranslate*aPosition;
}
</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 type="module">
import {mat4} from 'gl-matrix';
const canvas=document.querySelector('.canvas')
const gl=canvas.getContext("webgl")
//创建顶点着色器和片元着色器
const vertexShader=gl.createShader(gl.VERTEX_SHADER)
const fragmentShader=gl.createShader(gl.FRAGMENT_SHADER)
//获取着色器源码
const vertexSource=document.getElementById('vertex-shader').innerText
const fragmentSource=document.getElementById('fragment-shader').innerText
//绑定着色器源码
gl.shaderSource(vertexShader, vertexSource)
gl.shaderSource(fragmentShader, fragmentSource)
//编译着色器源码
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
//创建程序对象
const program=gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program);
const vertices=new Float32Array([
-0.5,-0.5,0.5, //第一个点的x轴和y轴坐标
-0.5,0,0.5 //第二个点的xy轴坐标
])
const buffer=gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
const posLocation=gl.getAttribLocation(program, 'aPosition')
gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false, 2*Float32Array.BYTES_PER_ELEMENT, 0)
gl.enableVertexAttribArray(posLocation)
const uniformTranslate=gl.getUniformLocation(program,'mTranslate')
const matrix=mat4.create()
mat4.translate(matrix,matrix,[0.5,0.5,0])
gl.uniformMatrix4fv(uniformTranslate,false,matrix)
gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>
</body>
</html>
19-矩阵方法的使用
<!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 class="canvas" width="500" height="500"></canvas>
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 aPosition;
uniform mat4 mTranslate;
void main(){
gl_Position=mTranslate * aPosition;
}
</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 type="module">
import { mat4 } from "gl-matrix";
const canvas = document.querySelector(".canvas");
const gl = canvas.getContext("webgl");
//创建顶点着色器和片元着色器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
//获取着色器源码
const vertexSource = document.getElementById("vertex-shader").innerText;
const fragmentSource =
document.getElementById("fragment-shader").innerText;
//绑定着色器源码
gl.shaderSource(vertexShader, vertexSource);
gl.shaderSource(fragmentShader, fragmentSource);
//编译着色器源码
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
//创建程序对象
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
const vertices = new Float32Array([
-0.5,
-0.5,
0.5, //第一个点的x轴和y轴坐标
-0.5,
0.0,
0.5, //第二个点的xy轴坐标
]);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
const posLocation = gl.getAttribLocation(program, "aPosition");
gl.vertexAttribPointer(
posLocation,
2,
gl.FLOAT,
false,
2 * Float32Array.BYTES_PER_ELEMENT,
0
);
gl.enableVertexAttribArray(posLocation);
const uniformTranslate = gl.getUniformLocation(program, "mTranslate");
const matrix = mat4.create();
// mat4.translate(matrix, matrix, [0.5, 0.5, 0]);
mat4.scale(matrix, matrix, [0.5, 0.5, 0]);
gl.uniformMatrix4fv(uniformTranslate, false, matrix);
gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>
</body>
</html>
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)