98 lines
No EOL
2.9 KiB
JavaScript
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)
|
|
}
|
|
|
|
} |