Browse Source

完成webglhelper

master
blobt 3 years ago
parent
commit
612fbabc7b
  1. 3
      src/App.tsx
  2. 34
      src/render/common.ts
  3. 285
      src/render/webgl/WebGLHepler.ts
  4. 3
      src/render/webgl/WebGLMesh.ts
  5. 3
      src/render/webgl/WebGLProgram.ts
  6. 75
      src/render/webgl/WebGLTexture.ts

3
src/App.tsx

@ -1,6 +1,7 @@
import React from 'react';
import './App.css';
import { vec3, vec4 } from "./render/math"
import { vec3, vec4 } from "./render/math";
import {} from "./render/webgl/WebGLTexture";
// eslint-disable-next-line
function App() {

34
src/render/common.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
}

285
src/render/webgl/WebGLHepler.ts

@ -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;
}
}

3
src/render/webgl/WebGLMesh.ts

@ -0,0 +1,3 @@
export abstract class GLMeshBase {
}

3
src/render/webgl/WebGLProgram.ts

@ -0,0 +1,3 @@
export class GLProgram {
}

75
src/render/webgl/WebGLTexture.ts

@ -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);
}
}
Loading…
Cancel
Save