封面

[惑鹿] OpenGL之~渲染~小课堂ヾ(≧▽≦*)o 渲染正方形!

<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 = 你的着色器

`

  1. 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;

}

`

  1. fShader (FRAGMENT_SHADER) 片元着色器 (渲染颜色的哦)

> tips: 使用WebGL1的小猫猫们这里要记得把默认精度补上哦,杂鱼OpenGL忘记加默认精度了呢precision mediump float;

这里咱也是先把vShader丢过来的传递变量接收了呢

在主函数里面我们简简单单的将颜色喂给OpenGL内置的颜色变量

`glsl

varying vec4 vColor;

void main(){

gl_FragColor = vColor;

}

`

step 4

诶,着色器写好了接下来让我们挂载着色器吧!

  1. 先写初始化着色器

<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. 上面会用到编译着色器代码的方法喵,这里给他补齐了!

这个方法的三个参数分别是:

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

这时候注意力惊人的小猫猫可能就发现了:"🦌啊🦌啊,我们写着色器的时候不是要传入几个参数吗,参呢¿",很好我的朋友,你看到捣蛋参数了吗¿在哪里¿

  1. 首先,咱先找到内存地址(雾)

<span style="color:red">!!!这一段代码放到onMounted里面喵!!!</span>

`js

const programInfo = {

program: program,

attribute: {

//获取位置逐顶点变量地址

position: gl.getAttribLocation(program, "position")

},

uniform: {

//获取颜色全局变量地址

color: gl.getUniformLocation(program, "uColor")

}

}

`

  1. 接下来写一个塞入数据的方法

这里的三个参数分别是

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

}

`

  1. 接着来声明一下坐标以及颜色,并且把数据拿去

<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))

`

  1. 启用刚刚初始化的数据

<span style="color:red">!!!这一段代码放到onMounted里面喵!!!</span>

`js

gl.enableVertexAttribArray(programInfo.attribute.position)

`

  1. 指定读取范围以及种类

<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百也不会更新(╯°□°)╯︵ ┻━┻

发布评论
全部评论(0)