blobt
4 years ago
1 changed files with 427 additions and 0 deletions
@ -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; |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue