blobt
4 years ago
6 changed files with 401 additions and 2 deletions
-
3src/App.tsx
-
34src/render/common.ts
-
285src/render/webgl/WebGLHepler.ts
-
3src/render/webgl/WebGLMesh.ts
-
3src/render/webgl/WebGLProgram.ts
-
75src/render/webgl/WebGLTexture.ts
@ -1 +1,33 @@ |
|||
export let EPSILON: number = 0.0001; |
|||
export let EPSILON: number = 0.0001; |
|||
|
|||
export enum EShaderType { |
|||
VS_SHADER, |
|||
FS_SHADER |
|||
} |
|||
|
|||
export enum EGLSLESDataType { |
|||
FLOAT_VEC2 = 0x8B50, |
|||
FLOAT_VEC3, |
|||
FLOAT_VEC4, |
|||
INT_VEC2, |
|||
INT_VEC3, |
|||
INT_VEC4, |
|||
BOOL, |
|||
BOOL_VEC2, |
|||
BOOL_VEC3, |
|||
BOOL_VEC4, |
|||
FLOAT_MAT2, |
|||
FLOAT_MAT3, |
|||
FLOAT_MAT4, |
|||
SAMPLER_2D, |
|||
SAMPLER_CUBE, |
|||
|
|||
FLOAT = 0x1406, |
|||
INT = 0x1404 |
|||
} |
|||
|
|||
export enum EGLTexWrapType { |
|||
GL_REPEAT, //设置为gl对应的常量
|
|||
GL_MIRRORED_REPEAT, |
|||
GL_CLAMP_TO_EDGE |
|||
} |
@ -0,0 +1,285 @@ |
|||
import { EShaderType, EGLSLESDataType } from "../common"; |
|||
|
|||
|
|||
/** |
|||
* uniform参数 |
|||
*/ |
|||
export class GLUniformInfo { |
|||
public size: number; |
|||
public type: EGLSLESDataType; |
|||
public location: WebGLUniformLocation; |
|||
|
|||
public constructor(size: number, type: number, loc: WebGLUniformLocation) { |
|||
this.size = size; |
|||
this.type = type; |
|||
this.location = loc; |
|||
} |
|||
} |
|||
|
|||
export class GLAttribInfo { |
|||
public size: number; |
|||
public type: EGLSLESDataType; |
|||
public location: number; |
|||
public constructor(size: number, type: number, loc: number) { |
|||
this.size = size; |
|||
this.type = type; |
|||
this.location = loc; |
|||
} |
|||
} |
|||
|
|||
export type GLUinformMap = { [key: string]: GLUniformInfo }; |
|||
export type GLAttribMap = { [key: string]: GLAttribInfo }; |
|||
|
|||
export class GLHelper { |
|||
|
|||
/** |
|||
* 打印webgl上下文的各个状态 |
|||
* @param gl |
|||
*/ |
|||
public static printStates(gl: WebGLRenderingContext): void { |
|||
// 所有的boolean状态变量,共9个
|
|||
console.log("1. isBlendEnable = " + gl.isEnabled(gl.BLEND)); |
|||
console.log("2. isCullFaceEnable = " + gl.isEnabled(gl.CULL_FACE)); |
|||
console.log("3. isDepthTestEnable = " + gl.isEnabled(gl.DEPTH_TEST)); |
|||
console.log("4. isDitherEnable = " + gl.isEnabled(gl.DITHER)); |
|||
console.log("5. isPolygonOffsetFillEnable = " + gl.isEnabled(gl.POLYGON_OFFSET_FILL)); |
|||
console.log("6. isSampleAlphtToCoverageEnable = " + gl.isEnabled(gl.SAMPLE_ALPHA_TO_COVERAGE)); |
|||
console.log("7. isSampleCoverageEnable = " + gl.isEnabled(gl.SAMPLE_COVERAGE)); |
|||
console.log("8. isScissorTestEnable = " + gl.isEnabled(gl.SCISSOR_TEST)); |
|||
console.log("9. isStencilTestEnable = " + gl.isEnabled(gl.STENCIL_TEST)); |
|||
} |
|||
|
|||
/** |
|||
* 打印webgl信息 |
|||
* @param gl |
|||
*/ |
|||
public static printWebGLInfo(gl: WebGLRenderingContext): void { |
|||
console.log("renderer = " + gl.getParameter(gl.RENDERER)); |
|||
console.log("version = " + gl.getParameter(gl.VERSION)); |
|||
console.log("vendor = " + gl.getParameter(gl.VENDOR)); |
|||
console.log("glsl version = " + gl.getParameter(gl.SHADING_LANGUAGE_VERSION)); |
|||
} |
|||
|
|||
/** |
|||
* 获取textture信息 |
|||
* @param gl |
|||
*/ |
|||
public static printWebGLTextureInfo(gl: WebGLRenderingContext): void { |
|||
console.log("MAX_COMBINED_TEXTURE_IMAGE_UINTS = ", gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS)); |
|||
console.log("MAX_TEXTURE_IMAGE_UNITS = ", gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS)); |
|||
console.log("MAX_TEXTURE_SIZE = ", gl.getParameter(gl.MAX_TEXTURE_SIZE)); |
|||
console.log("MAX_CUBE_MAP_TEXTURE_SIZE", gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE)); |
|||
} |
|||
|
|||
/** |
|||
* 触发context lose 事件 |
|||
* @param gl |
|||
*/ |
|||
public static triggerContextLosEvent(gl: WebGLRenderingContext): void { |
|||
let context: WEBGL_lose_context | null = gl.getExtension('WEBGL_lose_context'); |
|||
if (context !== null) { |
|||
context.loseContext(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 获取webgl错误 |
|||
* @param gl |
|||
*/ |
|||
public static checkGLError(gl: WebGLRenderingContext): boolean { |
|||
let err: number = gl.getError(); |
|||
if (err === 0) { |
|||
return false; |
|||
} else { |
|||
console.log("WebGL ERROR NO: ", err); |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 设置webgl的默认状态 |
|||
* @param gl |
|||
*/ |
|||
public static setDefaultState(gl: WebGLRenderingContext): void { |
|||
gl.clearColor(0.0, 0.0, 0.0, 0.0);//每次清屏时,将颜色缓冲区设置全透明 黑色
|
|||
gl.clearDepth(1.0);//每次清屏时,将深度缓冲区设置成1.0
|
|||
gl.enable(gl.DEPTH_TEST); //每次清屏时候开始深度测试
|
|||
gl.enable(gl.CULL_FACE);//每次清屏时候开始背面剔除
|
|||
gl.enable(gl.SCISSOR_TEST);//每次清屏时候开启剪切测试
|
|||
} |
|||
|
|||
/** |
|||
* 设置webgl的视口 |
|||
* @param gl |
|||
* @param v |
|||
*/ |
|||
public static setViewport(gl: WebGLRenderingContext, v: number[]) { |
|||
gl.viewport(v[0], v[1], v[2], v[3]); |
|||
} |
|||
|
|||
/** |
|||
* 创建着色器 |
|||
* @param gl |
|||
* @param type |
|||
* @returns |
|||
*/ |
|||
public static createShader(gl: WebGLRenderingContext, type: EShaderType): WebGLShader { |
|||
let ret: WebGLShader | null = null; |
|||
|
|||
if (type === EShaderType.VS_SHADER) { |
|||
ret = gl.createShader(gl.VERTEX_SHADER); |
|||
} else { |
|||
ret = gl.createShader(gl.FRAGMENT_SHADER); |
|||
} |
|||
|
|||
if (ret === null) { |
|||
throw new Error("WebGLShader create failed!"); |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
/** |
|||
* 编译着色器 |
|||
* @param gl |
|||
* @param code |
|||
* @param shader |
|||
* @returns |
|||
*/ |
|||
public static compileShader(gl: WebGLRenderingContext, code: string, shader: WebGLShader): boolean { |
|||
gl.shaderSource(shader, code);//载入shader源码
|
|||
gl.compileShader(shader); |
|||
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) === false) { |
|||
alert(gl.getShaderInfoLog(shader));//如果编译出错,弹出出错信息
|
|||
gl.deleteShader(shader); |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* 创建链接器对象 |
|||
* @param gl |
|||
* @returns |
|||
*/ |
|||
public static createProgram(gl: WebGLRenderingContext): WebGLProgram { |
|||
let ret: WebGLProgram | null = gl.createProgram(); |
|||
if (ret === null) { |
|||
throw new Error("WebGLProgram create falied!"); |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
/** |
|||
* |
|||
* @param gl 渲染上下文对象 |
|||
* @param program 链接器对象 |
|||
* @param vsShader 顶点着色器 |
|||
* @param fsShader 片段着色器 |
|||
* @param beforeProgramLink 链接前执行函数 |
|||
* @param afterProgramLink 链接后执行函数 |
|||
*/ |
|||
public static linkProgram( |
|||
gl: WebGLRenderingContext, |
|||
program: WebGLProgram, |
|||
vsShader: WebGLShader, |
|||
fsShader: WebGLShader, |
|||
beforeProgramLink: ((gl: WebGLRenderingContext, program: WebGLProgram) => void) | null = null, |
|||
afterProgramLink: ((gl: WebGLRenderingContext, program: WebGLProgram) => void) | null = null |
|||
): boolean { |
|||
|
|||
gl.attachShader(program, vsShader); |
|||
gl.attachShader(program, fsShader); |
|||
|
|||
if (beforeProgramLink !== null) { |
|||
beforeProgramLink(gl, program); |
|||
} |
|||
|
|||
gl.linkProgram(program); |
|||
if (gl.getProgramParameter(program, gl.LINK_STATUS) === false) { |
|||
alert(gl.getProgramInfoLog(program)); |
|||
gl.deleteShader(vsShader); |
|||
gl.deleteShader(fsShader); |
|||
gl.deleteProgram(program); |
|||
|
|||
return false; |
|||
} |
|||
|
|||
gl.validateProgram(program); |
|||
if (gl.getProgramParameter(program, gl.VALIDATE_STATUS) === false) { |
|||
alert(gl.getProgramInfoLog(program)); |
|||
gl.deleteShader(vsShader); |
|||
gl.deleteShader(fsShader); |
|||
gl.deleteProgram(program); |
|||
|
|||
return false; |
|||
} |
|||
|
|||
if (afterProgramLink !== null) { |
|||
afterProgramLink(gl, program); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* 获取生效的attribute |
|||
* @param gl |
|||
* @param program |
|||
* @param out |
|||
*/ |
|||
public static getProgramActiveAttribs(gl: WebGLRenderingContext, program: WebGLProgram, out: GLAttribMap): void { |
|||
|
|||
let count: number = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);//获取当前active状态的attribute的数量, active_attributes/uniforms必须在link后才能获得
|
|||
|
|||
for (let i = 0; i < count; i++) { |
|||
let info: WebGLActiveInfo | null = gl.getActiveAttrib(program, i); |
|||
if (info) { |
|||
out[info.name] = new GLAttribInfo(info.size, info.type, gl.getAttribLocation(program, info.name)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 获取生效的uniform |
|||
* @param gl |
|||
* @param program |
|||
* @param out |
|||
*/ |
|||
public static getProgramActiveUniforms(gl: WebGLRenderingContext, program: WebGLProgram, out: GLUinformMap): void { |
|||
let count: number = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); |
|||
|
|||
for (let i = 0; i < count; i++) { |
|||
let info: WebGLActiveInfo | null = gl.getActiveUniform(program, i); |
|||
if (info) { |
|||
let loc: WebGLUniformLocation | null = gl.getUniformLocation(program, info.name); |
|||
if (loc !== null) { |
|||
out[info.name] = new GLUniformInfo(info.size, info.type, loc); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 创建一个webgl buffer |
|||
* @param gl |
|||
* @returns |
|||
*/ |
|||
public static createBuffer(gl: WebGLRenderingContext): WebGLBuffer { |
|||
let ret: WebGLBuffer | null = gl.createBuffer(); |
|||
if (ret === null) { |
|||
throw new Error("webgl create buffer failed!"); |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
/** |
|||
* 创建color buffer |
|||
* @param gl |
|||
* @returns |
|||
*/ |
|||
public static getColorBufferData(gl: WebGLRenderingContext): Uint8Array { |
|||
let ret: Uint8Array = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4); |
|||
gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, ret); |
|||
return ret; |
|||
} |
|||
} |
@ -0,0 +1,3 @@ |
|||
export abstract class GLMeshBase { |
|||
|
|||
} |
@ -0,0 +1,3 @@ |
|||
export class GLProgram { |
|||
|
|||
} |
@ -0,0 +1,75 @@ |
|||
import { EGLTexWrapType } from "../common"; |
|||
import { GLHelper } from "./WebGLHepler"; |
|||
|
|||
|
|||
export class GLTexture { |
|||
|
|||
public gl: WebGLRenderingContext; |
|||
public isMipmap: boolean; //是否使用了mipmap
|
|||
public width: number; |
|||
public height: number; |
|||
public format: number; //在内存或显存中的存储格式,默认是gl.RGBA
|
|||
public type: number; //像素的数据类型,默认是gl.UNSIGNED_BYTE
|
|||
public texture: WebGLTexture; |
|||
public target: number; //gl.TEXTURE_2D
|
|||
public name: string; //纹理的名称
|
|||
|
|||
public constructor(gl: WebGLRenderingContext, name: string = '') { |
|||
this.gl = gl; |
|||
this.isMipmap = false; |
|||
this.width = this.height = 0; |
|||
this.format = gl.RGBA; |
|||
this.type = gl.UNSIGNED_BYTE; |
|||
let tex: WebGLTexture | null = gl.createTexture(); |
|||
if (tex === null) { |
|||
throw new Error("WebGL texture create falied!"); |
|||
} |
|||
this.texture = tex; |
|||
this.target = gl.TEXTURE_2D; |
|||
this.name = name; |
|||
this.wrap(); |
|||
this.filter(); |
|||
} |
|||
|
|||
/** |
|||
* 判断是否是2的倍数 |
|||
* @param x |
|||
* @returns |
|||
*/ |
|||
public static isPowerOfTwo(x: number) { |
|||
return (x & (x - 1)) == 0; |
|||
} |
|||
|
|||
/** |
|||
* 纹理包装设置 |
|||
* @param mode |
|||
*/ |
|||
public wrap(mode: EGLTexWrapType = EGLTexWrapType.GL_REPEAT): void { |
|||
this.gl.bindTexture(this.target, this.texture); |
|||
if (mode === EGLTexWrapType.GL_CLAMP_TO_EDGE) { |
|||
this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); |
|||
this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); |
|||
} else if (mode === EGLTexWrapType.GL_REPEAT) { |
|||
this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_S, this.gl.REPEAT); |
|||
this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_T, this.gl.REPEAT); |
|||
} else { |
|||
this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_S, this.gl.MIRRORED_REPEAT); |
|||
this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_T, this.gl.MIRRORED_REPEAT); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 设置纹理滤波 |
|||
* @param minLinear |
|||
* @param magLinear |
|||
*/ |
|||
public filter(minLinear: boolean = true, magLinear: boolean = true): void { |
|||
this.gl.bindTexture(this.target, this.texture); |
|||
if (this.isMipmap) { |
|||
this.gl.texParameteri(this.target, this.gl.TEXTURE_MIN_FILTER, minLinear ? this.gl.LINEAR_MIPMAP_LINEAR : this.gl.NEAREST_MIPMAP_NEAREST); |
|||
} else { |
|||
this.gl.texParameteri(this.target, this.gl.TEXTURE_MIN_FILTER, minLinear ? this.gl.LINEAR : this.gl.NEAREST); |
|||
} |
|||
this.gl.texParameteri(this.target, this.gl.TEXTURE_MIN_FILTER, magLinear ? this.gl.LINEAR : this.gl.NEAREST); |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue