Browse Source

WebGLProgram完成

master
blobt 4 years ago
parent
commit
0b0aaa5b2a
  1. 427
      src/render/webgl/WebGLProgram.ts

427
src/render/webgl/WebGLProgram.ts

@ -1,3 +1,430 @@
import { GLAttribBits, GLAttribState } from "./WebGLAttribState";
import { vec2, vec3, vec4, mat4, quat } from "../math";
import { GLTexture } from "./WebGLTexture";
import { GLShaderSource } from "./WebGLShaderSource";
import { GLHelper, GLAttribMap, GLUinformMap } from "./WebGLHepler";
import { EShaderType } from "../common";
export class GLProgram {
public static readonly MVMatrix: string = "uMVMatrix";
public static readonly ModelMatrix: string = "uModelMatrix";
public static readonly ViewMatrix: string = "uViewMatrix";
public static readonly ProjectMatrix: string = "uProjectMatrix";
public static readonly NormalMatrix: string = "uNormalMatrix";
public static readonly MVPMatrix: string = "uMVPMatrix";
public static readonly Color: string = "uColor";
public static readonly Sampler: string = "uSampler"; //纹理采样器
public static readonly DiffuseSampler: string = "uDiffuseSampler"; //漫反射采样器
public static readonly NormalSampler: string = "uNormalSampler"; //法线采样器
public static readonly SpecularSampler: string = "uSpecularSampler"; //高光采样器
public static readonly DepthSampler: string = "uDepthSampler"; //高光采样器
/**
* @var WebGL上下文
*/
public gl: WebGLRenderingContext;
/**
* @var program name
*/
public name: string;
/**
* @var bits值
*/
private _attribuState: GLAttribBits;
/**
* @var
*/
public program: WebGLProgram;
/**
* @var vs编译器
*/
public vsShader: WebGLShader;
/**
* @var fs编译器
*/
public fsShader: WebGLShader;
/**
* @var attribute
*/
public attribMap: GLAttribMap;
/**
* @var uniform
*/
public uniformMap: GLUinformMap;
/**
* @function gl.useProgram(this.program)bindCallback回调
*/
public bindCallback: ((program: GLProgram) => void) | null;
/**
* @function gl.useProgram(null)unbindCallback回调函数
*/
public unbindCallback: ((program: GLProgram) => void) | null;
/**
* @arr
*/
private _vsShaderDefineStrings: string[] = [];
/**
* @arr
*/
private _fsShaderDefineStrings: string[] = [];
/**
* bits值
*/
public get attribState(): GLAttribBits {
return this._attribuState;
}
/**
*
*/
private programBeforeLink(gl: WebGLRenderingContext, program: WebGLProgram): void {
if (GLAttribState.hasPosition(this._attribuState)) {
gl.bindAttribLocation(program, GLAttribState.POSITION_LOCATION, GLAttribState.POSITION_NAME);
}
if (GLAttribState.hasNormal(this._attribuState)) {
gl.bindAttribLocation(program, GLAttribState.NORMAL_LOCATION, GLAttribState.NORMAL_NAME);
}
if (GLAttribState.hasTexCoord_0(this._attribuState)) {
gl.bindAttribLocation(program, GLAttribState.TEXCOORD_LOCATION, GLAttribState.TEXCOORD_NAME);
}
if (GLAttribState.hasTexCoord_1(this._attribuState)) {
gl.bindAttribLocation(program, GLAttribState.TEXCOORD1_LOCATION, GLAttribState.TEXCOORD1_NAME);
}
if (GLAttribState.hasColor(this._attribuState)) {
gl.bindAttribLocation(program, GLAttribState.COLOR_LOCATION, GLAttribState.COLOR_NAME);
}
if (GLAttribState.hasTangent(this._attribuState)) {
gl.bindAttribLocation(program, GLAttribState.TANGENT_LOCATION, GLAttribState.TANGENT_NAME);
}
}
/**
* attribute uniform map
* @param gl
* @param program
*/
private programAfterLink(gl: WebGLRenderingContext, program: WebGLProgram): void {
GLHelper.getProgramActiveAttribs(gl, program, this.attribMap);
GLHelper.getProgramActiveUniforms(gl, program, this.uniformMap);
}
public constructor(context: WebGLRenderingContext, attribState: GLAttribBits, vsShader: string | null = null, fsShader: string | null = null, name: string = "") {
this.gl = context;
this._attribuState = attribState;
this.bindCallback = null;
this.unbindCallback = null;
let shader: WebGLShader | null = GLHelper.createShader(this.gl, EShaderType.VS_SHADER);
if (shader === null) {
throw new Error("create vertex shader failed!");
}
this.vsShader = shader;
shader = null;
shader = GLHelper.createShader(this.gl, EShaderType.FS_SHADER);
if (shader === null) {
throw new Error("create fragment shader failed!");
}
this.fsShader = shader;
let program: WebGLProgram | null = GLHelper.createProgram(this.gl);
if (program === null) {
throw new Error("create webgl program failed!");
}
this.program = program;
this.attribMap = {};
this.uniformMap = {};
if (vsShader !== null && fsShader !== null) {
this.loadShader(vsShader, fsShader);
}
this.name = name;
}
/**
* Vertex Shader中动态添加宏
* @param str
*/
public addVSShaderMacro(str: string): void {
if (str.indexOf("#define ") === -1) {
str = "#define " + str;
}
this._vsShaderDefineStrings.push(str);
}
/**
* fragment Shader中动态添加宏
* @param str
*/
public addFSShaderMacro(str: string): void {
if (str.indexOf("#define ") === -1) {
str = "#define " + str;
}
this._fsShaderDefineStrings.push(str);
}
/**
* shader到program
* @param vs
* @param fs
*/
public loadShader(vs: string, fs: string): void {
if (this._vsShaderDefineStrings.length > 0) {
let join: string = this._vsShaderDefineStrings.join("\n");
vs = join + vs;
}
if (this._fsShaderDefineStrings.length > 0) {
let join: string = this._fsShaderDefineStrings.join("\n");
fs = join + fs;
}
if (GLHelper.compileShader(this.gl, vs, this.vsShader) === false) {
throw new Error("compiler vs shader failed!");
}
if (GLHelper.compileShader(this.gl, fs, this.fsShader) === false) {
throw new Error("compiler fs shader failed!");
}
if (GLHelper.linkProgram(this.gl, this.program, this.vsShader, this.fsShader, this.programBeforeLink.bind(this), this.programAfterLink.bind(this)) === false) {
throw new Error("link program failed!");
}
}
/**
*
*/
public bind(): void {
this.gl.useProgram(this.program);
if (this.bindCallback !== null) {
this.bindCallback(this);
}
}
/**
*
*/
public unbind(): void {
if (this.unbindCallback !== null) {
this.unbindCallback(this);
}
this.gl.useProgram(null);
}
/**
* uniform
* @param name
* @returns
*/
public getUniformLocation(name: string): WebGLUniformLocation | null {
return this.gl.getUniformLocation(this.program, name);
}
/**
* attribute地址
* @param name
* @returns
*/
public getAttributeLocation(name: string): number {
return this.gl.getAttribLocation(this.program, name);
}
/**
* attribute地址
* @param name
* @returns
*/
public setAttributeLocation(name: string, loc: number): void {
this.gl.bindAttribLocation(this.program, loc, name);
}
/**
* uniform
* @param name
* @param i
* @returns
*/
public setInt(name: string, i: number): boolean {
let loc: WebGLUniformLocation | null = this.getUniformLocation(name);
if (loc !== null) {
this.gl.uniform1i(loc, i);
return true;
}
return false;
}
/**
* uniform
* @param name
* @param i
* @returns
*/
public setFloat(name: string, f: number): boolean {
let loc: WebGLUniformLocation | null = this.getUniformLocation(name);
if (loc !== null) {
this.gl.uniform1f(loc, f);
return true;
}
return false;
}
/**
* uniform
* @param name
* @param i
* @returns
*/
public setVector2(name: string, v: vec2): boolean {
let loc: WebGLUniformLocation | null = this.getUniformLocation(name);
if (loc !== null) {
this.gl.uniform2fv(loc, v.values);
return true;
}
return false;
}
/**
* uniform
* @param name
* @param i
* @returns
*/
public setVector3(name: string, v: vec3): boolean {
let loc: WebGLUniformLocation | null = this.getUniformLocation(name);
if (loc !== null) {
this.gl.uniform3fv(loc, v.values);
return true;
}
return false;
}
/**
* uniform
* @param name
* @param i
* @returns
*/
public setVector4(name: string, v: vec4): boolean {
let loc: WebGLUniformLocation | null = this.getUniformLocation(name);
if (loc !== null) {
this.gl.uniform4fv(loc, v.values);
return true;
}
return false;
}
/**
* uniform
* @param name
* @param i
* @returns
*/
public setQuat(name: string, q: quat): boolean {
let loc: WebGLUniformLocation | null = this.getUniformLocation(name);
if (loc !== null) {
this.gl.uniform4fv(loc, q.values);
return true;
}
return false;
}
/**
* uniform
* @param name
* @param i
* @returns
*/
public setMatrix3(name: string, m: mat4): boolean {
let loc: WebGLUniformLocation | null = this.getUniformLocation(name);
if (loc !== null) {
this.gl.uniformMatrix3fv(loc, false, m.values);
return true;
}
return false;
}
/**
* uniform
* @param name
* @param i
* @returns
*/
public setMatrix4(name: string, m: mat4): boolean {
let loc: WebGLUniformLocation | null = this.getUniformLocation(name);
if (loc !== null) {
this.gl.uniformMatrix4fv(loc, false, m.values);
return true;
}
return false;
}
/**
* uniform
* @param name
* @param i
* @returns
*/
public setSampler(name: string, s: number): boolean {
let loc: WebGLUniformLocation | null = this.getUniformLocation(name);
if (loc !== null) {
this.gl.uniform1i(loc, s);
return true;
}
return false;
}
/**
*
* @param mat
* @returns
*/
public loadModelViewMatrix(mat: mat4): boolean {
return this.setMatrix4(GLProgram.MVMatrix, mat);
}
/**
*
* @param unit
* @returns
*/
public loadSampler(unit: number = 0): boolean {
return this.setSampler(GLProgram.Sampler, unit);
}
/**
* program
* @param gl
* @returns
*/
public static createDefaultTextureProgram(gl: WebGLRenderingContext): GLProgram {
let ret: GLProgram = new GLProgram(gl, GLAttribState.makeVertexAttribs(true, false, false, false, false), GLShaderSource.textureShader.vs, GLShaderSource.textureShader.fs)
return ret;
}
/**
* program
* @param gl
* @returns
*/
public static createDefaultColorProgram(gl: WebGLRenderingContext): GLProgram {
let ret: GLProgram = new GLProgram(gl, GLAttribState.makeVertexAttribs(false, false, false, false, true), GLShaderSource.colorShader.vs, GLShaderSource.colorShader.fs)
return ret;
}
}
Loading…
Cancel
Save