Add basic shader

This commit is contained in:
MrKBear 2022-02-08 17:36:26 +08:00
parent 2550e2e14f
commit 2235063a24
5 changed files with 138 additions and 25 deletions

View File

@ -0,0 +1,97 @@
import { ObjectData } from "@Model/Renderer";
import { GLContext } from "./GLContext";
import { GLShader } from "./GLShader";
export { BasicsShader }
interface IBasicsShaderAttribute {
aPosition: ObjectData
}
interface IBasicsShaderUniform {
uRadius: ObjectData,
uMvp: ObjectData,
uPosition: ObjectData,
uColor: ObjectData
}
/**
* Shader
* @class BasicsShader
*/
class BasicsShader extends GLShader<IBasicsShaderAttribute, IBasicsShaderUniform>{
public onLoad(context: GLContext) {
super.onLoad(context);
// 顶点着色
const vertex = `
attribute vec3 aPosition;
uniform vec3 uRadius;
uniform mat4 uMvp;
uniform vec3 uPosition;
void main(){
gl_Position = uMvp * vec4(aPosition * uRadius + uPosition, 1.);
}
`;
// 片段着色
const fragment = `
precision lowp float;
uniform vec3 uColor;
void main(){
gl_FragColor = vec4(uColor, 1.);
}
`;
// 保存代码
this.setSource(vertex, fragment);
// 编译
this.compile();
}
/**
*
*/
public radius(r: ObjectData){
this.gl.uniform3fv(
this.uniformLocate("uRadius"), r
);
return this;
}
/**
*
*/
public position(position: ObjectData){
this.gl.uniform3fv(
this.uniformLocate("uPosition"), position
);
return this;
}
/**
*
*/
public mvp(mat: ObjectData, transpose: boolean = false){
this.gl.uniformMatrix4fv(
this.uniformLocate("uMvp"), transpose, mat
);
return this;
}
/**
*
*/
public color(rgb: ObjectData){
this.gl.uniform3fv(
this.uniformLocate("uColor"), rgb
);
}
}

View File

@ -1,13 +1,21 @@
import { ObjectID, ObjectData, ICommonParam } from "@Model/Renderer"; import { ObjectID, ObjectData, ICommonParam } from "@Model/Renderer";
import { BasicRenderer, IRendererParams } from "./BasicRenderer"; import { BasicRenderer, IRendererParams } from "./BasicRenderer";
import { BasicsShader } from "./BasicShader";
interface IClassicRendererParams {} interface IClassicRendererParams {}
class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> {
onLoad(param: Partial<IClassicRendererParams & IRendererParams>): void { onLoad(param: Partial<IClassicRendererParams & IRendererParams>): void {
this.run();
// 自动调节分辨率
this.autoResize(); this.autoResize();
let shader = new BasicsShader();
!shader.isLoad && shader.onLoad(this.gl);
// 运行
this.run();
} }
clean(id?: ObjectID | ObjectID[]): this { clean(id?: ObjectID | ObjectID[]): this {
@ -22,7 +30,7 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> {
throw new Error("Method not implemented."); throw new Error("Method not implemented.");
} }
loop(): void { loop(t: number): void {
this.cleanCanvas(); this.cleanCanvas();
} }
} }

View File

@ -24,5 +24,7 @@ export abstract class GLContextObject<
/** /**
* *
*/ */
public abstract onLoad(context: GLContext): any; public onLoad(context: GLContext): any {
this.gl = context;
};
} }

View File

@ -1,10 +1,14 @@
import { EventType } from "@Model/Emitter"; import { EventType } from "@Model/Emitter";
import { GLContextObject } from "./GLContext" import { GLContextObject } from "./GLContext"
type IAnyObject = Record<string, any>;
/** /**
* Shader类 * Shader类
*/ */
abstract class GLShader< abstract class GLShader<
A extends IAnyObject = {},
U extends IAnyObject = {},
E extends Record<EventType, any> = {} E extends Record<EventType, any> = {}
> extends GLContextObject<E> { > extends GLContextObject<E> {
@ -60,34 +64,36 @@ abstract class GLShader<
this.fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER);
// 绑定源代码 // 绑定源代码
this.gl.shaderSource(!this.vertexShader, this.vertexShaderSource); this.gl.shaderSource(this.vertexShader!, this.vertexShaderSource);
this.gl.shaderSource(!this.fragmentShader, this.fragmentShaderSource); this.gl.shaderSource(this.fragmentShader!, this.fragmentShaderSource);
// 编译 // 编译
this.gl.compileShader(!this.vertexShader); this.gl.compileShader(this.vertexShader!);
this.gl.compileShader(!this.fragmentShader); this.gl.compileShader(this.fragmentShader!);
// 检测编译错误 // 检测编译错误
if(!this.gl.getShaderParameter(!this.vertexShader, this.gl.COMPILE_STATUS)){ if(!this.gl.getShaderParameter(this.vertexShader!, this.gl.COMPILE_STATUS)){
console.error("vertex:\r\n" + this.gl.getShaderInfoLog(!this.vertexShader)); return console.error("vertex:\r\n" + this.gl.getShaderInfoLog(this.vertexShader!));
} }
if(!this.gl.getShaderParameter(!this.fragmentShader, this.gl.COMPILE_STATUS)){ if(!this.gl.getShaderParameter(this.fragmentShader!, this.gl.COMPILE_STATUS)){
console.error("fragment:\r\n" + this.gl.getShaderInfoLog(!this.fragmentShader)); return console.error("fragment:\r\n" + this.gl.getShaderInfoLog(this.fragmentShader!));
} }
// 附加到程序 // 附加到程序
this.gl.attachShader(!this.program, !this.vertexShader); this.gl.attachShader(this.program!, this.vertexShader!);
this.gl.attachShader(!this.program, !this.fragmentShader); this.gl.attachShader(this.program!, this.fragmentShader!);
// 连接程序 // 连接程序
this.gl.linkProgram(!this.program); this.gl.linkProgram(this.program!);
// 检测链接错误 // 检测链接错误
if(!this.gl.getProgramParameter(!this.program, this.gl.LINK_STATUS)){ if(!this.gl.getProgramParameter(this.program!, this.gl.LINK_STATUS)){
console.error("link:\r\n" + this.gl.getProgramInfoLog(!this.program)); return console.error("link:\r\n" + this.gl.getProgramInfoLog(this.program!));
} }
console.log("shader compile success");
return this; return this;
} }
@ -104,15 +110,15 @@ abstract class GLShader<
/** /**
* attribLocation * attribLocation
*/ */
public attribLocate(attr: string){ public attribLocate<T extends keyof A>(attr: T){
// 获取缓存 // 获取缓存
let cache = this.attribLocationCache.get(attr); let cache = this.attribLocationCache.get(attr as string);
// 缓存搜索 // 缓存搜索
if (cache === undefined || cache <= -1){ if (cache === undefined || cache <= -1){
cache = this.gl.getAttribLocation(!this.program, attr); cache = this.gl.getAttribLocation(!this.program, attr as string);
if (cache === undefined || cache <= -1) { if (cache === undefined || cache <= -1) {
console.error("Attrib: can not get locate of " + attr); console.error("Attrib: can not get locate of " + attr);
@ -120,7 +126,7 @@ abstract class GLShader<
this.gl.enableVertexAttribArray(cache); this.gl.enableVertexAttribArray(cache);
} }
this.attribLocationCache.set(attr, cache); this.attribLocationCache.set(attr as string, cache);
return cache; return cache;
} }
@ -136,19 +142,19 @@ abstract class GLShader<
/** /**
* attribLocation * attribLocation
*/ */
public uniformLocate(uni: string) { public uniformLocate<T extends keyof U>(uni: T) {
// 获取缓存 // 获取缓存
let cache: WebGLUniformLocation | null = this.uniformLocationCache.get(uni) as any; let cache: WebGLUniformLocation | null = this.uniformLocationCache.get(uni as string) as any;
if (cache === undefined) cache = null; if (cache === undefined) cache = null;
// 缓存搜索 // 缓存搜索
if (!cache) { if (!cache) {
cache = this.gl.getUniformLocation(!this.program, uni); cache = this.gl.getUniformLocation(!this.program, uni as string);
if (!cache) console.error("Uniform: can not get locate of " + uni); if (!cache) console.error("Uniform: can not get locate of " + uni);
this.uniformLocationCache.set(uni, cache as any); this.uniformLocationCache.set(uni as string, cache as any);
return cache; return cache;
} }

View File

@ -45,7 +45,7 @@ type ObjectID = Symbol | string | number;
/** /**
* *
*/ */
type ObjectData = Array<number> | Float32Array | Float64Array; type ObjectData = Array<number> | Float32Array;
interface IRendererConstructor< interface IRendererConstructor<
M extends IAnyObject = {} M extends IAnyObject = {}