webgl/webgl2--之shader传值的三种方式

75 阅读1分钟
import initShaders from './initShaders.js'

let canvas = document.getElementById('canvas')
let gl = canvas.getContext('webgl2')

// vertexShader, fragmentShader
// let vertexShader = `
// attribute vec2 a_position;
// uniform float u_size;
// varying vec2 v_xx;

// void main() {
//     v_xx = a_position;
//     gl_Position = vec4(a_position, 0.0, 1.0);
//     gl_PointSize = u_size;
// }
// `
// let fragmentShader = `
// precision mediump float;
// varying vec2 v_xx;

// uniform vec3 u_color;
// void main() {
//     gl_FragColor = vec4(v_xx, 0.0, 1.0);
// }
// `

let vertexShader = `#version 300 es

layout (location = 0) in vec2 a_position;
uniform float u_size;
out vec2 v_xx;

void main() {
    v_xx = a_position;
    gl_Position = vec4(a_position, 0.0, 1.0);
    gl_PointSize = u_size;
}
`

let fragmentShader = `#version 300 es
precision mediump float;
in vec2 v_xx;
uniform vec3 u_color;
out vec4 fragColor;
void main() {
    fragColor = vec4(u_color, 1.0); 
}
`;


initShaders(gl, vertexShader, fragmentShader)

// 清空canvas画布
gl.clearColor(0.5, 0.5, 0.5, 1.0) // rgba()
gl.clear(gl.COLOR_BUFFER_BIT)

// (1)Attribute (vertexShader): 将js中的数据传给vertexShader
let a_position = gl.getAttribLocation(gl.program, 'a_position')
gl.vertexAttrib2f(a_position, 0.5, 0.5)

// (2)Uniform (vertexShader, fragment):将js中的数据传给vertexShader/fragmentShader
let u_color = gl.getUniformLocation(gl.program, 'u_color')
gl.uniform3f(u_color, 0.0, 1.0, 0.0)

let u_size = gl.getUniformLocation(gl.program, 'u_size')
gl.uniform1f(u_size, 50.0)

// (3) Varying:将vertexShader中的数据传给fragmentShader

// 画一个点
gl.drawArrays(gl.POINTS, 0, 1)

initShaders.js文件内容

export default function initShaders(gl, vertexSource, fragmentSource) {
    let vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSource)
    let fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSource)

    let program = createProgram(gl, vertexShader, fragmentShader)

    if (program) {
        gl.useProgram(program)
        // 为了获得program的作用域,所以把他挂在gl对象上,作为一个属性
        gl.program = program
        return true
    } else {
        console.log('Failed to create program.')
        return false
    }
}

/**
 * Create Shades
 */
function createShader(gl, type, source) {
    let shader = gl.createShader(type)
    gl.shaderSource(shader, source)

    gl.compileShader(shader)

    // complie shader result
    let compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS)
    if (compiled) {
        return shader
    } else {
        let error = gl.getShaderInfoLog(shader)
        console.log('compile shaders error: ' + error)
        gl.deleteShader(shader)
        return null
    }
}

/**
 * Create Program
 */
function createProgram(gl, vertexShader, fragmentShader) {
    let program = gl.createProgram()
    if (!program) return null

    gl.attachShader(program, vertexShader)
    gl.attachShader(program, fragmentShader)

    gl.linkProgram(program)
    // link prgram result
    let linked = gl.getProgramParameter(program, gl.LINK_STATUS)
    if (linked) {
        return program
    } else {
        let error = gl.getProgramInfoLog(program)
        console.log('link program error: ' + error)
        gl.deleteProgram(program)
        gl.deleteShader(vertexShader)
        gl.deleteShader(fragmentShader)
        return null
    }
}