mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-02-28 17:37:07 +08:00
feat: 实例化绘制支持 & 可选渲染模式
This commit is contained in:
parent
0989c82a6b
commit
a8aaaed8ea
@ -60,6 +60,13 @@ const enum ShaderVersion {
|
||||
ES_300
|
||||
}
|
||||
|
||||
const enum RenderMode {
|
||||
Arrays,
|
||||
Elements,
|
||||
ArraysInstanced,
|
||||
ElementsInstanced
|
||||
}
|
||||
|
||||
export const enum UniformType {
|
||||
Uniform1f,
|
||||
Uniform1fv,
|
||||
@ -172,6 +179,11 @@ export class Shader extends Container<EShaderEvent> {
|
||||
readonly ATTRIB_I4iv: AttribType.AttribI4iv = AttribType.AttribI4iv;
|
||||
readonly ATTRIB_I4ui: AttribType.AttribI4ui = AttribType.AttribI4ui;
|
||||
readonly ATTRIB_I4uiv: AttribType.AttribI4uiv = AttribType.AttribI4uiv;
|
||||
// 渲染模式
|
||||
readonly DRAW_ARRAYS = RenderMode.Arrays;
|
||||
readonly DRAW_ELEMENTS = RenderMode.Elements;
|
||||
readonly DRAW_ARRAYS_INSTANCED = RenderMode.ArraysInstanced;
|
||||
readonly DRAW_ELEMENTS_INSTANCED = RenderMode.ElementsInstanced;
|
||||
// 其他常量
|
||||
readonly MAX_TEXTURE_COUNT: number = 0;
|
||||
|
||||
@ -264,10 +276,14 @@ export class Shader extends Container<EShaderEvent> {
|
||||
const gl = this.gl;
|
||||
const program = this.program;
|
||||
if (!gl || !program) return;
|
||||
const ready = this.defaultReady() && program.ready();
|
||||
const useDefault = program.defaultReady;
|
||||
const dr = useDefault ? this.defaultReady() : true;
|
||||
const ready = dr && program.ready();
|
||||
if (!ready) return;
|
||||
const indices = program.usingIndices;
|
||||
if (!indices) return;
|
||||
const param = program.getDrawParams(program.renderMode);
|
||||
if (!param) return;
|
||||
|
||||
// 清空画布
|
||||
gl.viewport(0, 0, this.canvas.width, this.canvas.height);
|
||||
@ -281,11 +297,34 @@ export class Shader extends Container<EShaderEvent> {
|
||||
return;
|
||||
}
|
||||
|
||||
// 准备顶点索引
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indices.data);
|
||||
|
||||
// 绘制
|
||||
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
|
||||
switch (program.renderMode) {
|
||||
case RenderMode.Arrays: {
|
||||
const { mode, first, count } = param as DrawArraysParam;
|
||||
gl.drawArrays(mode, first, count);
|
||||
}
|
||||
case RenderMode.Elements: {
|
||||
const { mode, count, type, offset } =
|
||||
param as DrawElementsParam;
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indices.data);
|
||||
gl.drawElements(mode, count, type, offset);
|
||||
}
|
||||
case RenderMode.ArraysInstanced: {
|
||||
const { mode, first, count, instanceCount } =
|
||||
param as DrawArraysInstancedParam;
|
||||
gl.drawArraysInstanced(mode, first, count, instanceCount);
|
||||
}
|
||||
case RenderMode.ElementsInstanced: {
|
||||
const {
|
||||
mode,
|
||||
count,
|
||||
type,
|
||||
offset,
|
||||
instanceCount: ins
|
||||
} = param as DrawElementsInstancedParam;
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indices.data);
|
||||
gl.drawElementsInstanced(mode, count, type, offset, ins);
|
||||
}
|
||||
}
|
||||
|
||||
this.postDraw();
|
||||
}
|
||||
@ -529,6 +568,12 @@ interface IShaderAttribArray {
|
||||
stride: GLsizei,
|
||||
offset: GLintptr
|
||||
): void;
|
||||
/**
|
||||
* 设置顶点指针更新时刻。
|
||||
* 参考 https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/vertexAttribDivisor
|
||||
* @param divisor 每多少个实例更新一次,0表示每个顶点都更新
|
||||
*/
|
||||
divisor(divisor: number): void;
|
||||
/**
|
||||
* 启用这个顶点数据
|
||||
*/
|
||||
@ -871,6 +916,11 @@ class ShaderAttribArray implements IShaderAttribArray {
|
||||
gl.vertexAttribIPointer(this.location, size, type, stride, offset);
|
||||
}
|
||||
|
||||
divisor(divisor: number): void {
|
||||
const gl = this.gl;
|
||||
gl.vertexAttribDivisor(this.location, divisor);
|
||||
}
|
||||
|
||||
enable(): void {
|
||||
this.gl.enableVertexAttribArray(this.location);
|
||||
}
|
||||
@ -1041,7 +1091,6 @@ class ShaderTexture2D implements IShaderTexture2D {
|
||||
width = Math.min(width, this.width - x);
|
||||
height = Math.min(height, this.height - y);
|
||||
}
|
||||
console.log(1);
|
||||
|
||||
gl.texSubImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
@ -1057,6 +1106,41 @@ class ShaderTexture2D implements IShaderTexture2D {
|
||||
}
|
||||
}
|
||||
|
||||
interface DrawArraysParam {
|
||||
mode: GLenum;
|
||||
first: number;
|
||||
count: number;
|
||||
}
|
||||
|
||||
interface DrawElementsParam {
|
||||
mode: GLenum;
|
||||
count: number;
|
||||
type: GLenum;
|
||||
offset: GLintptr;
|
||||
}
|
||||
|
||||
interface DrawArraysInstancedParam {
|
||||
mode: GLenum;
|
||||
first: number;
|
||||
count: number;
|
||||
instanceCount: number;
|
||||
}
|
||||
|
||||
interface DrawElementsInstancedParam {
|
||||
mode: GLenum;
|
||||
count: number;
|
||||
type: GLenum;
|
||||
offset: GLintptr;
|
||||
instanceCount: number;
|
||||
}
|
||||
|
||||
interface DrawParamsMap {
|
||||
[RenderMode.Arrays]: DrawArraysParam;
|
||||
[RenderMode.ArraysInstanced]: DrawArraysInstancedParam;
|
||||
[RenderMode.Elements]: DrawElementsParam;
|
||||
[RenderMode.ElementsInstanced]: DrawElementsInstancedParam;
|
||||
}
|
||||
|
||||
interface ShaderProgramEvent {
|
||||
load: [];
|
||||
unload: [];
|
||||
@ -1099,6 +1183,15 @@ export class ShaderProgram extends EventEmitter<ShaderProgramEvent> {
|
||||
|
||||
/** 着色器内容是否是默认内容,可以用于优化空着色器 */
|
||||
modified: boolean = false;
|
||||
/** 是否使用默认内容 */
|
||||
defaultReady: boolean = true;
|
||||
/** 渲染模式 */
|
||||
renderMode: RenderMode = RenderMode.Elements;
|
||||
|
||||
private arraysParams: DrawArraysParam | null = null;
|
||||
private elementsParams: DrawElementsParam | null = null;
|
||||
private arraysInstancedParams: DrawArraysInstancedParam | null = null;
|
||||
private elementsInstancedParams: DrawElementsInstancedParam | null = null;
|
||||
|
||||
/** 是否需要重新编译着色器 */
|
||||
private shaderDirty: boolean = true;
|
||||
@ -1128,6 +1221,131 @@ export class ShaderProgram extends EventEmitter<ShaderProgramEvent> {
|
||||
return this.readyFn?.() ?? true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否使用默认内容,设为 false 后,将不再将子元素的内容绑定到纹理上
|
||||
*/
|
||||
useDefault(use: boolean) {
|
||||
this.defaultReady = use;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置渲染模式,目前可选 {@link Shader.DRAW_ARRAYS} 至 {@link Shader.DRAW_INSTANCED}
|
||||
*/
|
||||
mode(mode: RenderMode) {
|
||||
this.renderMode = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定渲染模式的渲染参数
|
||||
* @param param 渲染模式
|
||||
*/
|
||||
getDrawParams<T extends RenderMode>(param: T): DrawParamsMap[T] | null {
|
||||
switch (param) {
|
||||
case RenderMode.Arrays:
|
||||
return this.arraysParams as DrawParamsMap[T];
|
||||
case RenderMode.ArraysInstanced:
|
||||
return this.arraysInstancedParams as DrawParamsMap[T];
|
||||
case RenderMode.Elements:
|
||||
return this.elementsParams as DrawParamsMap[T];
|
||||
case RenderMode.ElementsInstanced:
|
||||
return this.elementsInstancedParams as DrawParamsMap[T];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 DRAW_ARRAYS 模式下的渲染参数
|
||||
* 参考 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/drawArrays
|
||||
* @param mode 渲染模式
|
||||
* @param first 第一个元素的位置
|
||||
* @param count 渲染多少个元素
|
||||
*/
|
||||
paramArrays(mode: GLenum, first: number, count: number) {
|
||||
if (!this.arraysParams) {
|
||||
this.arraysParams = { mode, first, count };
|
||||
} else {
|
||||
this.arraysParams.mode = mode;
|
||||
this.arraysParams.first = first;
|
||||
this.arraysParams.count = count;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 DRAW_ARRAYS_INSTANCED 模式下的渲染参数
|
||||
* 参考 https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/drawArraysInstanced
|
||||
* @param mode 渲染模式
|
||||
* @param first 第一个元素的位置
|
||||
* @param count 渲染多少个元素
|
||||
* @param instanceCount 渲染实例数量
|
||||
*/
|
||||
paramArraysInstanced(
|
||||
mode: GLenum,
|
||||
first: number,
|
||||
count: number,
|
||||
instanceCount: number
|
||||
) {
|
||||
if (!this.arraysInstancedParams) {
|
||||
this.arraysInstancedParams = { mode, first, count, instanceCount };
|
||||
} else {
|
||||
this.arraysInstancedParams.mode = mode;
|
||||
this.arraysInstancedParams.first = first;
|
||||
this.arraysInstancedParams.count = count;
|
||||
this.arraysInstancedParams.instanceCount = instanceCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 DRAW_ELEMENTS 模式下的渲染参数
|
||||
* 参考 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/drawElements
|
||||
* @param mode 渲染模式
|
||||
* @param count 渲染元素数量
|
||||
* @param type 数据类型
|
||||
* @param offset 偏移量
|
||||
*/
|
||||
paramElements(mode: GLenum, count: number, type: GLenum, offset: number) {
|
||||
if (!this.elementsParams) {
|
||||
this.elementsParams = { mode, count, type, offset };
|
||||
} else {
|
||||
this.elementsParams.mode = mode;
|
||||
this.elementsParams.count = count;
|
||||
this.elementsParams.type = type;
|
||||
this.elementsParams.offset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 DRAW_ELEMENTS 模式下的渲染参数
|
||||
* 参考 https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/drawElementsInstanced
|
||||
* @param mode 渲染模式
|
||||
* @param count 渲染元素数量
|
||||
* @param type 数据类型
|
||||
* @param offset 偏移量
|
||||
* @param instanceCount 渲染实例数量
|
||||
*/
|
||||
paramElementsInstanced(
|
||||
mode: GLenum,
|
||||
count: number,
|
||||
type: GLenum,
|
||||
offset: number,
|
||||
instanceCount: number
|
||||
) {
|
||||
if (!this.elementsInstancedParams) {
|
||||
this.elementsInstancedParams = {
|
||||
mode,
|
||||
count,
|
||||
type,
|
||||
offset,
|
||||
instanceCount
|
||||
};
|
||||
} else {
|
||||
this.elementsInstancedParams.mode = mode;
|
||||
this.elementsInstancedParams.count = count;
|
||||
this.elementsInstancedParams.type = type;
|
||||
this.elementsInstancedParams.offset = offset;
|
||||
this.elementsInstancedParams.instanceCount = instanceCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换渲染时使用的顶点索引
|
||||
* @param name 要使用的顶点索引名称
|
||||
@ -1564,6 +1782,7 @@ export class ShaderProgram extends EventEmitter<ShaderProgramEvent> {
|
||||
tex.enable();
|
||||
indices.buffer(new Uint16Array([0, 1, 2, 2, 3, 1]), gl.STATIC_DRAW);
|
||||
this.useIndices(indices);
|
||||
this.paramElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user