matlab三角形旋转动态,新手向!用WebGL写一个旋转的动态三角形,总共分三步!!(注释超详细!!)...

html部分还是比较简单,引入的matrix.js是矩阵变换的一些方法,网上有很多,大家可以搜一搜(我的线性代数知识已经还给我的高数老师了,最近考虑着手捡起来)

demo

下面是demo.js的代码

第一步(准备画一个静态三角形):先把顶点着色器和片元着色器和context绑定

program代表一个程序(着色程序),这个程序可以绑定顶点着色器和片元着色器,从而将顶点着色器和片元着色器加载到当前canvas要执行的程序段里来

let canvas = document.getElementById('myCanvas');

let gl = canvas.getContext('webgl');

let program = gl.createProgram();

// 先定义两个源代码

let VSHADER_SOURCE, FSHADER_SOURCE;

// 先定义两个shader

let vertexShader, fragmentShader;

function createShader(gl, sourceCode, type) {

// 创建shader

let shader = gl.createShader(type);

// 给创建的shader挂载sourceCode

gl.sourceCode(shader, sourceCode);

// 编译shader

gl.compileShader(shader);

return shader;

}

// 定义vertexShader

vertexShader = createShader(gl, VSHADER_SOURCE, gl.VERTEX_SHADER);

// 定义fragmentShader

fragmentShader = createShader(gl, FSHADER_SOURCE, gl.FRAGMENT_SHADER);

// program和shader绑定

gl.attachShader(program, vertexShader);

gl.attachShader(program, fragmentShader);

// 给context绑定program(这里是一个,也可以定义多个shader挂载到多个program上)

gl.linkProgram(program);

gl.useProgram(program);

gl.program = program;

第二步(画出一个静态三角形):实现a_Position和对应的buffer绑定

const gl = document.getElementById('myCanvas').getContext('webgl');

const program = gl.createProgram();

// vec4 是一个四维向量,要render的顶点坐标

const VSHADER_SOURCE = `

attribute vec4 a_Position;

void main() {

gl_Position = a_Position;

}

`;

const FSHADER_SOURCE = `

void main() {

gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);

}

`;

function createShader(gl, sourceCode, type) {

// 创建shader

const shader = gl.createShader(type);

// 给创建的shader挂载sourceCode

gl.shaderSource(shader, sourceCode);

// 编译shader

gl.compileShader(shader);

return shader;

}

// 定义vertexShader

const vertexShader = createShader(gl, VSHADER_SOURCE, gl.VERTEX_SHADER);

// 定义fragmentShader

const fragmentShader = createShader(gl, FSHADER_SOURCE, gl.FRAGMENT_SHADER);

// program和shader绑定

gl.attachShader(program, vertexShader);

gl.attachShader(program, fragmentShader);

// 给context绑定program(这里是一个,也可以定义多个shader挂载到多个program上)

gl.linkProgram(program);

gl.useProgram(program);

gl.program = program;

// 实现a_Position和对应的buffer绑定,从而将三角形三个顶点坐标传递到 a_Position attribute vec4中

function initVertexBuffers(gl) {

// 3个顶点坐标,坐标没有z值,默认是0

const vertices = new Float32Array([

0, 0.5, -0.5, -0.5, 0.5, -0.5

]);

const n = 3;

// 创建buffer,利用buffer往vertexShader传递数据

const vertexBuffer = gl.createBuffer();

// 将vertexBuffer绑定到webgl上

// gl.ARRAY_BUFFER叫做顶点缓冲区,还有一种顶点索引缓冲区(存的是顶点的索引)

// 顶点缓冲区里有一些数据是重复的,比如同一个点在两个三角形或多个图形中都是顶点,多次重复出现,这种情况可以用索引来减少buffer的使用空间,对于相同的顶点坐标设为相同的顶点即可

gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);

// 将data灌入buffer

// gl.STATIC_DRAW第一次对缓冲区进行render后再也不会对缓冲区的顶点数据进行修改

gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

// 获取attribute a_position变量地址

const a_Position = gl.getAttribLocation(gl.program, 'a_Position');

// 将当前buffer绑定到vertex attribute上并且带有一些特定的规则

// 传入的2代表每两个数字为一个顶点坐标

gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

// 启用a_Position变量

gl.enableVertexAttribArray(a_Position);

return n;

}

// 顶点位置传到vertexShader

const n = initVertexBuffers(gl);

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

function draw() {

// 绘制,先清空画布,增加背景色

gl.clear(gl.COLOR_BUFFER_BIT);

// 以三角形的方式绘制,从buffer最开始的位置拿数据,拿n个(在上面 initVertexBuffers定义的)

gl.drawArrays(gl.TRIANGLES, 0, n);

}

draw();

bVbIZIr

第三步(画出动态三角形):让三角形动起来

/** @type {HTMLCanvasElement} */

const gl = document.getElementById('myCanvas').getContext('webgl');

const program = gl.createProgram();

// vec4 是一个四维向量,要render的顶点坐标

const VSHADER_SOURCE = `

attribute vec4 a_Position;

uniform mat4 u_ModelMatrix;

void main() {

gl_Position = u_ModelMatrix * a_Position;

}

`;

const FSHADER_SOURCE = `

void main() {

gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);

}

`;

function createShader(gl, sourceCode, type) {

// 创建shader

const shader = gl.createShader(type);

// 给创建的shader挂载sourceCode

gl.shaderSource(shader, sourceCode);

// 编译shader

gl.compileShader(shader);

return shader;

}

// 定义vertexShader

const vertexShader = createShader(gl, VSHADER_SOURCE, gl.VERTEX_SHADER);

// 定义fragmentShader

const fragmentShader = createShader(gl, FSHADER_SOURCE, gl.FRAGMENT_SHADER);

// program和shader绑定

gl.attachShader(program, vertexShader);

gl.attachShader(program, fragmentShader);

// 给context绑定program(这里是一个,也可以定义多个shader挂载到多个program上)

gl.linkProgram(program);

gl.useProgram(program);

gl.program = program;

let currentAngle = 0;

// 第一次初始值

let g_last = Date.now();

function tick() {

// 更新 新的旋转角度

animate();

// 绘制

draw();

// 常用绘制方法

requestAnimationFrame(tick);

}

// 实现a_Position和对应的buffer绑定,从而将三角形三个顶点坐标传递到 a_Position attribute vec4中

function initVertexBuffers(gl) {

// 3个顶点坐标,坐标没有z值,默认是0

const vertices = new Float32Array([

0, 0.5, -0.5, -0.5, 0.5, -0.5

]);

const n = 3;

// 创建buffer,利用buffer往vertexShader传递数据

const vertexBuffer = gl.createBuffer();

// 将vertexBuffer绑定到webgl上

// gl.ARRAY_BUFFER叫做顶点缓冲区,还有一种顶点索引缓冲区(存的是顶点的索引)

// 顶点缓冲区里有一些数据是重复的,比如同一个点在两个三角形或多个图形中都是顶点,多次重复出现,这种情况可以用索引来减少buffer的使用空间,对于相同的顶点坐标设为相同的顶点即可

gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);

// 将data灌入buffer

// gl.STATIC_DRAW第一次对缓冲区进行render后再也不会对缓冲区的顶点数据进行修改

gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

// 获取attribute a_position变量地址

const a_Position = gl.getAttribLocation(gl.program, 'a_Position');

// 将当前buffer绑定到vertex attribute上并且带有一些特定的规则

// 传入的2代表每两个数字为一个顶点坐标

gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

// 启用a_Position变量

gl.enableVertexAttribArray(a_Position);

return n;

}

// 顶点位置传到vertexShader

const n = initVertexBuffers(gl);

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

// 拿到gl.program里面的u_ModelMatrix(在VSHADER_SOURCE中定义的那个)

const u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');

// Matrix4比较好的封装了一些矩阵变换的操作

const modelMatrix = new Matrix4();

function animate() {

// 记下时间,拿到现在的时间戳,因为每次requestAnimationFrame间隔时间是不知道的

const now = Date.now();

// 减去老的时间戳

const duration = now - g_last;

g_last = now;

// 想要requestAnimationFrame间隔时间内转180度

currentAngle = currentAngle + duration / 1000 * 180;

}

// webgl视角是沿着z轴负方向,望向圆点的,想让三角形在3D的世界里转起来,是需要z轴的

function draw() {

// 绕y轴旋转currentAngle度

modelMatrix.setRotate(currentAngle, 0, 1, 0);

// 往uniform里传matrix的api

gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);

// 绘制,先清空画布,增加背景色

gl.clear(gl.COLOR_BUFFER_BIT);

// 以三角形的方式绘制,从buffer最开始的位置拿数据,拿n个(在上面initVertexBuffers定义的)

gl.drawArrays(gl.TRIANGLES, 0, n);

}

tick();

bVbIZU7

我在vscode上没有发现webgl的语法提示,就用了 @type {HTMLCanvasElement} 这句来做语法提示,大家有啥好用的插件推荐吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值