Initial commit
This commit is contained in:
106
C#/TSEngine/Core/GL/shader.ts
Normal file
106
C#/TSEngine/Core/GL/shader.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
namespace TSE {
|
||||
|
||||
export abstract class Shader {
|
||||
private _name: string;
|
||||
private _program: WebGLProgram;
|
||||
private _attributes: { [name: string]: number } = {};
|
||||
private _uniforms: { [name: string]: WebGLUniformLocation } = {};
|
||||
|
||||
/**
|
||||
* Create a new Shader.
|
||||
* @param name The name of the Shader.
|
||||
* @param vertexSource The source of the VertexShader
|
||||
* @param fragementSource The source of the FragmentShader
|
||||
*/
|
||||
public constructor(name: string) {
|
||||
this._name = name;
|
||||
}
|
||||
|
||||
protected setSource(vertexSource: string, fragementSource: string): void {
|
||||
let vertexShader = this.loadShader(vertexSource, gl.VERTEX_SHADER);
|
||||
let fragmentShader = this.loadShader(fragementSource, gl.FRAGMENT_SHADER);
|
||||
this.createProgram(vertexShader, fragmentShader);
|
||||
|
||||
this.detectAtrributes();
|
||||
this.detectUniforms();
|
||||
}
|
||||
|
||||
/** Use this Shader. */
|
||||
public use(): void {
|
||||
gl.useProgram(this._program);
|
||||
}
|
||||
|
||||
private loadShader(source: string, shaderType: number): WebGLShader {
|
||||
let shader: WebGLShader = gl.createShader(shaderType);
|
||||
|
||||
gl.shaderSource(shader, source);
|
||||
gl.compileShader(shader);
|
||||
|
||||
const error = gl.getShaderInfoLog(shader);
|
||||
if (error != "")
|
||||
throw new Error("Error compiling shader '" + this._name + "': " + error);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
/** The name of this Shader. */
|
||||
public get name(): string { return this._name; }
|
||||
|
||||
/**
|
||||
* Get the Location of an Attribute with the provided Name.
|
||||
* @param name The name of the Attribute.
|
||||
*/
|
||||
public getAttributeLocation(name: string): number {
|
||||
if (this._attributes[name] === undefined) throw new Error(`Unable to find Attribute '${name}' in shader '${this._name}'`);
|
||||
|
||||
return this._attributes[name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Location of an Uniform with the provided Name.
|
||||
* @param name The name of the Uniform.
|
||||
*/
|
||||
public getUniformLocation(name: string): WebGLUniformLocation {
|
||||
if (this._uniforms[name] === undefined) throw new Error(`Unable to find Uniform '${name}' in shader '${this._name}'`);
|
||||
|
||||
return this._uniforms[name];
|
||||
}
|
||||
|
||||
private createProgram(vertexShader: WebGLShader, fragmentShader: WebGLShader): void {
|
||||
this._program = gl.createProgram();
|
||||
|
||||
gl.attachShader(this._program, vertexShader);
|
||||
gl.attachShader(this._program, fragmentShader);
|
||||
|
||||
gl.linkProgram(this._program);
|
||||
|
||||
const error = gl.getProgramInfoLog(this._program);
|
||||
if (error != "")
|
||||
throw new Error("Error linking shader '" + this._name + "': " + error);
|
||||
}
|
||||
|
||||
private detectAtrributes(): void {
|
||||
let attributeCount = gl.getProgramParameter(this._program, gl.ACTIVE_ATTRIBUTES);
|
||||
|
||||
for (let i = 0; i < attributeCount; i++) {
|
||||
let attributeInfo: WebGLActiveInfo = gl.getActiveAttrib(this._program, i);
|
||||
if (!attributeInfo) break;
|
||||
|
||||
this._attributes[attributeInfo.name] = gl.getAttribLocation(this._program, attributeInfo.name);
|
||||
}
|
||||
}
|
||||
|
||||
private detectUniforms(): void {
|
||||
let uniformCount = gl.getProgramParameter(this._program, gl.ACTIVE_UNIFORMS);
|
||||
|
||||
for (let i = 0; i < uniformCount; i++) {
|
||||
let uniformInfo: WebGLActiveInfo = gl.getActiveUniform(this._program, i);
|
||||
if (!uniformInfo) break;
|
||||
|
||||
this._uniforms[uniformInfo.name] = gl.getUniformLocation(this._program, uniformInfo.name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user