webgl/public/gl/core/Shader.js
Tyler Murphy 30cf48cd70 cube
2023-01-18 22:43:02 -05:00

98 lines
No EOL
2.9 KiB
JavaScript

import { gl } from './Renderer.js'
export class Shader {
#vertexShader;
#fragmentShader;
#program;
#attributes;
#uniforms;
constructor(vertexCode, fragmentCode) {
this.#vertexShader = gl.createShader(gl.VERTEX_SHADER)
this.#fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(this.#vertexShader, vertexCode)
gl.shaderSource(this.#fragmentShader, fragmentCode)
gl.compileShader(this.#vertexShader)
if (!gl.getShaderParameter(this.#vertexShader, gl.COMPILE_STATUS)) {
console.error('Failed to compile vertex shader!', gl.getShaderInfoLog(this.#vertexShader))
return
}
gl.compileShader(this.#fragmentShader)
if (!gl.getShaderParameter(this.#fragmentShader, gl.COMPILE_STATUS)) {
console.error('Failed to compile fragment shader!', gl.getShaderInfoLog(this.#fragmentShader))
return
}
this.#program = gl.createProgram()
gl.attachShader(this.#program, this.#vertexShader)
gl.attachShader(this.#program, this.#fragmentShader)
gl.linkProgram(this.#program)
if (!gl.getProgramParameter(this.#program, gl.LINK_STATUS)) {
console.error("Failed to link shader program!", gl.getProgramInfoLog(this.#program));
return
}
gl.validateProgram(this.#program);
if (!gl.getProgramParameter(this.#program, gl.VALIDATE_STATUS)) {
console.error("Failed to validate shader program!", gl.getProgramInfoLog(this.#program));
return
}
this.#attributes = []
this.#uniforms = {}
vertexCode.split('\n').forEach((line) => {
const tokens = line.split(" ")
if (tokens.length != 3) return
if (tokens[0] === "attribute") {
this.#attributes.push(tokens[2].replace(/\s+/g, '').split(';')[0])
}
if (tokens[0] == "uniform") {
const loc = gl.getUniformLocation(this.#program, tokens[2].replace(/\s+/g, '').split(';')[0])
this.#uniforms[tokens[2].replace(/\s+/g, '').split(';')[0]] = loc
}
})
}
start() {
gl.useProgram(this.#program)
for (let i = 0; i < this.#attributes.length; i++) {
gl.bindAttribLocation(this.#program, i, this.#attributes[i])
}
}
stop() {
gl.useProgram(null)
}
loadFloat(name, float) {
gl.uniform1f(this.#uniforms[name], float)
}
loadInt(name, int) {
gl.uniform1i(this.#uniforms[name], int)
}
loadVec2(name, v) {
gl.uniform2f(this.#uniforms[name], v.x, v.y)
}
loadVec3(name, v) {
gl.uniform3f(this.#uniforms[name], v.x, v.y, v.z)
}
loadMat4(name, m) {
gl.uniformMatrix4fv(this.#uniforms[name], gl.FALSE, new Float32Array(m.get()))
}
loadBool(name, bool) {
gl.uniform1f(this.#uniforms[name], bool ? 1 : 0)
}
}