<span style="color:red">这系列教程将使用VUE架构哦</span><span style="color: gray">不用其实也可以的啦(>д<)</span>
诶,小猫猫们,有没有试图使用js调用gpu的经历呀:D,没关系呢,不管有没有这次我将教大家如何用原生js调用gpu呢φ(゜▽゜*)♪ 好的接下来让我们开始吧!
step 1
首先创建一个canvas画布,不要忘记加ref哦:D,不想要画面被压缩的猫猫可以加上width 以及height 来限制哦
//script中 const canvas = ref(null)
<!--template中--> <canvas ref="canvas" width="150" height="150"></canvas>
step 2
咱现在有画布了现在要将我们的渲染绑定到这块画布上捏
<span style="color:red">!!!这一段代码放到onMounted里面喵!!!</span>
const gl = canvas.value.getContext("webgl")
step 3
现在咱的画布已经绑定上WebGL了!?强强?!让我们来写着色器吧!
tips: 原生的js要写着色器的方法是定义一串字符串哦
`js
const vShader =
你的着色器`
- vShader (
VERTEX_SHADER) 顶点着色器 (渲染坐标点哦)
这里咱先创建了一个逐顶点(attribute)4维向量(vec4)用来接收坐标
紧接着创建了一个4维(vec4)全局变量(uniform)用来接收颜色
又创建了一个4维(vec4)传递变量(varying)用来把变量传递给fShader
在主函数中咱也是先把接收到的全局变量赋值给了传递变量呢
接下来就是把位置丢给OpenGL内置的变量定位了呢
`glsl
attribute vec4 position;
uniform vec4 uColor;
varying vec4 vColor;
void main(){
vColor = uColor;
gl_Position = position;
}
`
- fShader (
FRAGMENT_SHADER) 片元着色器 (渲染颜色的哦)
> tips: 使用WebGL1的小猫猫们这里要记得把默认精度补上哦,杂鱼OpenGL忘记加默认精度了呢precision mediump float;
这里咱也是先把vShader丢过来的传递变量接收了呢
在主函数里面我们简简单单的将颜色喂给OpenGL内置的颜色变量
`glsl
varying vec4 vColor;
void main(){
gl_FragColor = vColor;
}
`
step 4
诶,着色器写好了接下来让我们挂载着色器吧!
- 先写初始化着色器
<span style="color:red">!!!这一段代码放到onMounted里面喵!!!</span>
`js
//获取编译好的代码
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vShader)
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fShader)
//创建程序
const program = gl.createProgram()
//挂载着色器
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('(龙门粗口)初始化:', gl.getProgramInfoLog(program))
return
}
//着色器,启动!
gl.useProgram(program)
`
- 上面会用到编译着色器代码的方法喵,这里给他补齐了!
这个方法的三个参数分别是:
1. 步骤2获得的画布上下文
2. 着色器品种(VERTEX_SHADER, FRAGMENT_SHADER)
3. 着色器源码
`js
const loadShader = (gl, type, source) => {
//创建
const shader = gl.createShader(type)
//挂载源码
gl.shaderSource(shader, source)
//编译
gl.compileShader(shader)
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('(龙门粗口)编译:', gl.getShaderInfoLog(shader))
gl.deleteShader(shader)
return
}
return shader
}
`
step 5
这时候注意力惊人的小猫猫可能就发现了:"🦌啊🦌啊,我们写着色器的时候不是要传入几个参数吗,参呢¿",很好我的朋友,你看到捣蛋参数了吗¿在哪里¿
- 首先,咱先找到内存地址(雾)
<span style="color:red">!!!这一段代码放到onMounted里面喵!!!</span>
`js
const programInfo = {
program: program,
attribute: {
//获取位置逐顶点变量地址
position: gl.getAttribLocation(program, "position")
},
uniform: {
//获取颜色全局变量地址
color: gl.getUniformLocation(program, "uColor")
}
}
`
- 接下来写一个塞入数据的方法
这里的三个参数分别是
1. 步骤2获得的画布上下文
2. 数据种类(自己找都有哪些:D,这里只会用到两种)
3. 数据
`js
const initBuffer = (gl, type, data) => {
//创建缓冲区
const buffer = gl.createBuffer()
//绑定缓冲区
gl.bindBuffer(type, buffer)
//绑定数据
gl.bufferData(type, data, gl.STATIC_DRAW)
return buffer
}
`
- 接着来声明一下坐标以及颜色,并且把数据拿去
<span style="color:red">!!!这一段代码放到onMounted里面喵!!!</span>
`js
//这里写你想要的位置
const position = [
-0.5, 0.5, 0,
-0.5, -0.5, 0,
0.5, -0.5, 0,
0.5, 0.5, 0]
//这里放你想要的RGBA
const color = [1.0,1.0,1.0,1.0]
initBuffer(gl, gl.ARRAY_BUFFER, new Float32Array(position))
`
- 启用刚刚初始化的数据
<span style="color:red">!!!这一段代码放到onMounted里面喵!!!</span>
`js
gl.enableVertexAttribArray(programInfo.attribute.position)
`
- 指定读取范围以及种类
<span style="color:red">!!!这一段代码放到onMounted里面喵!!!</span>
`js
gl.vertexAttribPointer(programInfo.attribute.position, 3, gl.FLOAT, false, 0, 0)
`
step 6
嗨呀,鼓捣了这么久,现在让我们看看结果吧!
<span style="color:red">!!!这一段代码放到onMounted里面喵!!!</span>
gl.drawArrays(gl.TRIANGLE_FAN,0 ,4)
让我们看看完整的代码!
<script setup>
const canvas = ref(null)
const vShader = /* glsl */`
attribute vec4 position;
uniform vec4 uColor;
varying vec4 vColor;
void main(){
vColor = uColor;
gl_Position = position;
}
`
const fShader = /* glsl */`
precision mediump float;
varying vec4 vColor;
void main(){
gl_FragColor = vColor;
}
`
const loadShader = (gl, type, source) => {
const shader = gl.createShader(type)
gl.shaderSource(shader, source)
gl.compileShader(shader)
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('(龙门粗口)编译:', gl.getShaderInfoLog(shader))
gl.deleteShader(shader)
return
}
return shader
}
const initBuffer = (gl, type, data) => {
const buffer = gl.createBuffer()
gl.bindBuffer(type, buffer)
gl.bufferData(type, data, gl.STATIC_DRAW)
return buffer
}
onMounted(() => {
const gl = canvas.value.getContext("webgl")
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vShader)
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fShader)
const program = gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('(龙门粗口)初始化:', gl.getProgramInfoLog(program))
return
}
gl.useProgram(program)
const programInfo = {
program: program,
attribute: {
position: gl.getAttribLocation(program, "position")
},
uniform: {
color: gl.getUniformLocation(program, "uColor")
}
}
const position = [
-0.5, 0.5, 0,
-0.5, -0.5, 0,
0.5, -0.5, 0,
0.5, 0.5, 0]
const color = [1.0, 1.0, 1.0, 1.0]
initBuffer(gl, gl.ARRAY_BUFFER, new Float32Array(position))
gl.enableVertexAttribArray(programInfo.attribute.position)
gl.vertexAttribPointer(programInfo.attribute.position, 3, gl.FLOAT, false, 0, 0)
gl.uniform4fv(programInfo.uniform.color, color)
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4)
})
</script>
<template>
<canvas ref="canvas" width="150" height="150"></canvas>
</template>
点赞投币过0千0百也不会更新(╯°□°)╯︵ ┻━┻




