bilca's picture
Upload 56 files
352fb85 verified
raw
history blame
3.8 kB
import { Camera } from "../../../cameras/Camera";
import { Scene } from "../../../core/Scene";
import { WebGLRenderer } from "../../WebGLRenderer";
import { ShaderPass } from "../passes/ShaderPass";
abstract class ShaderProgram {
private _renderer: WebGLRenderer;
private _program: WebGLProgram;
private _passes: ShaderPass[];
protected _scene: Scene | null = null;
protected _camera: Camera | null = null;
protected _started: boolean = false;
protected _initialized: boolean = false;
protected abstract _initialize: () => void;
protected abstract _resize: () => void;
protected abstract _render: () => void;
protected abstract _dispose: () => void;
initialize: () => void;
resize: () => void;
render: (scene: Scene, camera: Camera) => void;
dispose: () => void;
constructor(renderer: WebGLRenderer, passes: ShaderPass[]) {
this._renderer = renderer;
const gl = renderer.gl;
this._program = gl.createProgram() as WebGLProgram;
this._passes = passes || [];
const vertexShader = gl.createShader(gl.VERTEX_SHADER) as WebGLShader;
gl.shaderSource(vertexShader, this._getVertexSource());
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
console.error(gl.getShaderInfoLog(vertexShader));
}
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER) as WebGLShader;
gl.shaderSource(fragmentShader, this._getFragmentSource());
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
console.error(gl.getShaderInfoLog(fragmentShader));
}
gl.attachShader(this.program, vertexShader);
gl.attachShader(this.program, fragmentShader);
gl.linkProgram(this.program);
if (!gl.getProgramParameter(this.program, gl.LINK_STATUS)) {
console.error(gl.getProgramInfoLog(this.program));
}
this.resize = () => {
gl.useProgram(this._program);
this._resize();
};
this.initialize = () => {
console.assert(!this._initialized, "ShaderProgram already initialized");
gl.useProgram(this._program);
this._initialize();
for (const pass of this.passes) {
pass.initialize(this);
}
this._initialized = true;
this._started = true;
};
this.render = (scene: Scene, camera: Camera) => {
gl.useProgram(this._program);
if (this._scene !== scene || this._camera !== camera) {
this.dispose();
this._scene = scene;
this._camera = camera;
this.initialize();
}
for (const pass of this.passes) {
pass.render();
}
this._render();
};
this.dispose = () => {
if (!this._initialized) return;
gl.useProgram(this._program);
for (const pass of this.passes) {
pass.dispose();
}
this._dispose();
this._scene = null;
this._camera = null;
this._initialized = false;
};
}
get renderer() {
return this._renderer;
}
get scene() {
return this._scene;
}
get camera() {
return this._camera;
}
get program() {
return this._program;
}
get passes() {
return this._passes;
}
get started() {
return this._started;
}
protected abstract _getVertexSource(): string;
protected abstract _getFragmentSource(): string;
}
export { ShaderProgram };