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
    评论
好的,以下是一个简单的webglRenderer对象的代码示例: ``` class webglRenderer { constructor(canvas) { this.canvas = canvas; this.gl = canvas.getContext("webgl"); if (!this.gl) { console.error("WebGL not supported"); return; } this.program = this.createProgram(); } createProgram() { const vertexShaderSource = ` attribute vec3 aPosition; void main() { gl_Position = vec4(aPosition, 1.0); } `; const fragmentShaderSource = ` precision mediump float; void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } `; const vertexShader = this.createShader( this.gl.VERTEX_SHADER, vertexShaderSource ); const fragmentShader = this.createShader( this.gl.FRAGMENT_SHADER, fragmentShaderSource ); const program = this.gl.createProgram(); this.gl.attachShader(program, vertexShader); this.gl.attachShader(program, fragmentShader); this.gl.linkProgram(program); if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) { console.error("Program link error:", this.gl.getProgramInfoLog(program)); } return program; } createShader(type, source) { const shader = this.gl.createShader(type); this.gl.shaderSource(shader, source); this.gl.compileShader(shader); if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) { console.error("Shader compile error:", this.gl.getShaderInfoLog(shader)); } return shader; } render() { this.gl.clearColor(0.0, 0.0, 0.0, 1.0); this.gl.clear(this.gl.COLOR_BUFFER_BIT); const positionAttributeLocation = this.gl.getAttribLocation( this.program, "aPosition" ); const positionBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, positionBuffer); const positions = [-0.5, -0.5, 0.0, 0.5, -0.5, 0.0, 0.0, 0.5, 0.0]; this.gl.bufferData( this.gl.ARRAY_BUFFER, new Float32Array(positions), this.gl.STATIC_DRAW ); this.gl.enableVertexAttribArray(positionAttributeLocation); this.gl.vertexAttribPointer( positionAttributeLocation, 3, this.gl.FLOAT, false, 0, 0 ); this.gl.useProgram(this.program); this.gl.drawArrays(this.gl.TRIANGLES, 0, 3); } } ``` 这个webglRenderer对象包含一个构造函数,它接受一个canvas元素作为参数,并创建了一个webgl上下文。它还包含了一个createProgram方法,用于创建着色器程序,并且包含了一个render方法,用于绘制图形。 在createProgram方法中,我们创建了一个简单的顶点着色器和片段着色器,并将它们连接为一个着色器程序。在render方法中,我们使用gl.drawArrays来绘制一个简单的三角形。 我们可以像这样使用webglRenderer对象来绘制图形: ``` const canvas = document.querySelector("canvas"); const renderer = new webglRenderer(canvas); renderer.render(); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值