diff --git a/index.html b/index.html index 696e69b5..ff36f92d 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - Orillusion | Samples + Graphic3D | Samples - + \ No newline at end of file diff --git a/index.ts b/index.ts new file mode 100644 index 00000000..3b86b522 --- /dev/null +++ b/index.ts @@ -0,0 +1 @@ +export * from "./src/index" diff --git a/packages/debug/GUIHelp.ts b/packages/debug/GUIHelp.ts index 12b24969..324b4320 100644 --- a/packages/debug/GUIHelp.ts +++ b/packages/debug/GUIHelp.ts @@ -1,9 +1,11 @@ +import { GTAOPost } from '../../src/index.js'; import { GUI } from './dat.gui.module.js' /** * @internal */ class _GUIHelp { + public debug: boolean = false; public data: any; public gui: GUI; diff --git a/packages/effect/grass/geometry/GrassGeometry.ts b/packages/effect/grass/geometry/GrassGeometry.ts index fe8c89d7..0289b3b5 100644 --- a/packages/effect/grass/geometry/GrassGeometry.ts +++ b/packages/effect/grass/geometry/GrassGeometry.ts @@ -110,6 +110,9 @@ export class GrassGeometry extends GeometryBase { indexCount: indexes.length, vertexStart: 0, index: 0, + vertexCount: 0, + firstStart: 0, + topology: 0 }); this.bounds = new BoundingBox(Vector3.ZERO, new Vector3(9999, 9999, 9999)); diff --git a/packages/effect/grass/material/GrassMaterial.ts b/packages/effect/grass/material/GrassMaterial.ts index 3d3920a8..0974e034 100644 --- a/packages/effect/grass/material/GrassMaterial.ts +++ b/packages/effect/grass/material/GrassMaterial.ts @@ -1,4 +1,4 @@ -import { BlendMode, Color, GPUAddressMode, Material, RenderShader, RendererType, ShaderLib, Texture, Vector2, Vector3, Vector4 } from "@orillusion/core"; +import { BlendMode, Color, GPUAddressMode, Material, RenderShaderPass, PassType, Shader, ShaderLib, Texture, Vector2, Vector3, Vector4 } from "@orillusion/core"; import { GrassShader } from "../shader/GrassShader"; import { GrassVertexAttributeShader } from "../shader/GrassVertexAttributeShader"; import { GrassCastShadowShader } from "../shader/GrassCastShadowShader"; @@ -7,11 +7,12 @@ export class GrassMaterial extends Material { constructor() { super(); + let newShader = new Shader(); ShaderLib.register("GrassVertexAttributeShader", GrassVertexAttributeShader); ShaderLib.register("GrassShader", GrassShader); - let colorPass = new RenderShader(`GrassShader`, `GrassShader`); - this.defaultPass = colorPass; + let colorPass = new RenderShaderPass(`GrassShader`, `GrassShader`); + colorPass.passType = PassType.COLOR; colorPass.setShaderEntry(`VertMain`, `FragMain`) colorPass.setDefine("TRANSFORMVERTEX", true); let shaderState = colorPass.shaderState; @@ -21,17 +22,18 @@ export class GrassMaterial extends Material { shaderState.useLight = true; shaderState.castShadow = false; shaderState.blendMode = BlendMode.NONE; + newShader.addRenderPass(colorPass); ShaderLib.register("GrassCastShadowShader", GrassCastShadowShader); - let shadowPass = new RenderShader(`GrassCastShadowShader`, `GrassCastShadowShader`); + let shadowPass = new RenderShaderPass(`GrassCastShadowShader`, `GrassCastShadowShader`); + shadowPass.passType = PassType.SHADOW shadowPass.setDefine("USE_ALPHACUT", true); shadowPass.setDefine("TRANSFORMVERTEX", true); shadowPass.setShaderEntry(`VertMain`) shadowPass.shaderState.blendMode = BlendMode.NONE; shadowPass.shaderState.receiveEnv = false; - this.addPass(RendererType.SHADOW, shadowPass); - + newShader.addRenderPass(shadowPass); colorPass.setUniformColor("baseColor", new Color(0.0, 1.0, 0.0, 1.0)); colorPass.setUniformColor("grassBottomColor", new Color(3 / 255, 16 / 255, 3 / 255)); @@ -67,159 +69,118 @@ export class GrassMaterial extends Material { // this.baseMap = Engine3D.res.whiteTexture; colorPass.doubleSide = true; shadowPass.doubleSide = true; + + this.shader = newShader; } public set baseMap(texture: Texture) { - // texture.visibility = GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT; - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - this.defaultPass.setTexture(`baseMap`, texture); - shadowPass.setTexture(`baseMap`, texture); + this.shader.setTexture(`baseMap`, texture); } public get baseMap(): Texture { - return this.defaultPass.getTexture(`baseMap`); + return this.shader.getTexture(`baseMap`); } public set windMap(texture: Texture) { // texture.visibility = GPUShaderStage.VERTEX; texture.addressModeU = GPUAddressMode.repeat; texture.addressModeV = GPUAddressMode.repeat; - this.defaultPass.setTexture("windMap", texture); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setTexture("windMap", texture); + this.shader.setTexture("windMap", texture); } public set windBound(v: Vector4) { - this.defaultPass.setUniformVector4("windBound", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - this.defaultPass.setUniformVector4("windBound", v); - shadowPass.setUniformVector4("windBound", v); + this.shader.setUniformVector4("windBound", v); } public get windBound(): Vector4 { - return this.defaultPass.uniforms["windBound"].vector4; + return this.shader.getUniform("windBound").data; } public set grassBaseColor(v: Color) { - this.defaultPass.setUniformColor("grassBottomColor", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - shadowPass.setUniformColor("grassBottomColor", v); + this.shader.setUniformColor("grassBottomColor", v); } public get grassBaseColor(): Color { - return this.defaultPass.uniforms["grassBottomColor"].color; + return this.shader.getUniformColor("grassBottomColor"); } public set grassTopColor(v: Color) { - this.defaultPass.setUniformColor("grassTopColor", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformColor("grassTopColor", v); + this.shader.setUniformColor("grassTopColor", v); } public get grassTopColor(): Color { - return this.defaultPass.uniforms["grassTopColor"].color; + return this.shader.getUniformColor("grassTopColor"); } public set windDirection(v: Vector2) { - this.defaultPass.setUniformVector2("windDirection", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformVector2("windDirection", v); + this.shader.setUniformVector2("windDirection", v); } public get windDirection(): Vector2 { - return this.defaultPass.uniforms["windDirection"].vector2; + return this.shader.getUniform("windDirection").data; } public set windPower(v: number) { - this.defaultPass.setUniformFloat("windPower", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("windPower", v); + this.shader.setUniformFloat("windPower", v); } public get windPower(): number { - return this.defaultPass.uniforms["windPower"].data; + return this.shader.getUniform("windPower").data; } public set windSpeed(v: number) { - this.defaultPass.setUniformFloat("windSpeed", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("windSpeed", v); + this.shader.setUniformFloat("windSpeed", v); } public get windSpeed(): number { - return this.defaultPass.uniforms["windSpeed"].data; + return this.shader.getUniform("windSpeed").data; } public set grassHeight(v: number) { - this.defaultPass.setUniformFloat("grassHeight", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("grassHeight", v); + this.shader.setUniformFloat("grassHeight", v); } public get grassHeight(): number { - return this.defaultPass.uniforms["grassHeight"].data; + return this.shader.getUniform("grassHeight").data; } public set curvature(v: number) { - this.defaultPass.setUniformFloat("curvature", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("curvature", v); + this.shader.setUniformFloat("curvature", v); } public get curvature(): number { - return this.defaultPass.uniforms["curvature"].data; + return this.shader.getUniform("curvature").data; } public set roughness(v: number) { - this.defaultPass.setUniformFloat("roughness", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("roughness", v); + this.shader.setUniformFloat("roughness", v); } public get roughness(): number { - return this.defaultPass.uniforms["roughness"].data; + return this.shader.getUniform("roughness").data; } public set translucent(v: number) { - this.defaultPass.setUniformFloat("translucent", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("translucent", v); + this.shader.setUniformFloat("translucent", v); } public get translucent(): number { - return this.defaultPass.uniforms["translucent"].data; + return this.shader.getUniform("translucent").data; } public set soft(v: number) { - this.defaultPass.setUniformFloat("soft", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("soft", v); + this.shader.setUniformFloat("soft", v); } public get soft(): number { - return this.defaultPass.uniforms["soft"].data; + return this.shader.getUniform("soft").data; } public set specular(v: number) { - this.defaultPass.setUniformFloat("specular", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("specular", v); + this.shader.setUniformFloat("specular", v); } public get specular(): number { - return this.defaultPass.uniforms["specular"].data; + return this.shader.getUniform("specular").data; } } \ No newline at end of file diff --git a/packages/effect/grass/shader/GrassCastShadowShader.ts b/packages/effect/grass/shader/GrassCastShadowShader.ts index 57eeb1db..9446fa85 100644 --- a/packages/effect/grass/shader/GrassCastShadowShader.ts +++ b/packages/effect/grass/shader/GrassCastShadowShader.ts @@ -36,6 +36,7 @@ export let GrassCastShadowShader = /* wgsl */` var windMap: texture_2d; const DEGREES_TO_RADIANS : f32 = 3.1415926 / 180.0 ; + const PI : f32 = 3.1415926 ; @vertex fn VertMain( vertex:VertexAttributes ) -> VertexOutput { diff --git a/packages/effect/grass/shader/GrassShader.ts b/packages/effect/grass/shader/GrassShader.ts index 36f6bf5d..9b401019 100644 --- a/packages/effect/grass/shader/GrassShader.ts +++ b/packages/effect/grass/shader/GrassShader.ts @@ -42,6 +42,7 @@ export let GrassShader = /* wgsl */` var windMap: texture_2d; const DEGREES_TO_RADIANS : f32 = 3.1415926 / 180.0 ; + const PI : f32 = 3.1415926 ; @vertex fn VertMain( vertex:VertexAttributes ) -> VertexOutput { diff --git a/packages/media-extention/ChromaKeyMaterial.ts b/packages/media-extention/ChromaKeyMaterial.ts index d2c0fe23..c22c7e80 100644 --- a/packages/media-extention/ChromaKeyMaterial.ts +++ b/packages/media-extention/ChromaKeyMaterial.ts @@ -1,4 +1,4 @@ -import { Engine3D, ShaderLib, Vector4, Color, BlendMode, registerMaterial, Material, RenderShader, Texture } from "@orillusion/core"; +import { Engine3D, ShaderLib, Vector4, Color, BlendMode, registerMaterial, Material, RenderShaderPass, Texture } from "@orillusion/core"; import { ChromaKeyShader } from "./ChromaKeyShader"; /** @@ -14,7 +14,7 @@ export class ChromaKeyMaterial extends Material { super(); ShaderLib.register("ChromaKeyShader", ChromaKeyShader); - this.defaultPass = new RenderShader( + this.defaultPass = new RenderShaderPass( `ChromaKeyShader`, `ChromaKeyShader` ); diff --git a/packages/media-extention/ImageMaterial.ts b/packages/media-extention/ImageMaterial.ts index bba37b19..7c396d18 100644 --- a/packages/media-extention/ImageMaterial.ts +++ b/packages/media-extention/ImageMaterial.ts @@ -1,4 +1,4 @@ -import { Engine3D, ShaderLib, Vector4, Color, Texture, Material, RenderShader } from "@orillusion/core"; +import { Engine3D, ShaderLib, Vector4, Color, Texture, Material, RenderShaderPass } from "@orillusion/core"; import ImageMaterialShader from "./ImageMaterialShader.wgsl?raw"; @@ -15,7 +15,7 @@ export class ImageMaterial extends Material { constructor() { super(); ShaderLib.register("ImageMaterialShader", ImageMaterialShader); - this.defaultPass = new RenderShader(`ImageMaterialShader`, `ImageMaterialShader`); + this.defaultPass = new RenderShaderPass(`ImageMaterialShader`, `ImageMaterialShader`); this.defaultPass.setShaderEntry(`VertMain`, `FragMain`) this.defaultPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); this.defaultPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); diff --git a/packages/media-extention/VideoMaterial.ts b/packages/media-extention/VideoMaterial.ts index cba9ae88..acc01e85 100644 --- a/packages/media-extention/VideoMaterial.ts +++ b/packages/media-extention/VideoMaterial.ts @@ -1,5 +1,5 @@ -import { Color, Engine3D, Material, RenderShader, ShaderLib, Texture, Vector4, registerMaterial } from '@orillusion/core'; +import { Color, Engine3D, Material, PassType, RenderShaderPass, Shader, ShaderLib, Texture, Vector4 } from '@orillusion/core'; import { VideoShader } from './VideoShader'; /** @@ -16,18 +16,19 @@ export class VideoMaterial extends Material { super(); ShaderLib.register('VideoShader', VideoShader); - ShaderLib.register("VideoShader", VideoShader); + let newShader = new Shader(); - this.defaultPass = new RenderShader(`VideoShader`, `VideoShader`); - this.defaultPass.setShaderEntry(`VertMain`, `FragMain`) + let colorPass = new RenderShaderPass(`VideoShader`, `VideoShader`); + colorPass.passType = PassType.COLOR; + colorPass.setShaderEntry(`VertMain`, `FragMain`) - this.defaultPass.setShaderEntry(`VertMain`, `FragMain`) - this.defaultPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); - this.defaultPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); - this.defaultPass.setUniformColor(`baseColor`, new Color()); - this.defaultPass.setUniformVector4(`rectClip`, new Vector4(0, 0, 0, 0)); - this.defaultPass.setUniformFloat(`alphaCutoff`, 0.5); - let shaderState = this.defaultPass.shaderState; + colorPass.setShaderEntry(`VertMain`, `FragMain`) + colorPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + colorPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + colorPass.setUniformColor(`baseColor`, new Color()); + colorPass.setUniformVector4(`rectClip`, new Vector4(0, 0, 0, 0)); + colorPass.setUniformFloat(`alphaCutoff`, 0.5); + let shaderState = colorPass.shaderState; shaderState.acceptShadow = false; shaderState.receiveEnv = false; shaderState.acceptGI = false; @@ -35,30 +36,32 @@ export class VideoMaterial extends Material { shaderState.castShadow = false; shaderState.useZ = false; + newShader.addRenderPass(colorPass); + this.shader = newShader; // default value - this.defaultPass.setTexture(`baseMap`, Engine3D.res.whiteTexture); + colorPass.setTexture(`baseMap`, Engine3D.res.whiteTexture); } /** * Set the clip rect area */ public set rectClip(value: Vector4) { - this.defaultPass.uniforms[`rectClip`].vector4 = value; + this.shader.setUniformVector4("rectClip", value); } /** * Get the clip rect area */ public get rectClip(): Vector4 { - return this.defaultPass.uniforms[`rectClip`].vector4; + return this.shader.getUniform("rectClip").data; } public get baseMap(): Texture { - return this.defaultPass.getTexture(`baseMap`); + return this.shader.getTexture(`baseMap`); } public set baseMap(value: Texture) { - this.defaultPass.setTexture(`baseMap`, value); + this.shader.setTexture(`baseMap`, value); } /** @@ -74,11 +77,4 @@ export class VideoMaterial extends Material { public set shadowMap(texture: Texture) { //not need shadowMap texture } - - /** - * Start debug GUI - */ - debug() { - - } } \ No newline at end of file diff --git a/packages/particle/ParticleSystem.ts b/packages/particle/ParticleSystem.ts index a03334cc..b566267a 100644 --- a/packages/particle/ParticleSystem.ts +++ b/packages/particle/ParticleSystem.ts @@ -1,4 +1,4 @@ -import { ShaderLib, RenderNode, RendererMask, GeometryBase, Ctor, PlaneGeometry, Vector3, View3D, Time, Material, RendererType } from "@orillusion/core"; +import { ShaderLib, RenderNode, RendererMask, GeometryBase, Ctor, PlaneGeometry, Vector3, View3D, Time, Material, PassType } from "@orillusion/core"; import { ParticleMaterial } from "./material/ParticleMaterial"; import { ParticleSimulator } from "./simulator/ParticleSimulator"; import { ParticleDataStructShader } from "./shader/ParticleDataStruct"; @@ -136,7 +136,7 @@ export class ParticleSystem extends RenderNode { this.playing = true; } - let renderShader = this.material.getPass(RendererType.COLOR)[0]; + let renderShader = this.material.getPass(PassType.COLOR)[0]; renderShader.setStorageBuffer(`particleGlobalData`, this.particleSimulator.particleGlobalMemory); renderShader.setStorageBuffer(`particleLocalDatas`, this.particleSimulator.particleLocalMemory); this.instanceCount = this.particleSimulator.maxParticle; diff --git a/packages/particle/material/ParticleMaterial.ts b/packages/particle/material/ParticleMaterial.ts index 4931f844..ea52bae8 100644 --- a/packages/particle/material/ParticleMaterial.ts +++ b/packages/particle/material/ParticleMaterial.ts @@ -1,4 +1,4 @@ -import { Engine3D, ShaderLib, Texture, GPUCompareFunction, BlendMode, Color, Vector4, RenderShader, Material, RendererType } from "@orillusion/core"; +import { Engine3D, ShaderLib, Texture, GPUCompareFunction, BlendMode, Color, Vector4, RenderShaderPass, Material, PassType, Shader } from "@orillusion/core"; import { ParticleRenderShader } from "../shader/ParticleRenderShader"; /** @@ -10,42 +10,43 @@ export class ParticleMaterial extends Material { super(); ShaderLib.register("ParticleRenderShader", ParticleRenderShader); - let colorPass = new RenderShader(`ParticleRenderShader`, `ParticleRenderShader`); - this.defaultPass = colorPass; + let newShader = new Shader(); + + let colorPass = new RenderShaderPass(`ParticleRenderShader`, `ParticleRenderShader`); + colorPass.passType = PassType.COLOR; colorPass.setShaderEntry(`VertMain`, `FragMain`) + newShader.addRenderPass(colorPass); colorPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); colorPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); colorPass.setUniformColor(`baseColor`, new Color()); colorPass.setUniformFloat(`alphaCutoff`, 0.5); - - let shaderState = colorPass.shaderState; - shaderState.acceptShadow = false; - shaderState.receiveEnv = false; - shaderState.acceptGI = false; - shaderState.useLight = false; - shaderState.castShadow = false; - shaderState.depthWriteEnabled = true; + colorPass.renderOrder = 3001; + colorPass.shaderState.transparent = true; + colorPass.shaderState.depthWriteEnabled = false; + colorPass.shaderState.depthCompare = GPUCompareFunction.less; + colorPass.shaderState.acceptShadow = false; + colorPass.shaderState.receiveEnv = false; + colorPass.shaderState.acceptGI = false; + colorPass.shaderState.useLight = false; + colorPass.shaderState.castShadow = false; + + this.shader = newShader; // default value this.baseMap = Engine3D.res.whiteTexture; this.blendMode = BlendMode.ADD; - this.defaultPass.renderOrder = 3001; - this.defaultPass.shaderState.transparent = true; - this.defaultPass.shaderState.depthWriteEnabled = false; - this.defaultPass.shaderState.depthCompare = GPUCompareFunction.less; - } public set baseMap(texture: Texture) { //not need env texture - this.defaultPass.setTexture(`baseMap`, texture); + this.shader.setTexture(`baseMap`, texture); } public get baseMap() { - return this.defaultPass.getTexture(`baseMap`); + return this.shader.getTexture(`baseMap`); } - + public set envMap(texture: Texture) { //not need env texture } diff --git a/packages/particle/shader/FastMath.ts b/packages/particle/shader/FastMath.ts index bbcfc4b8..38dd3c11 100644 --- a/packages/particle/shader/FastMath.ts +++ b/packages/particle/shader/FastMath.ts @@ -14,4 +14,44 @@ fn lengthFast( v :vec3 ) -> f32 var LengthSqr = dot(v,v); return sqrtFast( LengthSqr ); } + +fn asinFast( x:f32 )-> f32 +{ + return (0.5 * PI) - acosFast(x); +} + +fn acosFast( inX: f32 ) -> f32 +{ + var x = abs(inX); + var res = -0.156583 * x + (0.5 * PI); + res *= sqrt(1.0 - x); + + if(inX >= 0.0){ + return res ; + }else{ + return PI - res ; + } +} + +fn acosFast4( inX : f32 ) +{ + var x1 = abs(inX); + var x2 = x1 * x1; + var x3 = x2 * x1; + var s; + + s = -0.2121144 * x1 + 1.5707288; + s = 0.0742610 * x2 + s; + s = -0.0187293 * x3 + s; + s = sqrt(1.0 - x1) * s; + + // acos function mirroring + // check per platform if compiles to a selector - no branch neeeded + if(inX >= 0.0){ + return s ; + }else{ + return PI - s ; + } +} + `; diff --git a/packages/particle/shader/ParticleRenderShader.ts b/packages/particle/shader/ParticleRenderShader.ts index 06a167a0..eddfd362 100644 --- a/packages/particle/shader/ParticleRenderShader.ts +++ b/packages/particle/shader/ParticleRenderShader.ts @@ -112,7 +112,7 @@ export let ParticleRenderShader = /* wgsl */ ` let v3Right: vec3 = normalize(cross(vec3( 0.0 , 1.0 , 0.0 ) * mat3, v3Look)); let v3Up: vec3 = cross(v3Look, v3Right); return mat3x3(v3Right, v3Up, v3Look); - } + } fn makeAxleRotationMatrix(axis: vec3, angle: f32) -> mat4x4 { var x = axis.x; diff --git a/public b/public index fcd386df..1e9b664b 160000 --- a/public +++ b/public @@ -1 +1 @@ -Subproject commit fcd386dff4f93f6e4d5de69ac6d0160a06dae799 +Subproject commit 1e9b664bf6b6fc2985cfa5608463b57eed1324e5 diff --git a/samples/animation/Sample_CurveAnimation.ts b/samples/animation/Sample_CurveAnimation.ts index c02ead0e..bd84a543 100644 --- a/samples/animation/Sample_CurveAnimation.ts +++ b/samples/animation/Sample_CurveAnimation.ts @@ -1,5 +1,6 @@ import { Object3D, Scene3D, AnimationCurve, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, Keyframe, Object3DUtil, Time } from "@orillusion/core"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { GUIUtil } from "@samples/utils/GUIUtil"; class Sample_AnimCurve { lightObj3D: Object3D; @@ -13,6 +14,7 @@ class Sample_AnimCurve { async run() { await Engine3D.init({ beforeRender: () => this.renderUpdate() }); + Engine3D.setting.render.debug = true; Engine3D.setting.shadow.autoUpdate = true; Engine3D.setting.shadow.updateFrameRate = 1; Engine3D.setting.shadow.type = `HARD`; @@ -36,6 +38,8 @@ class Sample_AnimCurve { await this.initScene(); sky.relativeTransform = this.lightObj3D.transform; + + GUIUtil.renderDebug(); } async initScene() { @@ -51,6 +55,8 @@ class Sample_AnimCurve { directLight.intensity = 30; this.scene.addChild(this.lightObj3D); + GUIUtil.renderDirLight(directLight); + //create animation curve 1 this.curve1 = new AnimationCurve(); this.curve1.addKeyFrame(new Keyframe(0, 1)); diff --git a/samples/animation/Sample_MorphTarget.ts b/samples/animation/Sample_MorphTarget.ts index 3f876564..bfab5393 100644 --- a/samples/animation/Sample_MorphTarget.ts +++ b/samples/animation/Sample_MorphTarget.ts @@ -3,7 +3,7 @@ import { Object3D, Scene3D, Engine3D, AtmosphericComponent, webGPUContext, Hover import { GUIUtil } from "@samples/utils/GUIUtil"; // Sample of how to control the morphtarget animation -class Sample_MorphTarget { +export class Sample_MorphTarget { lightObj3D: Object3D; scene: Scene3D; influenceData: { [key: string]: number } = {}; @@ -91,4 +91,4 @@ class Sample_MorphTarget { } -new Sample_MorphTarget().run(); \ No newline at end of file +// new Sample_MorphTarget().run(); \ No newline at end of file diff --git a/samples/animation/Sample_PropertyAnimation.ts b/samples/animation/Sample_PropertyAnimation.ts index 87277b02..9606cc89 100644 --- a/samples/animation/Sample_PropertyAnimation.ts +++ b/samples/animation/Sample_PropertyAnimation.ts @@ -67,6 +67,7 @@ class Sample_PropertyAnimation { } private displayGUI() { + GUIUtil.renderShadowSetting(true); // restart the animation clip GUIHelp.addFolder('Property Animation'); GUIHelp.addButton('Restart', () => { diff --git a/samples/base/Sample_InitEngine.ts b/samples/base/Sample_InitEngine.ts index b30c9382..b06dd80c 100644 --- a/samples/base/Sample_InitEngine.ts +++ b/samples/base/Sample_InitEngine.ts @@ -1,4 +1,4 @@ -import { AtmosphericComponent, BoxGeometry, CameraUtil, DirectLight, Engine3D, GTAOPost, HDRBloomPost, HoverCameraController, KelvinUtil, LambertMaterial, LitMaterial, MeshRenderer, Object3D, OcclusionSystem, PlaneGeometry, PostProcessingComponent, Quaternion, Scene3D, SphereGeometry, UnLitMaterial, Vector3, Vector3Ex, View3D } from '@orillusion/core'; +import { AtmosphericComponent, BloomPost, BoxGeometry, CameraUtil, DirectLight, Engine3D, GTAOPost, HoverCameraController, KelvinUtil, LambertMaterial, LitMaterial, MeshRenderer, Object3D, OcclusionSystem, PlaneGeometry, PostProcessingComponent, Quaternion, Scene3D, SphereGeometry, UnLitMaterial, Vector3, Vector3Ex, View3D } from '@orillusion/core'; import { GUIHelp } from '@orillusion/debug/GUIHelp'; import { Stats } from '@orillusion/stats'; import { GUIUtil } from '@samples/utils/GUIUtil'; @@ -37,7 +37,7 @@ export class Sample_InitEngine { Engine3D.startRenderView(this.view); let postCom = scene.addComponent(PostProcessingComponent); - let post = postCom.addPost(HDRBloomPost) as HDRBloomPost; + let post = postCom.addPost(BloomPost) as BloomPost; let post2 = postCom.addPost(GTAOPost) as GTAOPost; GUIUtil.renderBloom(post); diff --git a/samples/ext/Sample_Boxes.ts b/samples/ext/Sample_Boxes.ts index 2b628d9d..8907a5c7 100644 --- a/samples/ext/Sample_Boxes.ts +++ b/samples/ext/Sample_Boxes.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Engine3D, View3D, Scene3D, CameraUtil, AtmosphericComponent, webGPUContext, HoverCameraController, Object3D, DirectLight, KelvinUtil, PlaneGeometry, VertexAttributeName, LitMaterial, MeshRenderer, Vector4, Vector3, Matrix3, PostProcessingComponent, TAAPost, BitmapTexture2D, GlobalFog, Color, BoxGeometry, UnLitMaterial, PointLight, GTAOPost, HDRBloomPost } from "@orillusion/core"; +import { Engine3D, View3D, Scene3D, CameraUtil, AtmosphericComponent, webGPUContext, HoverCameraController, Object3D, DirectLight, KelvinUtil, PlaneGeometry, VertexAttributeName, LitMaterial, MeshRenderer, Vector4, Vector3, Matrix3, PostProcessingComponent, TAAPost, BitmapTexture2D, GlobalFog, Color, BoxGeometry, UnLitMaterial, PointLight, GTAOPost, BloomPost } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { GrassComponent, TerrainGeometry } from "@orillusion/effect"; @@ -32,7 +32,7 @@ class Sample_Boxes { this.post = this.view.scene.addComponent(PostProcessingComponent); this.post.addPost(GTAOPost); - this.post.addPost(HDRBloomPost); + this.post.addPost(BloomPost); let fog = this.post.addPost(GlobalFog); fog.start = 91.0862; fog.end = 487.5528; diff --git a/samples/ext/Sample_Grass.ts b/samples/ext/Sample_Grass.ts index f5a486d5..b85e6d3f 100644 --- a/samples/ext/Sample_Grass.ts +++ b/samples/ext/Sample_Grass.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Engine3D, View3D, Scene3D, CameraUtil, AtmosphericComponent, webGPUContext, HoverCameraController, Object3D, DirectLight, KelvinUtil, PlaneGeometry, VertexAttributeName, LitMaterial, MeshRenderer, Vector4, Vector3, Matrix3, PostProcessingComponent, TAAPost, BitmapTexture2D, GlobalFog, Color } from "@orillusion/core"; +import { Engine3D, View3D, Scene3D, CameraUtil, AtmosphericComponent, webGPUContext, HoverCameraController, Object3D, DirectLight, KelvinUtil, PlaneGeometry, VertexAttributeName, LitMaterial, MeshRenderer, Vector4, Vector3, Matrix3, PostProcessingComponent, TAAPost, BitmapTexture2D, GlobalFog, Color, FXAAPost } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { GrassComponent, TerrainGeometry } from "@orillusion/effect"; import { Stats } from "@orillusion/stats"; @@ -32,6 +32,7 @@ export class Sample_Grass { Engine3D.startRenderView(this.view); this.post = this.view.scene.addComponent(PostProcessingComponent); + let fxaa = this.post.addPost(FXAAPost); let fog = this.post.addPost(GlobalFog); fog.fogColor = new Color(136 / 255, 215 / 255, 236 / 255, 1); fog.start = 0; @@ -121,53 +122,32 @@ export class Sample_Grass { scene.addChild(grass); } - GUIHelp.addFolder("grass-wind"); - // GUIHelp.add(grassCom.grassMaterial.windBound, "x", -terrainSize * 0.5, terrainSize * 0.5, 0.0001).onChange((v) => { - // let bound = grassCom.grassMaterial.windBound; - // bound.x = v; - // grassCom.grassMaterial.windBound = bound; + // GUIHelp.addFolder("grass-wind"); + // GUIHelp.addColor(grassCom.grassMaterial, "grassBaseColor"); + // GUIHelp.addColor(grassCom.grassMaterial, "grassTopColor"); + // GUIHelp.add(grassCom.grassMaterial.windDirection, "x", -1.0, 1, 0.0001).onChange((v) => { + // let tv = grassCom.grassMaterial.windDirection; + // tv.x = v; + // grassCom.grassMaterial.windDirection = tv; // }); - // GUIHelp.add(grassCom.grassMaterial.windBound, "y", -terrainSize * 0.5, terrainSize * 0.5, 0.0001).onChange((v) => { - // let bound = grassCom.grassMaterial.windBound; - // bound.y = v; - // grassCom.grassMaterial.windBound = bound; + // GUIHelp.add(grassCom.grassMaterial.windDirection, "y", -1.0, 1, 0.0001).onChange((v) => { + // let tv = grassCom.grassMaterial.windDirection; + // tv.y = v; + // grassCom.grassMaterial.windDirection = tv; // }); - // GUIHelp.add(grassCom.grassMaterial.windBound, "z", 0, terrainSize, 0.0001).onChange((v) => { - // let bound = grassCom.grassMaterial.windBound; - // bound.z = v; - // grassCom.grassMaterial.windBound = bound; - // }); - // GUIHelp.add(grassCom.grassMaterial.windBound, "w", 0, terrainSize, 0.0001).onChange((v) => { - // let bound = grassCom.grassMaterial.windBound; - // bound.w = v; - // grassCom.grassMaterial.windBound = bound; - // }); - - GUIHelp.addColor(grassCom.grassMaterial, "grassBaseColor"); - GUIHelp.addColor(grassCom.grassMaterial, "grassTopColor"); - GUIHelp.add(grassCom.grassMaterial.windDirection, "x", -1.0, 1, 0.0001).onChange((v) => { - let tv = grassCom.grassMaterial.windDirection; - tv.x = v; - grassCom.grassMaterial.windDirection = tv; - }); - GUIHelp.add(grassCom.grassMaterial.windDirection, "y", -1.0, 1, 0.0001).onChange((v) => { - let tv = grassCom.grassMaterial.windDirection; - tv.y = v; - grassCom.grassMaterial.windDirection = tv; - }); - GUIHelp.add(grassCom.grassMaterial, "windPower", 0.0, 20, 0.0001); - GUIHelp.add(grassCom.grassMaterial, "windSpeed", 0.0, 20, 0.0001); - GUIHelp.add(grassCom.grassMaterial, "curvature", 0.0, 1, 0.0001); - GUIHelp.add(grassCom.grassMaterial, "grassHeight", 0.0, 100, 0.0001); - GUIHelp.add(grassCom.grassMaterial, "roughness", 0.0, 1, 0.0001); - GUIHelp.add(grassCom.grassMaterial, "translucent", 0.0, 1, 0.0001); - GUIHelp.add(grassCom.grassMaterial, "soft", 0.0, 10, 0.0001); - GUIHelp.add(grassCom.grassMaterial, "specular", 0.0, 10, 0.0001); - GUIHelp.endFolder(); - - GUIHelp.addFolder("shadow"); - GUIHelp.add(Engine3D.setting.shadow, "shadowBound", 0.0, 3000, 0.0001); - GUIHelp.endFolder(); + // GUIHelp.add(grassCom.grassMaterial, "windPower", 0.0, 20, 0.0001); + // GUIHelp.add(grassCom.grassMaterial, "windSpeed", 0.0, 20, 0.0001); + // GUIHelp.add(grassCom.grassMaterial, "curvature", 0.0, 1, 0.0001); + // GUIHelp.add(grassCom.grassMaterial, "grassHeight", 0.0, 100, 0.0001); + // GUIHelp.add(grassCom.grassMaterial, "roughness", 0.0, 1, 0.0001); + // GUIHelp.add(grassCom.grassMaterial, "translucent", 0.0, 1, 0.0001); + // GUIHelp.add(grassCom.grassMaterial, "soft", 0.0, 10, 0.0001); + // GUIHelp.add(grassCom.grassMaterial, "specular", 0.0, 10, 0.0001); + // GUIHelp.endFolder(); + + // GUIHelp.addFolder("shadow"); + // GUIHelp.add(Engine3D.setting.shadow, "shadowBound", 0.0, 3000, 0.0001); + // GUIHelp.endFolder(); let globalFog = this.post.getPost(GlobalFog); // GUIUtil.renderFog(globalFog); diff --git a/samples/ext/Sample_Terrain.ts b/samples/ext/Sample_Terrain.ts index 0e73b4b4..eb21cceb 100644 --- a/samples/ext/Sample_Terrain.ts +++ b/samples/ext/Sample_Terrain.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Engine3D, View3D, Scene3D, CameraUtil, AtmosphericComponent, webGPUContext, HoverCameraController, Object3D, DirectLight, KelvinUtil, PlaneGeometry, VertexAttributeName, LitMaterial, MeshRenderer, Vector4, Vector3, Matrix3, PostProcessingComponent, TAAPost, BitmapTexture2D, GlobalFog, Color } from "@orillusion/core"; +import { Engine3D, View3D, Scene3D, CameraUtil, AtmosphericComponent, webGPUContext, HoverCameraController, Object3D, DirectLight, KelvinUtil, PlaneGeometry, VertexAttributeName, LitMaterial, MeshRenderer, Vector4, Vector3, Matrix3, PostProcessingComponent, TAAPost, BitmapTexture2D, GlobalFog, Color, FXAAPost } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { GrassComponent, TerrainGeometry } from "@orillusion/effect"; @@ -29,6 +29,7 @@ class Sample_Terrain { Engine3D.startRenderView(this.view); this.post = this.view.scene.addComponent(PostProcessingComponent); + let fxaa = this.post.addPost(FXAAPost); let fog = this.post.addPost(GlobalFog); fog.start = 2000; fog.end = 0; diff --git a/samples/geometry/Sample_ConduitGeometry2.ts b/samples/geometry/Sample_ConduitGeometry2.ts index ca4d07f2..9bed6d7f 100644 --- a/samples/geometry/Sample_ConduitGeometry2.ts +++ b/samples/geometry/Sample_ConduitGeometry2.ts @@ -1,4 +1,4 @@ -import { AttributeAnimCurve, BitmapTexture2D, BlendMode, Color, Engine3D, ExtrudeGeometry, LitMaterial, MeshRenderer, Object3D, Object3DUtil, PropertyAnimClip, PropertyAnimation, Scene3D, Vector3, WrapMode } from "@orillusion/core"; +import { AttributeAnimCurve, BitmapTexture2D, BlendMode, BloomPost, Color, Engine3D, ExtrudeGeometry, LitMaterial, MeshRenderer, Object3D, Object3DUtil, PropertyAnimClip, PropertyAnimation, Scene3D, Vector3, WrapMode } from "@orillusion/core"; import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene"; import { UVMoveComponent } from "@samples/material/script/UVMoveComponent"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; @@ -25,7 +25,8 @@ class Sample_ConduitGeometry2 { let exampleScene = createExampleScene(param); exampleScene.camera.enableCSM = true; this.scene = exampleScene.scene; - Engine3D.startRenderView(exampleScene.view); + let job = Engine3D.startRenderView(exampleScene.view); + job.addPost(new BloomPost()); await this.createMaterial(); await this.loadCurveData(); @@ -53,6 +54,7 @@ class Sample_ConduitGeometry2 { animation.speed = 0.5; animation.appendClip(this.animClip); } + async loadCurveData() { // load external curve data let json: any = await Engine3D.res.loadJSON('json/anim_0.json'); @@ -76,6 +78,7 @@ class Sample_ConduitGeometry2 { let texture = new BitmapTexture2D(); texture.addressModeU = "repeat"; texture.addressModeV = "repeat"; + // await texture.load('textures/grid.jpg'); await texture.load('textures/cell.png'); this.material.baseMap = texture; } diff --git a/samples/gi/Sample_GI.ts b/samples/gi/Sample_GI.ts index 96730343..c5959152 100644 --- a/samples/gi/Sample_GI.ts +++ b/samples/gi/Sample_GI.ts @@ -1,5 +1,5 @@ import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene"; -import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Object3DUtil, GTAOPost, HDRBloomPost, PostProcessingComponent, TAAPost } from "@orillusion/core"; +import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Object3DUtil, GTAOPost, PostProcessingComponent, TAAPost, BloomPost, FXAAPost } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; @@ -12,6 +12,7 @@ class Sample_GI { Engine3D.setting.gi.enable = true; Engine3D.setting.gi.debug = true; + Engine3D.setting.render.debug = true; Engine3D.setting.gi.probeYCount = 3; Engine3D.setting.gi.probeXCount = 6; @@ -33,16 +34,6 @@ class Sample_GI { Engine3D.setting.shadow.autoUpdate = true; Engine3D.setting.shadow.updateFrameRate = 1; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - debug: false, - blurX: 4, - blurY: 4, - luminosityThreshold: 0.9, - radius: 4, - strength: 1.2 - }; - await Engine3D.init({ renderLoop: () => { if (this.giComponent?.isStart) { @@ -60,16 +51,20 @@ class Sample_GI { exampleScene.camera.enableCSM = true; Engine3D.startRenderViews([exampleScene.view]); let job = Engine3D.getRenderJob(exampleScene.view); + + let postProcessing = this.scene.addComponent(PostProcessingComponent); + // postProcessing.addPost(FXAAPost); + // postProcessing.addPost(TAAPost); + // postProcessing.addPost(GTAOPost); + postProcessing.addPost(BloomPost); await this.initScene(); this.addGIProbes(); // GUIUtil.renderAtomosphericSky(exampleScene.atmosphericSky); - GUIUtil.renderDirLight(exampleScene.light); + GUIUtil.renderDirLight(exampleScene.light, false); - let postProcessing = this.scene.addComponent(PostProcessingComponent); - postProcessing.addPost(TAAPost); - postProcessing.addPost(GTAOPost); - postProcessing.addPost(HDRBloomPost); + GUIUtil.renderDebug(); + GUIUtil.renderAtmosphericSky(exampleScene.atmosphericSky); } private giComponent: GlobalIlluminationComponent; @@ -83,7 +78,7 @@ class Sample_GI { async initScene() { { let floorHeight = 20; - let floor = Object3DUtil.GetSingleCube(1000, floorHeight, 1000, 0.6, 0.6, 0.6); + let floor = Object3DUtil.GetSingleCube(1000, floorHeight, 1000, 0.5, 0.5, 0.5); floor.y = -floorHeight; this.scene.addChild(floor); } diff --git a/samples/gi/Sample_GICornellBox.ts b/samples/gi/Sample_GICornellBox.ts index 6286e26b..d2fbd84a 100644 --- a/samples/gi/Sample_GICornellBox.ts +++ b/samples/gi/Sample_GICornellBox.ts @@ -1,5 +1,5 @@ import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene"; -import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Vector3, GTAOPost, PostProcessingComponent, HDRBloomPost } from "@orillusion/core"; +import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Vector3, GTAOPost, PostProcessingComponent, BloomPost } from "@orillusion/core"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { GUIUtil } from "@samples/utils/GUIUtil"; @@ -36,15 +36,6 @@ class Sample_GICornellBox { Engine3D.setting.shadow.updateFrameRate = 1; Engine3D.setting.render.debug = true; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - debug: false, - blurX: 4, - blurY: 4, - luminosityThreshold: 0.9, - radius: 4, - strength: 1.2 - }; await Engine3D.init({ renderLoop: () => { @@ -66,7 +57,7 @@ class Sample_GICornellBox { let postProcessing = this.scene.addComponent(PostProcessingComponent); postProcessing.addPost(GTAOPost); - postProcessing.addPost(HDRBloomPost); + postProcessing.addPost(BloomPost); Engine3D.setting.shadow.csmScatteringExp = 0.8; GUIHelp.add(Engine3D.setting.shadow, 'csmScatteringExp', 0.5, 1, 0.001); diff --git a/samples/graphic/Sample_GraphicLine.ts b/samples/graphic/Sample_GraphicLine.ts index 7907b96d..436abe52 100644 --- a/samples/graphic/Sample_GraphicLine.ts +++ b/samples/graphic/Sample_GraphicLine.ts @@ -1,5 +1,5 @@ import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene"; -import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Object3DUtil, GTAOPost, HDRBloomPost, PostProcessingComponent, TAAPost, Vector3, Color, AnimationCurve, Keyframe } from "@orillusion/core"; +import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Object3DUtil, GTAOPost, PostProcessingComponent, TAAPost, Vector3, Color, AnimationCurve, Keyframe } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; @@ -11,16 +11,6 @@ class Sample_GraphicLine { Engine3D.setting.material.materialChannelDebug = true; Engine3D.setting.material.materialDebug = false; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - debug: false, - blurX: 4, - blurY: 4, - luminosityThreshold: 0.9, - radius: 4, - strength: 1.2 - }; - await Engine3D.init({}); GUIHelp.init(); let param = createSceneParam(); diff --git a/samples/index.ts b/samples/index.ts index d05c6510..7558858f 100644 --- a/samples/index.ts +++ b/samples/index.ts @@ -68,19 +68,3 @@ document.body.appendChild(iframe) } } - -// new Sample_PointLight().run(); -// new Sample_LoadGLB4().run(); - -// import { Sample_Grass } from "./ext/Sample_Grass"; -// console.log("a"); -// new Sample_Grass().run(); - -// new Sample_drawCallShareGeometry().run(); - -// import { Sample_InitEngine } from "./base/Sample_InitEngine"; -// import { Sample_PointLight } from "./lights/Sample_PointLight"; -// new Sample_InitEngine().run(); -// // new Sample_PointLight().run(); - - diff --git a/samples/lights/Sample_PointLightShadow.ts b/samples/lights/Sample_PointLightShadow.ts index 3baabe03..d4f3dd0c 100644 --- a/samples/lights/Sample_PointLightShadow.ts +++ b/samples/lights/Sample_PointLightShadow.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, Vector3, View3D, SphereGeometry, Object3D, MeshRenderer, LitMaterial, PointLight, BoxGeometry, Object3DUtil } from "@orillusion/core"; +import { Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, Vector3, View3D, SphereGeometry, Object3D, MeshRenderer, LitMaterial, PointLight, BoxGeometry, Object3DUtil, PostProcessingComponent, FXAAPost } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; // sample of point light shadow @@ -10,6 +10,7 @@ class Sample_PointLightShadow { Engine3D.setting.shadow.enable = true; Engine3D.setting.shadow.debug = true; + Engine3D.setting.render.debug = true; Engine3D.setting.material.materialChannelDebug = true; Engine3D.setting.material.materialDebug = true; @@ -32,6 +33,13 @@ class Sample_PointLightShadow { view.camera = mainCamera; Engine3D.startRenderView(view); + + let post = this.scene.addComponent(PostProcessingComponent); + post.addPost(FXAAPost); + + setTimeout(() => { + GUIUtil.renderDebug(); + }, 1000); } async initScene(scene: Scene3D) { diff --git a/samples/lights/Sample_ShadowAlpha.ts b/samples/lights/Sample_ShadowAlpha.ts deleted file mode 100644 index e1f364e5..00000000 --- a/samples/lights/Sample_ShadowAlpha.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Scene3D, HoverCameraController, Engine3D, AtmosphericComponent, Object3D, Camera3D, Vector3, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, CameraUtil, SphereGeometry, Color, Object3DUtil, BlendMode, Vector4 } from "@orillusion/core"; -import { GUIUtil } from "@samples/utils/GUIUtil"; - -//sample of direction light -class Sample_ShadowAlpha { - scene: Scene3D; - async run() { - Engine3D.setting.shadow.enable = true; - // Engine3D.setting.render.zPrePass = true; - Engine3D.setting.shadow.autoUpdate = true; - Engine3D.setting.shadow.shadowSize = 1024; - Engine3D.setting.render.debug = true; - Engine3D.setting.render.useLogDepth = false; - Engine3D.setting.occlusionQuery.octree = { width: 1000, height: 1000, depth: 1000, x: 0, y: 0, z: 0 } - await Engine3D.init({}); - - GUIHelp.init(); - - this.scene = new Scene3D(); - let sky = this.scene.addComponent(AtmosphericComponent); - - // init camera3D - let mainCamera = CameraUtil.createCamera3D(null, this.scene); - // mainCamera.enableCSM = true; - mainCamera.perspective(60, Engine3D.aspect, 1, 5000.0); - //set camera data - mainCamera.object3D.z = -15; - mainCamera.object3D.addComponent(HoverCameraController).setCamera(-15, -35, 200); - - sky.relativeTransform = this.initLight(); - await this.initScene(); - - let view = new View3D(); - view.scene = this.scene; - view.camera = mainCamera; - - Engine3D.startRenderView(view); - GUIUtil.renderDebug(); - } - - // create direction light - private initLight() { - // add a direction light - let lightObj3D = new Object3D(); - lightObj3D.rotationX = 46; - lightObj3D.rotationY = 62; - lightObj3D.rotationZ = 0; - let sunLight = lightObj3D.addComponent(DirectLight); - sunLight.intensity = 15; - sunLight.lightColor = KelvinUtil.color_temperature_to_rgb(6553); - sunLight.castShadow = true; - - GUIUtil.renderDirLight(sunLight); - this.scene.addChild(lightObj3D); - return sunLight.transform; - } - - async initScene() { - let tex = await Engine3D.res.loadTexture("textures/grid.jpg"); - - { - let geometry = new SphereGeometry(20, 100, 20); - let material = new LitMaterial(); - let obj = new Object3D(); - let mr = obj.addComponent(MeshRenderer); - mr.geometry = geometry; - mr.material = material; - this.scene.addChild(obj); - } - { - let mat = new LitMaterial(); - // mat.baseMap = Engine3D.res.grayTexture; - mat.uvTransform_1 = new Vector4(0, 0, 100, 100); - let floor = new Object3D(); - let mr = floor.addComponent(MeshRenderer); - mr.geometry = new BoxGeometry(10000, 1, 10000); - mr.material = mat; - mat.baseMap = tex; - this.scene.addChild(floor); - } - } -} - -new Sample_ShadowAlpha().run(); diff --git a/samples/loader/Sample_FlightHelmet.ts b/samples/loader/Sample_FlightHelmet.ts index f2a67da9..10473a05 100644 --- a/samples/loader/Sample_FlightHelmet.ts +++ b/samples/loader/Sample_FlightHelmet.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Object3D, Scene3D, HoverCameraController, Engine3D, CameraUtil, View3D, SSRPost, HDRBloomPost, AtmosphericComponent, DirectLight, KelvinUtil, Time } from "@orillusion/core"; +import { Object3D, Scene3D, HoverCameraController, Engine3D, CameraUtil, View3D, SSRPost, AtmosphericComponent, DirectLight, KelvinUtil, Time } from "@orillusion/core"; import { GUIUtil as GUIUtil } from "@samples/utils/GUIUtil"; class Sample_FlightHelmet { @@ -22,16 +22,6 @@ class Sample_FlightHelmet { Engine3D.setting.shadow.shadowBound = 10; Engine3D.setting.render.postProcessing.ssao.radius = 0.018; Engine3D.setting.render.postProcessing.ssao.aoPower = 1; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - blurX: 4, - blurY: 4, - strength: 1.5, - luminosityThreshold: 0.1, - radius: 4, - debug: false - }; - this.scene = new Scene3D(); let camera = CameraUtil.createCamera3DObject(this.scene); diff --git a/samples/loader/Sample_LoadGLB.ts b/samples/loader/Sample_LoadGLB.ts index 780a0f83..2ef82b3b 100644 --- a/samples/loader/Sample_LoadGLB.ts +++ b/samples/loader/Sample_LoadGLB.ts @@ -1,4 +1,4 @@ -import { AtmosphericComponent, Engine3D, GTAOPost, HDRBloomPost, LitMaterial, MeshRenderer, Object3D, PlaneGeometry, PostProcessingComponent, Scene3D, SkyRenderer, TAAPost } from "@orillusion/core"; +import { AtmosphericComponent, BloomPost, Engine3D, GTAOPost, LitMaterial, MeshRenderer, Object3D, PlaneGeometry, PostProcessingComponent, Scene3D, SkyRenderer, TAAPost } from "@orillusion/core"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { createExampleScene } from "@samples/utils/ExampleScene"; import { GUIUtil } from "@samples/utils/GUIUtil"; @@ -27,7 +27,7 @@ export class Sample_LoadGLB { let post = this.scene.addComponent(PostProcessingComponent); let gtao = post.addPost(GTAOPost); // let taa = post.addPost(TAAPost); - let hdr = post.addPost(HDRBloomPost); + let hdr = post.addPost(BloomPost); GUIUtil.renderBloom(hdr); GUIUtil.renderDirLight(ex.light); diff --git a/samples/loader/Sample_LoadGLB2.ts b/samples/loader/Sample_LoadGLB2.ts index 8a951fe0..f6701594 100644 --- a/samples/loader/Sample_LoadGLB2.ts +++ b/samples/loader/Sample_LoadGLB2.ts @@ -9,8 +9,10 @@ export class Sample_LoadGLB2 { scene: Scene3D; async run() { - await Engine3D.init(); + Engine3D.setting.render.debug = true; Engine3D.setting.shadow.autoUpdate = true; + + await Engine3D.init(); let exampleScene = createExampleScene(); exampleScene.atmosphericSky.displaySun = false; exampleScene.atmosphericSky.sunRadiance = 1; @@ -22,7 +24,8 @@ export class Sample_LoadGLB2 { await this.initScene(); GUIHelp.init(); - GUIUtil.renderAtomosphericSky(exampleScene.atmosphericSky); + GUIUtil.renderAtmosphericSky(exampleScene.atmosphericSky); + GUIUtil.renderDebug(); } async initScene() { diff --git a/samples/loader/Sample_LoadGLTF.ts b/samples/loader/Sample_LoadGLTF.ts index 10364f32..a8b96b4b 100644 --- a/samples/loader/Sample_LoadGLTF.ts +++ b/samples/loader/Sample_LoadGLTF.ts @@ -9,16 +9,9 @@ class Sample_LoadGLTF { async run() { //config settings Engine3D.setting.material.materialChannelDebug = true; - Engine3D.setting.shadow.shadowBound = 5; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - blurX: 4, - blurY: 4, - luminosityThreshold: 0.8, - strength: 0.86, - radius: 4, - debug: false - }; + Engine3D.setting.shadow.shadowBound = 100; + Engine3D.setting.shadow.shadowSize = 2048; + //init engine await Engine3D.init(); diff --git a/samples/material/Sample_ChangeMaterial.ts b/samples/material/Sample_ChangeMaterial.ts index 7bcae940..020acd3f 100644 --- a/samples/material/Sample_ChangeMaterial.ts +++ b/samples/material/Sample_ChangeMaterial.ts @@ -12,17 +12,6 @@ class Sample_ChangeMaterial { Engine3D.setting.material.materialChannelDebug = true; Engine3D.setting.shadow.shadowBound = 5; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - blurX: 4, - blurY: 4, - luminosityThreshold: 0.8, - exposure: 1, - strength: 0.86, - radius: 4, - debug: false - }; - this.scene = new Scene3D(); let sky = this.scene.addComponent(AtmosphericComponent); @@ -107,6 +96,8 @@ class Sample_ChangeMaterial { GUIHelp.addButton("change-mat3", () => { mr.material = mat3; }); + + GUIHelp.open(); } } diff --git a/samples/material/Sample_ClearCoat.ts b/samples/material/Sample_ClearCoat.ts index 3d9ec9fc..dedc92c5 100644 --- a/samples/material/Sample_ClearCoat.ts +++ b/samples/material/Sample_ClearCoat.ts @@ -16,17 +16,6 @@ class Sample_ClearCoat { //config settings Engine3D.setting.shadow.shadowBound = 300; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - blurX: 4, - blurY: 4, - exposure: 1, - luminosityThreshold: 0.8, - strength: 0.86, - radius: 4, - debug: false - }; - this.scene = new Scene3D(); let camera = CameraUtil.createCamera3DObject(this.scene); diff --git a/samples/material/Sample_GraphicMeshWave.ts b/samples/material/Sample_GraphicMeshWave.ts new file mode 100644 index 00000000..d0bc573f --- /dev/null +++ b/samples/material/Sample_GraphicMeshWave.ts @@ -0,0 +1,146 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode, PrefabParser } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMeshWave { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + let view = new View3D(); + view.scene = this.scene; + view.camera = camera; + + Engine3D.startRenderView(view); + + GUIUtil.renderDebug(); + + await this.initScene(); + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + texts.push(await Engine3D.res.loadTexture("textures/128/star_0031.png") as BitmapTexture2D); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 100; + this.height = 100; + // let geometry = new BoxGeometry(1, 1, 1); + let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geometry, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + mr.material.blendMode = BlendMode.ADD; + mr.material.transparent = true; + mr.material.depthWriteEnabled = false; + mr.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + // mr.setTextureID(i, i % texts.length); + // mr.setTextureID(i, 52); + // mr.setTextureID(i, 35); + mr.setTextureID(i, 0); + // mr.setTextureID(i, 18); + + let size = 1.0; + element.transform.scaleX = size; + element.transform.scaleY = size; + element.transform.scaleZ = size; + } + } + } + + update() { + if (this.parts) { + let pos = new Vector3(); + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + this.wave(i, pos); + + element.transform.localPosition = pos; + } + } + } + + private wave(i: number, pos: Vector3) { + let x = Math.floor(i / this.width); + let z = i % this.height; + pos.set(x, 0, z); + pos.y = Math.sin((x + Time.frame * 0.01) / 8) * 15 * Math.cos((z + Time.frame * 0.01) / 15); + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + + } + +} diff --git a/samples/material/Sample_GraphicMesh_0.ts b/samples/material/Sample_GraphicMesh_0.ts new file mode 100644 index 00000000..c836e4d8 --- /dev/null +++ b/samples/material/Sample_GraphicMesh_0.ts @@ -0,0 +1,201 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_0 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + + cafe: number = 47; + frame: number = 16; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + let view = new View3D(); + view.scene = this.scene; + view.camera = camera; + + Engine3D.startRenderView(view); + + GUIUtil.renderDebug(); + + await this.initScene(); + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0003.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0025.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0026.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0001.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0003.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0009.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0016.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0017.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0019.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0020.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0021.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0022.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0024.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0025.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0004.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0008.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0011.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0012.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0014.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0016.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/star_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0004.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0008.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0011.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0013.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0014.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0016.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0018.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0019.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0020.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0021.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0023.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0024.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0025.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0027.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0028.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0031.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0035.png") as BitmapTexture2D); + + // texts.push(Engine3D.res.grayTexture); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + { + this.width = 200; + this.height = 100; + // let geometry = new BoxGeometry(1, 1, 1); + let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geometry, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + mr.material.blendMode = BlendMode.ADD; + // mr.material.doubleSide = true; + mr.material.transparent = true; + mr.material.depthWriteEnabled = false; + mr.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + // mr.setTextureID(i, i % texts.length); + // mr.setTextureID(i, 52); + mr.setTextureID(i, 35); + + + // mr.setTextureID(i, 39); + // mr.setTextureID(i, 18); + } + } + } + + update() { + if (this.parts) { + let pos = new Vector3(); + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + let tmp = this.sphericalFibonacci(i, this.parts.length); + tmp.scaleBy(Math.sin((i + Time.frame * 0.01)) * 50); + + element.transform.localPosition = tmp; + } + } + } + + private wave(i: number, pos: Vector3) { + let x = Math.floor(i / this.width); + let z = i % this.height; + pos.set(x, 0, z); + pos.y = Math.sin((x + Time.frame * 0.01) / 8) * 15 * Math.cos((z + Time.frame * 0.01) / 15); + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + + } + +} diff --git a/samples/material/Sample_GraphicMesh_1.ts b/samples/material/Sample_GraphicMesh_1.ts new file mode 100644 index 00000000..81a70d9f --- /dev/null +++ b/samples/material/Sample_GraphicMesh_1.ts @@ -0,0 +1,200 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_1 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + let view = new View3D(); + view.scene = this.scene; + view.camera = camera; + + Engine3D.startRenderView(view); + + GUIUtil.renderDebug(); + + await this.initScene(); + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0003.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0025.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0026.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0001.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0003.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0009.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0016.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0017.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0019.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0020.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0021.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0022.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0024.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0025.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0004.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0008.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0011.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0012.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0014.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0016.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/star_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0004.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0008.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0011.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0013.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0014.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0016.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0018.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0019.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0020.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0021.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0023.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0024.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0025.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0027.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0028.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0031.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0035.png") as BitmapTexture2D); + + // texts.push(Engine3D.res.grayTexture); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 200; + this.height = 100; + // let geometry = new BoxGeometry(1, 1, 1); + let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geometry, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + mr.material.blendMode = BlendMode.ADD; + // mr.material.doubleSide = true; + mr.material.transparent = true; + mr.material.depthWriteEnabled = false; + mr.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + // mr.setTextureID(i, i % texts.length); + // mr.setTextureID(i, 52); + mr.setTextureID(i, 35); + // mr.setTextureID(i, 39); + // mr.setTextureID(i, 18); + } + } + } + + update() { + if (this.parts) { + let pos = new Vector3(); + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + let tmp = this.sphericalFibonacci(i, this.parts.length); + tmp.scaleBy(Math.sin((i + Time.frame * 0.01 * this.frame * 0.01)) * this.cafe); + + element.transform.localPosition = tmp; + } + } + } + + private wave(i: number, pos: Vector3) { + let x = Math.floor(i / this.width); + let z = i % this.height; + pos.set(x, 0, z); + pos.y = Math.sin((x + Time.frame * 0.01) / 8) * 15 * Math.cos((z + Time.frame * 0.01) / 15); + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + + } + +} diff --git a/samples/material/Sample_GraphicMesh_2.ts b/samples/material/Sample_GraphicMesh_2.ts new file mode 100644 index 00000000..a6c7945e --- /dev/null +++ b/samples/material/Sample_GraphicMesh_2.ts @@ -0,0 +1,207 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_2 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + let view = new View3D(); + view.scene = this.scene; + view.camera = camera; + + Engine3D.startRenderView(view); + + GUIUtil.renderDebug(); + + await this.initScene(); + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0003.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0025.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0026.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0001.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0003.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0009.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0016.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0017.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0019.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0020.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0021.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0022.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0024.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0025.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0004.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0008.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0011.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0012.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0014.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0016.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/star_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0004.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0008.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0011.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0013.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0014.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0016.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0018.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0019.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0020.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0021.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0023.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0024.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0025.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0027.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0028.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0031.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0035.png") as BitmapTexture2D); + + // texts.push(Engine3D.res.grayTexture); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 200; + this.height = 100; + // let geometry = new BoxGeometry(1, 1, 1); + let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geometry, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + mr.material.blendMode = BlendMode.ADD; + // mr.material.doubleSide = true; + mr.material.transparent = true; + mr.material.depthWriteEnabled = false; + mr.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + // mr.setTextureID(i, i % texts.length); + // mr.setTextureID(i, 52); + mr.setTextureID(i, 35); + // mr.setTextureID(i, 39); + // mr.setTextureID(i, 18); + } + } + } + + update() { + if (this.parts) { + let pos = new Vector3(); + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + let tmp = this.sphericalFibonacci(i, this.parts.length); + let r = Math.sin((i + Time.frame * 0.01 * this.frame * 0.01)) * this.cafe; + tmp.scaleBy(r); + + let tr = 1.0 - (r / this.cafe); + + element.transform.scaleX = tr; + element.transform.scaleY = tr; + element.transform.scaleZ = tr; + + element.transform.localPosition = tmp; + } + } + } + + private wave(i: number, pos: Vector3) { + let x = Math.floor(i / this.width); + let z = i % this.height; + pos.set(x, 0, z); + pos.y = Math.sin((x + Time.frame * 0.01) / 8) * 15 * Math.cos((z + Time.frame * 0.01) / 15); + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + + } + +} diff --git a/samples/material/Sample_GraphicMesh_3.ts b/samples/material/Sample_GraphicMesh_3.ts new file mode 100644 index 00000000..4890c6b7 --- /dev/null +++ b/samples/material/Sample_GraphicMesh_3.ts @@ -0,0 +1,158 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode, PrefabParser } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_3 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + let view = new View3D(); + view.scene = this.scene; + view.camera = camera; + + Engine3D.startRenderView(view); + + GUIUtil.renderDebug(); + + await this.initScene(); + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + PrefabParser.useWebp = false; + let node = await Engine3D.res.loadGltf("gltfs/glb/beer.glb") as Object3D; + let geo = node.getComponents(MeshRenderer)[0].geometry; + + // texts.push(await Engine3D.res.loadTexture("textures/128/star_0031.png") as BitmapTexture2D); + texts.push(Engine3D.res.yellowTexture); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 100; + this.height = 20; + // let geometry = new BoxGeometry(1, 1, 1); + // let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geo, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + // mr.material.blendMode = BlendMode.ADD; + // mr.material.transparent = true; + // mr.material.depthWriteEnabled = false; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + // mr.setTextureID(i, i % texts.length); + // mr.setTextureID(i, 52); + // mr.setTextureID(i, 35); + mr.setTextureID(i, 0); + // mr.setTextureID(i, 18); + + let size = Math.random() * 5.0 + 1.0; + element.transform.scaleX = size; + element.transform.scaleY = size; + element.transform.scaleZ = size; + } + } + } + + update() { + if (this.parts) { + let pos = new Vector3(); + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + let tmp = this.sphericalFibonacci(i, this.parts.length); + let r = this.cafe; + tmp.scaleBy(r); + + let tr = Math.sin(i * (Time.frame * 0.0001) * this.frame * 0.01) + 1.0; + tr *= 0.1; + element.transform.scaleX = tr; + element.transform.scaleY = tr; + element.transform.scaleZ = tr; + + element.transform.localPosition = tmp; + } + } + } + + private wave(i: number, pos: Vector3) { + let x = Math.floor(i / this.width); + let z = i % this.height; + pos.set(x, 0, z); + pos.y = Math.sin((x + Time.frame * 0.01) / 8) * 15 * Math.cos((z + Time.frame * 0.01) / 15); + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + + } + +} diff --git a/samples/material/Sample_GraphicMesh_4.ts b/samples/material/Sample_GraphicMesh_4.ts new file mode 100644 index 00000000..ae7424d1 --- /dev/null +++ b/samples/material/Sample_GraphicMesh_4.ts @@ -0,0 +1,147 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode, PrefabParser } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_4 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + let view = new View3D(); + view.scene = this.scene; + view.camera = camera; + + Engine3D.startRenderView(view); + + GUIUtil.renderDebug(); + + await this.initScene(); + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + texts.push(await Engine3D.res.loadTexture("textures/128/star_0031.png") as BitmapTexture2D); + // texts.push(Engine3D.res.yellowTexture); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 80; + this.height = 80; + // let geometry = new BoxGeometry(1, 1, 1); + let geo = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geo, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + mr.material.useBillboard = true; + mr.material.blendMode = BlendMode.ADD; + mr.material.transparent = true; + mr.material.depthWriteEnabled = false; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + mr.setTextureID(i, 0); + + let size = Math.random() * 5.0 + 1.0; + element.transform.scaleX = size; + element.transform.scaleY = size; + element.transform.scaleZ = size; + } + } + } + + update() { + if (this.parts) { + let pos = new Vector3(); + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + let tmp = this.sphericalFibonacci(i, this.parts.length); + let r = this.cafe; + + // let tr = Math.sin((i * (Time.frame % 3600 * 0.0001 / 5) * this.frame * 0.01)) + 1.0; + let tr = Math.sin((tmp.x * (Time.frame * 0.001)) % 1000) * 3 + 1.0; + element.transform.scaleX = tr; + element.transform.scaleY = tr; + element.transform.scaleZ = tr; + tmp.scaleBy(r + tr * 2); + + element.transform.localPosition = tmp; + } + } + } + + private wave(i: number, pos: Vector3) { + let x = Math.floor(i / this.width); + let z = i % this.height; + pos.set(x, 0, z); + pos.y = Math.sin((x + Time.frame * 0.01) / 8) * 15 * Math.cos((z + Time.frame * 0.01) / 15); + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + + } + +} diff --git a/samples/material/Sample_PBR.ts b/samples/material/Sample_PBR.ts index 0901950d..4259ffbc 100644 --- a/samples/material/Sample_PBR.ts +++ b/samples/material/Sample_PBR.ts @@ -11,6 +11,7 @@ class Sample_PBR { async run() { await Engine3D.init({}); + Engine3D.setting.render.debug = true; Engine3D.setting.shadow.shadowBound = 5; GUIHelp.init(); @@ -28,6 +29,8 @@ class Sample_PBR { Engine3D.startRenderView(view); + GUIUtil.renderDebug(); + await this.initScene(); sky.relativeTransform = this.lightObj3D.transform; } diff --git a/samples/material/Sample_PBRMaterial.ts b/samples/material/Sample_PBRMaterial.ts index 8a4c6b18..40eeba35 100644 --- a/samples/material/Sample_PBRMaterial.ts +++ b/samples/material/Sample_PBRMaterial.ts @@ -11,16 +11,6 @@ class Sample_PBRMaterial { //config settings Engine3D.setting.render.debug = true; Engine3D.setting.shadow.shadowBound = 50; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - blurX: 4, - blurY: 4, - luminosityThreshold: 0.8, - strength: 0.86, - exposure: 1, - radius: 4, - debug: false - }; await Engine3D.init({ canvasConfig: { alpha: true, zIndex: 11, backgroundImage: '/logo/bg.webp' } }); @@ -73,7 +63,7 @@ class Sample_PBRMaterial { if (material instanceof LitMaterial) { material.metallic = 1; material.roughness = 0.35; - material.defaultPass.setDefine("USE_TANGENT", false); + material.setDefine("USE_TANGENT", false); } } model.transform.scaleX = 10; diff --git a/samples/material/Sample_UVMove.ts b/samples/material/Sample_UVMove.ts index 05308fd2..77b36736 100644 --- a/samples/material/Sample_UVMove.ts +++ b/samples/material/Sample_UVMove.ts @@ -12,16 +12,6 @@ class Sample_UVMove { Engine3D.setting.material.materialChannelDebug = true; Engine3D.setting.shadow.shadowBound = 5; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - blurX: 4, - blurY: 4, - exposure: 1, - luminosityThreshold: 0.8, - strength: 0.86, - radius: 4, - debug: false - }; this.scene = new Scene3D(); let sky = this.scene.addComponent(AtmosphericComponent); diff --git a/samples/material/script/UVMoveComponent.ts b/samples/material/script/UVMoveComponent.ts index ce8ab2ac..f083e222 100644 --- a/samples/material/script/UVMoveComponent.ts +++ b/samples/material/script/UVMoveComponent.ts @@ -22,12 +22,12 @@ export class UVMoveComponent extends ComponentBase { onUpdate(): void { if (this._material) { - let value = this._material.defaultPass.getUniform(`transformUV1`); + let value = this._material.getUniformV4(`transformUV1`); value.x += Time.delta * this._speed.x * 0.001; value.y += Time.delta * this._speed.y * 0.001; value.z = this._speed.z; value.w = this._speed.w; - this._material.defaultPass.setUniform(`transformUV1`, value); + this._material.setUniformVector4(`transformUV1`, value); } } } \ No newline at end of file diff --git a/samples/pick/Sample_OutlineEffectPick.ts b/samples/pick/Sample_OutlineEffectPick.ts index 400e4148..4264e65c 100644 --- a/samples/pick/Sample_OutlineEffectPick.ts +++ b/samples/pick/Sample_OutlineEffectPick.ts @@ -1,7 +1,7 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { createExampleScene } from "@samples/utils/ExampleScene"; -import { Object3D, Scene3D, Color, Engine3D, OutlinePost, SphereGeometry, LitMaterial, MeshRenderer, ColliderComponent, PointerEvent3D, outlinePostManager } from "@orillusion/core"; +import { Object3D, Scene3D, Color, Engine3D, OutlinePost, SphereGeometry, LitMaterial, MeshRenderer, ColliderComponent, PointerEvent3D, outlinePostManager, FXAAPost } from "@orillusion/core"; class Sample_OutlineEffectPick { lightObj: Object3D; @@ -32,6 +32,7 @@ class Sample_OutlineEffectPick { GUIUtil.renderDirLight(exampleScene.light, false); let job = Engine3D.startRenderView(exampleScene.view); + // job.addPost(new FXAAPost()); job.addPost(new OutlinePost()); this.initPickObject(this.scene); diff --git a/samples/pick/Sample_PixelPick.ts b/samples/pick/Sample_PixelPick.ts index 910d74b0..5c23a384 100644 --- a/samples/pick/Sample_PixelPick.ts +++ b/samples/pick/Sample_PixelPick.ts @@ -2,7 +2,7 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { MaterialStateComponent } from "@samples/pick/MaterialStateComponent"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { createExampleScene } from "@samples/utils/ExampleScene"; -import { Scene3D, Engine3D, MeshRenderer, ColliderComponent, PointerEvent3D, SphereGeometry, Object3D, LitMaterial, Color } from "@orillusion/core"; +import { Scene3D, Engine3D, MeshRenderer, ColliderComponent, PointerEvent3D, SphereGeometry, Object3D, LitMaterial, Color, FXAAPost, PostProcessingComponent, BloomPost } from "@orillusion/core"; class Sample_PixelPick { scene: Scene3D; @@ -18,6 +18,9 @@ class Sample_PixelPick { Engine3D.startRenderView(exampleScene.view); + let postProcessing = this.scene.getOrAddComponent(PostProcessingComponent); + let bloomPost = postProcessing.addPost(BloomPost); + GUIHelp.init(); GUIUtil.renderDirLight(exampleScene.light, false); @@ -65,8 +68,8 @@ class Sample_PixelPick { let mat = new LitMaterial(); mat.roughness = i / 10; - mat.metallic_max = 1.0; - mat.metallic_min = 0.0; + // mat.metallic_max = 1.0; + // mat.metallic_min = 0.0; mat.metallic = 0.6; let renderer = obj.addComponent(MeshRenderer); diff --git a/samples/post/Sample_Bloom.ts b/samples/post/Sample_Bloom.ts index ef231f7e..e52ca91f 100644 --- a/samples/post/Sample_Bloom.ts +++ b/samples/post/Sample_Bloom.ts @@ -2,7 +2,7 @@ import { View3D, DirectLight, Engine3D, PostProcessingComponent, LitMaterial, HoverCameraController, KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, - CameraUtil, webGPUContext, BoxGeometry, TAAPost, AtmosphericComponent, GTAOPost, Color, HDRBloomPost + CameraUtil, webGPUContext, BoxGeometry, TAAPost, AtmosphericComponent, GTAOPost, Color, BloomPost } from '@orillusion/core'; import { GUIHelp } from '@orillusion/debug/GUIHelp'; import { GUI } from '@orillusion/debug/dat.gui.module'; @@ -36,12 +36,7 @@ class Sample_Bloom { Engine3D.startRenderView(view); let postProcessing = this.scene.addComponent(PostProcessingComponent); - let post = postProcessing.addPost(HDRBloomPost); - post.blurX = 5; - post.blurY = 5; - post.luminosityThreshold = 1.1; - post.strength = 1.0; - + let post = postProcessing.addPost(BloomPost); GUIHelp.init(); GUIUtil.renderBloom(post, true); } @@ -61,13 +56,8 @@ class Sample_Bloom { { let mat = new LitMaterial(); - mat.baseMap = Engine3D.res.grayTexture; - mat.normalMap = Engine3D.res.normalTexture; - mat.aoMap = Engine3D.res.whiteTexture; - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 255.0, 0.0, 1); - mat.emissiveMap = Engine3D.res.blackTexture; - mat.roughness = 1.5; - mat.metallic = 0.0; + mat.roughness = 1.0; + mat.metallic = 0.1; let floor = new Object3D(); let mr = floor.addComponent(MeshRenderer); @@ -105,9 +95,8 @@ class Sample_Bloom { { { let litMat = new LitMaterial(); - litMat.emissiveMap = Engine3D.res.whiteTexture; litMat.emissiveColor = new Color(0.0, 0.0, 1.0); - litMat.emissiveIntensity = 5.0; + litMat.emissiveIntensity = 1.8; let sp = new Object3D(); let mr = sp.addComponent(MeshRenderer); mr.geometry = new SphereGeometry(15, 30, 30); @@ -120,9 +109,8 @@ class Sample_Bloom { { let litMat = new LitMaterial(); - litMat.emissiveMap = Engine3D.res.whiteTexture; litMat.emissiveColor = new Color(1.0, 1.0, 0.0); - litMat.emissiveIntensity = 5; + litMat.emissiveIntensity = 1.2; let sp = new Object3D(); let mr = sp.addComponent(MeshRenderer); mr.geometry = new SphereGeometry(15, 30, 30); diff --git a/samples/post/Sample_Fog.ts b/samples/post/Sample_Fog.ts index 3285c043..144bc509 100644 --- a/samples/post/Sample_Fog.ts +++ b/samples/post/Sample_Fog.ts @@ -1,4 +1,4 @@ -import { AtmosphericComponent, BoxGeometry, CameraUtil, CylinderGeometry, DirectLight, Engine3D, GlobalFog, HoverCameraController, KelvinUtil, LitMaterial, MeshRenderer, Object3D, PlaneGeometry, PostProcessingComponent, Scene3D, View3D, webGPUContext } from '@orillusion/core'; +import { AtmosphericComponent, BoxGeometry, CameraUtil, CylinderGeometry, DirectLight, Engine3D, FXAAPost, GlobalFog, HoverCameraController, KelvinUtil, LitMaterial, MeshRenderer, Object3D, PlaneGeometry, PostProcessingComponent, Scene3D, View3D, webGPUContext } from '@orillusion/core'; import { GUIHelp } from '@orillusion/debug/GUIHelp'; import { GUIUtil } from '@samples/utils/GUIUtil'; @@ -28,8 +28,9 @@ class Sample_Fog { Engine3D.startRenderView(view); GUIHelp.init(); - GUIUtil.renderAtomosphericSky(sky, false); + GUIUtil.renderAtmosphericSky(sky, false); let postProcessing = this.scene.addComponent(PostProcessingComponent); + let fXAAPost = postProcessing.addPost(FXAAPost); let fog = postProcessing.addPost(GlobalFog); GUIUtil.renderGlobalFog(fog, true); } @@ -49,7 +50,6 @@ class Sample_Fog { { let mat = new LitMaterial(); - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 255.0, 0.0, 1); mat.roughness = 0.5; mat.metallic = 0.5; @@ -65,7 +65,6 @@ class Sample_Fog { private createPlane(scene: Scene3D) { let mat = new LitMaterial(); - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 255.0, 0.0, 1); mat.roughness = 1.0; mat.metallic = 0.0; diff --git a/samples/post/Sample_GTAO.ts b/samples/post/Sample_GTAO.ts index bc16409f..1402dbc8 100644 --- a/samples/post/Sample_GTAO.ts +++ b/samples/post/Sample_GTAO.ts @@ -2,7 +2,7 @@ import { View3D, DirectLight, Engine3D, PostProcessingComponent, LitMaterial, HoverCameraController, KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, - CameraUtil, webGPUContext, BoxGeometry, TAAPost, AtmosphericComponent, GTAOPost, Color, HDRBloomPost + CameraUtil, webGPUContext, BoxGeometry, TAAPost, AtmosphericComponent, GTAOPost, Color } from '@orillusion/core'; import { GUIHelp } from '@orillusion/debug/GUIHelp'; import { GUIUtil } from '@samples/utils/GUIUtil'; @@ -59,11 +59,6 @@ class Sample_GTAO { async initScene() { { let mat = new LitMaterial(); - mat.baseMap = Engine3D.res.whiteTexture; - mat.normalMap = Engine3D.res.normalTexture; - mat.aoMap = Engine3D.res.whiteTexture; - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 255.0, 0.0, 1); - mat.emissiveMap = Engine3D.res.blackTexture; mat.roughness = 1.0; mat.metallic = 0.0; @@ -107,8 +102,6 @@ class Sample_GTAO { mat.baseColor = new Color(1.0, 0.464, 0.0); mat.normalMap = Engine3D.res.normalTexture; mat.aoMap = Engine3D.res.whiteTexture; - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 255.0, 0.0, 1); - mat.emissiveMap = Engine3D.res.blackTexture; mat.roughness = 1.0; mat.metallic = 0.0; diff --git a/samples/post/Sample_GodRay.ts b/samples/post/Sample_GodRay.ts index ad6e5b2c..fc920bec 100644 --- a/samples/post/Sample_GodRay.ts +++ b/samples/post/Sample_GodRay.ts @@ -2,8 +2,7 @@ import { View3D, DirectLight, Engine3D, PostProcessingComponent, LitMaterial, HoverCameraController, KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, - CameraUtil, webGPUContext, BoxGeometry, AtmosphericComponent, Time, - HDRBloomPost, GodRayPost + CameraUtil, webGPUContext, BoxGeometry, AtmosphericComponent, Time, GodRayPost, BloomPost } from '@orillusion/core'; import { GUIHelp } from '@orillusion/debug/GUIHelp'; import { GUIUtil } from '@samples/utils/GUIUtil'; @@ -38,9 +37,9 @@ class Sample_GodRay { let postProcessing = this.scene.addComponent(PostProcessingComponent); postProcessing.addPost(GodRayPost); - postProcessing.addPost(HDRBloomPost); + postProcessing.addPost(BloomPost); - GUIUtil.renderAtomosphericSky(sky, false); + GUIUtil.renderAtmosphericSky(sky, false); } async initScene() { { @@ -72,13 +71,7 @@ class Sample_GodRay { private ball: Object3D; private createPlane(scene: Scene3D) { let mat = new LitMaterial(); - mat.baseMap = Engine3D.res.whiteTexture; - mat.normalMap = Engine3D.res.normalTexture; - mat.aoMap = Engine3D.res.whiteTexture; - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 10.0, 0.0, 1); - mat.emissiveMap = Engine3D.res.blackTexture; mat.roughness = 0.5; - mat.roughness_max = 0.1; mat.metallic = 0.2; { let sphereGeometry = new SphereGeometry(20, 50, 50); diff --git a/samples/post/Sample_TAA.ts b/samples/post/Sample_TAA.ts index 66df356b..08a4abb1 100644 --- a/samples/post/Sample_TAA.ts +++ b/samples/post/Sample_TAA.ts @@ -53,11 +53,6 @@ class Sample_TAA { { let mat = new LitMaterial(); - mat.baseMap = Engine3D.res.grayTexture; - mat.normalMap = Engine3D.res.normalTexture; - mat.aoMap = Engine3D.res.whiteTexture; - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 255.0, 0.0, 1); - mat.emissiveMap = Engine3D.res.blackTexture; mat.roughness = 1.0; mat.metallic = 0.0; @@ -74,13 +69,7 @@ class Sample_TAA { private createPlane(scene: Scene3D) { let mat = new LitMaterial(); - mat.baseMap = Engine3D.res.whiteTexture; - mat.normalMap = Engine3D.res.normalTexture; - mat.aoMap = Engine3D.res.whiteTexture; - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 10.0, 0.0, 1); - mat.emissiveMap = Engine3D.res.blackTexture; mat.roughness = 0.5; - mat.roughness_max = 0.1; mat.metallic = 0.2; { let sphereGeometry = new SphereGeometry(1, 50, 50); diff --git a/samples/render/Sample_BlendMode.ts b/samples/render/Sample_BlendMode.ts index 5f273e88..8840313e 100644 --- a/samples/render/Sample_BlendMode.ts +++ b/samples/render/Sample_BlendMode.ts @@ -9,15 +9,6 @@ class Sample_BlendMode2 { Engine3D.setting.material.materialChannelDebug = true; Engine3D.setting.shadow.shadowBound = 5; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - blurX: 4, - blurY: 4, - luminosityThreshold: 0.8, - strength: 0.86, - radius: 4, - debug: false - }; this.scene = new Scene3D(); let sky = this.scene.addComponent(AtmosphericComponent); diff --git a/samples/sky/Sample_AtmosphericSky.ts b/samples/sky/Sample_AtmosphericSky.ts index 927abefb..883845a4 100644 --- a/samples/sky/Sample_AtmosphericSky.ts +++ b/samples/sky/Sample_AtmosphericSky.ts @@ -28,7 +28,7 @@ class Sample_AtmosphericSky { // gui GUIHelp.init(); - GUIUtil.renderAtomosphericSky(sky); + GUIUtil.renderAtmosphericSky(sky); } } diff --git a/samples/utils/GUIUtil.ts b/samples/utils/GUIUtil.ts index ca4b4060..64afaa3d 100644 --- a/samples/utils/GUIUtil.ts +++ b/samples/utils/GUIUtil.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { AtmosphericComponent, BillboardType, BlendMode, Color, DirectLight, Engine3D, GPUCullMode, GlobalFog, GlobalIlluminationComponent, HDRBloomPost, LitMaterial, Material, PointLight, SpotLight, Transform, UIImage, UIPanel, UIShadow, View3D } from "@orillusion/core"; +import { AnimatorComponent, AtmosphericComponent, BillboardType, BlendMode, BloomPost, Color, DirectLight, Engine3D, GPUCullMode, GTAOPost, GlobalFog, GlobalIlluminationComponent, LitMaterial, Material, MorphTargetBlender, Object3D, PointLight, SkinnedMeshRenderer2, SpotLight, Transform, UIImage, UIPanel, UIShadow, View3D } from "@orillusion/core"; import { UVMoveComponent } from "@samples/material/script/UVMoveComponent"; export class GUIUtil { @@ -8,13 +8,15 @@ export class GUIUtil { public static renderShadowSetting(open: boolean = true) { GUIHelp.addFolder('ShadowSetting'); let setting = Engine3D.setting.shadow; + GUIHelp.add(setting, 'shadowBound', 0, 2048, 1); + GUIHelp.add(setting, 'shadowBias', 0.0001, 0.2, 0.00001); open && GUIHelp.open(); GUIHelp.endFolder(); } //render AtmosphericComponent - public static renderAtomosphericSky(component: AtmosphericComponent, open: boolean = true, name?: string) { + public static renderAtmosphericSky(component: AtmosphericComponent, open: boolean = true, name?: string) { name ||= 'AtmosphericSky'; GUIHelp.addFolder(name); GUIHelp.add(component, 'sunX', 0, 1, 0.01); @@ -66,27 +68,37 @@ export class GUIUtil { GUIHelp.add(transform, 'rotationX', 0.0, 360.0, 0.01); GUIHelp.add(transform, 'rotationY', 0.0, 360.0, 0.01); GUIHelp.add(transform, 'rotationZ', 0.0, 360.0, 0.01); - GUIHelp.add(transform, 'scaleX', 0.0, 2.0, 0.01); - GUIHelp.add(transform, 'scaleY', 0.0, 2.0, 0.01); - GUIHelp.add(transform, 'scaleZ', 0.0, 2.0, 0.01); + GUIHelp.add(transform, 'scaleX', -2.0, 2.0, 0.01); + GUIHelp.add(transform, 'scaleY', -2.0, 2.0, 0.01); + GUIHelp.add(transform, 'scaleZ', -2.0, 2.0, 0.01); open && GUIHelp.open(); GUIHelp.endFolder(); } + public static renderBloom(bloom: BloomPost, open: boolean = true, name?: string) { + name ||= 'Bloom'; + GUIHelp.addFolder(name); + GUIHelp.add(bloom, 'downSampleBlurSize', 3, 15, 1); + GUIHelp.add(bloom, 'downSampleBlurSigma', 0.01, 1, 0.001); + GUIHelp.add(bloom, 'upSampleBlurSize', 3, 15, 1); + GUIHelp.add(bloom, 'upSampleBlurSigma', 0.01, 1, 0.001); + GUIHelp.add(bloom, 'luminanceThreshole', 0.001, 10.0, 0.001); + GUIHelp.add(bloom, 'bloomIntensity', 0.001, 10.0, 0.001); + open && GUIHelp.open(); + GUIHelp.endFolder(); + } - //render bloom gui panel - public static renderBloom(bloom: HDRBloomPost, open: boolean = true, name?: string) { - name ||= 'HDRBloom'; + public static renderVector3(obj: Object3D, open: boolean = true, name?: string) { + name ||= 'Vector3'; GUIHelp.addFolder(name); - GUIHelp.add(bloom, 'enable'); - GUIHelp.addColor(bloom, 'tintColor'); - GUIHelp.add(bloom, 'luminosityThreshold'); - GUIHelp.add(bloom, 'strength', 0, 3, 0.001); - GUIHelp.add(bloom, 'exposure'); - GUIHelp.add(bloom, 'radius', 0, 1.0, 0.001); - GUIHelp.add(bloom, 'blurX'); - GUIHelp.add(bloom, 'blurY'); + GUIHelp.add(obj, 'x', -10.0, 10.0, 0.01); + GUIHelp.add(obj, 'y', -10.0, 10.0, 0.01); + GUIHelp.add(obj, 'z', -10.0, 10.0, 0.01); + + GUIHelp.add(obj.transform, 'rotationX', 0.0, 360.0, 0.01); + GUIHelp.add(obj.transform, 'rotationY', 0.0, 360.0, 0.01); + GUIHelp.add(obj.transform, 'rotationZ', 0.0, 360.0, 0.01); open && GUIHelp.open(); GUIHelp.endFolder(); } @@ -362,18 +374,20 @@ export class GUIUtil { static renderDebug() { // if (Engine3D.setting.render.debug) { - let debugTextures = Engine3D.getRenderJob(Engine3D.views[0]).postRenderer.debugTextures; - let debugTextureObj = { normalRender: -1 }; - for (let i = 0; i < debugTextures.length; i++) { - const tex = debugTextures[i]; - debugTextureObj[tex.name] = i; - } GUIHelp.removeFolder(`RenderPerformance`); //debug let f = GUIHelp.addFolder('RenderPerformance'); f.open(); - GUIHelp.add(Engine3D.setting.render, 'debugQuad', debugTextureObj); + if (Engine3D.getRenderJob(Engine3D.views[0]).postRenderer) { + let debugTextures = Engine3D.getRenderJob(Engine3D.views[0]).postRenderer.debugTextures; + let debugTextureObj = { normalRender: -1 }; + for (let i = 0; i < debugTextures.length; i++) { + const tex = debugTextures[i]; + debugTextureObj[tex.name] = i; + } + GUIHelp.add(Engine3D.setting.render, 'debugQuad', debugTextureObj); + } let debugChanel = { PositionView: 0, ColorView: 1, @@ -400,50 +414,126 @@ export class GUIUtil { GUIHelp.add(Engine3D.setting.render, 'drawOpMax', 0.0, 10000, 1); GUIHelp.endFolder(); } - // } - public static renderMaterial(mat: Material, open: boolean = true, name?: string) { - name ||= 'Material'; - GUIHelp.addFolder(name); + static renderLitMaterial(mat: LitMaterial) { + GUIHelp.addFolder(mat.name); + GUIHelp.addColor(mat, 'baseColor').onChange((v) => { + let color = mat.baseColor; + color.copyFromArray(v); + mat.baseColor = color; + }); - if (mat instanceof LitMaterial) { - GUIHelp.addColor(mat, 'baseColor').onChange((v) => { - mat.defaultPass.baseColor = v; - }); + let blendMode = { + NONE: BlendMode.NONE, + NORMAL: BlendMode.NORMAL, + ADD: BlendMode.ADD, + ALPHA: BlendMode.ALPHA, + } + // change blend mode by click dropdown box + GUIHelp.add({ blendMode: mat.blendMode }, 'blendMode', blendMode).onChange((v) => { + mat.blendMode = BlendMode[BlendMode[parseInt(v)]]; + }); - let blendMode = { - NONE: BlendMode.NONE, - NORMAL: BlendMode.NORMAL, - ADD: BlendMode.ADD, - ALPHA: BlendMode.ALPHA, - } - // change blend mode by click dropdown box - GUIHelp.add({ blendMode: mat.blendMode }, 'blendMode', blendMode).onChange((v) => { - mat.blendMode = BlendMode[BlendMode[parseInt(v)]]; - }); + GUIHelp.add(mat, 'alphaCutoff', 0.0, 1.0, 0.0001).onChange((v) => { + mat.alphaCutoff = v; + }); - GUIHelp.add(mat, 'alphaCutoff', 0.0, 1.0, 0.0001).onChange((v) => { - mat.alphaCutoff = v; - }); + GUIHelp.add(mat, 'doubleSide').onChange((v) => { + mat.doubleSide = v; + }); - GUIHelp.add(mat, 'doubleSide').onChange((v) => { - mat.doubleSide = v; - }); + GUIHelp.add(mat, 'roughness', 0.0, 1.0, 0.0001).onChange((v) => { + mat.roughness = v; + }); - GUIHelp.add(mat, 'roughness').onChange((v) => { - mat.roughness = v; - }); + GUIHelp.add(mat, 'metallic', 0.0, 1.0, 0.0001).onChange((v) => { + mat.metallic = v; + }); - GUIHelp.add(mat, 'metallic').onChange((v) => { - mat.metallic = v; - }); + GUIHelp.endFolder(); + } - GUIHelp.add(mat, 'envIntensity').onChange((v) => { - mat.envIntensity = v; + public static blendShape(obj: Object3D) { + GUIHelp.addFolder('morph controller'); + // register MorphTargetBlender component + let blendShapeComponent = obj.addComponent(MorphTargetBlender); + let targetRenderers = blendShapeComponent.cloneMorphRenderers(); + + let influenceData = {}; + // bind influenceData to gui + for (let key in targetRenderers) { + influenceData[key] = 0.0; + GUIHelp.add(influenceData, key, 0, 1, 0.01).onChange((v) => { + influenceData[key] = v; + let list = blendShapeComponent.getMorphRenderersByKey(key); + for (let renderer of list) { + renderer.setMorphInfluence(key, v); + } }); } - open && GUIHelp.open(); + GUIHelp.open(); + GUIHelp.endFolder(); + } + + public static renderBlendShape(obj: Object3D) { + GUIHelp.addFolder('morph controller'); + // register MorphTargetBlender component + let blendShapeComponents = obj.getComponents(SkinnedMeshRenderer2); + let targetRenderers = null; + for (let ii = 0; ii < blendShapeComponents.length; ii++) { + if (blendShapeComponents[ii].geometry.blendShapeData) { + targetRenderers = blendShapeComponents[ii].geometry.blendShapeData.shapeNames; + } + } + + if (targetRenderers) { + let influenceData = {}; + // bind influenceData to gui + for (let i in targetRenderers) { + let key = targetRenderers[i]; + influenceData[key] = 0.0; + GUIHelp.add(influenceData, key, 0, 1, 0.01).onChange((v) => { + influenceData[key] = v; + for (let index = 0; index < blendShapeComponents.length; index++) { + for (let renderer of blendShapeComponents) { + renderer.setMorphInfluence(key, v); + } + } + }); + } + } + + GUIHelp.open(); + GUIHelp.endFolder(); + } + + static renderAnimator(com: AnimatorComponent) { + let anim = {} + for (let i = 0; i < com.clips.length; i++) { + const clip = com.clips[i]; + anim[clip.clipName] = clip.clipName; + } + + GUIHelp.addFolder('morph controller'); + + GUIHelp.add({ anim: anim }, 'anim', anim).onChange((v) => { + com.playAnim(v); + com.playBlendShape(v); + }); + GUIHelp.endFolder(); + + } + + + public static renderGTAO(post: GTAOPost) { + GUIHelp.addFolder("GTAO"); + GUIHelp.add(post, "maxDistance", 0.0, 149, 1); + GUIHelp.add(post, "maxPixel", 0.0, 150, 1); + GUIHelp.add(post, "rayMarchSegment", 0.0, 50, 0.001); + GUIHelp.add(post, "darkFactor", 0.0, 5, 0.001); + GUIHelp.add(post, "blendColor"); + GUIHelp.add(post, "multiBounce"); GUIHelp.endFolder(); } } \ No newline at end of file diff --git a/src/Engine3D.ts b/src/Engine3D.ts index 9b39d96a..609c9878 100644 --- a/src/Engine3D.ts +++ b/src/Engine3D.ts @@ -5,12 +5,15 @@ import { Time } from './util/Time'; import { InputSystem } from './io/InputSystem'; import { View3D } from './core/View3D'; import { version } from '../package.json'; + +import { GPUTextureFormat } from './gfx/graphics/webGpu/WebGPUConst'; import { webGPUContext } from './gfx/graphics/webGpu/Context3D'; -import { FXAAPost } from './gfx/renderJob/post/FXAAPost'; +import { RTResourceConfig } from './gfx/renderJob/config/RTResourceConfig'; +import { RTResourceMap } from './gfx/renderJob/frame/RTResourceMap'; + import { ForwardRenderJob } from './gfx/renderJob/jobs/ForwardRenderJob'; import { GlobalBindGroup } from './gfx/graphics/webGpu/core/bindGroups/GlobalBindGroup'; import { Interpolator } from './math/TimeInterpolator'; -import { RTResourceMap } from './gfx/renderJob/frame/RTResourceMap'; import { RendererJob } from './gfx/renderJob/jobs/RendererJob'; import { Res } from './assets/Res'; import { ShaderLib } from './assets/shader/ShaderLib'; @@ -19,7 +22,10 @@ import { ComponentCollect } from './gfx/renderJob/collect/ComponentCollect'; import { ShadowLightsCollect } from './gfx/renderJob/collect/ShadowLightsCollect'; import { GUIConfig } from './components/gui/GUIConfig'; import { WasmMatrix } from '@orillusion/wasm-matrix/WasmMatrix'; -import { Matrix4 } from '.'; +import { Matrix4 } from './math/Matrix4'; +import { FXAAPost } from './gfx/renderJob/post/FXAAPost'; +import { PostProcessingComponent } from './components/post/PostProcessingComponent'; +import { Texture } from './gfx/graphics/webGpu/core/texture/Texture'; /** * Orillusion 3D Engine @@ -136,6 +142,15 @@ export class Engine3D { useLogDepth: false, gi: false, postProcessing: { + bloom: { + downSampleStep: 5, + downSampleBlurSize: 5, + downSampleBlurSigma: 1.0, + upSampleBlurSize: 5, + upSampleBlurSigma: 1.0, + luminanceThreshole: 1.0, + bloomIntensity: 1.0, + }, globalFog: { debug: false, enable: false, @@ -148,7 +163,7 @@ export class Engine3D { skyFactor: 0.5, skyRoughness: 0.4, overrideSkyFactor: 0.8, - fogColor: new Color(112 / 255, 61 / 255, 139 / 255, 1), + fogColor: new Color(96 / 255, 117 / 255, 133 / 255, 1), falloff: 0.7, rayLength: 200.0, scatteringExponent: 2.7, @@ -203,16 +218,6 @@ export class Engine3D { mixThreshold: 0.1, debug: true, }, - bloom: { - enable: false, - blurX: 4, - blurY: 4, - strength: 0.25, - exposure: 1, - radius: 1.3, - luminosityThreshold: 0.98, - debug: false, - }, fxaa: { enable: false, }, @@ -229,12 +234,10 @@ export class Engine3D { enable: true, type: 'HARD', pointShadowBias: 0.002, - // shadowQuality: 2.5, shadowSize: 1024, pointShadowSize: 1024, shadowSoft: 0.005, - // shadowNear: 1, - // shadowFar: 2000, + shadowBias: 0.0001, needUpdate: true, autoUpdate: true, updateFrameRate: 2, @@ -286,6 +289,9 @@ export class Engine3D { materialChannelDebug: false, materialDebug: false }, + loader: { + numConcurrent: 20, + } }; @@ -327,6 +333,8 @@ export class Engine3D { this.res = new Res(); + this.res.initDefault(); + this._beforeRender = descriptor.beforeRender; this._renderLoop = descriptor.renderLoop; this._lateRender = descriptor.lateRender; @@ -345,8 +353,20 @@ export class Engine3D { this.views = [view]; let renderJob = new ForwardRenderJob(view); this.renderJobs.set(view, renderJob); - renderJob.addPost(new FXAAPost()); - renderJob.start(); + let presentationSize = webGPUContext.presentationSize; + // RTResourceMap.createRTTexture(RTResourceConfig.colorBufferTex_NAME, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float, false); + + if (this.setting.pick.mode == `pixel`) { + let postProcessing = view.scene.getOrAddComponent(PostProcessingComponent); + postProcessing.addPost(FXAAPost); + + } else { + } + + if (this.setting.pick.mode == `pixel` || this.setting.pick.mode == `bound`) { + view.enablePick = true; + } + this.resume(); return renderJob; } @@ -364,8 +384,18 @@ export class Engine3D { const view = views[i]; let renderJob = new ForwardRenderJob(view); this.renderJobs.set(view, renderJob); - renderJob.addPost(new FXAAPost()); - renderJob.start(); + let presentationSize = webGPUContext.presentationSize; + + if (this.setting.pick.mode == `pixel`) { + let postProcessing = view.scene.addComponent(PostProcessingComponent); + postProcessing.addPost(FXAAPost); + } else { + RTResourceMap.createRTTexture(RTResourceConfig.colorBufferTex_NAME, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float, false); + } + + if (this.setting.pick.mode == `pixel` || this.setting.pick.mode == `bound`) { + view.enablePick = true; + } } this.resume(); } @@ -401,6 +431,9 @@ export class Engine3D { * @internal */ private static render(time) { + webGPUContext.updateSize(); + Texture.destroyTexture(); + this._deltaTime = time - this._time; this._time = time; @@ -489,6 +522,18 @@ export class Engine3D { } } + for (const iterator of ComponentCollect.graphicComponent) { + let k = iterator[0]; + let v = iterator[1]; + for (const iterator2 of v) { + let f = iterator2[0]; + let c = iterator2[1]; + if (k && f.enable) { + c(k); + }; + } + } + if (this._renderLoop) { this._renderLoop(); } @@ -503,6 +548,9 @@ export class Engine3D { globalMatrixBindGroup.writeBuffer(Matrix4.useCount * 16); this.renderJobs.forEach((v, k) => { + if (!v.renderState) { + v.start(); + } v.renderFrame(); }); @@ -520,6 +568,7 @@ export class Engine3D { } if (this._lateRender) this._lateRender(); + } diff --git a/src/assets/Res.ts b/src/assets/Res.ts index 05a1e06e..8e2b768c 100644 --- a/src/assets/Res.ts +++ b/src/assets/Res.ts @@ -23,20 +23,26 @@ import { FontParser, FontInfo } from '../loader/parser/FontParser'; import { fonts } from './Fonts'; import { AtlasParser } from '../loader/parser/AtlasParser'; import { Reference } from '../util/Reference'; -import { Material } from '..'; +import { Material } from '../materials/Material'; +import { Ctor, Parser } from '../util/Global'; +import { ParserBase } from '../loader/parser/ParserBase'; +import { GeometryBase } from '../core/geometry/GeometryBase'; +import { LitMaterial } from '../materials/LitMaterial'; /** * Resource management classes for textures, materials, models, and preset bodies. * @group Assets */ export class Res { + private _texturePool: Map; private _materialPool: Map; private _prefabPool: Map; // private _prefabLoaderPool: Map; private _gltfPool: Map; + private _geometryPool: Map; private _atlasList: Map; - + private _obj: Map; /** * @constructor @@ -45,17 +51,36 @@ export class Res { this._texturePool = new Map(); this._materialPool = new Map(); this._prefabPool = new Map(); + this._geometryPool = new Map(); // this._prefabLoaderPool = new Map; this._gltfPool = new Map; this._atlasList = new Map(); - - this.initDefault(); + this._obj = new Map(); + // this.initDefault(); } public getGltf(url: string): GLTF_Info { return this._gltfPool.get(url); } + /** + * add a obj with reference of url + * @param url file path + * @param texture source obj + */ + public addObj(url: string, obj: any) { + this._obj.set(url, obj); + } + + /** + * get obj by url + * @param url file path + * @returns + */ + public getObj(url: string): any { + return this._obj.get(url); + } + /** * add a texture with reference of url * @param url file path @@ -74,6 +99,14 @@ export class Res { return this._texturePool.get(url); } + public addGeometry(url: string, geo: GeometryBase) { + this._geometryPool.set(url, geo); + } + + public getGeometry(url: string): GeometryBase { + return this._geometryPool.get(url); + } + /** * add a material with reference of name * @param name material name @@ -129,6 +162,13 @@ export class Res { return null; } + public async load(url: string, c: Parser, loaderFunctions?: LoaderFunctions) { + let loader = new FileLoader(); + let parser = await loader.load(url, c, loaderFunctions); + let ret = parser.data; + return ret; + } + /** * load a gltf file * @param url the url of file @@ -231,6 +271,39 @@ export class Res { return texture; } + private async loadTextureCount(urls: string[], count: number, loaderFunctions?: LoaderFunctions, flipY?: boolean) { + return new Promise( + async (suc, fail) => { + let total = 0; + let loadTexture = []; + if (count == 0) { + suc(loadTexture); + } + for (let j = 0; j < count; j++) { + const url = urls.shift(); + this.loadTexture(url, loaderFunctions, flipY).then((t) => { + loadTexture.push(t); + total++; + if (total == count) { + suc(loadTexture); + } + }); + } + } + ); + } + + public async loadBitmapTextures(urls: string[], count: number = 5, loaderFunctions?: LoaderFunctions, flipY?: boolean) { + let loadTexture: BitmapTexture2D[] = []; + let loadCount = Math.floor(urls.length / count) + 1; + let last = Math.floor(urls.length % count) + for (let i = 0; i < loadCount; i++) { + let list = await this.loadTextureCount(urls, i == loadCount - 1 ? last : count, loaderFunctions, flipY); + loadTexture.push(...list); + } + return loadTexture; + } + /** * load a hdr texture * @param url texture url @@ -373,6 +446,7 @@ export class Res { public defaultGUITexture: GUITexture; public defaultGUISprite: GUISprite; + public defaultMaterial: LitMaterial; /** * create a texture @@ -424,9 +498,9 @@ export class Res { /** * Initialize a common texture object. Provide a universal solid color texture object. */ - private initDefault() { + public initDefault() { this.normalTexture = this.createTexture(32, 32, 255 * 0.5, 255 * 0.5, 255.0, 255.0, 'default-normalTexture'); - this.maskTexture = this.createTexture(32, 32, 255, 255 * 0.5, 0.0, 255.0, 'default-maskTexture'); + this.maskTexture = this.createTexture(32, 32, 255, 255 * 0.5, 255.0, 255.0, 'default-maskTexture'); this.whiteTexture = this.createTexture(32, 32, 255, 255, 255, 255, 'default-whiteTexture'); this.blackTexture = this.createTexture(32, 32, 0, 0, 0, 255.0, 'default-blackTexture'); this.redTexture = this.createTexture(32, 32, 255, 0, 0, 255.0, 'default-redTexture'); @@ -458,5 +532,7 @@ export class Res { this.defaultGUITexture = new GUITexture(this.whiteTexture); this.defaultGUISprite = new GUISprite(this.defaultGUITexture); this.defaultGUISprite.trimSize.set(4, 4) + + this.defaultMaterial = new LitMaterial(); } } diff --git a/src/assets/shader/ShaderLib.ts b/src/assets/shader/ShaderLib.ts index 94575115..612dfc6d 100644 --- a/src/assets/shader/ShaderLib.ts +++ b/src/assets/shader/ShaderLib.ts @@ -1,4 +1,3 @@ -import { Bloom_shader } from './post/Bloom_shader'; import { ClusterDebug_frag } from './materials/program/ClusterDebug_frag'; import { CubeSky_Shader } from './sky/CubeSky_Shader'; import { LightingFunction_frag } from './lighting/LightingFunction_frag'; @@ -28,13 +27,24 @@ import { Irradiance_frag } from './lighting/Irradiance_frag'; import { BRDF_frag } from './lighting/BRDF_frag'; import { BxDF_frag } from './lighting/BxDF_frag'; import { Clearcoat_frag } from './materials/program/Clearcoat_frag'; -import { LitShader } from './materials/LitShader'; +import { Lit_shader } from './materials/Lit_shader'; import { PBRLItShader } from './materials/PBRLItShader'; import { BxdfDebug_frag } from './materials/program/BxdfDebug_frag'; import { Quad_depth2d_frag_wgsl, Quad_depthCube_frag_wgsl, Quad_frag_wgsl, Quad_vert_wgsl } from './quad/Quad_shader'; import { ColorUtil } from './utils/ColorUtil'; import { GenerayRandomDir } from './utils/GenerayRandomDir'; -import { ClusterLight, GBuffer_pass, LambertShader, MatrixShader, QuadGlsl_fs, QuadGlsl_vs, SkyGBuffer_pass, UnLit, ZPassShader_fs, ZPassShader_vs, castPointShadowMap_vert, directionShadowCastMap_frag, shadowCastMap_frag, shadowCastMap_vert } from '../..'; +import { MatrixShader } from './math/MatrixShader'; +import { ClusterLight } from './core/struct/ClusterLight'; +import { Hair_frag } from './lighting/Hair_frag'; +import { BsDF_frag } from './lighting/BsDF_frag'; +import { UnLit } from './materials/UnLit'; +import { Lambert_shader } from './materials/Lambert_shader'; +import { QuadGlsl_fs, QuadGlsl_vs } from './glsl/Quad_glsl'; +import { SkyGBuffer_pass } from './core/pass/SkyGBuffer_pass'; +import { GBuffer_pass } from './core/pass/GBuffer_pass'; +import { castPointShadowMap_vert, directionShadowCastMap_frag, shadowCastMap_frag, shadowCastMap_vert } from './core/pass/CastShadow_pass'; +import { ZPassShader_vs } from './core/pass/ZPassShader_vs'; +import { ZPassShader_fs } from './core/pass/ZPassShader_fs'; /** * @internal @@ -44,6 +54,7 @@ export class ShaderLib { public static init() { ShaderLib.register('MathShader', MathShader); ShaderLib.register('FastMathShader', FastMathShader); + ShaderLib.register('MatrixShader', MatrixShader); ShaderLib.register('GlobalUniform', GlobalUniform); @@ -78,11 +89,13 @@ export class ShaderLib { ShaderLib.register('ColorUtil_frag', ColorUtil); ShaderLib.register('ColorUtil', ColorUtil); ShaderLib.register('BRDF_frag', BRDF_frag); + ShaderLib.register('Hair_frag', Hair_frag); ShaderLib.register('BxDF_frag', BxDF_frag); + ShaderLib.register('BsDF_frag', BsDF_frag); ShaderLib.register('UnLit_frag', UnLit_frag); ShaderLib.register('UnLit', UnLit); ShaderLib.register('Clearcoat_frag', Clearcoat_frag); - ShaderLib.register('LitShader', LitShader); + ShaderLib.register('LitShader', Lit_shader); ShaderLib.register('PBRLItShader', PBRLItShader); ShaderLib.register('ClusterDebug_frag', ClusterDebug_frag); @@ -94,11 +107,8 @@ export class ShaderLib { ShaderLib.register('Quad_depthCube_frag_wgsl', Quad_depthCube_frag_wgsl); ShaderLib.register('sky_vs_frag_wgsl', CubeSky_Shader.sky_vs_frag_wgsl); ShaderLib.register('sky_fs_frag_wgsl', CubeSky_Shader.sky_fs_frag_wgsl); - ShaderLib.register('Bloom_Brightness_frag_wgsl', Bloom_shader.Bloom_Brightness_frag_wgsl); - ShaderLib.register('Bloom_blur_frag_wgsl', Bloom_shader.Bloom_blur_frag_wgsl); - ShaderLib.register('Bloom_composite_frag_wgsl', Bloom_shader.Bloom_composite_frag_wgsl); - ShaderLib.register("LambertShader", LambertShader); + ShaderLib.register("LambertShader", Lambert_shader); ShaderLib.register("QuadGlsl_vs", QuadGlsl_vs); ShaderLib.register("QuadGlsl_fs", QuadGlsl_fs); diff --git a/src/assets/shader/utils/BRDFLUT.ts b/src/assets/shader/compute/BRDFLUT.ts similarity index 100% rename from src/assets/shader/utils/BRDFLUT.ts rename to src/assets/shader/compute/BRDFLUT.ts diff --git a/src/assets/shader/compute/BloomEffect_cs.ts b/src/assets/shader/compute/BloomEffect_cs.ts new file mode 100644 index 00000000..36b4e3d7 --- /dev/null +++ b/src/assets/shader/compute/BloomEffect_cs.ts @@ -0,0 +1,214 @@ + +let BloomCfg = /*wgsl*/ ` +struct BloomCfg{ + downSampleStep: f32, + downSampleBlurSize: f32, + downSampleBlurSigma: f32, + upSampleBlurSize: f32, + upSampleBlurSigma: f32, + luminanceThreshole: f32, + bloomIntensity: f32, + slot: f32, +} +@group(0) @binding(0) var bloomCfg: BloomCfg; +` +//_______________calc weight + +let GaussWeight2D: string = /*wgsl*/ ` +fn GaussWeight2D(x:f32, y:f32, sigma:f32) -> f32 + { + let PI = 3.14159265358; + let E = 2.71828182846; + let sigma_2 = pow(sigma, 2); + + let a = -(x*x + y*y) / (2.0 * sigma_2); + return pow(E, a) / (2.0 * PI * sigma_2); + } +` + +let GaussBlur = function (GaussNxN: string, inTex: string, inTexSampler: string) { + var code: string = /*wgsl*/ ` + + + fn ${GaussNxN}(uv:vec2, n:i32, stride:vec2, sigma:f32) -> vec3 + { + var color = vec3(0.0); + let r:i32 = n / 2; + var weight:f32 = 0.0; + + for(var i:i32=-r; i<=r; i+=1) + { + for(var j=-r; j<=r; j+=1) + { + let w = GaussWeight2D(f32(i), f32(j), sigma); + var coord:vec2 = uv + vec2(f32(i), f32(j)) * stride; + // color += tex2D(tex, coord).rgb * w; + color += textureSampleLevel(${inTex}, ${inTexSampler}, coord, 0.0).xyz * w; + weight += w; + } + } + + color /= weight; + return color; + }`; + return code; + +} + + + +//________________________pixel filter + +export let threshold: string = /*wgsl*/ ` +${BloomCfg} + +@group(0) @binding(1) var inTex : texture_2d; +@group(0) @binding(2) var outTex : texture_storage_2d; + +var texSize: vec2; +var fragCoord: vec2; + +@compute @workgroup_size( 8 , 8 , 1 ) +fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) +{ + fragCoord = vec2( globalInvocation_id.xy ); + texSize = textureDimensions(inTex).xy; + if(fragCoord.x >= i32(texSize.x) || fragCoord.y >= i32(texSize.y)){ + return; + } + var color = textureLoad(inTex, fragCoord, 0); + let lum = dot(vec3(0.2126, 0.7152, 0.0722), color.rgb); + + // if(lum<=bloomCfg.luminanceThreshole) { + // color = vec4(0,0,0,color.w); + // } + var ret = color.xyz; + var brightness = lum; + var contribution = max(0, brightness - bloomCfg.luminanceThreshole); + contribution /=max(brightness, 0.00001); + ret = ret * contribution; + + textureStore(outTex, fragCoord, vec4(ret, color.w)); +} +` + +//________________________down sample + +export let downSample: string = /*wgsl*/ ` +${BloomCfg} + +@group(0) @binding(1) var inTex : texture_2d; +@group(0) @binding(2) var inTexSampler: sampler; +@group(0) @binding(3) var outTex : texture_storage_2d; + +var texSize: vec2; +var fragCoord: vec2; + +${GaussWeight2D} +${GaussBlur('GaussNxN', 'inTex', 'inTexSampler')} + +@compute @workgroup_size( 8 , 8 , 1 ) +fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) +{ + fragCoord = vec2( globalInvocation_id.xy ); + texSize = textureDimensions(outTex).xy; + if(fragCoord.x >= i32(texSize.x) || fragCoord.y >= i32(texSize.y)){ + return; + } + var color = vec4(0.0, 0.0, 0.0, 1.0); + var uv = vec2(f32(fragCoord.x), f32(fragCoord.y)) / vec2(f32(texSize.x - 1), f32(texSize.y -1)); + let stride = vec2(1.0) / vec2(f32(texSize.x), f32(texSize.y)); // texel size of last level + let rgb = GaussNxN(uv, i32(bloomCfg.downSampleBlurSize), stride, bloomCfg.downSampleBlurSigma); + color = vec4(rgb, color.w); + textureStore(outTex, fragCoord, color); +} +` + + +//__________________________up sample +export let upSample = /*wgsl*/ ` +${BloomCfg} + +@group(0) @binding(1) var _MainTex : texture_2d; +@group(0) @binding(2) var _MainTexSampler: sampler; +@group(0) @binding(3) var _PrevMip : texture_2d; +@group(0) @binding(4) var _PrevMipSampler: sampler; +@group(0) @binding(5) var outTex : texture_storage_2d; + +var texSize: vec2; +var fragCoord: vec2; + +${GaussWeight2D} +${GaussBlur('GaussNxN_0', '_MainTex', '_MainTexSampler')} +${GaussBlur('GaussNxN_1', '_PrevMip', '_PrevMipSampler')} + +@compute @workgroup_size( 8 , 8 , 1 ) +fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) +{ + fragCoord = vec2( globalInvocation_id.xy ); + texSize = textureDimensions(outTex).xy; + if(fragCoord.x >= i32(texSize.x) || fragCoord.y >= i32(texSize.y)){ + return; + } + var color = vec4(0.0, 0.0, 0.0, 1.0); + var uv = vec2(f32(fragCoord.x), f32(fragCoord.y)) / vec2(f32(texSize.x - 1), f32(texSize.y -1)); + // half stride + let prev_stride = vec2(0.5) / vec2(f32(texSize.x), f32(texSize.y)); + let curr_stride = vec2(1.0) / vec2(f32(texSize.x), f32(texSize.y)); + + let rgb1 = GaussNxN_0(uv, i32(bloomCfg.upSampleBlurSize), prev_stride, bloomCfg.upSampleBlurSigma); + let rgb2 = GaussNxN_1(uv, i32(bloomCfg.upSampleBlurSize), curr_stride, bloomCfg.upSampleBlurSigma); + color = vec4(rgb1+rgb2, color.w); + textureStore(outTex, fragCoord, color); +} +` + + +//__________________________blend +export let post = /*wgsl*/ ` +${BloomCfg} + +@group(0) @binding(1) var _MainTex : texture_2d; +@group(0) @binding(2) var _BloomTex : texture_2d; +@group(0) @binding(3) var _BloomTexSampler : sampler; +@group(0) @binding(4) var outTex : texture_storage_2d; + +var texSize: vec2; +var fragCoord: vec2; + +fn ACESToneMapping(color: vec3, adapted_lum: f32) -> vec3 +{ + let A = 2.51; + let B = 0.03; + let C = 2.43; + let D = 0.59; + let E = 0.14; + + var color2 = color * adapted_lum; + color2 = (color2 * (A * color2 + B)) / (color2 * (C * color2 + D) + E); + return color2; +} + +@compute @workgroup_size( 8 , 8 , 1 ) +fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) +{ + fragCoord = vec2( globalInvocation_id.xy ); + texSize = textureDimensions(outTex).xy; + if(fragCoord.x >= i32(texSize.x) || fragCoord.y >= i32(texSize.y)){ + return; + } + var color = textureLoad(_MainTex, fragCoord, 0); + let uv = vec2(f32(fragCoord.x), f32(fragCoord.y)) / vec2(f32(texSize.x - 1), f32(texSize.y - 1)); + + // var bloom = textureLoad(_BloomTex, fragCoord, 0).xyz; + var bloom = textureSampleLevel(_BloomTex, _BloomTexSampler, uv, 0.0).xyz * bloomCfg.bloomIntensity; + + // tone map + bloom = ACESToneMapping(bloom, 1.0); + let g = 1.0 / 2.2; + bloom = saturate(pow(bloom, vec3(g))); + + color = vec4(color.xyz + bloom.xyz, color.w); + textureStore(outTex, fragCoord, color); +} +` \ No newline at end of file diff --git a/src/assets/shader/compute/DDGIIrradiance_Cs.ts b/src/assets/shader/compute/DDGIIrradiance_Cs.ts index 2ca6d611..ae97f6c1 100644 --- a/src/assets/shader/compute/DDGIIrradiance_Cs.ts +++ b/src/assets/shader/compute/DDGIIrradiance_Cs.ts @@ -2,6 +2,7 @@ export let DDGIIrradiance_shader = /*wgsl*/` #include "GenerayRandomDir" #include "MathShader" #include "IrradianceVolumeData_frag" +var PI: f32 = 3.14159265359; struct ProbeData{ offsetX:f32, @@ -32,7 +33,7 @@ struct CacheHitData{ @group(0) @binding(0) var probes : array; @group(0) @binding(1) var irradianceBuffer : array>; @group(0) @binding(2) var depthBuffer : array>; -@group(0) @binding(3) var uniformData : IrradianceVolumeData ; +@group(0) @binding(3) var uniformData : IrradianceVolumeData ; @group(0) @binding(4) var probeIrradianceMap : texture_storage_2d; @group(0) @binding(5) var probeDepthMap : texture_storage_2d; @group(0) @binding(6) var depthRaysBuffer : array>; diff --git a/src/assets/shader/compute/DDGILighting_CSShader.ts b/src/assets/shader/compute/DDGILighting_CSShader.ts index 98fe584d..e650ee67 100644 --- a/src/assets/shader/compute/DDGILighting_CSShader.ts +++ b/src/assets/shader/compute/DDGILighting_CSShader.ts @@ -1,6 +1,7 @@ import { CSM } from "../../../core/csm/CSM"; export let DDGILighting_shader = /*wgsl*/` +var PI: f32 = 3.14159265359; #include "GlobalUniform" #include "MathShader" diff --git a/src/assets/shader/compute/GTAO_cs.ts b/src/assets/shader/compute/GTAO_cs.ts index 35ef5351..683d2f9d 100644 --- a/src/assets/shader/compute/GTAO_cs.ts +++ b/src/assets/shader/compute/GTAO_cs.ts @@ -63,6 +63,7 @@ export let GTAO_cs: string = /*wgsl*/ ` if(gtaoData.blendColor > 0.5){ outColor = oc.xyz * gtao; } + // textureStore(outTex, fragCoord , vec4(vec3f(newFactor), oc.w)); textureStore(outTex, fragCoord , vec4(outColor, oc.w)); } @@ -115,14 +116,16 @@ export let GTAO_cs: string = /*wgsl*/ ` && sampleCoord.y < i32(texSize.y) ) { totalWeight += 1.0; - let samplePosition = textureLoad(posTex, sampleCoord, 0).xyz; - let distanceVec2 = samplePosition - wPosition; - let distance = length(distanceVec2); - if(distance < gtaoData.maxDistance && distance > 1.0){ - let sampleDir = normalize(distanceVec2); - var factor = saturate(dot(sampleDir, originNormal) - 0.1); - factor *= 1.0 - distance / gtaoData.maxDistance; - weight += factor; + let samplePosition = textureLoad(posTex, sampleCoord, 0).xyzw; + if(samplePosition.w>0.0){ + let distanceVec2 = samplePosition.xyz - wPosition; + let distance = length(distanceVec2); + if(distance < gtaoData.maxDistance ){ + let sampleDir = normalize(distanceVec2); + var factor = saturate( dot(sampleDir, originNormal)); + factor *= 1.0 - distance / gtaoData.maxDistance; + weight += factor; + } } } } diff --git a/src/assets/shader/compute/MultiBouncePass_cs.ts b/src/assets/shader/compute/MultiBouncePass_cs.ts index 55ba48c4..bf44b2db 100644 --- a/src/assets/shader/compute/MultiBouncePass_cs.ts +++ b/src/assets/shader/compute/MultiBouncePass_cs.ts @@ -13,7 +13,7 @@ export let MultiBouncePass_cs: string = /*wgsl*/ ` }; @group(0) @binding(0) var outputBuffer : texture_storage_2d; - @group(0) @binding(1) var uniformData : IrradianceVolumeData ; + @group(0) @binding(1) var uniformData : IrradianceVolumeData ; @group(1) @binding(0) var normalMapSampler : sampler; @group(1) @binding(1) var normalMap : texture_2d; diff --git a/src/assets/shader/compute/PreIntegratedLut.ts b/src/assets/shader/compute/PreIntegratedLut.ts new file mode 100644 index 00000000..e3676e29 --- /dev/null +++ b/src/assets/shader/compute/PreIntegratedLut.ts @@ -0,0 +1,70 @@ + +export let PreIntegratedLut: string = /*wgsl*/ ` +varPI: f32 = 3.141592653589793; + +fn Scatter( r:f32) -> vec3f +{ + return Gaussian(0.0064 * 1.414, r) * vec3f(0.233, 0.455, 0.649) + + Gaussian(0.0484 * 1.414, r) * vec3f(0.100, 0.336, 0.344) + + Gaussian(0.1870 * 1.414, r) * vec3f(0.118, 0.198, 0.000) + + Gaussian(0.5670 * 1.414, r) * vec3f(0.113, 0.007, 0.007) + + Gaussian(1.9900 * 1.414, r) * vec3f(0.358, 0.004, 0.00001) + + Gaussian(7.4100 * 1.414, r) * vec3f(0.078, 0.00001, 0.00001); +} + +fn Gaussian( v:f32 , r:f32 ) -> f32 +{ + return 1.0 / sqrt(2.0 * PI * v) * exp(-(r * r) / (2.0 * v)); +} + +fn Integrate( cosTheta : f32 , skinRadius: f32 ) -> vec3f +{ + var theta = acos(cosTheta); // theta -> the angle from lighting direction + var totalWeights = vec3f(0.0); + var totalLight = vec3f(0.0); + + var a = -(PI / 2.0); + let inc = 0.05; + + while ( a <= (PI / 2.0) ) { + var sampleAngle = theta + a; + var diffuse = clamp(cos(sampleAngle),0.0,1.0); + + // calc distance + var sampleDist = abs(2.0 * skinRadius * sin(a * 0.5)); + + // estimated by Gaussian pdf + var weights = Scatter(sampleDist); + + totalWeights += weights; + totalLight += diffuse * weights; + a += inc; + } + + var result = vec3f(totalLight.x / totalWeights.x, totalLight.y / totalWeights.y, totalLight.z / totalWeights.z); + return result; +} + +@group(0) @binding(0) var sssMap: texture_storage_2d; + +@compute @workgroup_size(8, 8, 1) +// fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(local_invocation_id) local_invocation_id : vec3 ){ +fn CsMain(@builtin(global_invocation_id) global_invocation_id : vec3){ + var fragCoord = vec2(global_invocation_id.x, global_invocation_id.y); + + var fragColor = vec4(1.0,1.0,0.0,1.0); + // // Output to screen + // var res = integrateBRDF(f32(fragCoord.y + 1u) / 256.0, f32(fragCoord.x + 1u) / 256.0); + // fragColor = vec4(res.x, res.y, 0.0, 1.0); + + var NDotL = mix(-1.0, 1.0, f32(fragCoord.x) / 256.0) ; + var oneOverR = 2.0 * 1.0 / (f32((fragCoord.y + 1u)) / 256.0); + + //Integrate Diffuse Scattering + var diff = Integrate(NDotL, oneOverR); + // fragColor = vec4f(diff,1.0); + fragColor = vec4f(vec3f(diff),1.0); + textureStore(sssMap, vec2(fragCoord.xy), fragColor); +} +` + diff --git a/src/assets/shader/core/base/Common_frag.ts b/src/assets/shader/core/base/Common_frag.ts index 58ca186d..b793b400 100644 --- a/src/assets/shader/core/base/Common_frag.ts +++ b/src/assets/shader/core/base/Common_frag.ts @@ -8,8 +8,11 @@ export let Common_frag: string = /*wgsl*/ ` var ORI_VertexVarying: FragmentVarying; var ORI_ShadingInput: ShadingInput; var viewDir:vec3; + var modelIndex:u32; @fragment fn FragMain( vertex_varying:FragmentVarying ) -> FragmentOutput { + modelIndex = u32(round(vertex_varying.index)) ; + ORI_VertexVarying = vertex_varying; ORI_FragmentOutput.color = vec4(1.0, 0.0, 0.0, 1.0); viewDir = normalize(globalUniform.CameraPos.xyz - ORI_VertexVarying.vWorldPos.xyz) ; @@ -26,9 +29,6 @@ export let Common_frag: string = /*wgsl*/ ` debugFragmentOut(); #endif - // var d1 = logDepth( ORI_VertexVarying.fragCoord.w , globalUniform.far); - // ORI_FragmentOutput.out_depth = d1 ; - #if USE_OUTDEPTH #if USE_LOGDEPTH ORI_FragmentOutput.out_depth = log2Depth(ORI_VertexVarying.fragCoord.z,globalUniform.near,globalUniform.far) ; @@ -37,10 +37,6 @@ export let Common_frag: string = /*wgsl*/ ` #endif #endif - // var d1 = log2(ORI_VertexVarying.fragCoord.w + 1.0) * 2.0 / (log(f + 1.0) / 0.6931471805599453) * 0.5 ; - // 2.0 / (Math.log(camera.far + 1.0) / Math.LN2) - // ORI_FragmentOutput.out_depth = d1 ; - return ORI_FragmentOutput ; } diff --git a/src/assets/shader/core/common/GlobalUniform.ts b/src/assets/shader/core/common/GlobalUniform.ts index 954e679e..89750c83 100644 --- a/src/assets/shader/core/common/GlobalUniform.ts +++ b/src/assets/shader/core/common/GlobalUniform.ts @@ -40,10 +40,16 @@ export let GlobalUniform: string = /*wgsl*/ ` enableCSM:f32, csmMargin:f32, - notUsed1:f32, - notUsed2:f32, - notUsed3:f32 - + nDirShadowStart: i32, + nDirShadowEnd: i32, + nPointShadowStart: i32, + + nPointShadowEnd: i32, + empty1: i32, + empty2: i32, + empty3: i32, + + shadowLights:mat4x4 }; @group(0) @binding(0) diff --git a/src/assets/shader/core/pass/CastShadow_pass.ts b/src/assets/shader/core/pass/CastShadow_pass.ts index cd43c7bb..38087140 100644 --- a/src/assets/shader/core/pass/CastShadow_pass.ts +++ b/src/assets/shader/core/pass/CastShadow_pass.ts @@ -20,37 +20,68 @@ struct VertexOutput { var worldMatrix: mat4x4; struct VertexAttributes{ - @builtin(instance_index) index : u32, - @location(0) position: vec3, - @location(1) normal: vec3, - @location(2) uv: vec2, - @location(3) TEXCOORD_1: vec2, + @builtin(instance_index) index : u32, + @location(0) position: vec3, + @location(1) normal: vec3, + @location(2) uv: vec2, + @location(3) TEXCOORD_1: vec2, + + #if USE_METAHUMAN + #if USE_TANGENT + @location(4) TANGENT: vec4, + @location(5) joints0: vec4, + @location(6) weights0: vec4, + #if USE_JOINT_VEC8 + @location(7) joints1: vec4, + @location(8) weights1: vec4, + ${MorphTarget_shader.getMorphTargetAttr(9)} + #else + ${MorphTarget_shader.getMorphTargetAttr(7)} + #endif + #else + @location(4) joints0: vec4, + @location(5) weights0: vec4, + #if USE_JOINT_VEC8 + @location(6) joints1: vec4, + @location(7) weights1: vec4, + ${MorphTarget_shader.getMorphTargetAttr(8)} + #else + ${MorphTarget_shader.getMorphTargetAttr(6)} + #endif + #endif + #else + #if USE_TANGENT + @location(4) TANGENT: vec4, + #endif - #if USE_TANGENT - @location(4) TANGENT: vec4, - #if USE_SKELETON - @location(5) joints0: vec4, - @location(6) weights0: vec4, - #if USE_JOINT_VEC8 - @location(7) joints1: vec4, - @location(8) weights1: vec4, - #endif - #elseif USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetAttr(5)} - #endif - #elseif USE_SKELETON - @location(4) joints0: vec4, - @location(5) weights0: vec4, - #if USE_JOINT_VEC8 - @location(6) joints1: vec4, - @location(7) weights1: vec4, - #endif - #elseif USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetAttr(4)} - #endif -} + #if USE_SKELETON + #if USE_TANGENT + @location(5) joints0: vec4, + @location(6) weights0: vec4, + #if USE_JOINT_VEC8 + @location(7) joints1: vec4, + @location(8) weights1: vec4, + #endif + #else + @location(4) joints0: vec4, + @location(5) weights0: vec4, + #if USE_JOINT_VEC8 + @location(6) joints1: vec4, + @location(7) weights1: vec4, + #endif + #endif + #endif + #if USE_MORPHTARGETS + #if USE_TANGENT + ${MorphTarget_shader.getMorphTargetAttr(5)} + #else + ${MorphTarget_shader.getMorphTargetAttr(4)} + #endif + #endif + #endif +} @vertex fn main(vertex:VertexAttributes) -> VertexOutput { @@ -105,28 +136,54 @@ struct VertexAttributes{ @location(2) uv: vec2, @location(3) TEXCOORD_1: vec2, - #if USE_TANGENT - @location(4) TANGENT: vec4, - #if USE_SKELETON - @location(5) joints0: vec4, - @location(6) weights0: vec4, - #if USE_JOINT_VEC8 - @location(7) joints1: vec4, - @location(8) weights1: vec4, - #endif - #elseif USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetAttr(5)} - #endif - #elseif USE_SKELETON - @location(4) joints0: vec4, - @location(5) weights0: vec4, - #if USE_JOINT_VEC8 - @location(6) joints1: vec4, - @location(7) weights1: vec4, - #endif - #elseif USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetAttr(4)} - #endif + + #if USE_METAHUMAN + #if USE_TANGENT + @location(4) TANGENT: vec4, + @location(5) joints0: vec4, + @location(6) weights0: vec4, + @location(7) joints1: vec4, + @location(8) weights1: vec4, + ${MorphTarget_shader.getMorphTargetAttr(9)} + #else + @location(4) joints0: vec4, + @location(5) weights0: vec4, + @location(6) joints1: vec4, + @location(7) weights1: vec4, + ${MorphTarget_shader.getMorphTargetAttr(8)} + #endif + #else + #if USE_TANGENT + @location(4) TANGENT: vec4, + #endif + + #if USE_SKELETON + #if USE_TANGENT + @location(5) joints0: vec4, + @location(6) weights0: vec4, + #if USE_JOINT_VEC8 + @location(7) joints1: vec4, + @location(8) weights1: vec4, + #endif + #else + @location(4) joints0: vec4, + @location(5) weights0: vec4, + #if USE_JOINT_VEC8 + @location(6) joints1: vec4, + @location(7) weights1: vec4, + #endif + #endif + #endif + + #if USE_MORPHTARGETS + #if USE_TANGENT + ${MorphTarget_shader.getMorphTargetAttr(5)} + #else + ${MorphTarget_shader.getMorphTargetAttr(4)} + #endif + #endif + + #endif } @vertex @@ -135,6 +192,15 @@ fn main(vertex:VertexAttributes) -> VertexOutput { let shadowMatrix: mat4x4 = globalUniform.projMat * globalUniform.viewMat ; var vertexPosition = vertex.position.xyz; + #if USE_METAHUMAN + ${MorphTarget_shader.getMorphTargetCalcVertex()} + #if USE_JOINT_VEC8 + worldMatrix *= getSkeletonWorldMatrix_8(vertex.joints0, vertex.weights0, vertex.joints1, vertex.weights1); + #else + worldMatrix *= getSkeletonWorldMatrix_4(vertex.joints0, vertex.weights0); + #endif + #endif + #if USE_MORPHTARGETS ${MorphTarget_shader.getMorphTargetCalcVertex()} #endif diff --git a/src/assets/shader/core/pass/SkyGBuffer_pass.ts b/src/assets/shader/core/pass/SkyGBuffer_pass.ts index 72add096..a7166de1 100644 --- a/src/assets/shader/core/pass/SkyGBuffer_pass.ts +++ b/src/assets/shader/core/pass/SkyGBuffer_pass.ts @@ -2,8 +2,9 @@ export let SkyGBuffer_pass: string = /*wgsl*/ ` #include "GlobalUniform" struct uniformData { + eyesPos: vec3, exposure: f32, - roughness: f32 + roughness: f32, }; struct FragmentOutput { @@ -21,14 +22,10 @@ var baseMap: texture_cube; var global: uniformData; fn LinearToGammaSpace(linRGB: vec3) -> vec3 { - var linRGB1: vec3; - linRGB1 = linRGB; - linRGB1 = max(linRGB1, vec3(0.0, 0.0, 0.0)); - linRGB1.x = pow(linRGB1.x, 0.4166666567325592); - linRGB1.y = pow(linRGB1.y, 0.4166666567325592); - linRGB1.z = pow(linRGB1.z, 0.4166666567325592); + var linRGB1 = max(linRGB, vec3(0.0)); + linRGB1 = pow(linRGB1, vec3(0.4166666567325592)); return max(((1.0549999475479126 * linRGB1) - vec3(0.054999999701976776)), vec3(0.0)); -} + } @fragment fn main(@location(0) fragUV: vec2, @location(1) vWorldPos: vec4, @location(2) vWorldNormal: vec3) -> FragmentOutput { diff --git a/src/assets/shader/core/struct/FragmentVarying.ts b/src/assets/shader/core/struct/FragmentVarying.ts index b3f36f66..8a0ccc99 100644 --- a/src/assets/shader/core/struct/FragmentVarying.ts +++ b/src/assets/shader/core/struct/FragmentVarying.ts @@ -1,20 +1,21 @@ export let FragmentVarying: string = /*wgsl*/ ` struct FragmentVarying { - @location(0) fragUV0: vec2, - @location(1) fragUV1: vec2, - @location(2) viewPosition: vec4, - @location(3) fragPosition: vec4, - @location(4) vWorldPos: vec4, - @location(5) vWorldNormal: vec3, - @location(6) vColor: vec4, + @location(0) index: f32, + @location(1) fragUV0: vec2, + @location(2) fragUV1: vec2, + @location(3) viewPosition: vec4, + @location(4) fragPosition: vec4, + @location(5) vWorldPos: vec4, + @location(6) vWorldNormal: vec3, + @location(7) vColor: vec4, #if USE_SHADOWMAPING - @location(7) vShadowPos: vec4, + @location(8) vShadowPos: vec4, #endif #if USE_TANGENT - @location(8) TANGENT: vec4, + @location(9) TANGENT: vec4, #endif @builtin(front_facing) face: bool, diff --git a/src/assets/shader/core/struct/ShadingInput.ts b/src/assets/shader/core/struct/ShadingInput.ts index 4d626624..77f76427 100644 --- a/src/assets/shader/core/struct/ShadingInput.ts +++ b/src/assets/shader/core/struct/ShadingInput.ts @@ -1,21 +1,29 @@ export let ShadingInput: string = /*wgsl*/ ` struct ShadingInput{ BaseColor:vec4, + Roughness:f32, Metallic:f32, Specular:f32, + EmissiveColor:vec4, SurfaceColor:vec4, + Normal:vec3, + HairNormal:vec3, Tangent:vec4, + WorldPositionOffset:vec3, AmbientOcclusion:f32, + PixelDepthOffset:f32, Opacity:f32, OpacityMask:f32, Refraction:f32, - FragDepth:f32 + FragDepth:f32, + + SSS:vec3f, } ` diff --git a/src/assets/shader/core/struct/VertexAttributeIndexShader.ts b/src/assets/shader/core/struct/VertexAttributeIndexShader.ts new file mode 100644 index 00000000..99821333 --- /dev/null +++ b/src/assets/shader/core/struct/VertexAttributeIndexShader.ts @@ -0,0 +1,86 @@ + +export let VertexAttributeIndexShader: string = /*wgsl*/ ` + #include "WorldMatrixUniform" + struct VertexAttributes{ + @builtin(instance_index) index : u32, + + @location(0) position: vec3, + @location(1) normal: vec3, + @location(2) uv: vec2, + @location(3) TEXCOORD_1: vec2, + @location(4) vIndex: f32, + } + + struct VertexOutput { + @location(0) index: f32, + @location(1) varying_UV0: vec2, + @location(2) varying_UV1: vec2, + @location(3) varying_ViewPos: vec4, + @location(4) varying_Clip: vec4, + @location(5) varying_WPos: vec4, + @location(6) varying_WNormal: vec3, + @location(7) varying_Color: vec4, + #if USE_SHADOWMAPING + @location(8) varying_ShadowPos: vec4, + #endif + @builtin(position) member: vec4 + }; + + struct TransformVertex{ + position:vec3, + normal:vec3, + } + + struct GraphicNodeStruct{ + matrixIndex:f32, + texIndex:f32, + } + + var ORI_VertexOut: VertexOutput ; + var worldMatrix: mat4x4 ; + var graphicNode: GraphicNodeStruct ; + + fn ORI_Vert(vertex:VertexAttributes){ + var vertexPosition = vertex.position; + var vertexNormal = vertex.normal; + + ORI_VertexOut.index = f32(vertex.vIndex) ; + graphicNode = graphicBuffer[u32(round(vertex.vIndex))]; + let node_Matrix_M = models.matrix[u32(round(graphicNode.matrixIndex))]; + + #if USE_TANGENT + ORI_VertexOut.varying_Tangent = vertex.TANGENT ; + #endif + + ORI_MATRIX_M = node_Matrix_M * ORI_MATRIX_M ; + + #if USE_BILLBOARD + let billboardMatrix: mat3x3 = calculateBillboardMatrix2(globalUniform.CameraPos.xyz,ORI_MATRIX_M[3].xyz,globalUniform.cameraWorldMatrix[1].xyz); + vertexPosition = billboardMatrix * vertexPosition.xyz; + #endif + + worldMatrix = ORI_MATRIX_M ; + + let nMat = mat3x3(ORI_MATRIX_M[0].xyz,ORI_MATRIX_M[1].xyz,ORI_MATRIX_M[2].xyz) ; + ORI_NORMALMATRIX = transpose(inverse( nMat )); + + var worldPos = (ORI_MATRIX_M * vec4(vertexPosition.xyz, 1.0)); + + #if TRANSFORMVERTEX + var transformVertex = transformVertex(worldPos.xyz,vertexNormal,vertex); + worldPos = vec4(transformVertex.position ,worldPos.w); + vertexNormal = transformVertex.normal ; + #endif + + var viewPosition = ORI_MATRIX_V * worldPos; + var clipPosition = ORI_MATRIX_P * viewPosition ; + + ORI_VertexOut.varying_UV0 = vertex.uv.xy ; + ORI_VertexOut.varying_UV1 = vertex.TEXCOORD_1.xy; + ORI_VertexOut.varying_ViewPos = viewPosition / viewPosition.w; + ORI_VertexOut.varying_Clip = clipPosition; + ORI_VertexOut.varying_WPos = worldPos; + ORI_VertexOut.varying_WNormal = normalize( vertexNormal.xyz); + ORI_VertexOut.member = clipPosition ; + } +` \ No newline at end of file diff --git a/src/assets/shader/core/struct/VertexAttributes.ts b/src/assets/shader/core/struct/VertexAttributes.ts index 5ed5f5da..74031a90 100644 --- a/src/assets/shader/core/struct/VertexAttributes.ts +++ b/src/assets/shader/core/struct/VertexAttributes.ts @@ -2,60 +2,100 @@ import { SkeletonAnimation_shader } from "../../anim/SkeletonAnimation_shader"; import { MorphTarget_shader } from "../../../../components/anim/morphAnim/MorphTarget_shader"; export let VertexAttributes: string = /*wgsl*/ ` - #if USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetShaderBinding(3, 0)} - #endif + var PI: f32 = 3.14159265359; + #if USE_METAHUMAN + ${MorphTarget_shader.getMorphTargetShaderBinding(3, 0)} + ${SkeletonAnimation_shader.groupBindingAndFunctions(3, 2)} + #else + #if USE_MORPHTARGETS + ${MorphTarget_shader.getMorphTargetShaderBinding(3, 0)} + #endif - #if USE_SKELETON - ${SkeletonAnimation_shader.groupBindingAndFunctions(3, 0)} + #if USE_SKELETON + ${SkeletonAnimation_shader.groupBindingAndFunctions(3, 0)} + #endif #endif struct VertexAttributes{ - @builtin(instance_index) index : u32, - @location(0) position: vec3, - @location(1) normal: vec3, - @location(2) uv: vec2, - @location(3) TEXCOORD_1: vec2, + @builtin(instance_index) index : u32, + @location(0) position: vec3, + @location(1) normal: vec3, + @location(2) uv: vec2, + @location(3) TEXCOORD_1: vec2, + + #if USE_METAHUMAN + #if USE_TANGENT + @location(4) TANGENT: vec4, + @location(5) joints0: vec4, + @location(6) weights0: vec4, + #if USE_JOINT_VEC8 + @location(7) joints1: vec4, + @location(8) weights1: vec4, + ${MorphTarget_shader.getMorphTargetAttr(9)} + #else + ${MorphTarget_shader.getMorphTargetAttr(7)} + #endif + #else + @location(4) joints0: vec4, + @location(5) weights0: vec4, + #if USE_JOINT_VEC8 + @location(6) joints1: vec4, + @location(7) weights1: vec4, + ${MorphTarget_shader.getMorphTargetAttr(8)} + #else + ${MorphTarget_shader.getMorphTargetAttr(6)} + #endif + #endif + #else + #if USE_TANGENT + @location(4) TANGENT: vec4, + #endif + + #if USE_SKELETON + #if USE_TANGENT + @location(5) joints0: vec4, + @location(6) weights0: vec4, + #if USE_JOINT_VEC8 + @location(7) joints1: vec4, + @location(8) weights1: vec4, + #endif + #else + @location(4) joints0: vec4, + @location(5) weights0: vec4, + #if USE_JOINT_VEC8 + @location(6) joints1: vec4, + @location(7) weights1: vec4, + #endif + #endif + #endif + + #if USE_MORPHTARGETS + #if USE_TANGENT + ${MorphTarget_shader.getMorphTargetAttr(5)} + #else + ${MorphTarget_shader.getMorphTargetAttr(4)} + #endif + #endif - #if USE_TANGENT - @location(4) TANGENT: vec4, - #if USE_SKELETON - @location(5) joints0: vec4, - @location(6) weights0: vec4, - #if USE_JOINT_VEC8 - @location(7) joints1: vec4, - @location(8) weights1: vec4, - #endif - #elseif USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetAttr(5)} - #endif - #elseif USE_SKELETON - @location(4) joints0: vec4, - @location(5) weights0: vec4, - #if USE_JOINT_VEC8 - @location(6) joints1: vec4, - @location(7) weights1: vec4, #endif - #elseif USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetAttr(4)} - #endif } struct VertexOutput { - @location(0) varying_UV0: vec2, - @location(1) varying_UV1: vec2, - @location(2) varying_ViewPos: vec4, - @location(3) varying_Clip: vec4, - @location(4) varying_WPos: vec4, - @location(5) varying_WNormal: vec3, - @location(6) varying_Color: vec4, + @location(0) index: f32, + @location(1) varying_UV0: vec2, + @location(2) varying_UV1: vec2, + @location(3) varying_ViewPos: vec4, + @location(4) varying_Clip: vec4, + @location(5) varying_WPos: vec4, + @location(6) varying_WNormal: vec3, + @location(7) varying_Color: vec4, #if USE_SHADOWMAPING - @location(7) varying_ShadowPos: vec4, + @location(8) varying_ShadowPos: vec4, #endif #if USE_TANGENT - @location(8) varying_Tangent: vec4, + @location(9) varying_Tangent: vec4, #endif @builtin(position) member: vec4 @@ -67,11 +107,8 @@ export let VertexAttributes: string = /*wgsl*/ ` var vertexPosition = vertex.position; var vertexNormal = vertex.normal; - #if USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetCalcVertex()} - #endif - - #if USE_SKELETON + #if USE_METAHUMAN + ${MorphTarget_shader.getMorphTargetCalcVertex()} #if USE_JOINT_VEC8 let skeletonNormal = getSkeletonWorldMatrix_8(vertex.joints0, vertex.weights0, vertex.joints1, vertex.weights1); ORI_MATRIX_M *= skeletonNormal ; @@ -79,13 +116,27 @@ export let VertexAttributes: string = /*wgsl*/ ` let skeletonNormal = getSkeletonWorldMatrix_4(vertex.joints0, vertex.weights0); ORI_MATRIX_M *= skeletonNormal ; #endif - #endif + #else + #if USE_MORPHTARGETS + ${MorphTarget_shader.getMorphTargetCalcVertex()} + #endif - #if USE_TANGENT - ORI_VertexOut.varying_Tangent = vertex.TANGENT ; + #if USE_SKELETON + #if USE_JOINT_VEC8 + let skeletonNormal = getSkeletonWorldMatrix_8(vertex.joints0, vertex.weights0, vertex.joints1, vertex.weights1); + ORI_MATRIX_M *= skeletonNormal ; + #else + let skeletonNormal = getSkeletonWorldMatrix_4(vertex.joints0, vertex.weights0); + ORI_MATRIX_M *= skeletonNormal ; + #endif + #endif #endif - + ORI_NORMALMATRIX = transpose(inverse( mat3x3(ORI_MATRIX_M[0].xyz,ORI_MATRIX_M[1].xyz,ORI_MATRIX_M[2].xyz) )); + + #if USE_TANGENT + ORI_VertexOut.varying_Tangent = vec4f(normalize(ORI_NORMALMATRIX * vertex.TANGENT.xyz),vertex.TANGENT.w) ; + #endif var worldPos = (ORI_MATRIX_M * vec4(vertexPosition.xyz, 1.0)); var viewPosition = ORI_MATRIX_V * worldPos; @@ -93,8 +144,12 @@ export let VertexAttributes: string = /*wgsl*/ ` ORI_CameraWorldDir = normalize(ORI_CAMERAMATRIX[3].xyz - worldPos.xyz) ; + ORI_VertexOut.index = f32(vertex.index) ; + ORI_VertexOut.varying_UV0 = vertex.uv.xy ; + ORI_VertexOut.varying_UV1 = vertex.TEXCOORD_1.xy; + ORI_VertexOut.varying_ViewPos = viewPosition ; ORI_VertexOut.varying_Clip = clipPosition ; ORI_VertexOut.varying_WPos = worldPos ; diff --git a/src/assets/shader/lighting/BRDF_frag.ts b/src/assets/shader/lighting/BRDF_frag.ts index 99f04012..20154d19 100644 --- a/src/assets/shader/lighting/BRDF_frag.ts +++ b/src/assets/shader/lighting/BRDF_frag.ts @@ -11,15 +11,19 @@ export let BRDF_frag: string = /*wgsl*/ ` Albedo: vec4, Emissive: vec3, + Specular: vec3, N: vec3, V: vec3, R: vec3, + T: vec3, F0: vec3, F: vec3, KS: vec3, KD: vec3, + + Alpha: f32, Shadow: f32, Indirect: f32, Reflectance: f32, @@ -31,8 +35,7 @@ export let BRDF_frag: string = /*wgsl*/ ` EnvColor: vec3, Irradiance: vec3, - LightChannel: vec3, - TangentChannel: vec3, + LightChannel: vec3 }; var fragData: FragData; @@ -43,23 +46,19 @@ export let BRDF_frag: string = /*wgsl*/ ` NoL : f32 , VoL : f32 , NoH : f32 , + HoL : f32 , VoH : f32 }; fn getContext( N:vec3, V:vec3, H:vec3, L:vec3 ) -> BxDFContext { var Context:BxDFContext ; - Context.NoL = saturate(dot(N, L)) ; - Context.NoV = saturate(dot(N, V)) ; - Context.VoL = saturate(dot(V, L)) ; + Context.NoL = saturate(dot(N, L)); + Context.NoV = saturate(dot(N, V)); + Context.VoL = saturate(dot(V, L)); Context.NoH = saturate(dot(N, H)); Context.VoH = saturate(dot(V, H)); - - // Context.NoL = max(dot(N, L),0.0); - // Context.NoV = max(dot(N, V),0.0); - // Context.VoL = max(dot(V, L),0.0) ; - // Context.NoH = saturate(dot(N, H)); - // Context.VoH = max(dot(V, H),0.0); + Context.HoL = saturate(dot(H, L)); return Context ; } @@ -219,24 +218,30 @@ export let BRDF_frag: string = /*wgsl*/ ` fn simpleBRDF( albedo:vec3, N:vec3, V:vec3,L:vec3,att:f32,lightColor:vec3,roughness:f32 ,metallic:f32)-> vec3{ let H = normalize(V + L); let Context:BxDFContext = getContext(N,V,H,L); - + let alpha = roughness ;//pow(roughness,5.0) ; let F0 = mix(vec3(materialUniform.materialF0.rgb), albedo , metallic); - let D = DistributionGGX( Context.NoH , roughness); - let G = GeometrySmith(Context.NoV,Context.NoL, roughness ); + let D = DistributionGGX( Context.NoH , alpha); + let G = GeometrySmith(Context.NoV,Context.NoL, alpha ); let F = FresnelSchlick(Context.VoH, vec3(F0)); let specular = ( D * G * F ) / (4.0 * Context.NoV * Context.NoL + 0.001); - let kS = F; + + // let kS = exp2( (-5.55473 * Context.HoL - 6.98316) * Context.HoL ); + let kS = F ; var kd = 1.0 - kS ; kd *= 1.0 - metallic ; - var diffuse = kd * (albedo.rgb / PI ) ; - let ambient = specular.rgb ; - fragData.KD += kd; - fragData.KS += F; + #if USE_SRGB_ALBEDO + var diffuse = kd ; + #else + var diffuse = kd * (albedo.rgb / PI ) ; + #endif - var col = (diffuse + ambient) * Context.NoL * lightColor * att ; - // var col = (diffuse + ambient) * Context.NoL * lightColor ; - return (col.rgb ) ; + let lightAtt = Context.NoL * lightColor * att ; + var diffuseColor = diffuse * lightAtt; + // diffuseColor = vec3f(0.0) ; + var specularColor = specular * lightAtt; + var col = (diffuseColor + specularColor ) ; + return (col.rgb) ; } fn getSpecularDominantDir ( N : vec3 , R : vec3 , roughness : f32 ) -> vec3 @@ -251,10 +256,11 @@ export let BRDF_frag: string = /*wgsl*/ ` let MAX_REFLECTION_LOD = i32(textureNumLevels(prefilterMap)) ; let mip = roughnessToMipmapLevel(roughness,MAX_REFLECTION_LOD); - var prefilteredColor: vec3 = (textureSampleLevel(prefilterMap, prefilterMapSampler, getSpecularDominantDir(fragData.N,R,roughness) , mip ).rgb); - prefilteredColor = globalUniform.skyExposure * (prefilteredColor); + fragData.EnvColor = (textureSampleLevel(prefilterMap, prefilterMapSampler, getSpecularDominantDir(fragData.N,R,roughness) , mip ).rgb); + // var prefilteredColor: vec3 = (textureSampleLevel(prefilterMap, prefilterMapSampler, getSpecularDominantDir(fragData.N,R,roughness) , mip ).rgb); + fragData.EnvColor = globalUniform.skyExposure * (fragData.EnvColor); var envBRDF = textureSampleLevel(brdflutMap, brdflutMapSampler, vec2(NoV, roughness) , 0.0 ) ; - return prefilteredColor * (specularColor.rgb * envBRDF.x + saturate( 50.0 * specularColor.g ) * envBRDF.y) ; + return fragData.EnvColor * (specularColor.rgb * envBRDF.x + saturate( 50.0 * specularColor.g ) * envBRDF.y) ; } fn fresnel_coat(n:vec3,v:vec3,ior:f32) -> f32 { @@ -347,5 +353,25 @@ export let BRDF_frag: string = /*wgsl*/ ` } #endif + + fn EnvBRDF( SpecularColor : vec3f , Roughness : f32 , NoV : f32) -> vec3f + { + // brdflutMap, brdflutMapSampler + var AB = textureSampleLevel( brdflutMap, brdflutMapSampler, vec2f( NoV, Roughness ), 0.0 ).rg; + var GF = SpecularColor * AB.x + saturate( 50.0 * SpecularColor.g ) * AB.y; + return GF; + } + + fn IBLEnv( V:vec3f , N:vec3f , Roughness : f32) -> vec3f + { + let NdotV = max(dot(N,V),0.0); + let MAX_REFLECTION_LOD = i32(textureNumLevels(prefilterMap)); + + let mip = roughnessToMipmapLevel(Roughness,MAX_REFLECTION_LOD); + + let R = 2.0 * dot( V , N ) * N - V ; + var envIBL: vec3 = textureSampleLevel(prefilterMap, prefilterMapSampler, R , mip ).rgb ; + return envIBL; + } ` diff --git a/src/assets/shader/lighting/BsDF_frag.ts b/src/assets/shader/lighting/BsDF_frag.ts new file mode 100644 index 00000000..5cab6294 --- /dev/null +++ b/src/assets/shader/lighting/BsDF_frag.ts @@ -0,0 +1,154 @@ +export let BsDF_frag: string = /*wgsl*/ ` + #include "Clearcoat_frag" + #include "BRDF_frag" + #include "MathShader" + #include "FastMathShader" + #include "Common_frag" + #include "GlobalUniform" + + #include "PhysicMaterialUniform_frag" + #include "NormalMap_frag" + #include "LightingFunction_frag" + #include "Irradiance_frag" + #include "ColorUtil_frag" + #include "BxdfDebug_frag" + + + + //ORI_ShadingInput + fn initFragData() { + fragData.Albedo = ORI_ShadingInput.BaseColor ; + fragData.Ao = clamp( pow(ORI_ShadingInput.AmbientOcclusion,materialUniform.ao) , 0.0 , 1.0 ) ; + fragData.Roughness = clamp((ORI_ShadingInput.Roughness),0.003,1.0) ; + fragData.Metallic = ORI_ShadingInput.Metallic ; + fragData.Emissive = ORI_ShadingInput.EmissiveColor.rgb ; + fragData.N = ORI_ShadingInput.Normal; + let viewDir = normalize(globalUniform.CameraPos.xyz - ORI_VertexVarying.vWorldPos.xyz) ; + fragData.V = viewDir ; + #if USE_TANGENT + fragData.T = ORI_VertexVarying.TANGENT.xyz ; + #endif + + let R = 2.0 * dot( fragData.V , fragData.N ) * fragData.N - fragData.V ; + fragData.R = R ;//reflect( fragData.V , fragData.N ) ; + + fragData.NoV = saturate(dot(fragData.N, fragData.V)) ; + + fragData.F0 = mix(vec3(materialUniform.specularColor.rgb), fragData.Albedo.rgb, fragData.Metallic); + + fragData.F = computeFresnelSchlick(fragData.NoV, fragData.F0); + fragData.KD = vec3(fragData.F) ; + fragData.KS = vec3(0.0) ; + + fragData.Indirect = 0.0 ; + fragData.Reflectance = 1.0 ; + + fragData.ClearcoatRoughness = materialUniform.clearcoatRoughnessFactor ; + #if USE_CLEARCOAT_ROUGHNESS + fragData.ClearcoatRoughness = getClearcoatRoughness() * materialUniform.clearcoatRoughnessFactor; + #endif + } + + fn BsDFShading(){ + initFragData(); + + var irradiance = vec3(0.0) ; + #if USEGI + irradiance += getIrradiance().rgb ; + #else + let MAX_REFLECTION_LOD = f32(textureNumLevels(prefilterMap)) ; + irradiance += (globalUniform.skyExposure * textureSampleLevel(prefilterMap, prefilterMapSampler, fragData.N.xyz, 0.8 * (MAX_REFLECTION_LOD) ).rgb); + #endif + irradiance = ORI_ShadingInput.SSS + LinearToGammaSpace(irradiance.rgb); + fragData.Irradiance = irradiance.rgb ; + + + + //***********lighting-PBR part********* + var specColor = vec3(0.0) ; + let lightIndex = getCluster(); + let start = max(lightIndex.start, 0.0); + let count = max(lightIndex.count, 0.0); + let end = max(start + count , 0.0); + for(var i:i32 = i32(start) ; i < i32(end); i += 1 ) + { + let light = getLight(i32(i)); + switch (light.lightType) { + case PointLightType: { + specColor += pointLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic,light) ; + } + case DirectLightType: { + specColor += directDulLighting( fragData.Albedo.rgb ,fragData.N,fragData.V,fragData.Roughness ,fragData.Metallic, light , globalUniform.shadowBias) ; + } + case SpotLightType: { + specColor += spotLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic , light ) ; + } + default: { + } + } + } + + + fragData.LightChannel = specColor ; + + let sunLight = lightBuffer[0] ; + //***********lighting-PBR part********* + var F = FresnelSchlickRoughness(fragData.NoV, fragData.F0, fragData.Roughness); + var kS = F; + var kD = vec3(1.0) - kS; + kD = kD * (1.0 - fragData.Metallic); + let envIBL = materialUniform.envIntensity * approximateSpecularIBL( F , fragData.Roughness , fragData.R , fragData.NoV ) ; + fragData.EnvColor = envIBL ; + //***********indirect-specular part********* + + var surfaceReduction = 1.0/(fragData.Roughness*fragData.Roughness+1.0); + var oneMinusReflectivity = oneMinusReflectivity(fragData.Metallic , materialUniform.materialF0.r ); + var grazingTerm = clamp((1.0 - fragData.Roughness ) + (1.0 - oneMinusReflectivity),0.0,1.0); + var t = pow5(fragData.NoV); + var fresnelLerp = FresnelLerp(fragData.NoV,fragData.F0.rgb,vec3(grazingTerm)) ; + var iblSpecularResult = surfaceReduction * fragData.EnvColor * fresnelLerp + envIBL; + iblSpecularResult *= max(sunLight.quadratic,0.05) ; + //***********indirect-specular part********* + + //***********indirect-ambient part********* + var kdLast = (1.0 - fragData.F0.r) * (1.0 - fragData.Metallic); + // Dim the edges, there should be more specular reflection at the edges + var iblDiffuseResult = irradiance * 2.0 * kdLast * fragData.Albedo.rgb * (vec3(1.0) - kS) ; + //irradiance + //***********indirect-ambient part********* + var indirectResult = (iblSpecularResult + iblDiffuseResult) * fragData.Ao * max(sunLight.quadratic,0.05); + // debugOut = vec4f(iblDiffuseResult,1.0); + + ORI_FragmentOutput.color = vec4(0.0); + + // Using stripped down, 'pure log', formula. Parameterized by grey points and dynamic range covered. + #if USEGBUFFER + var normal_rgba8unorm = (ORI_VertexVarying.vWorldNormal + 1.0) * 0.5; + normal_rgba8unorm = clamp(normal_rgba8unorm, vec3(0.0), vec3(1.0)); + ORI_FragmentOutput.worldNormal = vec4(normal_rgba8unorm,1.0); + ORI_FragmentOutput.material = vec4(1.0,fragData.Roughness,fragData.Metallic,1.0); + #endif + + #if USE_WORLDPOS + ORI_FragmentOutput.worldPos = vec4(ORI_VertexVarying.vWorldPos.xyzw); + #endif + + var color = specColor + indirectResult ; + color += fragData.Emissive.xyz ; + + var clearCoatColor = vec3(0.0); + #if USE_CLEARCOAT + let clearCoatBaseColor = vec3(1.0) * materialUniform.baseColor.rgb ; + let clearNormal = fragData.N ; + let clearcoatRoughness = fragData.ClearcoatRoughness ; + let att = sunLight.intensity / LUMEN ; + let clearCoatLayer = ClearCoat_BRDF( color , materialUniform.clearcoatColor.rgb , materialUniform.ior , clearNormal , -sunLight.direction ,-fragData.V , materialUniform.clearcoatWeight , clearcoatRoughness , att ); + color = vec3(clearCoatLayer.rgb/fragData.Albedo.a) ; + #endif + + let retColor = (LinearToGammaSpace(color.rgb)); + ORI_FragmentOutput.color = vec4( retColor ,fragData.Albedo.a) ; + } + + ` + diff --git a/src/assets/shader/lighting/BxDF_frag.ts b/src/assets/shader/lighting/BxDF_frag.ts index 33e98c2e..d2d39a73 100644 --- a/src/assets/shader/lighting/BxDF_frag.ts +++ b/src/assets/shader/lighting/BxDF_frag.ts @@ -17,22 +17,25 @@ export let BxDF_frag: string = /*wgsl*/ ` //ORI_ShadingInput fn initFragData() { - fragData.Albedo = ORI_ShadingInput.BaseColor * ORI_ShadingInput.BaseColor.a ; - fragData.Ao = ORI_ShadingInput.AmbientOcclusion ; - fragData.Roughness = clamp(ORI_ShadingInput.Roughness,0.003,1.0) ; + fragData.Albedo = ORI_ShadingInput.BaseColor ; + fragData.Ao = clamp( pow(ORI_ShadingInput.AmbientOcclusion,materialUniform.ao) , 0.0 , 1.0 ) ; + fragData.Roughness = clamp((ORI_ShadingInput.Roughness),0.003,1.0) ; fragData.Metallic = ORI_ShadingInput.Metallic ; fragData.Emissive = ORI_ShadingInput.EmissiveColor.rgb ; fragData.N = ORI_ShadingInput.Normal; let viewDir = normalize(globalUniform.CameraPos.xyz - ORI_VertexVarying.vWorldPos.xyz) ; fragData.V = viewDir ; - // fragData.V = normalize(globalUniform.cameraWorldMatrix[3].xyz - ORI_VertexVarying.vWorldPos.xyz) ; + #if USE_TANGENT + fragData.T = ORI_VertexVarying.TANGENT.xyz * ORI_VertexVarying.TANGENT.w ; + #endif + let R = 2.0 * dot( fragData.V , fragData.N ) * fragData.N - fragData.V ; fragData.R = R ;//reflect( fragData.V , fragData.N ) ; fragData.NoV = saturate(dot(fragData.N, fragData.V)) ; - fragData.F0 = mix(vec3(materialUniform.materialF0.rgb), fragData.Albedo.rgb, fragData.Metallic); + fragData.F0 = mix(vec3(materialUniform.specularColor.rgb), fragData.Albedo.rgb, fragData.Metallic); fragData.F = computeFresnelSchlick(fragData.NoV, fragData.F0); fragData.KD = vec3(fragData.F) ; @@ -60,9 +63,6 @@ export let BxDF_frag: string = /*wgsl*/ ` irradiance = LinearToGammaSpace(irradiance.rgb); fragData.Irradiance = irradiance.rgb ; - #if USE_TANGENT - fragData.TangentChannel = vec3(ORI_VertexVarying.TANGENT.w);// ORI_VertexVarying.TANGENT.xyz * ORI_VertexVarying.TANGENT.w ; - #endif //***********lighting-PBR part********* var specColor = vec3(0.0) ; @@ -72,66 +72,65 @@ export let BxDF_frag: string = /*wgsl*/ ` let end = max(start + count , 0.0); for(var i:i32 = i32(start) ; i < i32(end); i += 1 ) { - let light = getLight(i32(i)); - - switch (light.lightType) { - case PointLightType: { - specColor += pointLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic,light) ; + let light = getLight(i32(i)); + switch (light.lightType) { + case PointLightType: { + specColor += pointLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic,light) ; + } + case DirectLightType: { + specColor += directLighting( fragData.Albedo.rgb ,fragData.N,fragData.V,fragData.Roughness ,fragData.Metallic, light , globalUniform.shadowBias) ; + } + case SpotLightType: { + specColor += spotLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic , light ) ; + } + default: { + } } - case DirectLightType: { - specColor += directLighting( fragData.Albedo.rgb ,fragData.N,fragData.V,fragData.Roughness ,fragData.Metallic, light , globalUniform.shadowBias) ; - } - case SpotLightType: { - specColor += spotLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic , light ) ; - } - default: { - } - } } - fragData.LightChannel = specColor ; + fragData.LightChannel = specColor ; + let sunLight = lightBuffer[0] ; //***********lighting-PBR part********* var F = FresnelSchlickRoughness(fragData.NoV, fragData.F0, fragData.Roughness); var kS = F; var kD = vec3(1.0) - kS; kD = kD * (1.0 - fragData.Metallic); - let env = materialUniform.envIntensity * approximateSpecularIBL( F , fragData.Roughness , fragData.R , fragData.NoV ) ; - fragData.EnvColor = env ; + let envIBL = materialUniform.envIntensity * approximateSpecularIBL( F , fragData.Roughness , fragData.R , fragData.NoV ) ; + fragData.EnvColor = envIBL ; //***********indirect-specular part********* - var surfaceReduction = 1.0/(fragData.Roughness*fragData.Roughness+1.0); //Reduce the reflection coefficient of non-metallic materials - var oneMinusReflectivity = oneMinusReflectivity(fragData.Metallic , materialUniform.materialF0.r );// materialUniform.materialF0.a - materialUniform.materialF0.a * fragData.Metallic ; + var surfaceReduction = 1.0/(fragData.Roughness*fragData.Roughness+1.0); + var oneMinusReflectivity = oneMinusReflectivity(fragData.Metallic , materialUniform.materialF0.r ); var grazingTerm = clamp((1.0 - fragData.Roughness ) + (1.0 - oneMinusReflectivity),0.0,1.0); var t = pow5(fragData.NoV); - var fresnelLerp = FresnelLerp(fragData.NoV,fragData.F0.rgb,vec3(grazingTerm)) ; //Controlling Fresnel and metallic reflections - var iblSpecularResult = surfaceReduction*env*fresnelLerp ; + var fresnelLerp = FresnelLerp(fragData.NoV,fragData.F0.rgb,vec3(grazingTerm)) ; + var iblSpecularResult = surfaceReduction * fragData.EnvColor * fresnelLerp + envIBL; + iblSpecularResult *= max(sunLight.quadratic,0.05) ; //***********indirect-specular part********* //***********indirect-ambient part********* - var kdLast = (1.0 - fragData.F0.r) * (1.0 - fragData.Metallic); //Dim the edges, there should be more specular reflection at the edges - var iblDiffuseResult = irradiance * kdLast * fragData.Albedo.rgb ; + var kdLast = (1.0 - 0.04) * (1.0 - fragData.Metallic); + // Dim the edges, there should be more specular reflection at the edges + var iblDiffuseResult = irradiance * vec3f(kdLast) * fragData.Albedo.rgb ; + //irradiance //***********indirect-ambient part********* - let sunLight = lightBuffer[0] ; - var indirectResult = (iblSpecularResult + iblDiffuseResult) * fragData.Ao * max(sunLight.quadratic,0.05) ; - // let test = indirectResult ; + var indirectResult = (iblSpecularResult + iblDiffuseResult) * fragData.Ao * max(sunLight.quadratic,0.05); + // debugOut = vec4f(iblDiffuseResult,1.0); ORI_FragmentOutput.color = vec4(0.0); // Using stripped down, 'pure log', formula. Parameterized by grey points and dynamic range covered. #if USEGBUFFER var normal_rgba8unorm = (ORI_VertexVarying.vWorldNormal + 1.0) * 0.5; - normal_rgba8unorm = clamp(normal_rgba8unorm, vec3(0.0), vec3(1.0)); + ORI_FragmentOutput.worldNormal = vec4(normal_rgba8unorm,1.0); + ORI_FragmentOutput.material = vec4(1.0,fragData.Roughness,fragData.Metallic,1.0); #endif // ORI_FragmentOutput.color = vec4(ORI_FragmentOutput.color.xyz,fragData.Albedo.a) ; #if USE_WORLDPOS ORI_FragmentOutput.worldPos = vec4(ORI_VertexVarying.vWorldPos.xyzw); - #endif - - #if USEGBUFFER - ORI_FragmentOutput.worldNormal = vec4(normal_rgba8unorm,1.0); - ORI_FragmentOutput.material = vec4(1.0,fragData.Roughness,fragData.Metallic,1.0); + // ORI_FragmentOutput.worldPos = vec4(0.0,0.0,1.0,1.0); #endif var color = specColor + indirectResult ; @@ -147,10 +146,10 @@ export let BxDF_frag: string = /*wgsl*/ ` color = vec3(clearCoatLayer.rgb/fragData.Albedo.a) ; #endif - ORI_FragmentOutput.color = vec4(LinearToGammaSpace(color.rgb),fragData.Albedo.a) ; - - // var iblSpecularResult = surfaceReduction*env*fresnelLerp ; - // ORI_FragmentOutput.color = vec4(vec3(test),fragData.Albedo.a) ; + var retColor = (LinearToGammaSpace(color.rgb)); + // retColor += fragData.Emissive.xyz ; + // ORI_FragmentOutput.color = vec4( irradiance * min(fragData.Albedo.rgb,vec3f(1.0)) ,fragData.Albedo.a) ; + ORI_FragmentOutput.color = vec4( retColor.rgb * fragData.Albedo.a ,fragData.Albedo.a) ; } ` diff --git a/src/assets/shader/lighting/Hair_frag.ts b/src/assets/shader/lighting/Hair_frag.ts new file mode 100644 index 00000000..42b116d5 --- /dev/null +++ b/src/assets/shader/lighting/Hair_frag.ts @@ -0,0 +1,326 @@ +export let Hair_frag: string = /*wgsl*/ ` + #include "BRDF_frag" + #include "MathShader" + #include "FastMathShader" + #include "Common_frag" + #include "GlobalUniform" + + #include "PhysicMaterialUniform_frag" + #include "NormalMap_frag" + #include "LightingFunction_frag" + #include "Irradiance_frag" + #include "ColorUtil_frag" + #include "BxdfDebug_frag" + + struct FHairTransmittanceData{ + bUseBacklit:bool, + bUseSeparableR:bool, + bUseLegacyAbsorption:bool + }; + + //ORI_ShadingInput + fn initFragData() { + fragData.Albedo = ORI_ShadingInput.BaseColor ; + fragData.Ao = clamp( pow(ORI_ShadingInput.AmbientOcclusion,materialUniform.ao) , 0.0 , 1.0 ) ; + fragData.Roughness = ORI_ShadingInput.Roughness ; + fragData.Metallic = ORI_ShadingInput.Metallic ; + fragData.Emissive = ORI_ShadingInput.EmissiveColor.rgb ; + fragData.Specular = vec3f(materialUniform.specularColor.rgb) ; + fragData.N = ORI_ShadingInput.Normal; + let viewDir = normalize(globalUniform.CameraPos.xyz - ORI_VertexVarying.vWorldPos.xyz ) ; + fragData.V = viewDir ; + fragData.Ao = materialUniform.ao ; + #if USE_TANGENT + fragData.T = ORI_VertexVarying.TANGENT.xyz * ORI_VertexVarying.TANGENT.w ; + #endif + + let R = 2.0 * dot( fragData.V , fragData.N ) * fragData.N - fragData.V ; + fragData.R = R ;//reflect( fragData.V , fragData.N ) ; + + fragData.NoV = saturate(dot(fragData.N, fragData.V)) ; + + fragData.F0 = mix(vec3(materialUniform.specularColor.rgb), fragData.Albedo.rgb, fragData.Metallic); + + fragData.F = computeFresnelSchlick(fragData.NoV, fragData.F0); + fragData.KD = vec3(fragData.F) ; + fragData.KS = vec3(0.0) ; + + fragData.Indirect = 0.0 ; + fragData.Reflectance = 1.0 ; + } + + + + fn transformHairNormal(normal : vec3) -> vec3{ + var face = 1.0 ; + if(ORI_VertexVarying.face){ + face = 1.0 ; + }else{ + face = -1.0 ; + } + #if USE_TANGENT + let T = ORI_VertexVarying.TANGENT.xyz; + let N = ORI_VertexVarying.vWorldNormal ; + let B = cross(T,N) * ORI_VertexVarying.TANGENT.w * face; + let mat3 = mat3x3(T,B,N); + let n = mat3 * normal; + return n ; + #else + return normal ; + #endif + } + + + fn Hair_g( B:f32 , Theta:f32 ) -> f32 + { + return exp(-0.5 * pow2(Theta) / (B * B)) / (sqrt(2 * PI) * B); + } + + fn Hair_F( CosTheta:f32 )-> f32 + { + let n = 1.55; + let F0 = pow2((1.0 - n) / (1.0 + n)); + return F0 + (1.0 - F0) * pow5(1.0 - CosTheta); + } + + fn HairColorToAbsorption( C:vec3f , B:f32 ) -> vec3f + { + let b2 = B * B; + let b3 = B * b2; + let b4 = b2 * b2; + let b5 = B * b4; + let D = (5.969 - 0.215 * B + 2.532 * b2 - 10.73 * b3 + 5.574 * b4 + 0.245 * b5); + return pow2v3(log(C) / D); + } + + fn Luminance( LinearColor : vec3f ) -> f32 + { + return dot( LinearColor, vec3f( 0.3, 0.59, 0.11 ) ); + } + + fn KajiyaKayDiffuseAttenuation( L:vec3f, V:vec3f, N:vec3f, Shadow:f32 ) -> vec3f + { + // Use soft Kajiya Kay diffuse attenuation + var KajiyaDiffuse = 1.0 - abs(dot(N, L)); + + var FakeNormal = normalize(V - N * dot(V, N)); + //N = normalize( DiffuseN + FakeNormal * 2 ); + let nN = FakeNormal; + + let BaseColor = fragData.Albedo.rgb / PI ; + // Hack approximation for multiple scattering. + var Wrap = 1.0; + var NoL = saturate((dot(nN, L) + Wrap) / squareF(1.0 + Wrap)); + var DiffuseScatter = (1.0 / PI) * mix(NoL, KajiyaDiffuse, 0.33) * fragData.Metallic; + var Luma = Luminance(BaseColor); + var ScatterTint = pow(BaseColor / Luma, vec3f(1.0 - Shadow)); + return sqrt(BaseColor) * DiffuseScatter * ScatterTint; + } + + fn HairNormal( ID : f32 ) -> vec4f { + let tangentA = vec4f(0.0,0.0,0.3,1.0); + let tangentB = vec4f(0.0,0.0,-0.3,1.0); + + let iTangent = mix(tangentA,tangentB,vec4f(ID)); + var tangent = vec4f(0.0); + #if USE_FLOWER + + #else + let tt = vec4f(0.0,-1.0,0.0,1.0); + tangent = tt + iTangent; + #endif + + return normalize(tangent) ; + } + + fn hairShading( light:LightData , sV:vec3f, N:vec3f, Shadow:f32 , HairTransmittance : FHairTransmittanceData , InBacklit:f32 , Area:f32 , Random:vec2f ) -> vec3f{ + var ClampedRoughness = clamp(fragData.Roughness, 1/255.0, 1.0); + let Backlit = min(InBacklit, materialUniform.backlit); + let HairColor = fragData.Albedo.rgb ; + let lightCC = pow( light.lightColor.rgb,vec3(2.2)); + var lightColor = getHDRColor( lightCC.rgb , light.linear ) ; + var lightAtt = light.intensity ; + + let V = normalize(sV) ; + let L = normalize(-light.direction) ; + let H = normalize(N+L) ; + var S : vec3f= vec3f(0.0) ; + + var KajiyaKayDiffuseFactor = 1.0; + + let VoL = dot(V,L); + let SinThetaL = clamp(dot(N,L), -1.0, 1.0); + let SinThetaV = clamp(dot(N,V), -1.0, 1.0); + + var CosThetaD = cos( 0.5 * abs( asinFast( SinThetaV ) - asinFast( SinThetaL ) ) ); + // var CosThetaD = cos( 0.5 * abs( asin( SinThetaV ) - asin( SinThetaL ) ) ); + + var Lp = L - SinThetaL * N; + var Vp = V - SinThetaV * N; + var CosPhi = dot(Lp,Vp) * rsqrt( dot(Lp,Lp) * dot(Vp,Vp) + 1e-4 ); + var CosHalfPhi = sqrt( saturate( 0.5 + 0.5 * CosPhi ) ); + + let n = 1.55; + let n_prime = 1.19 / CosThetaD + 0.36 * CosThetaD; + + let Shift = 0.035; + var Alpha:array = array( + -Shift * 2.0, + Shift, + Shift * 4.0, + ); + + var B:array =array( + Area + pow2(ClampedRoughness), + (Area + pow2(ClampedRoughness) / 2.0), + Area + pow2(ClampedRoughness) * 2.0, + ); + + //S SR + let sa = sin(Alpha[0]); + let ca = cos(Alpha[0]); + var ShiftA = 2.0 * sa * (ca * CosHalfPhi * sqrt(1.0 - SinThetaV * SinThetaV) + sa * SinThetaV); + var BScale = 1.0; + if(HairTransmittance.bUseSeparableR){ + BScale = sqrt(2.0) * CosHalfPhi ; + } + var Mp_R = Hair_g(B[0] * BScale, SinThetaL + SinThetaV - ShiftA); + var Np_R = 0.25 * CosHalfPhi; + var Fp_R = Hair_F(sqrt(saturate(0.5 + 0.5 * (VoL)))); + S += vec3f(Mp_R* Np_R * Fp_R * (fragData.F0 * 2.0)) * mix(1.0, 0.0, saturate(-VoL)); + KajiyaKayDiffuseFactor -= Fp_R; + + //S ST + var Mp_ST = Hair_g( B[1], SinThetaL + SinThetaV - Alpha[1] ); + var a_ST = 1.0 / n_prime; + var h_ST = CosHalfPhi * ( 1.0 + a_ST * ( 0.6 - 0.8 * CosPhi ) ); + var f_ST = Hair_F( CosThetaD * sqrt( saturate( 1.0 - h_ST * h_ST ) ) ); + var Fp_ST = pow2(1.0 - f_ST); + var Tp_ST : vec3f = vec3f( 0.0 ); + if (HairTransmittance.bUseLegacyAbsorption) + { + Tp_ST = pow(HairColor.rgb, vec3f(0.5 * sqrt(1.0 - pow2(h_ST * a_ST)) / CosThetaD)); + } + else + { + let AbsorptionColor = HairColorToAbsorption(HairColor.rgb,0.3); + Tp_ST = exp(-AbsorptionColor * 2.0 * abs(1.0 - pow2(h_ST * a_ST) / CosThetaD)); + } + + var Np_ST = exp( -3.65 * CosPhi - 3.98 ); + + S += Mp_ST * Np_ST * Fp_ST * Tp_ST * Backlit; + KajiyaKayDiffuseFactor -= Fp_ST; + + //S TRT + var Mp_TRT = Hair_g( B[2], SinThetaL + SinThetaV - Alpha[2] ); + + //float h = 0.75; + var f_TRT = Hair_F( CosThetaD * 0.5 ); + var Fp_TRT = pow2(1.0 - f_TRT) * f_TRT; + var Tp_TRT = pow( HairColor.rgb , vec3f(0.8 / CosThetaD) ); + var Np_TRT = exp( 17.0 * CosPhi - 16.78 ); + + S += Mp_TRT * Np_TRT * Fp_TRT * Tp_TRT; + KajiyaKayDiffuseFactor -= Fp_TRT; + // S = vec3f((KajiyaKayDiffuseFactor)); + + S += KajiyaKayDiffuseAttenuation(L,V,N,Shadow) ;//* saturate(KajiyaKayDiffuseFactor); + // S = vec3f((KajiyaKayDiffuseFactor)); + S = -min(-S, vec3f(0.0)); + return 2.0 * PI *vec3f(S) * (lightAtt / LUMEN) ; + } + + fn BSSSRDFShading(){ + initFragData(); + + var irradiance = vec3(0.0) ; + #if USEGI + irradiance += getIrradiance().rgb ; + #else + let MAX_REFLECTION_LOD = f32(textureNumLevels(prefilterMap)) ; + irradiance += (globalUniform.skyExposure * textureSampleLevel(prefilterMap, prefilterMapSampler, fragData.N.xyz, 0.8 * (MAX_REFLECTION_LOD) ).rgb); + #endif + irradiance = ORI_ShadingInput.SSS + (irradiance.rgb); + fragData.Irradiance = irradiance.rgb ; + + //***********lighting-PBR part********* + var specColor = vec3(0.0) ; + let lightIndex = getCluster(); + let start = max(lightIndex.start, 0.0); + let count = max(lightIndex.count, 0.0); + let end = max(start + count , 0.0); + for(var i:i32 = i32(start) ; i < i32(end); i += 1 ) + { + let light = getLight(i32(i)); + switch (light.lightType) { + case PointLightType: { + // specColor += pointLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic,light) ; + } + case DirectLightType: { + // specColor += directHairLighting( fragData.Albedo.rgb ,fragData.N,fragData.V,fragData.Roughness ,fragData.Metallic, light , globalUniform.shadowBias) ; + var fHairTransmittanceData : FHairTransmittanceData ; + fHairTransmittanceData.bUseBacklit = true ; + fHairTransmittanceData.bUseSeparableR = true ; + fHairTransmittanceData.bUseLegacyAbsorption = false ; + + //use shadow visible backlit + // var shadow = 0.0 ; + // if(light.castShadow>=0){ + // #if USE_SHADOWMAPING + // shadow = shadowStrut.directShadowVisibility[i32(light.castShadow)] ; + // #endif + // } + + specColor = hairShading(light,fragData.V, ORI_ShadingInput.HairNormal , 1.0 ,fHairTransmittanceData,1.0,materialUniform.area,vec2f(0.0)); + } + case SpotLightType: { + // specColor += spotLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic , light ) ; + } + default: { + } + } + } + + + let sunLight = lightBuffer[0] ; + //***********lighting-PBR part********* + var F = FresnelSchlickRoughness(fragData.NoV, fragData.F0.rgb , fragData.Roughness); + var kS = F; + // var kD = vec3(1.0) - kS; + // kD = kD * (1.0 - fragData.Metallic); + let envIBL = materialUniform.envIntensity * IBLEnv(fragData.V ,fragData.N ,fragData.Roughness ) ; + fragData.EnvColor = envIBL ; + // fragData.Specular = envIBL ; + //***********indirect-specular part********* + + var iblSpecularResult = fragData.Metallic * fragData.EnvColor * materialUniform.specularColor.rgb ; + //***********indirect-specular part********* + + //***********indirect-ambient part********* + var kdLast = (1.0 - fragData.F0.r) * (1.0 - fragData.Metallic); + var iblDiffuseResult = irradiance * kdLast * fragData.Albedo.rgb * (vec3(1.0) - kS) ; + //irradiance + //***********indirect-ambient part********* + var indirectResult = (iblSpecularResult + iblDiffuseResult * max(sunLight.quadratic,0.05) ) * fragData.Ao ; + fragData.LightChannel = specColor ; + + // Using stripped down, 'pure log', formula. Parameterized by grey points and dynamic range covered. + #if USEGBUFFER + var normal_rgba8unorm = (ORI_VertexVarying.vWorldNormal + 1.0) * 0.5; + normal_rgba8unorm = clamp(normal_rgba8unorm, vec3(0.0), vec3(1.0)); + ORI_FragmentOutput.worldNormal = vec4(normal_rgba8unorm,1.0); + ORI_FragmentOutput.material = vec4(1.0,fragData.Roughness,fragData.Metallic,1.0); + #endif + + #if USE_WORLDPOS + ORI_FragmentOutput.worldPos = vec4(ORI_VertexVarying.vWorldPos.xyzw); + #endif + + let finalColor = LinearToGammaSpace(vec3f(specColor + indirectResult) ) ; + ORI_FragmentOutput.color = vec4( finalColor ,fragData.Albedo.a) ; + // ORI_FragmentOutput.color = vec4( vec3f(specColor) ,fragData.Albedo.a) ; +} + + ` + diff --git a/src/assets/shader/lighting/Irradiance_frag.ts b/src/assets/shader/lighting/Irradiance_frag.ts index 8ce3a883..477348d0 100644 --- a/src/assets/shader/lighting/Irradiance_frag.ts +++ b/src/assets/shader/lighting/Irradiance_frag.ts @@ -1,10 +1,5 @@ export let Irradiance_frag: string = /*wgsl*/ ` #include "IrradianceVolumeData_frag" - fn pow3( x : f32 ) -> f32 - { - return x*x*x; - } - struct IrradianceField { probeStartPosition: vec4, probeCounts:vec4, @@ -23,7 +18,7 @@ export let Irradiance_frag: string = /*wgsl*/ ` @group(1) @binding(auto) var irradianceDepthMap: texture_2d; @group(2) @binding(7) - var irradianceData : IrradianceVolumeData ; + var irradianceData : IrradianceVolumeData ; var irradianceFieldSurface: IrradianceField; var energyPreservation: f32 = 0.85; diff --git a/src/assets/shader/lighting/LightingFunction_frag.ts b/src/assets/shader/lighting/LightingFunction_frag.ts index 0682ed26..e1eb44dd 100644 --- a/src/assets/shader/lighting/LightingFunction_frag.ts +++ b/src/assets/shader/lighting/LightingFunction_frag.ts @@ -39,7 +39,7 @@ fn directLighting( albedo:vec3, N:vec3, V:vec3, roughness:f32 , #if USE_LAMBERT color = vec3(1.0,1.0,1.0) ; #endif - + #if USE_BRDF color = simpleBRDF(albedo,N,V,L,att,lightColor,roughness,metallic) ; #endif @@ -47,6 +47,63 @@ fn directLighting( albedo:vec3, N:vec3, V:vec3, roughness:f32 , return color; } +fn directDulLighting( albedo:vec3, N:vec3, V:vec3, roughness:f32 , metallic:f32 , light:LightData , shadowBias:f32 ) -> vec3 { + var color = vec3(0.0) ; + #if USE_LIGHT + var L = -normalize(light.direction.xyz) ; + let lightCC = pow( light.lightColor.rgb,vec3(2.2)); + var lightColor = getHDRColor( lightCC.rgb , light.linear ) ; + var att = light.intensity / LUMEN ; + if(light.castShadow>=0){ + #if USE_SHADOWMAPING + for (var j: i32 = 0; j < 8; j += 1) { + if(j == light.castShadow){ + att *= shadowStrut.directShadowVisibility[j] ; + } + } + #endif + } + #if USE_LAMBERT + color = vec3(1.0,1.0,1.0) ; + #endif + + #if USE_BRDF + color = 0.85 * simpleBRDF(albedo,N,V,L,att,lightColor,0.85 * roughness,metallic) ; + color += 0.15 * simpleBRDF(albedo,N,V,L,att,lightColor,0.15 * roughness,metallic) ; + #endif + #endif + return color; +} + +fn directHairLighting( albedo:vec3, N:vec3, V:vec3, roughness:f32 , metallic:f32 , light:LightData , shadowBias:f32 ) -> vec3 { + var color = vec3(0.0) ; + #if USE_LIGHT + var L = -normalize(light.direction.xyz) ; + let lightCC = pow( light.lightColor.rgb,vec3(2.2)); + var lightColor = getHDRColor( lightCC.rgb , light.linear ) ; + var att = light.intensity / LUMEN ; + if(light.castShadow>=0){ + #if USE_SHADOWMAPING + for (var j: i32 = 0; j < 8; j += 1) { + if(j == light.castShadow){ + att *= shadowStrut.directShadowVisibility[j] ; + } + } + #endif + } + #if USE_LAMBERT + color = vec3(1.0,1.0,1.0) ; + #endif + + #if USE_BRDF + color = 0.5 * simpleBRDF(albedo,N,V,L,att,lightColor,0.85 ,metallic) ; + color += 0.5 * simpleBRDF(albedo,N,V,L,att,lightColor,0.15 ,metallic) ; + #endif + #endif + return color; +} + + fn pointLighting( albedo:vec3,WP:vec3, N:vec3, V:vec3, roughness:f32 , metallic:f32 ,light:LightData ) -> vec3 { var color = vec3(0.0) ; let lightPos = light.position.xyz; diff --git a/src/assets/shader/materials/ColorLitShader.ts b/src/assets/shader/materials/ColorLitShader.ts index a2ea1ed2..b5aa1638 100644 --- a/src/assets/shader/materials/ColorLitShader.ts +++ b/src/assets/shader/materials/ColorLitShader.ts @@ -1,5 +1,4 @@ -export class ColorLitShader { - public static Ori_AllShader: string = /*wgsl*/` +export let ColorLitShader: string = /*wgsl*/` #include "Common_vert" #include "Common_frag" #include "BxDF_frag" @@ -14,7 +13,7 @@ export class ColorLitShader { ORI_ShadingInput.Roughness = materialUniform.roughness ; ORI_ShadingInput.Metallic = materialUniform.metallic ; ORI_ShadingInput.Specular = 0.5 ; - ORI_ShadingInput.AmbientOcclusion = materialUniform.ao ; + ORI_ShadingInput.AmbientOcclusion = 1.0 ; ORI_ShadingInput.EmissiveColor = vec4(0.0); ORI_ShadingInput.Normal = ORI_VertexVarying.vWorldNormal.rgb ; @@ -25,5 +24,4 @@ export class ColorLitShader { BxDFShading(); } - ` -} + ` \ No newline at end of file diff --git a/src/assets/shader/materials/Hair_shader.ts b/src/assets/shader/materials/Hair_shader.ts new file mode 100644 index 00000000..3e5f59d4 --- /dev/null +++ b/src/assets/shader/materials/Hair_shader.ts @@ -0,0 +1,247 @@ +export let Hair_shader_op: string = /*wgsl*/ ` + #include "Common_vert" + #include "Common_frag" + #include "Hair_frag" + + @group(1) @binding(auto) + var baseMapSampler: sampler; + @group(1) @binding(auto) + var baseMap: texture_2d; + + @group(1) @binding(auto) + var idMapSampler: sampler; + @group(1) @binding(auto) + var idMap: texture_2d; + + @group(1) @binding(auto) + var depthMapSampler: sampler; + @group(1) @binding(auto) + var depthMap: texture_2d; + + @group(1) @binding(auto) + var rootMapSampler: sampler; + @group(1) @binding(auto) + var rootMap: texture_2d; + + @group(1) @binding(auto) + var alphaMapSampler: sampler; + @group(1) @binding(auto) + var alphaMap: texture_2d; + + #if USE_CUSTOMUNIFORM + struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, + + baseColor0: vec4, + baseColor1: vec4, + emissiveColor: vec4, + materialF0: vec4, + specularColor: vec4, + envIntensity: f32, + normalScale: f32, + roughness: f32, + metallic: f32, + + ao: f32, + roughness_min: f32, + roughness_max: f32, + metallic_min: f32, + + metallic_max: f32, + emissiveIntensity: f32, + alphaCutoff: f32, + ior: f32, + + backlit: f32, + area: f32, + }; +#endif + + var debugOut : vec4f = vec4f(0.0) ; + var uv : vec2f = vec2f(0.0) ; + + fn vert(inputData:VertexAttributes) -> VertexOutput { + ORI_Vert(inputData) ; + return ORI_VertexOut ; + } + + fn frag(){ + var transformUV1 = materialUniform.transformUV1; + var transformUV2 = materialUniform.transformUV2; + uv = transformUV1.zw * ORI_VertexVarying.fragUV0 + transformUV1.xy; + + ORI_ShadingInput.Roughness = materialUniform.roughness; + ORI_ShadingInput.Metallic = materialUniform.metallic; + + + #if USE_HAIRCOLOR + let root = textureSample(rootMap, rootMapSampler, uv ).r ; + ORI_ShadingInput.BaseColor = mix(materialUniform.baseColor0,materialUniform.baseColor1,root) ; + #else + #if USE_SRGB_ALBEDO + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + #else + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + #endif + #endif + + fragData.Alpha = 1.0 ; + #if USE_ALPHA_A + // fragData.Alpha = textureSampleLevel(alphaMap, alphaMapSampler, uv , 0.0 ).r ; + // let shake = (globalUniform.frame % 5.0) / 5.0 * 2.0 ; + fragData.Alpha = textureSample(alphaMap, alphaMapSampler, uv ).r ; + #endif + + #if USE_ALPHACUT + if( (fragData.Alpha - materialUniform.alphaCutoff) < 0.0 ){ + #if USEGBUFFER + ORI_FragmentOutput.worldPos = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.worldNormal = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.material = vec4(0.0,0.0,0.0,1.0); + #endif + discard; + } + #endif + + #if USE_SHADOWMAPING + useShadow(); + #endif + + ORI_ShadingInput.Specular = 1.0 ; + + let idMap = textureSampleLevel(idMap, idMapSampler, uv , 0.0 ); + var hairNormal = HairNormal(idMap.r).rgb ; + hairNormal = transformHairNormal( hairNormal) ; + ORI_ShadingInput.HairNormal = hairNormal ; + + ORI_ShadingInput.Normal = unPackRGNormal(vec3f(0.5,0.5,1.0),1.0,1.0) ; + + ORI_ShadingInput.BaseColor.a = fragData.Alpha; + + BSSSRDFShading(); + } +` + +export let Hair_shader_tr: string = /*wgsl*/ ` +#include "Common_vert" +#include "Common_frag" +#include "Hair_frag" + +@group(1) @binding(auto) +var baseMapSampler: sampler; +@group(1) @binding(auto) +var baseMap: texture_2d; + +@group(1) @binding(auto) +var idMapSampler: sampler; +@group(1) @binding(auto) +var idMap: texture_2d; + +@group(1) @binding(auto) +var depthMapSampler: sampler; +@group(1) @binding(auto) +var depthMap: texture_2d; + +@group(1) @binding(auto) +var rootMapSampler: sampler; +@group(1) @binding(auto) +var rootMap: texture_2d; + +@group(1) @binding(auto) +var alphaMapSampler: sampler; +@group(1) @binding(auto) +var alphaMap: texture_2d; + +#if USE_CUSTOMUNIFORM +struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, + + baseColor0: vec4, + baseColor1: vec4, + emissiveColor: vec4, + materialF0: vec4, + specularColor: vec4, + envIntensity: f32, + normalScale: f32, + roughness: f32, + metallic: f32, + + ao: f32, + roughness_min: f32, + roughness_max: f32, + metallic_min: f32, + + metallic_max: f32, + emissiveIntensity: f32, + alphaCutoff: f32, + ior: f32, + + backlit: f32, + area: f32, +}; +#endif + +var debugOut : vec4f = vec4f(0.0) ; +var uv : vec2f = vec2f(0.0) ; + +fn vert(inputData:VertexAttributes) -> VertexOutput { + ORI_Vert(inputData) ; + return ORI_VertexOut ; +} + +fn frag(){ + var transformUV1 = materialUniform.transformUV1; + var transformUV2 = materialUniform.transformUV2; + uv = transformUV1.zw * ORI_VertexVarying.fragUV0 + transformUV1.xy; + + ORI_ShadingInput.Roughness = materialUniform.roughness; + ORI_ShadingInput.Metallic = materialUniform.metallic; + + #if USE_HAIRCOLOR + let root = textureSample(rootMap, rootMapSampler, uv ).r ; + ORI_ShadingInput.BaseColor = mix(materialUniform.baseColor0,materialUniform.baseColor1,root) ; + #else + #if USE_SRGB_ALBEDO + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + #else + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + #endif + #endif + + fragData.Alpha = 1.0 ; + #if USE_ALPHA_A + fragData.Alpha = textureSampleLevel(alphaMap, alphaMapSampler, uv , 0.0 ).r ; + #endif + + #if USE_ALPHACUT + if( (((1.0 - fragData.Alpha) - (1.0 - materialUniform.alphaCutoff))) < 0.0 ){ + #if USEGBUFFER + ORI_FragmentOutput.worldPos = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.worldNormal = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.material = vec4(0.0,0.0,0.0,1.0); + #endif + discard; + } + #endif + + #if USE_SHADOWMAPING + useShadow(); + #endif + + ORI_ShadingInput.Specular = 1.0 ; + + let idMap = textureSampleLevel(idMap, idMapSampler, uv , 0.0 ); + var hairNormal = HairNormal(idMap.r).rgb ; + hairNormal = transformHairNormal( hairNormal) ; + ORI_ShadingInput.HairNormal = hairNormal ; + + ORI_ShadingInput.Normal = unPackRGNormal(vec3f(0.5,0.5,1.0),1.0,1.0) ; + + ORI_ShadingInput.BaseColor.a = fragData.Alpha; + + BSSSRDFShading(); +} +` + diff --git a/src/assets/shader/materials/LambertShader.ts b/src/assets/shader/materials/Lambert_shader.ts similarity index 97% rename from src/assets/shader/materials/LambertShader.ts rename to src/assets/shader/materials/Lambert_shader.ts index a78a4ce6..83795ea0 100644 --- a/src/assets/shader/materials/LambertShader.ts +++ b/src/assets/shader/materials/Lambert_shader.ts @@ -1,4 +1,4 @@ -export let LambertShader: string = /*wgsl*/ ` +export let Lambert_shader: string = /*wgsl*/ ` #include "Common_vert" #include "Common_frag" #include "ClusterLight" diff --git a/src/assets/shader/materials/LitShader.ts b/src/assets/shader/materials/Lit_shader.ts similarity index 85% rename from src/assets/shader/materials/LitShader.ts rename to src/assets/shader/materials/Lit_shader.ts index 4dae19b4..ceca8bbd 100644 --- a/src/assets/shader/materials/LitShader.ts +++ b/src/assets/shader/materials/Lit_shader.ts @@ -1,4 +1,4 @@ -export let LitShader: string = /*wgsl*/ ` +export let Lit_shader: string = /*wgsl*/ ` #include "Common_vert" #include "Common_frag" #include "BxDF_frag" @@ -13,7 +13,7 @@ export let LitShader: string = /*wgsl*/ ` ORI_ShadingInput.Roughness = materialUniform.roughness ; ORI_ShadingInput.Metallic = materialUniform.metallic ; ORI_ShadingInput.Specular = 0.5 ; - ORI_ShadingInput.AmbientOcclusion = materialUniform.ao ; + ORI_ShadingInput.AmbientOcclusion = 1.0 ; ORI_ShadingInput.EmissiveColor = vec4(0.0); ORI_ShadingInput.Normal = ORI_VertexVarying.vWorldNormal.rgb ; diff --git a/src/assets/shader/materials/PBRLItShader.ts b/src/assets/shader/materials/PBRLItShader.ts index ba3ac3c2..df611066 100644 --- a/src/assets/shader/materials/PBRLItShader.ts +++ b/src/assets/shader/materials/PBRLItShader.ts @@ -13,25 +13,25 @@ export let PBRLItShader: string = /*wgsl*/ ` @group(1) @binding(auto) var normalMap: texture_2d; - #if USE_ARMC + // #if USE_ARMC + // @group(1) @binding(auto) + // var maskMapSampler: sampler; + // @group(1) @binding(auto) + // var maskMap: texture_2d; + // #endif + + // #if USE_MR @group(1) @binding(auto) var maskMapSampler: sampler; @group(1) @binding(auto) var maskMap: texture_2d; - #endif - - #if USE_MR - @group(1) @binding(auto) - var maskMapSampler: sampler; - @group(1) @binding(auto) - var maskMap: texture_2d; - #endif + // #endif #if USE_AOTEX @group(1) @binding(auto) var aoMapSampler: sampler; @group(1) @binding(auto) - var aomapMap: texture_2d; + var aoMap: texture_2d; #endif @group(1) @binding(auto) @@ -39,6 +39,8 @@ export let PBRLItShader: string = /*wgsl*/ ` @group(1) @binding(auto) var emissiveMap: texture_2d; + var debugOut : vec4f = vec4f(0.0) ; + fn vert(inputData:VertexAttributes) -> VertexOutput { ORI_Vert(inputData) ; return ORI_VertexOut ; @@ -50,14 +52,31 @@ export let PBRLItShader: string = /*wgsl*/ ` var uv = transformUV1.zw * ORI_VertexVarying.fragUV0 + transformUV1.xy; - ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; - ORI_ShadingInput.BaseColor = vec4(gammaToLiner(ORI_ShadingInput.BaseColor.rgb*ORI_ShadingInput.BaseColor.w ) * materialUniform.baseColor.rgb,ORI_ShadingInput.BaseColor.w*materialUniform.baseColor.a) ; - #if USE_ALPHACUT + #if USE_SRGB_ALBEDO + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + ORI_ShadingInput.BaseColor = gammaToLiner(ORI_ShadingInput.BaseColor.rgb) ; + ORI_ShadingInput.BaseColor = vec4( ORI_ShadingInput.BaseColor * materialUniform.baseColor.rgb, ORI_ShadingInput.BaseColor.w * materialUniform.baseColor.a) ; + #else + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + ORI_ShadingInput.BaseColor = vec4f(gammaToLiner(ORI_ShadingInput.BaseColor.rgb) * materialUniform.baseColor.rgb,ORI_ShadingInput.BaseColor.a) ; + #endif + + var maskTex = textureSample(maskMap, maskMapSampler, uv ) ; + + #if USE_ALPHA_A + ORI_ShadingInput.BaseColor.a = ORI_ShadingInput.BaseColor.a * (maskTex.a) ; + #endif + + #if USE_ALPHACUT if( (ORI_ShadingInput.BaseColor.a - materialUniform.alphaCutoff) <= 0.0 ){ ORI_FragmentOutput.color = vec4(0.0,0.0,0.0,1.0); - ORI_FragmentOutput.worldPos = vec4(0.0,0.0,0.0,1.0); - ORI_FragmentOutput.worldNormal = vec4(0.0,0.0,0.0,1.0); - ORI_FragmentOutput.material = vec4(0.0,0.0,0.0,1.0); + + #if USEGBUFFER + ORI_FragmentOutput.worldPos = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.worldNormal = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.material = vec4(0.0,0.0,0.0,1.0); + #endif + discard; } #endif @@ -66,54 +85,75 @@ export let PBRLItShader: string = /*wgsl*/ ` useShadow(); #endif - #if USE_ARMC - var maskTex = textureSample(maskMap, maskMapSampler, uv ) ; - - ORI_ShadingInput.AmbientOcclusion = maskTex.r * materialUniform.ao ; - - #if USE_AOTEX - var aoMap = textureSample(aomapMap, aoMapSampler, uv ); - ORI_ShadingInput.AmbientOcclusion = mix(0.0,aoMap.r,materialUniform.ao) ; - #endif - - ORI_ShadingInput.Roughness = maskTex.g * materialUniform.roughness ; - ORI_ShadingInput.Metallic = maskTex.b * materialUniform.metallic ; + var roughnessChannel:f32 = 1.0 ; + #if USE_ROUGHNESS_A + roughnessChannel = maskTex.a ; + #else if USE_ROUGHNESS_R + roughnessChannel = maskTex.r ; + #else if USE_ROUGHNESS_G + roughnessChannel = maskTex.g ; + #else if USE_ROUGHNESS_B + roughnessChannel = maskTex.b ; + #else if USE_ALBEDO_A + roughnessChannel = ORI_ShadingInput.BaseColor.a ; + #endif + + #if USE_SMOOTH + var roughness = ( 1.0 - roughnessChannel ) * materialUniform.roughness; + ORI_ShadingInput.Roughness = clamp(roughness , 0.0001 , 1.0); + #else + ORI_ShadingInput.Roughness = clamp(roughnessChannel * materialUniform.roughness ,0.0001,1.0); + #endif + + var metallicChannel:f32 = 1.0 ; + #if USE_METALLIC_A + metallicChannel = maskTex.a ; + #else if USE_METALLIC_R + metallicChannel = maskTex.r ; + #else if USE_METALLIC_G + metallicChannel = maskTex.g ; + #else if USE_METALLIC_B + metallicChannel = maskTex.b ; + #endif + + ORI_ShadingInput.Metallic = metallicChannel * materialUniform.metallic ; + + var aoChannel:f32 = 1.0 ; + #if USE_AOTEX + var aoMap = textureSample(aoMap, aoMapSampler, uv ); + aoChannel = aoMap.g ; + #else + #if USE_AO_A + aoChannel = maskTex.a ; + #else if USE_AO_R + aoChannel = maskTex.r ; + #else if USE_AO_G + aoChannel = maskTex.g ; + #else if USE_AO_B + aoChannel = maskTex.b ; + #endif + #endif - #elseif USE_MR - var maskTex = textureSample(maskMap, maskMapSampler, uv ) ; - #if USE_AOTEX - var aoMap = textureSample(aomapMap, aoMapSampler, uv ); - ORI_ShadingInput.AmbientOcclusion = mix(0.0,aoMap.r,materialUniform.ao) ; - #else - ORI_ShadingInput.AmbientOcclusion = materialUniform.ao ; - #endif + ORI_ShadingInput.AmbientOcclusion = aoChannel ; + ORI_ShadingInput.Specular = 1.0 ; - ORI_ShadingInput.Roughness = maskTex.g * materialUniform.roughness ; - ORI_ShadingInput.Metallic = maskTex.b * materialUniform.metallic; + #if USE_EMISSIVEMAP + var emissiveMapColor = textureSample(emissiveMap, emissiveMapSampler , ORI_VertexVarying.fragUV0.xy) ; + let emissiveColor = materialUniform.emissiveColor.rgb * emissiveMapColor.rgb * materialUniform.emissiveIntensity ; + ORI_ShadingInput.EmissiveColor = vec4(emissiveColor.rgb,1.0); #else - ORI_ShadingInput.Roughness = materialUniform.roughness ; - ORI_ShadingInput.Metallic = materialUniform.metallic ; - ORI_ShadingInput.AmbientOcclusion = materialUniform.ao ; - #if USE_AOTEX - var aoMap = textureSample(aomapMap, aoMapSampler, uv ); - ORI_ShadingInput.AmbientOcclusion = mix(0.0,aoMap.r,materialUniform.ao) ; - #endif + let emissiveColor = materialUniform.emissiveColor.rgb * materialUniform.emissiveIntensity ; + ORI_ShadingInput.EmissiveColor = vec4(emissiveColor,1.0); #endif - ORI_ShadingInput.Roughness = clamp(ORI_ShadingInput.Roughness,0.084,1.0); - ORI_ShadingInput.Specular = 0.5 ; - - var emissiveColor = textureSample(emissiveMap, emissiveMapSampler , ORI_VertexVarying.fragUV0.xy) ; - emissiveColor = vec4(gammaToLiner(emissiveColor.rgb),emissiveColor.w); - ORI_ShadingInput.EmissiveColor = vec4(materialUniform.emissiveColor.rgb * emissiveColor.rgb * materialUniform.emissiveIntensity,1.0); var Normal = textureSample(normalMap,normalMapSampler,uv).rgb ; - // Normal.y = 1.0 - Normal.y ; - // let normal = unPackNormal(Normal,1.0,materialUniform.normalScale) ; - let normal = unPackNormal(Normal,materialUniform.normalScale) ; + let normal = unPackRGNormal(Normal,1.0,1.0) ; ORI_ShadingInput.Normal = normal ; BxDFShading(); + + // ORI_FragmentOutput.color = vec4(vec3(normal.rgb),1.0) ; } ` diff --git a/src/assets/shader/materials/PBRLitSSSShader.ts b/src/assets/shader/materials/PBRLitSSSShader.ts new file mode 100644 index 00000000..3a8ee687 --- /dev/null +++ b/src/assets/shader/materials/PBRLitSSSShader.ts @@ -0,0 +1,218 @@ +export let PBRLitSSSShader: string = /*wgsl*/ ` + #include "Common_vert" + #include "Common_frag" + #include "BsDF_frag" + + @group(1) @binding(auto) + var baseMapSampler: sampler; + @group(1) @binding(auto) + var baseMap: texture_2d; + + @group(1) @binding(auto) + var normalMapSampler: sampler; + @group(1) @binding(auto) + var normalMap: texture_2d; + + #if USE_CUSTOMUNIFORM + struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, + + baseColor: vec4, + emissiveColor: vec4, + materialF0: vec4, + specularColor: vec4, + envIntensity: f32, + normalScale: f32, + roughness: f32, + metallic: f32, + + ao: f32, + roughness_min: f32, + roughness_max: f32, + metallic_min: f32, + + metallic_max: f32, + emissiveIntensity: f32, + alphaCutoff: f32, + ior: f32, + + clearcoatColor: vec4, + + clearcoatWeight: f32, + clearcoatFactor: f32, + clearcoatRoughnessFactor: f32, + skinPower: f32, + + skinColor: vec4, + skinColorIns: f32, + curveFactor: f32, + }; + #endif + // #if USE_ARMC + // @group(1) @binding(auto) + // var maskMapSampler: sampler; + // @group(1) @binding(auto) + // var maskMap: texture_2d; + // #endif + + // #if USE_MR + @group(1) @binding(auto) + var maskMapSampler: sampler; + @group(1) @binding(auto) + var maskMap: texture_2d; + // #endif + + #if USE_AOTEX + @group(1) @binding(auto) + var aoMapSampler: sampler; + @group(1) @binding(auto) + var aoMap: texture_2d; + #endif + + @group(1) @binding(auto) + var emissiveMapSampler: sampler; + @group(1) @binding(auto) + var emissiveMap: texture_2d; + + @group(1) @binding(auto) + var sssMapSampler: sampler; + @group(1) @binding(auto) + var sssMap: texture_2d; + + @group(1) @binding(auto) + var lutMapSampler: sampler; + @group(1) @binding(auto) + var lutMap: texture_2d; + + var debugOut : vec4f = vec4f(0.0) ; + + fn vert(inputData:VertexAttributes) -> VertexOutput { + ORI_Vert(inputData) ; + return ORI_VertexOut ; + } + + fn frag(){ + var transformUV1 = materialUniform.transformUV1; + var transformUV2 = materialUniform.transformUV2; + + var uv = transformUV1.zw * ORI_VertexVarying.fragUV0 + transformUV1.xy; + + #if USE_SRGB_ALBEDO + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + ORI_ShadingInput.BaseColor = vec4f(ORI_ShadingInput.BaseColor.rgb/ORI_ShadingInput.BaseColor.a,ORI_ShadingInput.BaseColor.a) ; + ORI_ShadingInput.BaseColor = vec4(gammaToLiner(ORI_ShadingInput.BaseColor.rgb) * materialUniform.baseColor.rgb, ORI_ShadingInput.BaseColor.w * materialUniform.baseColor.a) ; + #else + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + ORI_ShadingInput.BaseColor = vec4f(ORI_ShadingInput.BaseColor.rgb/ORI_ShadingInput.BaseColor.a,ORI_ShadingInput.BaseColor.a) ; + ORI_ShadingInput.BaseColor = vec4(gammaToLiner(ORI_ShadingInput.BaseColor.rgb) * materialUniform.baseColor.rgb, ORI_ShadingInput.BaseColor.w * materialUniform.baseColor.a) ; + #endif + + var maskTex = textureSample(maskMap, maskMapSampler, uv ) ; + + #if USE_ALPHA_A + ORI_ShadingInput.BaseColor.a = ORI_ShadingInput.BaseColor.a * (maskTex.a) ; + ORI_ShadingInput.BaseColor = vec4f(ORI_ShadingInput.BaseColor.rgb/ORI_ShadingInput.BaseColor.a,ORI_ShadingInput.BaseColor.a) ; + #endif + + #if USE_ALPHACUT + if( (ORI_ShadingInput.BaseColor.a - materialUniform.alphaCutoff) <= 0.0 ){ + ORI_FragmentOutput.color = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.worldPos = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.worldNormal = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.material = vec4(0.0,0.0,0.0,1.0); + discard; + } + #endif + + #if USE_SHADOWMAPING + useShadow(); + #endif + + // maskTex =vec4f( gammaToLiner(maskTex.rgb), maskTex.a ); + + var roughnessChannel:f32 = 1.0 ; + #if USE_ROUGHNESS_A + roughnessChannel = maskTex.a ; + #else if USE_ROUGHNESS_R + roughnessChannel = maskTex.r ; + #else if USE_ROUGHNESS_G + roughnessChannel = maskTex.g ; + #else if USE_ROUGHNESS_B + roughnessChannel = maskTex.b ; + #else if USE_ALBEDO_A + roughnessChannel = ORI_ShadingInput.BaseColor.a ; + #endif + + #if USE_SMOOTH + var roughness = ( 1.0 - roughnessChannel ) * materialUniform.roughness; + ORI_ShadingInput.Roughness = clamp(roughness , 0.0001 , 1.0); + #else + ORI_ShadingInput.Roughness = clamp(roughnessChannel * materialUniform.roughness ,0.0001,1.0); + #endif + + var metallicChannel:f32 = 1.0 ; + #if USE_METALLIC_A + metallicChannel = maskTex.a ; + #else if USE_METALLIC_R + metallicChannel = maskTex.r ; + #else if USE_METALLIC_G + metallicChannel = maskTex.g ; + #else if USE_METALLIC_B + metallicChannel = maskTex.b ; + #endif + ORI_ShadingInput.Metallic = metallicChannel * metallicChannel * materialUniform.metallic ; + + var aoChannel:f32 = 1.0 ; + #if USE_AOTEX + var aoMap = textureSample(aoMap, aoMapSampler, uv ); + aoChannel = aoMap.g ; + #else + #if USE_AO_A + aoChannel = maskTex.a ; + #else if USE_AO_R + aoChannel = maskTex.r ; + #else if USE_AO_G + aoChannel = maskTex.g ; + #else if USE_AO_B + aoChannel = maskTex.b ; + #endif + #endif + + // ORI_ShadingInput.BaseColor.a = maskTex.a ; + + ORI_ShadingInput.AmbientOcclusion = aoChannel ; + + ORI_ShadingInput.Specular = 1.0 ; + + var emissiveColor = textureSample(emissiveMap, emissiveMapSampler , ORI_VertexVarying.fragUV0.xy) ; + + emissiveColor = vec4(gammaToLiner(emissiveColor.rgb),emissiveColor.w); + + ORI_ShadingInput.EmissiveColor = vec4(materialUniform.emissiveColor.rgb * emissiveColor.rgb * materialUniform.emissiveIntensity,1.0); + + + + var Normal = textureSample(normalMap,normalMapSampler,uv).rgb ; + + let normal = unPackRGNormal(Normal,1.0,1.0) ; + + ORI_ShadingInput.Normal = normal ; + + var sssColor = vec3f(pow(textureSample(sssMap, sssMapSampler, uv ).r,materialUniform.skinPower)) * materialUniform.skinColor.rgb ; + let sunLight = lightBuffer[0] ; + let sunLightIntensity = (sunLight.intensity / LUMEN) ; + let ndl = 1.0 - clamp(dot(normalize(normal),-normalize(sunLight.direction)),0.0,1.0) * 0.5 + 0.5 ;//1.0 - saturate( dot(normalize(normal),normalize(sunLight.direction)) ) * 0.5 + 0.5 ; + ORI_ShadingInput.SSS += 0.5 * vec3f(sssColor * sunLightIntensity * materialUniform.skinColorIns * ndl * sunLight.lightColor.rgb ) ; + + var curve = clamp(materialUniform.curveFactor * (length(fwidth(ORI_ShadingInput.Normal.xyz)) / length(fwidth(ORI_VertexVarying.vWorldPos.xyz*100.0))),0.0,1.0); + var NDotL = dot(ORI_ShadingInput.Normal, -sunLight.direction ); + var sssColor2 = textureSample(lutMap, lutMapSampler ,vec2f(NDotL * 0.5 + 0.5, materialUniform.curveFactor * sssColor.r)).rgb * sunLight.lightColor.rgb * sunLightIntensity ; + ORI_ShadingInput.SSS = sssColor2.rgb * ORI_ShadingInput.BaseColor.rgb ; + + BsDFShading(); + + // ORI_FragmentOutput.color = vec4f(vec3f(0.5*ORI_ShadingInput.SSS),1.0) ; + } +` + diff --git a/src/assets/shader/materials/PavementShader.ts b/src/assets/shader/materials/PavementShader.ts index 6a1f306b..a3a8b752 100644 --- a/src/assets/shader/materials/PavementShader.ts +++ b/src/assets/shader/materials/PavementShader.ts @@ -1,4 +1,4 @@ -export let PavementShader:string = /*wgsl*/` +export let PavementShader: string = /*wgsl*/` #include "Common_vert" #include "Common_frag" #include "BxDF_frag" @@ -57,7 +57,7 @@ export let PavementShader:string = /*wgsl*/` ORI_ShadingInput.Roughness = ReflectMap * materialUniform.roughness ; ORI_ShadingInput.Metallic = materialUniform.metallic ; ORI_ShadingInput.Specular = 0.5 ; - ORI_ShadingInput.AmbientOcclusion = Ao * materialUniform.ao ; + ORI_ShadingInput.AmbientOcclusion = Ao; ORI_ShadingInput.EmissiveColor = vec4(0.0); let normal = unPackRGNormal(Normal,Displace.r*materialUniform.normalScale,1.0) ; diff --git a/src/assets/shader/materials/UnLit.ts b/src/assets/shader/materials/UnLit.ts index 4e8e439b..52a4ea89 100644 --- a/src/assets/shader/materials/UnLit.ts +++ b/src/assets/shader/materials/UnLit.ts @@ -4,6 +4,15 @@ export let UnLit: string = /*wgsl*/ ` #include "UnLit_frag" #include "UnLitMaterialUniform_frag" + #if USE_CUSTOMUNIFORM + struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, + baseColor: vec4, + alphaCutoff: f32, + }; + #endif + @group(1) @binding(0) var baseMapSampler: sampler; @group(1) @binding(1) @@ -25,7 +34,10 @@ export let UnLit: string = /*wgsl*/ ` } ORI_ShadingInput.BaseColor = color * materialUniform.baseColor ; + UnLit(); + + // ORI_FragmentOutput.color = vec4( 1.0,0.0,0.0,1.0) ; } ` diff --git a/src/assets/shader/materials/UnLitTextureArray.ts b/src/assets/shader/materials/UnLitTextureArray.ts new file mode 100644 index 00000000..ad161668 --- /dev/null +++ b/src/assets/shader/materials/UnLitTextureArray.ts @@ -0,0 +1,77 @@ +export let UnLitTextureArray: string = /*wgsl*/ ` + // #include "Common_vert" + #include "Common_frag" + #include "UnLit_frag" + #include "UnLitMaterialUniform_frag" + + #include "WorldMatrixUniform" + #include "VertexAttributeIndexShader" + #include "GlobalUniform" + #include "Inline_vert" + #include "EnvMap_frag" + #include "ColorUtil_frag" + + const DEGREES_TO_RADIANS : f32 = 3.1415926 / 180.0 ; + const PI : f32 = 3.1415926 ; + + #if USE_CUSTOMUNIFORM + struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, + baseColor: vec4, + alphaCutoff: f32, + }; + #endif + + @group(1) @binding(0) + var baseMapSampler: sampler; + @group(1) @binding(1) + var baseMap: texture_2d_array; + + @group(2) @binding(5) + var graphicBuffer : array; + + @vertex + fn VertMain( vertex:VertexAttributes ) -> VertexOutput { + vertex_inline(vertex); + vert(vertex); + return ORI_VertexOut ; + } + + fn vert(inputData:VertexAttributes) -> VertexOutput { + ORI_Vert(inputData) ; + return ORI_VertexOut ; + } + + fn frag(){ + var transformUV1 = materialUniform.transformUV1; + var transformUV2 = materialUniform.transformUV2; + + // var irradiance = vec3(0.0) ; + // let MAX_REFLECTION_LOD = f32(textureNumLevels(prefilterMap)) ; + // irradiance += (globalUniform.skyExposure * textureSampleLevel(prefilterMap, prefilterMapSampler, ORI_VertexVarying.vWorldNormal.xyz, 0.8 * (MAX_REFLECTION_LOD) ).rgb); + + graphicNode = graphicBuffer[u32(round(ORI_VertexVarying.index))]; + + var uv = transformUV1.zw * ORI_VertexVarying.fragUV0 + transformUV1.xy; + let color = textureSample(baseMap,baseMapSampler,uv, u32(round(graphicNode.texIndex)) ); + // let color = textureSample(baseMap,baseMapSampler,uv, u32(round(ORI_VertexVarying.index))); + + // ORI_ViewDir = normalize( globalUniform.CameraPos.xyz - ORI_VertexVarying.vWorldPos.xyz); + // let att = dot( ORI_ViewDir , ORI_VertexVarying.vWorldNormal.xyz ); + + // irradiance = LinearToGammaSpace(irradiance.rgb) * color.rgb ;//* att ; + + if(color.w < 0.5){ + discard ; + } + + // let outColor = vec4f( color.rgb * (att * 0.5 + 0.5 ) , 1.0 ) * materialUniform.baseColor ; + let outColor = vec4f( color.rgb , 1.0 ) * materialUniform.baseColor ; + + // ORI_ShadingInput.BaseColor = color ; + ORI_ShadingInput.BaseColor = vec4f(outColor.xyz,1.0) ; + UnLit(); + } +` + diff --git a/src/assets/shader/materials/program/BxdfDebug_frag.ts b/src/assets/shader/materials/program/BxdfDebug_frag.ts index 12c42382..3b94deed 100644 --- a/src/assets/shader/materials/program/BxdfDebug_frag.ts +++ b/src/assets/shader/materials/program/BxdfDebug_frag.ts @@ -6,7 +6,7 @@ export let BxdfDebug_frag: string = /*wgsl*/ ` } fn debugMeshID(){ - let meshIDColor = u32(ORI_VertexVarying.vWorldPos.w ) ; + let meshIDColor = u32(round(ORI_VertexVarying.vWorldPos.w) ) ; let color = colorSet[ meshIDColor % 9u] ; ORI_FragmentOutput.color = vec4(vec3(color.rgb),1.0); } @@ -29,7 +29,7 @@ export let BxdfDebug_frag: string = /*wgsl*/ ` } fn debugAmbient(){ - ORI_FragmentOutput.color = vec4(fragData.Irradiance * fragData.Albedo.rgb,1.0); + ORI_FragmentOutput.color = vec4(vec3f(fragData.Alpha) ,1.0); } fn debugEmissive(){ @@ -57,7 +57,7 @@ export let BxdfDebug_frag: string = /*wgsl*/ ` } fn debugTangent(){ - ORI_FragmentOutput.color = vec4(vec3(fragData.TangentChannel),1.0); + ORI_FragmentOutput.color = vec4(vec3(fragData.T),1.0); } fn debugFragmentOut(){ diff --git a/src/assets/shader/materials/program/NormalMap_frag.ts b/src/assets/shader/materials/program/NormalMap_frag.ts index 374ba7eb..d8795563 100644 --- a/src/assets/shader/materials/program/NormalMap_frag.ts +++ b/src/assets/shader/materials/program/NormalMap_frag.ts @@ -1,18 +1,19 @@ export let NormalMap_frag: string = /*wgsl*/ ` + fn perturbNormal( worldPos:vec3, surf_norm:vec3, mapN:vec3 , normalScale:f32 , face:f32 ) -> vec3 { var q0 = vec3( dpdx( worldPos.x ), dpdx( worldPos.y ), dpdx( worldPos.z ) ); var q1 = vec3( dpdy( worldPos.x ), dpdy( worldPos.y ), dpdy( worldPos.z ) ); var st0 = dpdx( ORI_VertexVarying.fragUV0.xy ); var st1 = dpdy( ORI_VertexVarying.fragUV0.xy ); var N = surf_norm; - var q1perp = cross( q1, N ); var q0perp = cross( N, q0 ); + var q1perp = cross( q1, N ); - #if USE_TANGENT - var T = ORI_VertexVarying.TANGENT.xyz ; - #else + // #if USE_TANGENT + // var T = ORI_VertexVarying.TANGENT.xyz ; + // #else var T = q1perp * st0.x + q0perp * st1.x; - #endif + // #endif var B = q1perp * st0.y + q0perp * st1.y; @@ -21,9 +22,10 @@ export let NormalMap_frag: string = /*wgsl*/ ` if( det != 0.0 ){ scale = inverseSqrt( det ) ; } - #if USE_TANGENT - scale = scale * ORI_VertexVarying.TANGENT.w ; - #endif + + // #if USE_TANGENT + // scale = scale * ORI_VertexVarying.TANGENT.w ; + // #endif scale *= normalScale; return normalize( (T * ( -mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z ) * face ) ; @@ -51,7 +53,7 @@ export let NormalMap_frag: string = /*wgsl*/ ` n.y = 1.0 - n.y ; #endif - var mapNormal: vec3 = unpackNormalMap(n) ; + var mapNormal: vec3 = n ;//unpackNormalMap(n) ; return perturbNormal(ORI_VertexVarying.vWorldPos.xyz , ORI_VertexVarying.vWorldNormal.xyz , mapNormal , height , face ) ; #endif } diff --git a/src/assets/shader/materials/program/ShadowMapping_frag.ts b/src/assets/shader/materials/program/ShadowMapping_frag.ts index 457a5562..62a839ad 100644 --- a/src/assets/shader/materials/program/ShadowMapping_frag.ts +++ b/src/assets/shader/materials/program/ShadowMapping_frag.ts @@ -13,22 +13,7 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` directShadowVisibility: array, pointShadows: array, } - - varshadowStrut: ShadowStruct; - - struct ShadowBuffer{ - nDirShadowStart: i32, - nDirShadowEnd: i32, - nPointShadowStart: i32, - nPointShadowEnd: i32, - shadowLights:array - } - - #if DEBUG_CLUSTER - @group(2) @binding(6) var shadowBuffer: ShadowBuffer; - #else - @group(2) @binding(5) var shadowBuffer: ShadowBuffer; - #endif + var shadowStrut: ShadowStruct ; fn useShadow(){ shadowStrut.directShadowVisibility = array( 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0) ; @@ -51,9 +36,9 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` #if USE_SHADOWMAPING let enableCSM:bool = globalUniform.enableCSM > 0.5; for (var i: i32 = 0; i < dirCount ; i = i + 1) { - if( i >= shadowBuffer.nDirShadowStart && i < shadowBuffer.nDirShadowEnd ){ - let ldx = shadowBuffer.shadowLights[i]; - var light = lightBuffer[ldx]; + if( i >= globalUniform.nDirShadowStart && i < globalUniform.nDirShadowEnd ){ + let ldx = globalUniform.shadowLights[u32(i) / 4u][u32(i) % 4u]; + let light = lightBuffer[u32(ldx)] ; var shadowIndex = i32(light.castShadow); var visibility = 1.0; var shadowMatrix:mat4x4; @@ -96,7 +81,7 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` if(validCount == 0){ visibility = 1.0; }else{ - visibility = visibility / totalWeight; + visibility = visibility / totalWeight ; } }else{ shadowMatrix = globalUniform.shadowMatrix[shadowIndex]; @@ -135,8 +120,9 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` isOutSideArea = 0.0; var uvOnePixel = 1.0 / vec2(globalUniform.shadowMapSize); var totalWeight = 0.0; - var NoL = abs(dot(normalize(ORI_VertexVarying.vWorldNormal), normalize(light.direction))); - var bias = shadowBias / max(NoL, 0.000001); + var NoL = (dot(normalize(ORI_VertexVarying.vWorldNormal), normalize(-light.direction))); + let v = max(NoL, 0.0) ; + var bias = shadowBias / v; for (var y = -1; y <= 1; y++) { for (var x = -1; x <= 1; x++) { var offset = vec2(f32(x), f32(y)) * uvOnePixel; @@ -144,7 +130,7 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` // visibility += textureSampleCompare(shadowMap, shadowMapSampler, varying_shadowUV + offset, depthTexIndex, shadowPos.z - bias); var depth = textureSampleLevel(shadowMap, shadowMapSampler, varying_shadowUV + offset, depthTexIndex, 0); if ((shadowPos.z - bias ) < depth) { - visibility += 1.0 ;//* dot(offsetDir, dir.xyz); + visibility += 1.0 ; } totalWeight += 1.0; } @@ -161,76 +147,75 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` let offset = 0.1; for (var i: i32 = 0; i < pointCount ; i = i + 1) { - if( i >= shadowBuffer.nPointShadowStart && i < shadowBuffer.nPointShadowEnd ){ - let ldx = shadowBuffer.shadowLights[i]; - let light = lightBuffer[ldx] ; + if( i >= globalUniform.nPointShadowStart && i < globalUniform.nPointShadowEnd ){ + let ldx = globalUniform.shadowLights[u32(i) / 4u][u32(i) % 4u]; + let light = lightBuffer[u32(ldx)] ; #if USE_SHADOWMAPING - let lightPos = light.position.xyz; - var shadow = 0.0; - let frgToLight = worldPos - lightPos.xyz; - var dir: vec3 = normalize(frgToLight); - var len = length(frgToLight); - var bias = max(shadowBias * globalUniform.far * (1.0 - dot(ORI_ShadingInput.Normal, dir)), 0.005); + let lightPos = light.position.xyz; + var shadow = 0.0; + let frgToLight = worldPos - lightPos.xyz; + var dir: vec3 = normalize(frgToLight); + var len = length(frgToLight); + var bias = max(shadowBias * globalUniform.far * (1.0 - dot(ORI_ShadingInput.Normal, dir)), 0.005); #if USE_PCF_SHADOW - let samples = 4.0; - for (var x: f32 = -offset; x < offset; x += offset / (samples * 0.5)) { - for (var y: f32 = -offset; y < offset; y += offset / (samples * 0.5)) { - for (var z: f32 = -offset; z < offset; z += offset / (samples * 0.5)) { - let offsetDir = normalize(dir.xyz + vec3(x, y, z)); + let samples = 4.0; + for (var x: f32 = -offset; x < offset; x += offset / (samples * 0.5)) { + for (var y: f32 = -offset; y < offset; y += offset / (samples * 0.5)) { + for (var z: f32 = -offset; z < offset; z += offset / (samples * 0.5)) { + let offsetDir = normalize(dir.xyz + vec3(x, y, z)); + var depth = textureSampleLevel(pointShadowMap, pointShadowMapSampler, offsetDir, light.castShadow, 0); + depth *= globalUniform.far; + if ((len - bias) > depth) { + shadow += 1.0 * dot(offsetDir, dir.xyz); + } + } + } + } + shadow = min(max(shadow / (samples * samples * samples), 0.0), 1.0); + #endif + + #if USE_SOFT_SHADOW + let vDis = length(globalUniform.CameraPos.xyz - worldPos.xyz); + let sampleRadies = globalUniform.shadowSoft; + let samples = 20; + for (var j: i32 = 0; j < samples; j += 1) { + let offsetDir = normalize(dir.xyz + sampleOffsetDir[j] * sampleRadies); var depth = textureSampleLevel(pointShadowMap, pointShadowMapSampler, offsetDir, light.castShadow, 0); depth *= globalUniform.far; if ((len - bias) > depth) { shadow += 1.0 * dot(offsetDir, dir.xyz); } } - } - } - shadow = min(max(shadow / (samples * samples * samples), 0.0), 1.0); - #endif - - #if USE_SOFT_SHADOW - let vDis = length(globalUniform.CameraPos.xyz - worldPos.xyz); - let sampleRadies = globalUniform.shadowSoft; - let samples = 20; - for (var j: i32 = 0; j < samples; j += 1) { - let offsetDir = normalize(dir.xyz + sampleOffsetDir[j] * sampleRadies); - var depth = textureSampleLevel(pointShadowMap, pointShadowMapSampler, offsetDir, light.castShadow, 0); - depth *= globalUniform.far; - if ((len - bias) > depth) { - shadow += 1.0 * dot(offsetDir, dir.xyz); - } - } - shadow = min(max(shadow / f32(samples), 0.0), 1.0); + shadow = min(max(shadow / f32(samples), 0.0), 1.0); #endif #if USE_HARD_SHADOW - var depth = textureSampleLevel(pointShadowMap, pointShadowMapSampler, dir.xyz, light.castShadow, 0); - depth *= globalUniform.far; - if ((len - bias) > depth) { - shadow = 1.0; - } + var depth = textureSampleLevel(pointShadowMap, pointShadowMapSampler, dir.xyz, light.castShadow, 0); + depth *= globalUniform.far; + if ((len - bias) > depth) { + shadow = 1.0; + } #endif - - for (var j = 0; j < pointCount ; j+=1 ) { - if(i32(light.castShadow) == j){ - shadowStrut.pointShadows[j] = 1.0 - shadow ; + for (var j = 0; j < pointCount ; j+=1 ) { + if(i32(light.castShadow) == j){ + shadowStrut.pointShadows[j] = 1.0 - shadow ; + } } - } #endif } } } #if USE_SOFT_SHADOW - varsampleOffsetDir : array, 20> = array, 20>( - vec3(1.0, 1.0, 1.0), vec3(1.0, -1.0, 1.0), vec3(-1.0, -1.0, 1.0), vec3(-1.0, 1.0, 1.0), - vec3(1.0, 1.0, -1.0), vec3(1.0, -1.0, -1.0), vec3(-1.0, -1.0, -1.0), vec3(-1.0, 1.0, -1.0), - vec3(1.0, 1.0, 0.0), vec3(1.0, -1.0, 0.0), vec3(-1.0, -1.0, 0.0), vec3(-1.0, 1.0, 0.0), - vec3(1.0, 0.0, 1.0), vec3(-1.0, 0.0, 1.0), vec3(1.0, 0.0, -1.0), vec3(-1.0, 0.0, -1.0), - vec3(0.0, 1.0, 1.0), vec3(0.0, -1.0, 1.0), vec3(0.0, -1.0, -1.0), vec3(0.0, 1.0, -1.0), - ); + varsampleOffsetDir : array, 20> = array, 20>( + vec3(1.0, 1.0, 1.0), vec3(1.0, -1.0, 1.0), vec3(-1.0, -1.0, 1.0), vec3(-1.0, 1.0, 1.0), + vec3(1.0, 1.0, -1.0), vec3(1.0, -1.0, -1.0), vec3(-1.0, -1.0, -1.0), vec3(-1.0, 1.0, -1.0), + vec3(1.0, 1.0, 0.0), vec3(1.0, -1.0, 0.0), vec3(-1.0, -1.0, 0.0), vec3(-1.0, 1.0, 0.0), + vec3(1.0, 0.0, 1.0), vec3(-1.0, 0.0, 1.0), vec3(1.0, 0.0, -1.0), vec3(-1.0, 0.0, -1.0), + vec3(0.0, 1.0, 1.0), vec3(0.0, -1.0, 1.0), vec3(0.0, -1.0, -1.0), vec3(0.0, 1.0, -1.0), + ); #endif ` diff --git a/src/assets/shader/materials/uniforms/PhysicMaterialUniform_frag.ts b/src/assets/shader/materials/uniforms/PhysicMaterialUniform_frag.ts index a92cddcb..6aab2ff0 100644 --- a/src/assets/shader/materials/uniforms/PhysicMaterialUniform_frag.ts +++ b/src/assets/shader/materials/uniforms/PhysicMaterialUniform_frag.ts @@ -1,29 +1,33 @@ export let PhysicMaterialUniform_frag = /* wgsl */` - struct MaterialUniform { - transformUV1:vec4, - transformUV2:vec4, + #if USE_CUSTOMUNIFORM + #else + struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, - baseColor: vec4, - emissiveColor: vec4, - materialF0: vec4, - envIntensity: f32, - normalScale: f32, - roughness: f32, - metallic: f32, - ao: f32, + baseColor: vec4, + emissiveColor: vec4, + materialF0: vec4, + specularColor: vec4, + envIntensity: f32, + normalScale: f32, + roughness: f32, + metallic: f32, + ao: f32, - roughness_min: f32, - roughness_max: f32, - metallic_min: f32, - metallic_max: f32, - emissiveIntensity: f32, - alphaCutoff: f32, - ior: f32, - clearcoatColor: vec4, - clearcoatWeight: f32, - clearcoatFactor: f32, - clearcoatRoughnessFactor: f32, - }; + roughness_min: f32, + roughness_max: f32, + metallic_min: f32, + metallic_max: f32, + emissiveIntensity: f32, + alphaCutoff: f32, + ior: f32, + clearcoatColor: vec4, + clearcoatWeight: f32, + clearcoatFactor: f32, + clearcoatRoughnessFactor: f32, + }; + #endif @group(2) @binding(0) var materialUniform: MaterialUniform; diff --git a/src/assets/shader/materials/uniforms/UnLitMaterialUniform_frag.ts b/src/assets/shader/materials/uniforms/UnLitMaterialUniform_frag.ts index 07f05673..5847578f 100644 --- a/src/assets/shader/materials/uniforms/UnLitMaterialUniform_frag.ts +++ b/src/assets/shader/materials/uniforms/UnLitMaterialUniform_frag.ts @@ -1,10 +1,16 @@ export let UnLitMaterialUniform_frag = /* wgsl */` -struct MaterialUniform { - transformUV1:vec4, - transformUV2:vec4, - baseColor: vec4, - alphaCutoff: f32, -}; + + +#if USE_CUSTOMUNIFORM +#else + struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, + baseColor: vec4, + alphaCutoff: f32, + }; +#endif + @group(2) @binding(0) var materialUniform: MaterialUniform; diff --git a/src/assets/shader/math/FastMathShader.ts b/src/assets/shader/math/FastMathShader.ts index 4a4eb495..c3ae62f8 100644 --- a/src/assets/shader/math/FastMathShader.ts +++ b/src/assets/shader/math/FastMathShader.ts @@ -1,11 +1,22 @@ export let FastMathShader: string = /*wgsl*/ ` - fn Pow3( x : f32 ) -> f32 + fn pow2( x : f32 ) -> f32 + { + return x * x; + } + + fn pow2v3( x : vec3f ) -> vec3f + { + return x * x; + } + + + fn pow3( x : f32 ) -> f32 { var xx = x*x; return x * xx; } - fn Pow4( x : f32 ) -> f32 + fn pow4( x : f32 ) -> f32 { var xx = x*x; return xx * xx; @@ -30,5 +41,72 @@ export let FastMathShader: string = /*wgsl*/ ` { return pow(a, -0.5); } + + fn squareF( a : f32 ) -> f32 + { + return a * a; + } + + fn squareV2( a : vec2f ) -> vec2f + { + return a * a; + } + + fn squareV3( a : vec3f ) -> vec3f + { + return a * a; + } + + fn sqrtFast( x : f32 ) -> f32 + { + var i = i32(x); + i = 0x1FBD1DF5 + (i / 2 ); + return f32(i); + } + + fn lengthFast( v :vec3 ) -> f32 + { + var LengthSqr = dot(v,v); + return sqrtFast( LengthSqr ); + } + + fn asinFast( x:f32 )-> f32 + { + return (0.5 * PI) - acosFast(x); + } + + fn acosFast( inX: f32 ) -> f32 + { + var x = abs(inX); + var res = -0.156583 * x + (0.5 * PI); + res *= sqrt(1.0 - x); + + if(inX >= 0.0){ + return res ; + }else{ + return PI - res ; + } + } + + fn acosFast4( inX : f32 )-> f32 + { + var x1 = abs(inX); + var x2 = x1 * x1; + var x3 = x2 * x1; + var s = 0.0 ; + + s = -0.2121144 * x1 + 1.5707288; + s = 0.0742610 * x2 + s; + s = -0.0187293 * x3 + s; + s = sqrt(1.0 - x1) * s; + + // acos function mirroring + // check per platform if compiles to a selector - no branch neeeded + if(inX >= 0.0){ + return s ; + }else{ + return PI - s ; + } + } ` diff --git a/src/assets/shader/math/MathShader.ts b/src/assets/shader/math/MathShader.ts index 665522d0..20d3e8b4 100644 --- a/src/assets/shader/math/MathShader.ts +++ b/src/assets/shader/math/MathShader.ts @@ -2,7 +2,6 @@ * @internal */ export let MathShader = /* wgsl */ ` -var PI: f32 = 3.14159265359; fn applyQuaternion(position:vec3, q:vec4) -> vec3{ @@ -302,4 +301,13 @@ fn dir_to_faceId(pt:vec3) -> i32 { comp -= comp.xxyz * bitMsk; return comp; } + + fn calculateBillboardMatrix2(eye:vec3f,pos:vec3f,up:vec3f) -> mat3x3 { + + let zAxis: vec3f = -normalize(pos.xyz - eye); + var xAxis: vec3f = cross(up,zAxis); + xAxis = normalize(cross(zAxis,xAxis)); + let yAxis = normalize(cross(zAxis, xAxis)); + return mat3x3(xAxis, yAxis, zAxis); + } `; diff --git a/src/assets/shader/post/Bloom_shader.ts b/src/assets/shader/post/Bloom_shader.ts deleted file mode 100644 index d573d925..00000000 --- a/src/assets/shader/post/Bloom_shader.ts +++ /dev/null @@ -1,248 +0,0 @@ -export class Bloom_shader { - public static Bloom_Brightness_frag_wgsl: string = /* wgsl */ ` - struct uniformData { - luminosityThreshold: f32 - }; - - struct FragmentOutput { - @location(0) o_Target: vec4 - }; - - var fragUV1: vec2; - var o_Target: vec4; - @group(1) @binding(0) - var baseMapSampler: sampler; - @group(1) @binding(1) - var baseMap: texture_2d; - @group(2) @binding(0) - var global: uniformData; - - fn Brightness(c: vec3) -> f32 { - var c1: vec3; - - c1 = c; - let e8: vec3 = c1; - let e10: vec3 = c1; - let e12: vec3 = c1; - let e14: vec3 = c1; - let e17: vec3 = c1; - let e19: vec3 = c1; - let e21: vec3 = c1; - let e23: vec3 = c1; - let e25: vec3 = c1; - let e28: vec3 = c1; - return max(max(e23.x, e25.y), e28.z); - } - - fn main1() { - var uv: vec2; - var LinearColor: vec4; - var TotalLuminance: f32; - var BloomLuminance: f32; - var BloomAmount: f32; - - let e6: vec2 = fragUV1; - uv = e6.xy; - let e11: vec2 = uv; - uv.y = (1.0 - e11.y); - let e15: vec2 = uv; - let e16: vec4 = textureSample(baseMap, baseMapSampler, e15); - LinearColor = e16; - let e18: vec4 = LinearColor; - let e27: vec4 = LinearColor; - let e36: vec4 = LinearColor; - let e38: vec3 = min(vec3(f32(65000), f32(65000), f32(65000)), e36.xyz); - LinearColor.x = e38.x; - LinearColor.y = e38.y; - LinearColor.z = e38.z; - let e45: vec4 = LinearColor; - let e47: vec4 = LinearColor; - let e49: f32 = Brightness(e47.xyz); - TotalLuminance = e49; - let e51: f32 = TotalLuminance; - let e52: f32 = global.luminosityThreshold; - BloomLuminance = (e51 - e52); - let e55: f32 = BloomLuminance; - let e60: f32 = BloomLuminance; - BloomAmount = clamp((e60 * 0.5), 0.0, 1.0); - let e67: f32 = BloomAmount; - let e68: vec4 = LinearColor; - o_Target = vec4((e67 * e68.xyz), f32(0)); - return; - } - - @fragment - fn main(@location(0) fragUV: vec2) -> FragmentOutput { - fragUV1 = fragUV; - main1(); - let e13: vec4 = o_Target; - return FragmentOutput(e13); - } - `; - - - public static Bloom_blur_frag_wgsl: string = /* wgsl */ ` - struct uniformData { - texSize: vec2, - hScale: f32, - vScale: f32, - horizontal: f32 - }; - - struct FragmentOutput { - @location(0) o_Target: vec4 - }; - - var fragUV1: vec2; - var o_Target: vec4; - @group(1) @binding(0) - var baseMapSampler: sampler; - @group(1) @binding(1) - var baseMap: texture_2d; - @group(2) @binding(0) - var global: uniformData; - - fn main1() { - - return; - } - - const buffer1: array = array(0.22702699899673462, 0.194594606757164, 0.12162160128355026, 0.05405399948358536, 0.01621600054204464); - - @fragment - fn main(@location(0) fragUV: vec2) -> FragmentOutput { - var result: vec3; - var i: i32 = 1; - var j: i32 = 1; - var uv: vec2 = fragUV; - uv.y = (1.0 - uv.y); - var tex_offset: vec2 = (vec2(1.0) / vec2(global.texSize)); - let color: vec4 = textureSample(baseMap, baseMapSampler, uv); - result = (color.xyz * buffer1[0]); - - if ((global.horizontal > 1.0)) { - { - loop { - if (!((i < 5))) { - break; - } - { - let c1: vec4 = textureSample(baseMap, baseMapSampler, (uv + vec2(((tex_offset.x * f32(i)) * global.hScale), 0.0))); - result = (result + (c1.xyz * buffer1[i])); - let e101: vec4 = textureSample(baseMap, baseMapSampler, (uv - vec2(((tex_offset.x * f32(i)) * global.hScale), 0.0))); - result = (result + (e101.xyz * buffer1[i])); - } - continuing { - i = (i + 1); - } - } - } - } - if ((global.horizontal < 1.0)) { - { - loop { - let e114: i32 = j; - if (!((e114 < 5))) { - break; - } - { - let e144: vec4 = textureSample(baseMap, baseMapSampler, (uv + vec2(0.0, ((tex_offset.y * f32(j)) * global.vScale)))); - result = (result + (e144.xyz * buffer1[j])); - let e175: vec4 = textureSample(baseMap, baseMapSampler, (uv - vec2(0.0, ((tex_offset.y * f32(j)) * global.vScale)))); - result = (result + (e175.xyz * buffer1[j])); - } - continuing { - j = (j + 1); - } - } - } - } - o_Target = vec4(result, 1.0); - return FragmentOutput(o_Target); - } - `; - - public static Bloom_composite_frag_wgsl: string = /* wgsl */ ` - #include "ColorUtil" - struct UniformData { - tintColor:vec4, - bloomStrength: f32, - exposure: f32, - bloomRadius: f32, - }; - - struct FragmentOutput { - @location(0) o_Target: vec4 - }; - - var fragUV1: vec2; - var o_Target: vec4; - @group(1) @binding(0) - var baseMapSampler: sampler; - @group(1) @binding(1) - var baseMap: texture_2d; - @group(1) @binding(2) - var blurTex1Sampler: sampler; - @group(1) @binding(3) - var blurTex1: texture_2d; - @group(1) @binding(4) - var blurTex2Sampler: sampler; - @group(1) @binding(5) - var blurTex2: texture_2d; - @group(1) @binding(6) - var blurTex3Sampler: sampler; - @group(1) @binding(7) - var blurTex3: texture_2d; - @group(1) @binding(8) - var blurTex4Sampler: sampler; - @group(1) @binding(9) - var blurTex4: texture_2d; - @group(1) @binding(10) - var blurTex5Sampler: sampler; - @group(1) @binding(11) - var blurTex5: texture_2d; - @group(2) @binding(0) - var global: UniformData; - - const bloomFactors = array(1.0, 0.800000011920929, 0.6000000238418579, 0.4000000059604645, 0.20000000298023224); - - fn lerpBloomFactor(factor: f32) -> f32 { - var mirrorFactor: f32 = (1.2000000476837158 - factor); - return mix(factor, mirrorFactor, global.bloomRadius); - } - - fn main1() { - - return; - } - - @fragment - fn main(@location(0) fragUV: vec2) -> FragmentOutput { - var uv: vec2 = fragUV; - uv.y = (1.0 - uv.y); - - let e38: f32 = lerpBloomFactor(bloomFactors[0]); - let e46: vec4 = textureSample(blurTex1, blurTex1Sampler, uv); - let e52: f32 = lerpBloomFactor(bloomFactors[1]); - let e60: vec4 = textureSample(blurTex2, blurTex2Sampler, uv); - let e67: f32 = lerpBloomFactor(bloomFactors[2]); - let e75: vec4 = textureSample(blurTex3, blurTex3Sampler, uv); - let e82: f32 = lerpBloomFactor(bloomFactors[3]); - let e90: vec4 = textureSample(blurTex4, blurTex4Sampler, uv); - let e97: f32 = lerpBloomFactor(bloomFactors[4]); - let e105: vec4 = textureSample(blurTex5, blurTex5Sampler, uv); - o_Target = ((((((((e38 * vec4(array,5>(vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0))[0], 1.0)) * e46) + ((e52 * vec4(array,5>(vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0))[1], 1.0)) * e60)) + ((e67 * vec4(array,5>(vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0))[2], 1.0)) * e75)) + ((e82 * vec4(array,5>(vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0))[3], 1.0)) * e90)) + ((e97 * vec4(array,5>(vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0))[4], 1.0)) * e105)))); - - let baseColor: vec4 = textureSample(baseMap, baseMapSampler, uv); - - var bloomLight = global.bloomStrength * o_Target.rgb; - - bloomLight = getHDRColor(bloomLight.rgb,global.exposure); - bloomLight = LinearToGammaSpace(bloomLight); - - o_Target = baseColor + vec4(bloomLight * global.tintColor.rgb, baseColor.a) ; - o_Target.a = min(o_Target.a,1.0); - return FragmentOutput(o_Target); - } - `; -} \ No newline at end of file diff --git a/src/assets/shader/post/GlobalFog_shader.ts b/src/assets/shader/post/GlobalFog_shader.ts index d3a4da3e..7b38703e 100644 --- a/src/assets/shader/post/GlobalFog_shader.ts +++ b/src/assets/shader/post/GlobalFog_shader.ts @@ -4,6 +4,8 @@ import { GlobalUniform } from "../core/common/GlobalUniform"; * @internal */ export let GlobalFog_shader = /* wgsl */ ` +var PI: f32 = 3.14159265359; + struct FragmentOutput { @location(0) o_Target: vec4 }; diff --git a/src/assets/shader/utils/ColorUtil.ts b/src/assets/shader/utils/ColorUtil.ts index 719b8229..b2fc1803 100644 --- a/src/assets/shader/utils/ColorUtil.ts +++ b/src/assets/shader/utils/ColorUtil.ts @@ -97,6 +97,14 @@ export let ColorUtil: string = /*wgsl*/ ` } } + fn BlendNormalRNM( n1:vec3f, n2:vec3f) -> vec3f + { + let t = n1.xyz + vec3f(0.0, 0.0, 1.0); + let u = n2.xyz * vec3f(-1.0, -1.0, 1.0); + let r = (t / t.z) * dot(t, u) - u; + return r; + } + // fn ReorientedBlendNormal(){ // vec3 t = texture(baseMap, uv).xyz * vec3( 2.0, 2.0, 2.0) + vec3(-1.0, -1.0, 0.0); // vec3 u = texture(detailMap, uv).xyz * vec3(-2.0, -2.0, 2.0) + vec3( 1.0, 1.0, -1.0); diff --git a/src/components/SkeletonAnimationComponent.ts b/src/components/SkeletonAnimationComponent.ts index b94cfcca..d30e6b5f 100644 --- a/src/components/SkeletonAnimationComponent.ts +++ b/src/components/SkeletonAnimationComponent.ts @@ -1,3 +1,4 @@ +import { RegisterComponent } from ".."; import { Object3D } from "../core/entities/Object3D"; import { StorageGPUBuffer } from "../gfx/graphics/webGpu/core/buffer/StorageGPUBuffer"; import { Time } from "../util/Time"; @@ -11,6 +12,7 @@ import { SkeletonPose } from "./anim/skeletonAnim/SkeletonPose"; * skeleton animation * @group Animation */ +@RegisterComponent export class SkeletonAnimationComponent extends ComponentBase { /** * Whether it is playing diff --git a/src/components/anim/AnimatorComponent.ts b/src/components/anim/AnimatorComponent.ts new file mode 100644 index 00000000..d03ae871 --- /dev/null +++ b/src/components/anim/AnimatorComponent.ts @@ -0,0 +1,286 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { BoxGeometry, DEGREES_TO_RADIANS, Engine3D, LitMaterial, Matrix4, MeshFilter, MeshRenderer, Object3D, PrefabAvatarData, Quaternion, RenderNode, RendererBase, Skeleton, SkeletonPose, SkinnedMeshRenderer2, StorageGPUBuffer, Time, Vector2, Vector3, Vector4, View3D, makeMatrix44 } from "../.."; +import { PropertyAnimationClip } from "../../math/AnimationCurveClip"; +import { RegisterComponent } from "../../util/SerializeDecoration"; +import { ComponentBase } from "../ComponentBase"; + +@RegisterComponent +export class AnimatorComponent extends ComponentBase { + public jointMatrixIndexTableBuffer: StorageGPUBuffer; + public playBlendShapeLoop: boolean = false; + protected inverseBindMatrices: Float32Array[]; + protected _avatar: PrefabAvatarData; + protected _rendererList: SkinnedMeshRenderer2[]; + protected propertyCache: Map + + protected _clips: PropertyAnimationClip[]; + protected _clipsMap: Map; + protected _currentSkeletonClip: PropertyAnimationClip; + protected _currentBlendAnimClip: PropertyAnimationClip; + + private _skeletonTime: number = 0; + private _blendShapeTime: number = 0; + private _skeletonSpeed: number = 1; + private _blendShapeSpeed: number = 1; + private _skeletonStart: boolean = true; + private _blendShapeStart: boolean = true; + root: Object3D; + private _avatarName: string; + + public init(param?: any): void { + this.propertyCache = new Map(); + this._clipsMap = new Map(); + this._clips = []; + } + + public start(): void { + this._rendererList = this.object3D.getComponentsInChild(SkinnedMeshRenderer2); + } + + private debug() { + } + + playAnim(anim: string, time: number = 0, speed: number = 1) { + if (this._clipsMap.has(anim)) { + this._currentSkeletonClip = this._clipsMap.get(anim); + this._skeletonTime = time; + this._skeletonSpeed = speed; + this._skeletonStart = true; + } else { + console.warn(`not has anim ${anim}`); + } + } + + playBlendShape(shapeName: string, time: number = 0, speed: number = 1) { + if (this._clipsMap.has(shapeName)) { + this._currentBlendAnimClip = this._clipsMap.get(shapeName); + this._blendShapeTime = time; + this._blendShapeSpeed = speed; + this._blendShapeStart = true; + } else { + console.warn(`not has blendShape ${shapeName}`); + } + } + + public set avatar(name: string) { + this._avatarName = name; + this.inverseBindMatrices = []; + + this._avatar = Engine3D.res.getObj(name) as PrefabAvatarData; + + let jointMapping = this.buildSkeletonPose(); + const jointMatrixIndexTable = new Float32Array(jointMapping); + this.jointMatrixIndexTableBuffer = new StorageGPUBuffer(this._avatar.count, 0, jointMatrixIndexTable); + } + + public getJointIndexTable(skinJointsName: Array) { + let result = new Array(); + for (let i = 0; i < skinJointsName.length; i++) { + let joint = this._avatar.boneMap.get(skinJointsName[i]); + result[i] = joint ? joint.boneID : -1; + } + return result; + } + + private skeltonPoseObject3D: { [name: string]: Object3D } = {}; + private skeltonTPoseObject3D: { [name: string]: Object3D } = {}; + private buildSkeletonPose(): number[] { + let list = []; + for (const joint of this._avatar.boneData) { + let obj = new Object3D(); + + Matrix4.getEuler(Vector3.HELP_6, joint.q, true, 'ZYX'); + obj.localPosition = joint.t.clone(); + obj.localRotation = Vector3.HELP_6.clone(); + obj.localScale = Vector3.ONE; joint.s.clone(); + + this.skeltonPoseObject3D[joint.boneName] = obj; + this.skeltonTPoseObject3D[joint.bonePath] = obj.clone(); + + if (joint.parentBoneName && joint.parentBoneName != "") { + this.skeltonPoseObject3D[joint.parentBoneName].addChild(obj); + } else { + // this.object3D.addChild(obj); + if (this.object3D.transform.scene3D) { + this.object3D.transform.scene3D.addChild(obj); + } + this.root = obj; + } + + list.push(obj.transform.worldMatrix.index); + let local = new Matrix4(); + local.copyFrom(obj.transform.worldMatrix); + local.invert(); + this.inverseBindMatrices.push(local.rawData); + } + + // GUIHelp.endFolder(); + + return list; + } + + public set clips(clips: PropertyAnimationClip[]) { + this._clips = clips; + for (const clip of clips) { + this._clipsMap.set(clip.clipName, clip); + } + // this.playAnim(clips[0].clipName); + } + + public get clips(): PropertyAnimationClip[] { + return this._clips; + } + + public cloneTo(obj: Object3D): void { + let animatorComponent = obj.addComponent(AnimatorComponent); + animatorComponent.avatar = this._avatarName; + animatorComponent.clips = this._clips; + } + + private updateTime() { + if (this._skeletonStart) { + this._skeletonTime += Time.delta * 0.001 * this._skeletonSpeed; + if (this._currentSkeletonClip && this._currentSkeletonClip.loopTime) { + this._skeletonTime = this._skeletonTime % this._currentSkeletonClip.stopTime; + } + } + + if (this._blendShapeStart) { + this._blendShapeTime += Time.delta * 0.001 * this._blendShapeSpeed; + if (this._currentBlendAnimClip) { + if (this._currentBlendAnimClip.loopTime && this.playBlendShapeLoop) { + this._blendShapeTime = this._blendShapeTime % this._currentBlendAnimClip.stopTime; + } else { + this._blendShapeTime = Math.min(this._blendShapeTime, this._currentBlendAnimClip.stopTime) - 0.0001; + } + } + } + } + + public onUpdate(view?: View3D) { + let worldMatrix = this.transform.worldMatrix; + // this.root.x = -worldMatrix.position.x ; + // this.root.y = -worldMatrix.position.y ; + // this.root.z = -worldMatrix.position.z ; + + this.updateTime(); + this.updateSkeletonAnim(); + this.updateMorphAnim(); + } + + private updateSkeletonAnim() { + if (this._currentSkeletonClip) { + let joints = this._avatar.boneData; + let i = 0; + let len = joints.length; + for (i = 0; i < len; i++) { + const joint = joints[i]; + let obj = this.skeltonPoseObject3D[joint.boneName]; + + if (this._currentSkeletonClip.useSkeletonPos) { + let pos = this.getPosition(joint.bonePath, this._skeletonTime); + obj.transform.localPosition = pos; + } + + let rot = this.getRotation(joint.bonePath, this._skeletonTime); + obj.transform.localRotation = rot; + + if (this._currentSkeletonClip.useSkeletonScale) { + let scale = this.getScale(joint.bonePath, this._skeletonTime); + obj.transform.localScale = scale; + } + } + } + } + + private updateMorphAnim() { + if (this._currentBlendAnimClip && this._currentBlendAnimClip.floatCurves) { + if (this._currentBlendAnimClip.floatCurves.size > 0 && this._rendererList) { + for (const iterator of this._currentBlendAnimClip.floatCurves) { + let key = iterator[0]; + let curve = iterator[1]; + let attributes = curve.propertys; + + let x = this._currentBlendAnimClip.floatCurves.get(key).getValue(this._blendShapeTime) as number; + let value = x / 100; + for (const renderer of this._rendererList) { + if (renderer.blendShape) { + let property: any = this.propertyCache.get(renderer); + if (property && key in property) { + property[key](value); + } else { + property = renderer; + for (const att of attributes) { + if (!property[att]) + break; + property = property[att]; + } + if (!property || property == renderer) break; + + if (!this.propertyCache.get(renderer)) + this.propertyCache.set(renderer, {}) + this.propertyCache.get(renderer)[key] = property; + property(value); + } + } + } + } + } + } + } + + public updateBlendShape(attributes: string[], key: string, value: number) { + for (const renderer of this._rendererList) { + if (renderer.blendShape) { + let property: any = this.propertyCache.get(renderer); + if (property && key in property) { + property[key](value); + } else { + property = renderer; + for (const att of attributes) { + if (!property[att]) + break; + property = property[att]; + } + if (!property || property == renderer) break; + + if (!this.propertyCache.get(renderer)) + this.propertyCache.set(renderer, {}) + this.propertyCache.get(renderer)[key] = property; + property(value); + } + } + } + } + + private getPosition(boneName: string, time: number) { + if (this._currentSkeletonClip.positionCurves.has(boneName)) { + let t = this._currentSkeletonClip.positionCurves.get(boneName).getValue(time) as Vector3; + return t; + } + return this.skeltonTPoseObject3D[boneName].localPosition; + } + + private getRotation(boneName: string, time: number) { + if (this._currentSkeletonClip.rotationCurves.has(boneName)) { + let v4 = this._currentSkeletonClip.rotationCurves.get(boneName).getValue(time) as Vector4; + Quaternion.HELP_2.set(v4.x, v4.y, v4.z, v4.w); + Matrix4.getEuler(Vector3.HELP_6, Quaternion.HELP_2, true, 'ZYX'); + return Vector3.HELP_6; + } + return this.skeltonTPoseObject3D[boneName].localRotation; + } + + private getScale(boneName: string, time: number) { + if (this._currentSkeletonClip.scaleCurves.has(boneName)) { + let x = this._currentSkeletonClip.scaleCurves.get(boneName).getValue(time) as Vector3; + return x; + } + return this.skeltonTPoseObject3D[boneName].localScale; + } + + private getFloat(propertyName: string, time: number) { + let x = this._currentSkeletonClip.floatCurves.get(propertyName).getValue(time) as number; + return x; + } +} \ No newline at end of file diff --git a/src/components/anim/morphAnim/MorphTargetBlender.ts b/src/components/anim/morphAnim/MorphTargetBlender.ts index 7e1af99a..ec0e05fd 100644 --- a/src/components/anim/morphAnim/MorphTargetBlender.ts +++ b/src/components/anim/morphAnim/MorphTargetBlender.ts @@ -5,17 +5,22 @@ import { Quaternion } from "../../../math/Quaternion"; import { Vector3 } from "../../../math/Vector3"; import { ComponentBase } from "../../ComponentBase"; import { MorphTargetFrame } from "./MorphTargetFrame"; -import { MeshRenderer } from "../../renderer/MeshRenderer"; +import { SkinnedMeshRenderer2 } from "../../renderer/SkinnedMeshRenderer2"; import { RendererMask, RendererMaskUtil } from "../../../gfx/renderJob/passRenderer/state/RendererMask"; +import { Ctor } from "../../../util/Global"; +import { MeshRenderer } from "../../renderer/MeshRenderer"; export class MorphTargetBlender extends ComponentBase { - private _targetRenderers: { [key: string]: MeshRenderer[] } = {}; + private _targetRenderers: { [key: string]: SkinnedMeshRenderer2[] } = {}; private _vec3 = new Vector3(); private _matrix4: Matrix4 = new Matrix4(); private _quaternion: Quaternion = new Quaternion(); public init(param?: any): void { - let meshRenders: MeshRenderer[] = this.fetchMorphRenderers(this.object3D); + let meshRenders: SkinnedMeshRenderer2[] = this.fetchMorphRenderers(this.object3D, SkinnedMeshRenderer2); + let meshRenders2: MeshRenderer[] = this.fetchMorphRenderers(this.object3D, MeshRenderer); + meshRenders.push(...meshRenders2 as any); + for (const renderer of meshRenders) { let hasMorphTarget = RendererMaskUtil.hasMask(renderer.rendererMask, RendererMask.MorphTarget); if (hasMorphTarget) { @@ -30,11 +35,11 @@ export class MorphTargetBlender extends ComponentBase { } - public getMorphRenderersByKey(key: string): MeshRenderer[] { + public getMorphRenderersByKey(key: string): SkinnedMeshRenderer2[] { return this._targetRenderers[key]; } - public cloneMorphRenderers(): { [key: string]: MeshRenderer[] } { + public cloneMorphRenderers(): { [key: string]: SkinnedMeshRenderer2[] } { let dst = {} as any; for (let key in this._targetRenderers) { dst[key] = this._targetRenderers[key]; @@ -79,15 +84,15 @@ export class MorphTargetBlender extends ComponentBase { } } - private applyMorphTargetInfluence(key: string, influence: number, rendererList: MeshRenderer[]): void { + private applyMorphTargetInfluence(key: string, influence: number, rendererList: SkinnedMeshRenderer2[]): void { for (let renderer of rendererList) { renderer.setMorphInfluence(key, influence); } } - private fetchMorphRenderers(obj: Object3D): MeshRenderer[] { - let sourceRenders: MeshRenderer[] = obj.getComponentsInChild(MeshRenderer); - let result: MeshRenderer[] = []; + private fetchMorphRenderers(obj: Object3D, c: Ctor): T[] { + let sourceRenders: T[] = obj.getComponentsInChild(c); + let result: T[] = []; for (let renderer of sourceRenders) { if (renderer.hasMask(RendererMask.MorphTarget)) { result.push(renderer); diff --git a/src/components/anim/morphAnim/MorphTargetData.ts b/src/components/anim/morphAnim/MorphTargetData.ts index af274400..e82d4e8b 100644 --- a/src/components/anim/morphAnim/MorphTargetData.ts +++ b/src/components/anim/morphAnim/MorphTargetData.ts @@ -3,7 +3,7 @@ import { UniformGPUBuffer } from '../../../gfx/graphics/webGpu/core/buffer/Unifo import { MorphTarget_shader } from '../../../components/anim/morphAnim/MorphTarget_shader'; import { ComputeShader } from '../../../gfx/graphics/webGpu/shader/ComputeShader'; import { GPUContext } from '../../../gfx/renderJob/GPUContext'; -import { RenderShader } from '../../../gfx/graphics/webGpu/shader/RenderShader'; +import { RenderShaderPass } from '../../../gfx/graphics/webGpu/shader/RenderShaderPass'; import { GeometryBase } from '../../../core/geometry/GeometryBase'; import { VertexAttributeData } from '../../../core/geometry/VertexAttributeData'; @@ -67,6 +67,9 @@ export class MorphTargetData { protected _collectMorphTargetData: MorphTargetCollectData; + private _blendTarget: { [key: string]: any } + + constructor() { this._isInfluenceDirty = true; this.generateGPUBuffer(); @@ -97,7 +100,7 @@ export class MorphTargetData { this._normalAttrDataGroup.reset(this._collectMorphTargetData.mergedNormal); } - public applyRenderShader(renderShader: RenderShader) { + public applyRenderShader(renderShader: RenderShaderPass) { this.uploadMorphTargetBuffer(); this.uploadConfigGBuffer(); // @@ -125,7 +128,9 @@ export class MorphTargetData { this._computeShader.workerSizeY = this._computeWorkGroupXY; this._computeShader.workerSizeZ = 1; + // if (false) { GPUContext.computeCommand(command, this._computeShaders); + // } } public updateInfluence(index: number, value: number) { @@ -133,11 +138,25 @@ export class MorphTargetData { this._morphInfluenceArray[index] = value; } + public get blendShape() { + return this._blendTarget; + } + private collectMorphTargetList(geometry: GeometryBase): MorphTargetCollectData { let posAttrList = this.collectAttribute('a_morphPositions_', geometry); let morphTargetCount = posAttrList.length; let vertexCount: number = posAttrList[0].data.length / 3; + this._blendTarget = {}; + if (geometry.blendShapeData) { + for (let i = 0; i < geometry.blendShapeData.shapeIndexs.length; i++) { + let index = geometry.blendShapeData.shapeIndexs[i]; + let shapeNames = geometry.blendShapeData.shapeNames[i].split("."); + let shapeName = shapeNames[shapeNames.length - 1]; + this._blendTarget[shapeName] = (value) => this.updateInfluence(index, value); + } + } + //position let posArray: Float32Array = new Float32Array(vertexCount * morphTargetCount * 3); { diff --git a/src/components/anim/morphAnim/MorphTargetKey.ts b/src/components/anim/morphAnim/MorphTargetKey.ts index 25807687..fcc9443c 100644 --- a/src/components/anim/morphAnim/MorphTargetKey.ts +++ b/src/components/anim/morphAnim/MorphTargetKey.ts @@ -52,3 +52,58 @@ export type MorphTargetStandardKey = 'cheekPuff' | 'mouthPress_R' | 'mouthSmile_R'; + +export enum MorphTargetTransformKey { + 'mouthRollLower' = "mouthRollLower", + 'browOuterUp_L' = "browOuterUpLeft", + 'mouthSmile_L' = "mouthSmileLeft", + 'jawRight' = "jawRight", + 'eyeLookOut_L' = "eyeLookOutLeft", + 'mouthFunnel' = "mouthFunnel", + 'mouthUpperUp_R' = "mouthUpperUpRight", + 'browDown_L' = "browDownLeft", + 'jawLeft' = "jawLeft", + 'mouthLowerDown_L' = "mouthLowerDownLeft", + 'noseSneer_R' = "noseSneerRight", + 'jawForward' = "jawForward", + 'mouthLowerDown_R' = "mouthLowerDownRight", + 'browInnerUp' = "browInnerUp", + 'mouthRollUpper' = "mouthRollUpper", + 'mouthStretch_R' = "mouthStretchRight", + 'mouthPucker' = "mouthPucker", + 'eyeBlink_L' = "eyeBlinkLeft", + 'mouthUpperUp_L' = "mouthUpperUpLeft", + 'mouthShrugUpper' = "mouthShrugUpper", + 'eyeLookIn_R' = "eyeLookInRight", + 'noseSneer_L' = "noseSneerLeft", + 'mouthFrown_L' = "mouthFrownLeft", + 'cheekSquint_L' = "cheekSquintLeft", + 'eyeLookDown_L' = "eyeLookDownLeft", + 'mouthDimple_L' = "mouthDimpleLeft", + 'mouthFrown_R' = "mouthFrownRight", + 'eyeLookIn_L' = "eyeLookInLeft", + 'eyeLookOut_R' = "eyeLookOutRight", + 'mouthLeft' = "mouthLeft", + 'mouthStretch_L' = "mouthStretchLeft", + 'mouthPress_L' = "mouthPressLeft", + 'mouthDimple_R' = "mouthDimpleRight", + 'eyeWide_R' = "eyeWideRight", + 'browDown_R' = "browDownRight", + 'eyeLookUp_R' = "eyeLookUpRight", + 'eyeBlink_R' = "eyeBlinkRight", + 'cheekSquint_R' = "cheekSquintRight", + 'mouthRight' = "mouthDimpleRight", + 'eyeLookDown_R' = "eyeLookDownRight", + 'eyeLookUp_L' = "eyeLookUpLeft", + 'eyeSquint_L' = "eyeSquintLeft", + 'jawOpen' = "jawOpen", + 'browOuterUp_R' = "browOuterUpRight", + 'mouthClose' = "mouthClose", + 'mouthShrugLower' = "mouthShrugLower", + 'eyeWide_L' = "eyeWideLeft", + 'tongueOut' = "tongueOut", + 'eyeSquint_R' = "eyeSquintRight", + 'cheekPuff' = "cheekPuff", + 'mouthPress_R' = "mouthPressRight", + 'mouthSmile_R' = "mouthSmileRight", +} \ No newline at end of file diff --git a/src/components/anim/skeletonAnim/Joint.ts b/src/components/anim/skeletonAnim/Joint.ts index 4a08a0af..170da8fc 100644 --- a/src/components/anim/skeletonAnim/Joint.ts +++ b/src/components/anim/skeletonAnim/Joint.ts @@ -17,6 +17,11 @@ export class Joint { */ public index: number = 0; + /** + * Bone instanceID + */ + public instanceID: string = ""; + /** * The parent of a bone joint */ @@ -25,7 +30,7 @@ export class Joint { /** * Bone joint child object */ - public children: Array = []; + // public children: Array = []; /** * The scaling value of the bone joint diff --git a/src/components/anim/skeletonAnim/SkeletonPose.ts b/src/components/anim/skeletonAnim/SkeletonPose.ts index f398a292..f439e690 100644 --- a/src/components/anim/skeletonAnim/SkeletonPose.ts +++ b/src/components/anim/skeletonAnim/SkeletonPose.ts @@ -10,109 +10,117 @@ import { Skeleton } from './Skeleton'; * @group Animation */ export class SkeletonPose { - /** - * time of this pose in owner animation clip - */ - public time: number; - protected _skeleton: Skeleton; - protected _jointsPose: Array; - protected mJointMatrixIndexTable: Array; + /** + * time of this pose in owner animation clip + */ + public time: number; + protected _skeleton: Skeleton; + protected _jointsPose: Array; + protected mJointMatrixIndexTable: Array; - constructor(skeleton: Skeleton, useGlobalMatrix: boolean = false) { - this._skeleton = skeleton; - this._jointsPose = new Array(skeleton.numJoint); - this.mJointMatrixIndexTable = new Array(skeleton.numJoint); - for (let index = 0; index < skeleton.numJoint; index++) { - let joint = new JointPose(index, useGlobalMatrix); - this._jointsPose[index] = joint; - this.mJointMatrixIndexTable[index] = joint.worldMatrix.index; + constructor(skeleton: Skeleton, useGlobalMatrix: boolean = false) { + this._skeleton = skeleton; + this._jointsPose = new Array(skeleton.numJoint); + this.mJointMatrixIndexTable = new Array(skeleton.numJoint); + for (let index = 0; index < skeleton.numJoint; index++) { + let joint = new JointPose(index, useGlobalMatrix); + this._jointsPose[index] = joint; + this.mJointMatrixIndexTable[index] = joint.worldMatrix.index; + } } - } - /** - * build this pose from float32 array data - */ - public buildSkeletonPose(poseData: Float32Array) { - let scale = new Vector3(); - let rotation = new Quaternion(); - let translation = new Vector3(); - let jointLocalMatrix = new Array(this._skeleton.numJoint); - this.time = poseData[11] > 0 ? poseData[11] : poseData[24]; - for (let jointIndex = 0; jointIndex < this._skeleton.numJoint; jointIndex++) { - let byteOffset = 12 * jointIndex * 4; - let jointData = new Float32Array(poseData.buffer, poseData.byteOffset + byteOffset, 12); + /** + * build this pose from float32 array data + */ + public buildSkeletonPose(poseData: Float32Array) { + let scale = new Vector3(); + let rotation = new Quaternion(); + let translation = new Vector3(); + let jointLocalMatrix = new Array(this._skeleton.numJoint); + this.time = poseData[11] > 0 ? poseData[11] : poseData[24]; + for (let jointIndex = 0; jointIndex < this._skeleton.numJoint; jointIndex++) { + let byteOffset = 12 * jointIndex * 4; + let jointData = new Float32Array(poseData.buffer, poseData.byteOffset + byteOffset, 12); - let localMatrix = new Matrix4(); - scale.set(jointData[0], jointData[1], jointData[2]); - rotation.set(jointData[4], jointData[5], jointData[6], jointData[7]); - translation.set(jointData[8], jointData[9], jointData[10]); - makeMatrix44(rotation.getEulerAngles(), translation, scale, localMatrix); - jointLocalMatrix[jointIndex] = localMatrix; + let localMatrix = new Matrix4(); + scale.set(jointData[0], jointData[1], jointData[2]); + rotation.set(jointData[4], jointData[5], jointData[6], jointData[7]); + translation.set(jointData[8], jointData[9], jointData[10]); + makeMatrix44(rotation.getEulerAngles(), translation, scale, localMatrix); + jointLocalMatrix[jointIndex] = localMatrix; - let joint = new JointPose(jointIndex); - const nParentIndex = this._skeleton.getJointParentIndex(jointIndex); - if (nParentIndex < 0) { - joint.worldMatrix.copyFrom(localMatrix); - } else { - let parentJoint = this._jointsPose[nParentIndex]; - multiplyMatrices4x4REF(parentJoint.worldMatrix, localMatrix, joint.worldMatrix); - } - this._jointsPose[jointIndex] = joint; + let joint = new JointPose(jointIndex); + const nParentIndex = this._skeleton.getJointParentIndex(jointIndex); + if (nParentIndex < 0) { + joint.worldMatrix.copyFrom(localMatrix); + } else { + let parentJoint = this._jointsPose[nParentIndex]; + multiplyMatrices4x4REF(parentJoint.worldMatrix, localMatrix, joint.worldMatrix); + } + this._jointsPose[jointIndex] = joint; + } } - } - /** - * Returns joints count of owner skeleton - */ - public get numJoint(): number { - return this._skeleton.numJoint; - } + /** + * Returns joints count of owner skeleton + */ + public get numJoint(): number { + return this._skeleton.numJoint; + } - /** - * Returns all joint pose - */ - public get joints(): Array { - return this._jointsPose; - } + /** + * Returns all joint pose + */ + public get joints(): Array { + return this._jointsPose; + } - /** - * Returns list of matrix's index - */ - public get jointMatrixIndexTable(): Array { - return this.mJointMatrixIndexTable; - } + /** + * Returns list of matrix's index + */ + public get jointMatrixIndexTable(): Array { + return this.mJointMatrixIndexTable; + } - /** - * Returns lerped skeletonPose from pose a to pose b - * @param a selected pose No.1 - * @param b selected pose No.2 - * @param weight number - */ - public lerp(a: SkeletonPose, b: SkeletonPose, weight: number) { - for (let index = 0; index < this._jointsPose.length; index++) { - let jointA = a._jointsPose[index]; - let jointB = b._jointsPose[index]; - let jointDst = this._jointsPose[index]; - jointDst.worldMatrix.lerp(jointA.worldMatrix, jointB.worldMatrix, weight); + /** + * Returns lerped skeletonPose from pose a to pose b + * @param a selected pose No.1 + * @param b selected pose No.2 + * @param weight number + */ + public lerp(a: SkeletonPose, b: SkeletonPose, weight: number) { + if (a && b) { + for (let index = 0; index < this._jointsPose.length; index++) { + let jointA = a._jointsPose[index]; + let jointB = b._jointsPose[index]; + let jointDst = this._jointsPose[index]; + jointDst.worldMatrix.lerp(jointA.worldMatrix, jointB.worldMatrix, weight); + } + } else { + for (let index = 0; index < this._jointsPose.length; index++) { + let jointA = a._jointsPose[index]; + let jointDst = this._jointsPose[index]; + jointDst.worldMatrix.copyFrom(jointA.worldMatrix); + } + } } - } - /** - * Copy skeleton pose from other skeleton pose - * @param other source skeleton pose - */ - public copyFrom(other: SkeletonPose) { - for (let index = 0; index < this._jointsPose.length; index++) { - this._jointsPose[index].worldMatrix.copyFrom(other._jointsPose[index].worldMatrix) + /** + * Copy skeleton pose from other skeleton pose + * @param other source skeleton pose + */ + public copyFrom(other: SkeletonPose) { + for (let index = 0; index < this._jointsPose.length; index++) { + this._jointsPose[index].worldMatrix.copyFrom(other._jointsPose[index].worldMatrix) + } } - } - /** - * Reset this skeleton pose - */ - public reset() { - for (let index = 0; index < this._jointsPose.length; index++) { - this._jointsPose[index].worldMatrix.identity(); + /** + * Reset this skeleton pose + */ + public reset() { + for (let index = 0; index < this._jointsPose.length; index++) { + this._jointsPose[index].worldMatrix.identity(); + } } - } } diff --git a/src/components/controller/HoverCameraController.ts b/src/components/controller/HoverCameraController.ts index cae7ab7d..468a972c 100644 --- a/src/components/controller/HoverCameraController.ts +++ b/src/components/controller/HoverCameraController.ts @@ -96,6 +96,8 @@ export class HoverCameraController extends ComponentBase { * @internal */ private _targetPos: Object3D; + private _flowTarget: Object3D; + private _flowOffset: Vector3; private _mouseLeftDown: boolean = false; private _mouseRightDown: boolean = false; @@ -122,7 +124,16 @@ export class HoverCameraController extends ComponentBase { Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_MOVE, this.onMouseMove, this); Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_UP, this.onMouseUp, this); Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_WHEEL, this.onMouseWheel, this); + } + + public flowTarget(target: Object3D, offset: Vector3 = Vector3.ZERO) { + this._flowTarget = target; + this._flowOffset ||= new Vector3(); + this._flowOffset.copyFrom(offset); + } + public getFlowTarget(): Object3D { + return this._flowTarget; } /** @@ -227,6 +238,12 @@ export class HoverCameraController extends ComponentBase { if (!this.enable) return; + if (this._flowTarget) { + Vector3.HELP_0.copyFrom(this._flowTarget.transform.worldPosition); + Vector3.HELP_0.add(this._flowOffset, Vector3.HELP_0); + this.target = Vector3.HELP_0; + } + let dt = clamp(Time.delta, 0.0, 0.016); if (this.smooth) { this._currentPos.x += (this._targetPos.x - this._currentPos.x) * dt * this.dragSmooth; @@ -271,5 +288,6 @@ export class HoverCameraController extends ComponentBase { Engine3D.inputSystem.removeEventListener(PointerEvent3D.POINTER_WHEEL, this.onMouseWheel, this); super.destroy(force); this.camera = null; + this._flowTarget = null; } } diff --git a/src/components/gui/core/GUIGeometry.ts b/src/components/gui/core/GUIGeometry.ts index 0fbcf71d..f8bec48a 100644 --- a/src/components/gui/core/GUIGeometry.ts +++ b/src/components/gui/core/GUIGeometry.ts @@ -124,7 +124,10 @@ export class GUIGeometry extends GeometryBase { indexStart: 0, indexCount: this._faceIndexes.length, vertexStart: 0, + vertexCount: 0, + firstStart: 0, index: 0, + topology: 0, }); return this; } diff --git a/src/components/gui/core/GUIMaterial.ts b/src/components/gui/core/GUIMaterial.ts index 10e20c2c..ecf81945 100644 --- a/src/components/gui/core/GUIMaterial.ts +++ b/src/components/gui/core/GUIMaterial.ts @@ -1,12 +1,11 @@ -import { RendererType } from "../../.."; +import { PassType, Shader } from "../../.."; import { Engine3D } from "../../../Engine3D"; import { ShaderLib } from "../../../assets/shader/ShaderLib"; import { GPUCompareFunction, GPUCullMode } from "../../../gfx/graphics/webGpu/WebGPUConst"; import { Texture } from "../../../gfx/graphics/webGpu/core/texture/Texture"; -import { RenderShader } from "../../../gfx/graphics/webGpu/shader/RenderShader"; +import { RenderShaderPass } from "../../../gfx/graphics/webGpu/shader/RenderShaderPass"; import { BlendMode } from "../../../materials/BlendMode"; import { Material } from "../../../materials/Material"; -import { registerMaterial } from "../../../materials/MaterialRegister"; import { Vector2 } from "../../../math/Vector2"; import { Vector4 } from "../../../math/Vector4"; import { GUISpace } from "../GUIConfig"; @@ -26,8 +25,11 @@ export class GUIMaterial extends Material { ShaderLib.register('GUI_shader_view', GUIShader.GUI_shader_view); ShaderLib.register('GUI_shader_world', GUIShader.GUI_shader_world); + let newShader = new Shader(); + let shaderKey: string = space == GUISpace.View ? 'GUI_shader_view' : 'GUI_shader_world'; - let colorPass = new RenderShader(shaderKey, shaderKey); + let colorPass = new RenderShaderPass(shaderKey, shaderKey); + colorPass.passType = PassType.COLOR; colorPass.setShaderEntry(`VertMain`, `FragMain`); colorPass.setUniformVector2('screenSize', this._screenSize); @@ -44,47 +46,46 @@ export class GUIMaterial extends Material { colorPass.blendMode = BlendMode.ALPHA; colorPass.depthCompare = space == GUISpace.View ? GPUCompareFunction.always : GPUCompareFunction.less_equal; colorPass.cullMode = GPUCullMode.back; - + newShader.addRenderPass(colorPass); // colorPass.transparent = true; // colorPass.receiveEnv = false; - this.defaultPass = colorPass; - + this.shader = newShader; } /** * Write effective vertex count (vertex index < vertexCount) */ public setLimitVertex(vertexCount: number) { - this.defaultPass.setUniformFloat('limitVertex', vertexCount); + this.shader.setUniformFloat('limitVertex', vertexCount); } public setGUISolution(value: Vector2, pixelRatio: number) { - this.defaultPass.setUniformVector2('guiSolution', value); - this.defaultPass.setUniformFloat('pixelRatio', pixelRatio); + this.shader.setUniformVector2('guiSolution', value); + this.shader.setUniformFloat('pixelRatio', pixelRatio); } public setScissorRect(left: number, bottom: number, right: number, top: number) { this._scissorRect ||= new Vector4(); this._scissorRect.set(left, bottom, right, top); - this.defaultPass.setUniformVector4('scissorRect', this._scissorRect); + this.shader.setUniformVector4('scissorRect', this._scissorRect); } public setScissorEnable(value: boolean) { if (this._scissorEnable != value) { this._scissorEnable = value; if (value) { - this.defaultPass.setDefine("SCISSOR_ENABLE", true); + this.shader.setDefine("SCISSOR_ENABLE", true); } else { - this.defaultPass.deleteDefine('SCISSOR_ENABLE'); + this.shader.deleteDefine('SCISSOR_ENABLE'); } - this.defaultPass.noticeValueChange(); + this.shader.noticeValueChange(); } } public setScissorCorner(radius: number, fadeOut: number) { - this.defaultPass.setUniformFloat('scissorCornerRadius', radius); - this.defaultPass.setUniformFloat('scissorFadeOutSize', fadeOut); + this.shader.setUniformFloat('scissorCornerRadius', radius); + this.shader.setUniformFloat('scissorFadeOutSize', fadeOut); } /** @@ -92,7 +93,7 @@ export class GUIMaterial extends Material { */ public setScreenSize(width: number, height: number): this { this._screenSize.set(width, height); - this.defaultPass.setUniformVector2('screenSize', this._screenSize); + this.shader.setUniformVector2('screenSize', this._screenSize); return this; } @@ -102,7 +103,7 @@ export class GUIMaterial extends Material { public setTextures(list: Texture[]) { for (let i = 0; i < 7; i++) { let texture = list[i] || Engine3D.res.whiteTexture; - this.defaultPass.setTexture(`tex_${i}`, texture); + this.shader.setTexture(`tex_${i}`, texture); this.setVideoTextureDefine(i, texture.isVideoTexture); } } @@ -112,16 +113,16 @@ export class GUIMaterial extends Material { let changed = false; if (isVideoTexture != this._videoTextureFlags[i]) { if (isVideoTexture) { - this.defaultPass.setDefine(`VideoTexture${i}`, true); + this.shader.setDefine(`VideoTexture${i}`, true); } else { - this.defaultPass.deleteDefine(`VideoTexture${i}`); + this.shader.deleteDefine(`VideoTexture${i}`); } this._videoTextureFlags[i] = isVideoTexture; changed = true; } if (changed) { - this.defaultPass.noticeValueChange(); + this.shader.noticeValueChange(); } } diff --git a/src/components/gui/core/GUIRenderer.ts b/src/components/gui/core/GUIRenderer.ts index fa7af163..b53c5ca0 100644 --- a/src/components/gui/core/GUIRenderer.ts +++ b/src/components/gui/core/GUIRenderer.ts @@ -3,7 +3,7 @@ import { View3D } from "../../../core/View3D"; import { ClusterLightingBuffer } from "../../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer"; import { RendererMask } from "../../../gfx/renderJob/passRenderer/state/RendererMask"; import { RendererPassState } from "../../../gfx/renderJob/passRenderer/state/RendererPassState"; -import { RendererType } from "../../../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../../../gfx/renderJob/passRenderer/state/RendererType"; import { MeshRenderer } from "../../renderer/MeshRenderer"; import { GUIGeometry } from "./GUIGeometry"; @@ -48,7 +48,7 @@ export class GUIRenderer extends MeshRenderer { * @param renderPassState * @param clusterLightingBuffer */ - public nodeUpdate(view: View3D, rendererType: RendererType, renderPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer) { + public nodeUpdate(view: View3D, rendererType: PassType, renderPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer) { for (let i = 0; i < this.materials.length; i++) { const material = this.materials[i]; let passes = material.getPass(rendererType); diff --git a/src/components/lights/DirectLight.ts b/src/components/lights/DirectLight.ts index d81c6ad2..848cb8e2 100644 --- a/src/components/lights/DirectLight.ts +++ b/src/components/lights/DirectLight.ts @@ -1,5 +1,6 @@ import { Camera3D } from '../../core/Camera3D'; import { UUID } from '../../util/Global'; +import { RegisterComponent } from '../../util/SerializeDecoration'; import { LightBase } from './LightBase'; import { LightType } from './LightData'; /** @@ -8,6 +9,7 @@ import { LightType } from './LightData'; *The light of this light source is parallel, for example, sunlight. This light source can generate shadows. * @group Lights */ +@RegisterComponent export class DirectLight extends LightBase { public shadowCamera: Camera3D; diff --git a/src/components/lights/Light.ts b/src/components/lights/Light.ts new file mode 100644 index 00000000..f1d1c1e4 --- /dev/null +++ b/src/components/lights/Light.ts @@ -0,0 +1,141 @@ +import { RegisterComponent } from '../..'; +import { Engine3D } from '../../Engine3D'; +import { View3D } from '../../core/View3D'; +import { Vector3 } from '../../math/Vector3'; +import { UUID } from '../../util/Global'; +import { LightBase } from './LightBase'; +import { LightType } from './LightData'; +/** + *Point light source. + *A single point light source that illuminates all directions. + *A common example is to simulate the light emitted by a light bulb, where a point light source cannot create shadows. + * @group Lights + */ +@RegisterComponent +export class Light extends LightBase { + + constructor() { + super(); + } + + public init(): void { + super.init(); + this.lightData.lightType = LightType.PointLight; + if (this.object3D.name == "") { + this.object3D.name = "PointLight" + UUID(); + } + } + + + /** + * + * Get the range of the light source + * @return {number} + */ + public get range(): number { + return this.lightData.range as number; + } + /** + * + * Set the range of the light source + * @param {number} + */ + public set range(value: number) { + this.lightData.range = value; + this.onChange(); + } + + /** + * + * Get the illumination distance of the light source + * @type {number} + * @memberof PointLight + */ + public get at(): number { + return this.lightData.linear as number; + } + + /** + * + * Set the illumination distance of the light source + * @param {value} It will decay linearly from the maximum value to the current light position at a distance of 0, + * with a default value of 0. This means that the intensity of the light will not decrease due to distance + * @memberof PointLight + */ + public set at(value: number) { + this.lightData.linear = value; + this.onChange(); + } + + /** + * Get the radius to control the light + */ + public get radius(): number { + return this.lightData.radius as number; + } + + /** + * Set the radius of the control light + */ + public set radius(value: number) { + this.lightData.radius = value; + this.onChange(); + } + + /** + * Get the radius to control the light + */ + public get quadratic(): number { + return this.lightData.quadratic as number; + } + + /** + * Set the radius of the control light + */ + public set quadratic(value: number) { + this.lightData.quadratic = value; + this.onChange(); + } + + + + public start(): void { + this.transform.rotationX = 90; + super.start(); + } + + public onUpdate(): void { + // this.transform.updateWorldMatrix(true); + } + + public onGraphic(view?: View3D): void { + let custom = view.graphic3D.createCustomShape( + `PointLight_${this.object3D.instanceID}`, + this.transform, + ); + custom.buildAxis(); + custom.buildCircle(Vector3.ZERO, this.range, 32, Vector3.X_AXIS); + custom.buildCircle(Vector3.ZERO, this.range, 32, Vector3.Y_AXIS); + custom.buildCircle(Vector3.ZERO, this.range, 32, Vector3.Z_AXIS); + } + + /** + * enable GUI debug + */ + public debug() { + } + + public debugDraw(show: boolean) { + // if (this.mShowDebugLine != show) { + // if (show) { + // this.drawDebugLine(); + // } else { + // let view = this.transform.view3D; + // view.graphic3D.Clear(`PointLight_${this.object3D.uuid}`); + // } + // this.mShowDebugLine = show; + // } + } + +} + diff --git a/src/components/lights/LightBase.ts b/src/components/lights/LightBase.ts index a5d942e1..48bc4f25 100644 --- a/src/components/lights/LightBase.ts +++ b/src/components/lights/LightBase.ts @@ -183,6 +183,24 @@ export class LightBase extends ComponentBase implements ILight { this.lightData.lightColor = value; this.onChange(); } + + /** + * Get light source color + * @return Color + */ + public get color(): Color { + return this.lightData.lightColor; + } + + /** + * Set light source color + * @param Color + */ + public set color(value: Color) { + this.lightData.lightColor = value; + this.onChange(); + } + /** * Get Illumination intensity of light source * @return number @@ -190,6 +208,7 @@ export class LightBase extends ComponentBase implements ILight { public get intensity(): number { return this.lightData.intensity as number; } + /** * Set Illumination intensity of light source * @param value diff --git a/src/components/lights/PointLight.ts b/src/components/lights/PointLight.ts index f6fd1f31..5e3cfe81 100644 --- a/src/components/lights/PointLight.ts +++ b/src/components/lights/PointLight.ts @@ -1,7 +1,7 @@ -import { Engine3D } from '../../Engine3D'; import { View3D } from '../../core/View3D'; import { Vector3 } from '../../math/Vector3'; import { UUID } from '../../util/Global'; +import { RegisterComponent } from '../../util/SerializeDecoration'; import { LightBase } from './LightBase'; import { LightType } from './LightData'; /** @@ -10,6 +10,7 @@ import { LightType } from './LightData'; *A common example is to simulate the light emitted by a light bulb, where a point light source cannot create shadows. * @group Lights */ +@RegisterComponent export class PointLight extends LightBase { constructor() { diff --git a/src/components/lights/SpotLight.ts b/src/components/lights/SpotLight.ts index 9f688031..a8060dc2 100644 --- a/src/components/lights/SpotLight.ts +++ b/src/components/lights/SpotLight.ts @@ -3,6 +3,7 @@ import { View3D } from '../../core/View3D'; import { clamp, DEGREES_TO_RADIANS, RADIANS_TO_DEGREES } from '../../math/MathUtil'; import { Vector3 } from '../../math/Vector3'; import { UUID } from '../../util/Global'; +import { RegisterComponent } from '../../util/SerializeDecoration'; import { LightBase } from './LightBase'; import { LightType } from './LightData'; @@ -12,6 +13,7 @@ import { LightType } from './LightData'; * Similar to a desk lamp, chandelier, or flashlight, this light source can produce shadows. * @group Lights */ +@RegisterComponent export class SpotLight extends LightBase { constructor() { super(); diff --git a/src/components/post/PostProcessingComponent.ts b/src/components/post/PostProcessingComponent.ts index 21c716e1..adc63477 100644 --- a/src/components/post/PostProcessingComponent.ts +++ b/src/components/post/PostProcessingComponent.ts @@ -1,3 +1,4 @@ +import { FXAAPost, webGPUContext } from "../.."; import { Engine3D } from "../../Engine3D"; import { PostBase } from "../../gfx/renderJob/post/PostBase"; import { Ctor } from "../../util/Global"; @@ -5,6 +6,8 @@ import { ComponentBase } from "../ComponentBase"; export class PostProcessingComponent extends ComponentBase { private _postList: Map; + + public init(param?: any): void { this._postList = new Map(); } @@ -26,6 +29,7 @@ export class PostProcessingComponent extends ComponentBase { } private activePost() { + webGPUContext.canResize = false; let view = this.transform.view3D; let job = Engine3D.getRenderJob(view); this._postList.forEach((v) => { @@ -34,6 +38,7 @@ export class PostProcessingComponent extends ComponentBase { } private unActivePost() { + webGPUContext.canResize = true; let view = this.transform.view3D; let job = Engine3D.getRenderJob(view); this._postList.forEach((v) => { @@ -42,20 +47,27 @@ export class PostProcessingComponent extends ComponentBase { } public addPost(c: Ctor): T { - if (this._postList.has(c.prototype)) return; + if (this._postList.has(c.name)) return; + if (!this._postList.has("FXAAPost")) { + let post = new FXAAPost(); + this._postList.set(post.constructor.name, post); + if (this._enable) + this.activePost(); + if (c.name == "FXAAPost") { + return post as T; + } + } let post = new c(); - this._postList.set(c.prototype, post); + this._postList.set(c.name, post); if (this._enable) this.activePost(); - // post.onAttach(this.transform.view3D); - // Engine3D.getRenderJob(this.transform.view3D).addPost(post); return post; } public removePost(c: Ctor) { - if (!this._postList.has(c.prototype)) return; - let post = this._postList.get(c.prototype); - this._postList.delete(c.prototype); + if (!this._postList.has(c.name)) return; + let post = this._postList.get(c.name); + this._postList.delete(c.name); let view = this.transform.view3D; let job = Engine3D.getRenderJob(view); @@ -63,7 +75,7 @@ export class PostProcessingComponent extends ComponentBase { } public getPost(c: Ctor): T { - if (!this._postList.has(c.prototype)) return null; - return this._postList.get(c.prototype) as T; + if (!this._postList.has(c.name)) return null; + return this._postList.get(c.name) as T; } } \ No newline at end of file diff --git a/src/components/renderer/InstanceDrawComponent.ts b/src/components/renderer/InstanceDrawComponent.ts index 450acb5f..b34f005e 100644 --- a/src/components/renderer/InstanceDrawComponent.ts +++ b/src/components/renderer/InstanceDrawComponent.ts @@ -7,7 +7,7 @@ import { RenderNode } from "./RenderNode"; import { StorageGPUBuffer } from "../../gfx/graphics/webGpu/core/buffer/StorageGPUBuffer"; import { View3D } from "../../core/View3D"; import { RendererPassState } from "../../gfx/renderJob/passRenderer/state/RendererPassState"; -import { RendererType } from "../../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../../gfx/renderJob/passRenderer/state/RendererType"; import { ClusterLightingBuffer } from "../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer"; export class InstanceDrawComponent extends RenderNode { @@ -63,7 +63,7 @@ export class InstanceDrawComponent extends RenderNode { } - public nodeUpdate(view: View3D, passType: RendererType, renderPassState: RendererPassState, clusterLightingBuffer?: ClusterLightingBuffer): void { + public nodeUpdate(view: View3D, passType: PassType, renderPassState: RendererPassState, clusterLightingBuffer?: ClusterLightingBuffer): void { this._keyRenderGroup.forEach((v, k) => { let instanceMatrixBuffer = this._keyBufferGroup.get(k); let renderNode = v[0]; @@ -84,7 +84,7 @@ export class InstanceDrawComponent extends RenderNode { } - public renderPass(view: View3D, passType: RendererType, renderContext: RenderContext) { + public renderPass(view: View3D, passType: PassType, renderContext: RenderContext) { this._keyRenderGroup.forEach((v, k) => { let renderNode = v[0]; renderNode.instanceCount = v.length; @@ -92,7 +92,7 @@ export class InstanceDrawComponent extends RenderNode { }) } - public renderItem(view: View3D, passType: RendererType, renderNode: RenderNode, renderContext: RenderContext) { + public renderItem(view: View3D, passType: PassType, renderNode: RenderNode, renderContext: RenderContext) { let worldMatrix = renderNode.transform._worldMatrix; for (let i = 0; i < renderNode.materials.length; i++) { @@ -114,7 +114,7 @@ export class InstanceDrawComponent extends RenderNode { if (renderShader.shaderState.splitTexture) { renderContext.endRenderPass(); RTResourceMap.WriteSplitColorTexture(renderNode.instanceID); - renderContext.beginRenderPass(); + renderContext.beginOpaqueRenderPass(); GPUContext.bindCamera(renderContext.encoder, view.camera); GPUContext.bindGeometryBuffer(renderContext.encoder, renderNode.geometry); diff --git a/src/components/renderer/MeshFilter.ts b/src/components/renderer/MeshFilter.ts new file mode 100644 index 00000000..56e067af --- /dev/null +++ b/src/components/renderer/MeshFilter.ts @@ -0,0 +1,36 @@ +import { GeometryBase, Object3D } from '../..'; +import { Engine3D } from '../../Engine3D'; +import { RegisterComponent } from '../../util/SerializeDecoration'; +import { MeshRenderer } from './MeshRenderer'; + +/** + * The mesh renderer component is a component used to render the mesh + * @group Components + */ +@RegisterComponent +export class MeshFilter extends MeshRenderer { + constructor() { + super(); + } + + public get geometry(): GeometryBase { + return null; + } + public set geometry(value: GeometryBase) { + + } + + public cloneTo(obj: Object3D): void { + + } + + public set meshURL(value: string) { + let geometry = Engine3D.res.getGeometry(value); + if (geometry) { + this.geometry = geometry; + } else { + console.error("no geometry set", value); + } + // this.material = Engine3D.res.defaltMaterial; + } +} diff --git a/src/components/renderer/MeshRenderer.ts b/src/components/renderer/MeshRenderer.ts index 1779f617..b028fe6f 100644 --- a/src/components/renderer/MeshRenderer.ts +++ b/src/components/renderer/MeshRenderer.ts @@ -4,16 +4,17 @@ import { ClusterLightingBuffer } from '../../gfx/renderJob/passRenderer/cluster/ import { GeometryBase } from '../../core/geometry/GeometryBase'; import { RendererMask } from '../../gfx/renderJob/passRenderer/state/RendererMask'; import { RendererPassState } from '../../gfx/renderJob/passRenderer/state/RendererPassState'; -import { RendererType } from '../../gfx/renderJob/passRenderer/state/RendererType'; +import { PassType } from '../../gfx/renderJob/passRenderer/state/RendererType'; import { MorphTargetData } from '../anim/morphAnim/MorphTargetData'; import { RenderNode } from './RenderNode'; -import { EditorInspector } from '../../util/SerializeDecoration'; -import { Material } from '../..'; +import { EditorInspector, RegisterComponent } from '../../util/SerializeDecoration'; +import { Color, Material, mergeFunctions } from '../..'; /** * The mesh renderer component is a component used to render the mesh * @group Components */ +@RegisterComponent export class MeshRenderer extends RenderNode { /** * Enabling this option allows the grid to display any shadows cast on the grid. @@ -71,8 +72,17 @@ export class MeshRenderer extends RenderNode { } this.object3D.bound = this._geometry.bounds.clone(); - if (this._readyPipeline) { + if (!this._readyPipeline) { this.initPipeline(); + + if (this._computes && this._computes) { + this.onCompute = mergeFunctions(this.onCompute, () => { + for (let i = 0; i < this._computes.length; i++) { + const compute = this._computes[i]; + compute.onUpdate(); + } + }); + } } } @@ -124,7 +134,7 @@ export class MeshRenderer extends RenderNode { * @param clusterLightingRender * @param probes */ - public nodeUpdate(view: View3D, passType: RendererType, renderPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer) { + public nodeUpdate(view: View3D, passType: PassType, renderPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer) { if (this.morphData && this.morphData.enable) { for (let i = 0; i < this.materials.length; i++) { const material = this.materials[i]; @@ -143,4 +153,8 @@ export class MeshRenderer extends RenderNode { super.destroy(force); } + // public onGraphic(view?: View3D) { + // if (this._geometry) + // view.graphic3D.drawMeshWireframe(this._geometry.instanceID, this._geometry, this.transform, Color.COLOR_RED); + // } } diff --git a/src/components/renderer/RenderNode.ts b/src/components/renderer/RenderNode.ts index e4ff1797..8e7b519f 100644 --- a/src/components/renderer/RenderNode.ts +++ b/src/components/renderer/RenderNode.ts @@ -13,7 +13,7 @@ import { RenderContext } from "../../gfx/renderJob/passRenderer/RenderContext"; import { ClusterLightingBuffer } from "../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer"; import { RendererMask, RendererMaskUtil } from "../../gfx/renderJob/passRenderer/state/RendererMask"; import { RendererPassState } from "../../gfx/renderJob/passRenderer/state/RendererPassState"; -import { RendererType } from "../../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../../gfx/renderJob/passRenderer/state/RendererType"; import { GetCountInstanceID, UUID } from "../../util/Global"; import { Reference } from "../../util/Reference"; import { ComponentBase } from "../ComponentBase"; @@ -23,6 +23,7 @@ import { OctreeEntity } from "../../core/tree/octree/OctreeEntity"; import { Transform } from "../Transform"; import { Material } from "../../materials/Material"; import { RenderLayer } from "../../gfx/renderJob/config/RenderLayer"; +import { RenderShaderCompute, ComputeShader } from "../.."; /** @@ -51,7 +52,7 @@ export class RenderNode extends ComponentBase { protected _renderOrder: number = 0; public isRenderOrderChange?: boolean; public needSortOnCameraZ?: boolean; - private _octreeBinder: { octree: Octree, entity: OctreeEntity }; + protected _octreeBinder: { octree: Octree, entity: OctreeEntity }; public preInit: boolean = false; /** @@ -60,13 +61,16 @@ export class RenderNode extends ComponentBase { * The object is only visible when it has at least one common layer with the camera in use. * When using a ray projector, this attribute can also be used to filter out unwanted objects in ray intersection testing. */ - private _renderLayer: RenderLayer = RenderLayer.None; + protected _renderLayer: RenderLayer = RenderLayer.None; + protected _computes: RenderShaderCompute[]; public init() { this.renderOrder = 0; this.rendererMask = RendererMask.Default; this.instanceID = GetCountInstanceID().toString(); + + this._computes = []; } public attachSceneOctree(octree: Octree) { @@ -169,10 +173,15 @@ export class RenderNode extends ComponentBase { for (let i = 0; i < this._materials.length; i++) { let mat = this._materials[i]; Reference.getInstance().detached(mat, this) + if (mat.shader && mat.shader.computes) + this.removeComputes(mat.shader.computes); } + for (let i = 0; i < value.length; i++) { let mat = value[i]; Reference.getInstance().attached(mat, this) + if (mat.shader && mat.shader.computes) + this.addComputes(mat.shader.computes); } this._materials = value; @@ -181,7 +190,7 @@ export class RenderNode extends ComponentBase { for (let i = 0; i < value.length; i++) { const element = value[i]; - const passArray = element.getPass(RendererType.COLOR); + const passArray = element.getPass(PassType.COLOR); const pass = passArray[0]; if (pass.shaderState.transparent) { transparent = true; @@ -196,7 +205,18 @@ export class RenderNode extends ComponentBase { } } + private addComputes(computes: RenderShaderCompute[]) { + this._computes.push(...computes); + } + private removeComputes(computes: RenderShaderCompute[]) { + for (const com of computes) { + let index = this._computes.indexOf(com); + if (index != -1) { + this._computes.splice(index, 1); + } + } + } public addRendererMask(tag: RendererMask) { this._rendererMask = RendererMaskUtil.addMask(this._rendererMask, tag); @@ -210,7 +230,9 @@ export class RenderNode extends ComponentBase { if (!this._readyPipeline) { this.initPipeline(); } + EntityCollect.instance.addRenderNode(this.transform.scene3D, this); + this.updateOctreeEntity(); } @@ -236,7 +258,7 @@ export class RenderNode extends ComponentBase { let index = 0; for (let j = 0; j < this._materials.length; j++) { const material = this._materials[j]; - let passList = material.getPass(RendererType.COLOR); + let passList = material.getPass(PassType.COLOR); for (let i = 0; i < passList.length; i++) { const pass = passList[i]; // let shader = RenderShader.getShader(pass.instanceID); @@ -253,7 +275,7 @@ export class RenderNode extends ComponentBase { let sort = 0; for (let i = 0; i < this.materials.length; i++) { const element = this.materials[i]; - const passArray = element.getPass(RendererType.COLOR); + const passArray = element.getPass(PassType.COLOR); const pass = passArray[0]; if (pass.renderOrder >= 3000) { sort = sort > pass.renderOrder ? sort : pass.renderOrder; @@ -275,7 +297,7 @@ export class RenderNode extends ComponentBase { if (this.castGI) { for (let i = 0; i < this.materials.length; i++) { const mat = this.materials[i]; - PassGenerate.createGIPass(this, mat); + PassGenerate.createGIPass(this, mat.shader); } } @@ -283,7 +305,7 @@ export class RenderNode extends ComponentBase { for (let i = 0; i < this.materials.length; i++) { const mat = this.materials[i]; if (mat.castShadow) { - PassGenerate.createShadowPass(this, mat); + PassGenerate.createShadowPass(this, mat.shader); } } // } @@ -292,7 +314,7 @@ export class RenderNode extends ComponentBase { for (let i = 0; i < this.materials.length; i++) { const mat = this.materials[i]; if (mat.castShadow) { - PassGenerate.createShadowPass(this, mat); + PassGenerate.createShadowPass(this, mat.shader); } } } @@ -302,12 +324,12 @@ export class RenderNode extends ComponentBase { if (!ignoreDepthPass && Engine3D.setting.render.zPrePass) { for (let i = 0; i < this.materials.length; i++) { const mat = this.materials[i]; - PassGenerate.createDepthPass(this, mat); + PassGenerate.createDepthPass(this, mat.shader); } } else { for (let i = 0; i < this.materials.length; i++) { const mat = this.materials[i]; - mat.removePass(RendererType.DEPTH, 0); + mat.shader.removeShaderByIndex(PassType.DEPTH, 0); } } } @@ -340,7 +362,7 @@ export class RenderNode extends ComponentBase { this._castReflection = value; } - public renderPass(view: View3D, passType: RendererType, renderContext: RenderContext) { + public renderPass(view: View3D, passType: PassType, renderContext: RenderContext) { let renderNode = this; let worldMatrix = renderNode.transform._worldMatrix; for (let i = 0; i < renderNode.materials.length; i++) { @@ -368,22 +390,23 @@ export class RenderNode extends ComponentBase { if (renderShader.shaderState.splitTexture) { renderContext.endRenderPass(); RTResourceMap.WriteSplitColorTexture(renderNode.instanceID); - renderContext.beginRenderPass(); + renderContext.beginOpaqueRenderPass(); GPUContext.bindCamera(renderContext.encoder, view.camera); GPUContext.bindGeometryBuffer(renderContext.encoder, renderNode._geometry); } GPUContext.bindPipeline(renderContext.encoder, renderShader); let subGeometries = renderNode._geometry.subGeometries; - // for (let k = 0; k < subGeometries.length; k++) { - const subGeometry = subGeometries[i]; - let lodInfos = subGeometry.lodLevels; - let lodInfo = lodInfos[renderNode.lodLevel]; - - if (renderNode.instanceCount > 0) { - GPUContext.drawIndexed(renderContext.encoder, lodInfo.indexCount, renderNode.instanceCount, lodInfo.indexStart, 0, 0); - } else { - GPUContext.drawIndexed(renderContext.encoder, lodInfo.indexCount, 1, lodInfo.indexStart, 0, worldMatrix.index); + for (let k = 0; k < subGeometries.length; k++) { + const subGeometry = subGeometries[k]; + let lodInfos = subGeometry.lodLevels; + let lodInfo = lodInfos[renderNode.lodLevel]; + + if (renderNode.instanceCount > 0) { + GPUContext.drawIndexed(renderContext.encoder, lodInfo.indexCount, renderNode.instanceCount, lodInfo.indexStart, 0, 0); + } else { + GPUContext.drawIndexed(renderContext.encoder, lodInfo.indexCount, 1, lodInfo.indexStart, 0, worldMatrix.index); + } } } } @@ -396,7 +419,7 @@ export class RenderNode extends ComponentBase { * @param encoder * @returns */ - public renderPass2(view: View3D, passType: RendererType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { + public renderPass2(view: View3D, passType: PassType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { if (!this.enable) return; // this.nodeUpdate(view, passType, rendererPassState, clusterLightingBuffer); @@ -405,6 +428,7 @@ export class RenderNode extends ComponentBase { let worldMatrix = node.object3D.transform._worldMatrix; for (let i = 0; i < this.materials.length; i++) { const material = this.materials[i]; + // material.applyUniform(); let passes = material.getPass(passType); if (!passes || passes.length == 0) return; @@ -428,10 +452,12 @@ export class RenderNode extends ComponentBase { if (matPass.pipeline) { GPUContext.bindPipeline(encoder, matPass); let subGeometries = node._geometry.subGeometries; - const subGeometry = subGeometries[i]; - let lodInfos = subGeometry.lodLevels; - let lodInfo = lodInfos[node.lodLevel]; - GPUContext.drawIndexed(encoder, lodInfo.indexCount, 1, lodInfo.indexStart, 0, worldMatrix.index); + for (let k = 0; k < subGeometries.length; k++) { + const subGeometry = subGeometries[k]; + let lodInfos = subGeometry.lodLevels; + let lodInfo = lodInfos[node.lodLevel]; + GPUContext.drawIndexed(encoder, lodInfo.indexCount, 1, lodInfo.indexStart, 0, worldMatrix.index); + } } } } @@ -441,7 +467,7 @@ export class RenderNode extends ComponentBase { } - public recordRenderPass2(view: View3D, passType: RendererType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { + public recordRenderPass2(view: View3D, passType: PassType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { if (!this.enable) return; // this.nodeUpdate(view, passType, rendererPassState, clusterLightingBuffer); @@ -472,7 +498,7 @@ export class RenderNode extends ComponentBase { } } - public nodeUpdate(view: View3D, passType: RendererType, renderPassState: RendererPassState, clusterLightingBuffer?: ClusterLightingBuffer) { + public nodeUpdate(view: View3D, passType: PassType, renderPassState: RendererPassState, clusterLightingBuffer?: ClusterLightingBuffer) { this.preInit = true; let node = this; let envMap = view.scene.envMap; @@ -510,7 +536,6 @@ export class RenderNode extends ComponentBase { let shadowRenderer = Engine3D.getRenderJob(view).shadowMapPassRenderer; if (shadowRenderer && shadowRenderer.depth2DArrayTexture) { renderShader.setTexture(`shadowMap`, Engine3D.getRenderJob(view).shadowMapPassRenderer.depth2DArrayTexture); - renderShader.setStorageBuffer(`shadowBuffer`, ShadowLightsCollect.shadowBuffer.get(view.scene)); } // let shadowLight = ShadowLights.list; // if (shadowLight.length) { @@ -534,7 +559,7 @@ export class RenderNode extends ComponentBase { if (lightUniformEntries) { renderShader.setStorageBuffer(`lightBuffer`, lightUniformEntries.storageGPUBuffer); if (lightUniformEntries.irradianceVolume) { - renderShader.setStructStorageBuffer(`irradianceData`, lightUniformEntries.irradianceVolume.irradianceVolumeBuffer); + renderShader.setUniformBuffer(`irradianceData`, lightUniformEntries.irradianceVolume.irradianceVolumeBuffer); } } diff --git a/src/components/renderer/SkinnedMeshRenderer.ts b/src/components/renderer/SkinnedMeshRenderer.ts index 21344dad..704fc397 100644 --- a/src/components/renderer/SkinnedMeshRenderer.ts +++ b/src/components/renderer/SkinnedMeshRenderer.ts @@ -3,10 +3,11 @@ import { Object3D } from "../../core/entities/Object3D"; import { MeshRenderer } from "./MeshRenderer"; import { RendererMask } from "../../gfx/renderJob/passRenderer/state/RendererMask"; import { StorageGPUBuffer } from "../../gfx/graphics/webGpu/core/buffer/StorageGPUBuffer"; -import { RendererType } from "../../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../../gfx/renderJob/passRenderer/state/RendererType"; import { RendererPassState } from "../../gfx/renderJob/passRenderer/state/RendererPassState"; import { SkeletonAnimationComponent } from "../SkeletonAnimationComponent"; import { ClusterLightingBuffer } from "../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer"; +import { GeometryBase, Matrix4, RegisterComponent } from "../.."; /** * Skin Mesh Renderer Component @@ -15,112 +16,116 @@ import { ClusterLightingBuffer } from "../../gfx/renderJob/passRenderer/cluster/ * meshes with mixed shapes, and meshes running cloth simulations. * @group Components */ +@RegisterComponent export class SkinnedMeshRenderer extends MeshRenderer { - public skinJointsName: Array; - protected mInverseBindMatrixData: Array; - protected mInverseBindMatrixBuffer: StorageGPUBuffer; - protected mSkeletonAnimation: SkeletonAnimationComponent; - protected mJointIndexTableBuffer: StorageGPUBuffer; + public skinJointsName: Array; + protected mInverseBindMatrixData: Array; + protected mInverseBindMatrixBuffer: StorageGPUBuffer; + protected mSkeletonAnimation: SkeletonAnimationComponent; + protected mJointIndexTableBuffer: StorageGPUBuffer; - constructor() { - super(); - this.addRendererMask(RendererMask.SkinnedMesh); - } - - public start() { - super.start(); - this.skeletonAnimation = this.object3D.getComponent(SkeletonAnimationComponent); - if (!this.skeletonAnimation) { - let comps = this.object3D.parentObject.parentObject.getComponentsInChild(SkeletonAnimationComponent); - if (comps.length > 0) { - this.skeletonAnimation = comps[0]; - } - if (!this.skeletonAnimation) { - this.skeletonAnimation = this.object3D.getComponentFromParent(SkeletonAnimationComponent); - } + constructor() { + super(); + this.addRendererMask(RendererMask.SkinnedMesh); } - } - public onEnable(): void { - super.onEnable(); - } + public start() { + super.start(); + this.skeletonAnimation = this.object3D.getComponent(SkeletonAnimationComponent); + if (!this.skeletonAnimation) { + let comps = this.object3D.parentObject.parentObject.getComponentsInChild(SkeletonAnimationComponent); + if (comps.length > 0) { + this.skeletonAnimation = comps[0]; + } + let parentObj = this.object3D; + while (!this.skeletonAnimation && parentObj) { + this.skeletonAnimation = parentObj.getComponentFromParent(SkeletonAnimationComponent); + if (parentObj.parent) { + parentObj = parentObj.parent.object3D; + } + } + } + } - public get skeletonAnimation(): SkeletonAnimationComponent { - return this.mSkeletonAnimation; - } + public onEnable(): void { + super.onEnable(); + } - public set skeletonAnimation(value: SkeletonAnimationComponent) { - this.mSkeletonAnimation = value; - if (!value) { - return; + public get skeletonAnimation(): SkeletonAnimationComponent { + return this.mSkeletonAnimation; } - if (!this.mJointIndexTableBuffer) { - let skinJointIndexData = this.mSkeletonAnimation.getJointIndexTable(this.skinJointsName); - this.mJointIndexTableBuffer = new StorageGPUBuffer(skinJointIndexData.length * 4, 0, new Float32Array(skinJointIndexData)); - this.mJointIndexTableBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.COMPUTE; + public set skeletonAnimation(value: SkeletonAnimationComponent) { + this.mSkeletonAnimation = value; + if (!value) { + return; + } + + if (!this.mJointIndexTableBuffer) { + let skinJointIndexData = this.mSkeletonAnimation.getJointIndexTable(this.skinJointsName); + this.mJointIndexTableBuffer = new StorageGPUBuffer(skinJointIndexData.length * 4, 0, new Float32Array(skinJointIndexData)); + this.mJointIndexTableBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.COMPUTE; + } } - } - public get skinInverseBindMatrices(): Array { - return this.mInverseBindMatrixData; - } + public get skinInverseBindMatrices(): Array { + return this.mInverseBindMatrixData; + } - public set skinInverseBindMatrices(inverseBindMatrices: Array) { - this.mInverseBindMatrixData = inverseBindMatrices; - var inverseBindMatricesData = new Float32Array(inverseBindMatrices.length * 16); - for (let i = 0; i < inverseBindMatrices.length; i++) { - let index = i * 16; - let mat4x4 = inverseBindMatrices[i]; - inverseBindMatricesData.set(mat4x4, index); + public set skinInverseBindMatrices(inverseBindMatrices: Array) { + this.mInverseBindMatrixData = inverseBindMatrices; + var inverseBindMatricesData = new Float32Array(inverseBindMatrices.length * 16); + for (let i = 0; i < inverseBindMatrices.length; i++) { + let index = i * 16; + let mat4x4 = inverseBindMatrices[i]; + inverseBindMatricesData.set(mat4x4, index); + } + this.mInverseBindMatrixBuffer = new StorageGPUBuffer(inverseBindMatricesData.byteLength, 0, inverseBindMatricesData); + this.mInverseBindMatrixBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.COMPUTE; } - this.mInverseBindMatrixBuffer = new StorageGPUBuffer(inverseBindMatricesData.byteLength, 0, inverseBindMatricesData); - this.mInverseBindMatrixBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.COMPUTE; - } - public get inverseBindMatrixBuffer(): StorageGPUBuffer { - return this.mInverseBindMatrixBuffer; - } + public get inverseBindMatrixBuffer(): StorageGPUBuffer { + return this.mInverseBindMatrixBuffer; + } - public get jointIndexTableBuffer(): GPUBuffer { - return this.mJointIndexTableBuffer.buffer; - } + public get jointIndexTableBuffer(): GPUBuffer { + return this.mJointIndexTableBuffer.buffer; + } - public cloneTo(obj: Object3D) { - let skinnedMesh = obj.addComponent(SkinnedMeshRenderer); - skinnedMesh.geometry = this.geometry; - skinnedMesh.material = this.material.clone(); - skinnedMesh.castShadow = this.castShadow; - skinnedMesh.castGI = this.castGI; - skinnedMesh.receiveShadow = this.receiveShadow; - skinnedMesh.rendererMask = this.rendererMask; - skinnedMesh.skinJointsName = this.skinJointsName; - skinnedMesh.skinInverseBindMatrices = this.skinInverseBindMatrices; - skinnedMesh.mJointIndexTableBuffer = this.mJointIndexTableBuffer; - } + public cloneTo(obj: Object3D) { + let skinnedMesh = obj.addComponent(SkinnedMeshRenderer); + skinnedMesh.geometry = this.geometry; + skinnedMesh.material = this.material.clone(); + skinnedMesh.castShadow = this.castShadow; + skinnedMesh.castGI = this.castGI; + skinnedMesh.receiveShadow = this.receiveShadow; + skinnedMesh.rendererMask = this.rendererMask; + skinnedMesh.skinJointsName = this.skinJointsName; + skinnedMesh.skinInverseBindMatrices = this.skinInverseBindMatrices; + skinnedMesh.mJointIndexTableBuffer = this.mJointIndexTableBuffer; + } - /** - * @internal - * @param passType - * @param renderPassState - * @param scene3D - * @param clusterLightingRender - * @param probes - */ - public nodeUpdate(view: View3D, passType: RendererType, renderPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer) { - for (let i = 0; i < this.materials.length; i++) { - const material = this.materials[i]; - let passes = material.getPass(passType); - if (passes) for (let i = 0; i < passes.length; i++) { - const renderShader = passes[i]; - if (!renderShader.pipeline) { - renderShader.setStorageBuffer('jointsMatrixIndexTable', this.mSkeletonAnimation.jointMatrixIndexTableBuffer); - renderShader.setStorageBuffer('jointsInverseMatrix', this.mInverseBindMatrixBuffer); - renderShader.setStorageBuffer('jointsIndexMapingTable', this.mJointIndexTableBuffer); + /** + * @internal + * @param passType + * @param renderPassState + * @param scene3D + * @param clusterLightingRender + * @param probes + */ + public nodeUpdate(view: View3D, passType: PassType, renderPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer) { + for (let i = 0; i < this.materials.length; i++) { + const material = this.materials[i]; + let passes = material.getPass(passType); + if (passes) for (let i = 0; i < passes.length; i++) { + const renderShader = passes[i]; + if (!renderShader.pipeline && this.mSkeletonAnimation) { + renderShader.setStorageBuffer('jointsMatrixIndexTable', this.mSkeletonAnimation.jointMatrixIndexTableBuffer); + renderShader.setStorageBuffer('jointsInverseMatrix', this.mInverseBindMatrixBuffer); + renderShader.setStorageBuffer('jointsIndexMapingTable', this.mJointIndexTableBuffer); + } + } } - } + super.nodeUpdate(view, passType, renderPassState, clusterLightingBuffer); } - super.nodeUpdate(view, passType, renderPassState, clusterLightingBuffer); - } - -} +} \ No newline at end of file diff --git a/src/components/renderer/SkinnedMeshRenderer2.ts b/src/components/renderer/SkinnedMeshRenderer2.ts new file mode 100644 index 00000000..469fcbde --- /dev/null +++ b/src/components/renderer/SkinnedMeshRenderer2.ts @@ -0,0 +1,154 @@ +import { View3D } from "../../core/View3D"; +import { Object3D } from "../../core/entities/Object3D"; +import { MeshRenderer } from "./MeshRenderer"; +import { RendererMask } from "../../gfx/renderJob/passRenderer/state/RendererMask"; +import { StorageGPUBuffer } from "../../gfx/graphics/webGpu/core/buffer/StorageGPUBuffer"; +import { PassType } from "../../gfx/renderJob/passRenderer/state/RendererType"; +import { RendererPassState } from "../../gfx/renderJob/passRenderer/state/RendererPassState"; +import { ClusterLightingBuffer } from "../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer"; +import { AnimatorComponent, GeometryBase, LitMaterial, Matrix4, RegisterComponent } from "../.."; + +/** + * Skin Mesh Renderer Component + * Renders a deformable mesh. + * Deformable meshes include skin meshes (meshes with bones and bound poses), + * meshes with mixed shapes, and meshes running cloth simulations. + * @group Components + */ +@RegisterComponent +export class SkinnedMeshRenderer2 extends MeshRenderer { + public skinJointsName: Array; + protected mInverseBindMatrixData: Array; + protected mInverseBindMatrixBuffer: StorageGPUBuffer; + protected mSkeletonAnimation: AnimatorComponent; + protected mJointIndexTableBuffer: StorageGPUBuffer; + + constructor() { + super(); + this.addRendererMask(RendererMask.SkinnedMesh); + } + + public get geometry(): GeometryBase { + return this._geometry; + } + + public set geometry(value: GeometryBase) { + this.skinJointsName = value.skinNames; + let matrixList: Float32Array[] = []; + for (let i = 0; i < value.bindPose.length; i++) { + matrixList.push(value.bindPose[i].rawData.slice(0, 16)); + } + this.skinInverseBindMatrices = matrixList; + super.geometry = value; + } + + public start() { + super.start(); + this.skeletonAnimation = this.object3D.getComponent(AnimatorComponent); + if (!this.skeletonAnimation) { + let comps = this.object3D.parentObject.parentObject.getComponentsInChild(AnimatorComponent); + if (comps.length > 0) { + this.skeletonAnimation = comps[0]; + } + let parentObj = this.object3D; + while (!this.skeletonAnimation && parentObj) { + this.skeletonAnimation = parentObj.getComponentFromParent(AnimatorComponent); + if (parentObj.parent) { + parentObj = parentObj.parent.object3D; + } + } + } + // this.skinInverseBindMatrices = this.skeletonAnimation.inverseBindMatrices; + } + + public get blendShape() { + // key: string, value: number + return this.morphData + } + + public onEnable(): void { + super.onEnable(); + } + + public get skeletonAnimation(): AnimatorComponent { + return this.mSkeletonAnimation; + } + + public set skeletonAnimation(value: AnimatorComponent) { + this.mSkeletonAnimation = value; + if (!value) { + return; + } + + if (!this.mJointIndexTableBuffer) { + let skinJointIndexData = this.mSkeletonAnimation.getJointIndexTable(this.skinJointsName); + this.mJointIndexTableBuffer = new StorageGPUBuffer(skinJointIndexData.length, 0, new Float32Array(skinJointIndexData)); + this.mJointIndexTableBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.COMPUTE; + } + } + + public get skinInverseBindMatrices(): Array { + return this.mInverseBindMatrixData; + } + + public set skinInverseBindMatrices(inverseBindMatrices: Array) { + this.mInverseBindMatrixData = inverseBindMatrices; + var inverseBindMatricesData = new Float32Array(inverseBindMatrices.length * 16); + for (let i = 0; i < inverseBindMatrices.length; i++) { + let index = i * 16; + let mat4x4 = inverseBindMatrices[i]; + inverseBindMatricesData.set(mat4x4, index); + } + this.mInverseBindMatrixBuffer = new StorageGPUBuffer(inverseBindMatricesData.byteLength, 0, inverseBindMatricesData); + this.mInverseBindMatrixBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.COMPUTE; + } + + public get inverseBindMatrixBuffer(): StorageGPUBuffer { + return this.mInverseBindMatrixBuffer; + } + + public get jointIndexTableBuffer(): GPUBuffer { + return this.mJointIndexTableBuffer.buffer; + } + + public cloneTo(obj: Object3D) { + let skinnedMesh = obj.addComponent(SkinnedMeshRenderer2); + let newMats = []; + for (const mat of this.materials) { + newMats.push(mat.clone()); + } + skinnedMesh.materials = newMats; + skinnedMesh.geometry = this.geometry; + skinnedMesh.castShadow = this.castShadow; + skinnedMesh.castGI = this.castGI; + skinnedMesh.receiveShadow = this.receiveShadow; + skinnedMesh.rendererMask = this.rendererMask; + skinnedMesh.skinJointsName = this.skinJointsName; + skinnedMesh.skinInverseBindMatrices = this.skinInverseBindMatrices; + skinnedMesh.mJointIndexTableBuffer = this.mJointIndexTableBuffer; + } + + /** + * @internal + * @param passType + * @param renderPassState + * @param scene3D + * @param clusterLightingRender + * @param probes + */ + public nodeUpdate(view: View3D, passType: PassType, renderPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer) { + for (let i = 0; i < this.materials.length; i++) { + const material = this.materials[i]; + let passes = material.getPass(passType); + if (passes) for (let i = 0; i < passes.length; i++) { + const renderShader = passes[i]; + if (!renderShader.pipeline && this.mSkeletonAnimation) { + renderShader.setStorageBuffer('jointsMatrixIndexTable', this.mSkeletonAnimation.jointMatrixIndexTableBuffer); + renderShader.setStorageBuffer('jointsInverseMatrix', this.mInverseBindMatrixBuffer); + renderShader.setStorageBuffer('jointsIndexMapingTable', this.mJointIndexTableBuffer); + } + } + } + super.nodeUpdate(view, passType, renderPassState, clusterLightingBuffer); + } +} \ No newline at end of file diff --git a/src/components/renderer/SkyRenderer.ts b/src/components/renderer/SkyRenderer.ts index 550422da..d20505dc 100644 --- a/src/components/renderer/SkyRenderer.ts +++ b/src/components/renderer/SkyRenderer.ts @@ -8,7 +8,7 @@ import { EntityCollect } from '../../gfx/renderJob/collect/EntityCollect'; import { ClusterLightingBuffer } from '../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer'; import { RendererMask } from '../../gfx/renderJob/passRenderer/state/RendererMask'; import { RendererPassState } from '../../gfx/renderJob/passRenderer/state/RendererPassState'; -import { RendererType } from '../../gfx/renderJob/passRenderer/state/RendererType'; +import { PassType } from '../../gfx/renderJob/passRenderer/state/RendererType'; import { SkyMaterial } from '../../materials/SkyMaterial'; import { Vector3 } from '../../math/Vector3'; import { SphereGeometry } from '../../shape/SphereGeometry'; @@ -57,7 +57,7 @@ export class SkyRenderer extends MeshRenderer { } } - public renderPass2(view: View3D, passType: RendererType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { + public renderPass2(view: View3D, passType: PassType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { // this.transform.updateWorldMatrix(); super.renderPass2(view, passType, rendererPassState, clusterLightingBuffer, encoder, useBundle); // this.transform.localPosition = Camera3D.mainCamera.transform.localPosition ; diff --git a/src/core/Camera3D.ts b/src/core/Camera3D.ts index 3bd81349..10d20559 100644 --- a/src/core/Camera3D.ts +++ b/src/core/Camera3D.ts @@ -127,7 +127,7 @@ export class Camera3D extends ComponentBase { public getShadowBias(depthTexSize: number): number { let sizeOnePixel = 2.0 * this.getShadowWorldExtents() / depthTexSize; let depth = this.far - this.near; - return sizeOnePixel / depth; + return sizeOnePixel / depth - Engine3D.setting.shadow.shadowBias * 0.01; } public getShadowWorldExtents(): number { diff --git a/src/core/View3D.ts b/src/core/View3D.ts index 7f334f66..c90ec262 100644 --- a/src/core/View3D.ts +++ b/src/core/View3D.ts @@ -28,7 +28,6 @@ export class View3D extends CEventListener { super(); this.canvasList = []; this._viewPort = new Vector4(x, y, width, height); - this.enablePick = true; this.graphic3D = new Graphic3D(); } @@ -60,7 +59,7 @@ export class View3D extends CEventListener { this._scene = value; value.view = this; - ShadowLightsCollect.createBuffer(value); + ShadowLightsCollect.createBuffer(this); if (this.graphic3D) value.addChild(this.graphic3D); diff --git a/src/core/ViewQuad.ts b/src/core/ViewQuad.ts index 8f8ea625..0f4db71b 100644 --- a/src/core/ViewQuad.ts +++ b/src/core/ViewQuad.ts @@ -2,20 +2,16 @@ import { MeshRenderer } from '../components/renderer/MeshRenderer'; import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; import { UniformNode } from '../gfx/graphics/webGpu/core/uniforms/UniformNode'; import { WebGPUDescriptorCreator } from '../gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator'; -import { GPUCompareFunction } from '../gfx/graphics/webGpu/WebGPUConst'; import { webGPUContext } from '../gfx/graphics/webGpu/Context3D'; import { RTFrame } from '../gfx/renderJob/frame/RTFrame'; -import { BlendMode } from '../materials/BlendMode'; -import { Color } from '../math/Color'; import { PlaneGeometry } from '../shape/PlaneGeometry'; - import { Object3D } from './entities/Object3D'; import { RendererPassState } from '../gfx/renderJob/passRenderer/state/RendererPassState'; -import { Engine3D } from '../Engine3D'; import { GPUContext } from '../gfx/renderJob/GPUContext'; -import { RendererType } from '../gfx/renderJob/passRenderer/state/RendererType'; +import { PassType } from '../gfx/renderJob/passRenderer/state/RendererType'; import { View3D } from './View3D'; -import { Material, RenderShader } from '..'; +import { Material } from '../materials/Material'; +import { QuadShader } from '../loader/parser/prefab/mats/shader/QuadShader'; /** * @internal * @group Entity @@ -25,27 +21,18 @@ export class ViewQuad extends Object3D { height: number = 128; quadRenderer: MeshRenderer; material: Material; - uniforms: { [key: string]: UniformNode }; + // uniforms: { [key: string]: UniformNode }; rendererPassState: RendererPassState; - pass: RenderShader; + quadShader: QuadShader; - constructor(vs: string = 'QuadGlsl_vs', fs: string = 'QuadGlsl_fs', rtFrame: RTFrame, shaderUniforms?: { [uniName: string]: UniformNode }, multisample: number = 0, f: boolean = false) { + constructor(vs: string = 'QuadGlsl_vs', fs: string = 'QuadGlsl_fs', rtFrame: RTFrame, multisample: number = 0, f: boolean = false) { super(); - let renderTexture = rtFrame ? rtFrame.attachments : []; + let renderTexture = rtFrame ? rtFrame.renderTargets : []; this.material = new Material(); - this.pass = new RenderShader(vs, fs); - this.material.addPass(RendererType.COLOR, this.pass); - - this.pass.blendMode = BlendMode.NONE; - let shaderState = this.pass.shaderState; - shaderState.frontFace = `cw`; - // shaderState.cullMode = `back`; - shaderState.depthWriteEnabled = false; - shaderState.depthCompare = GPUCompareFunction.always; - shaderState.multisample = multisample; - this.uniforms = this.pass.uniforms = shaderUniforms ? shaderUniforms : { color: new UniformNode(new Color()) }; + this.quadShader = new QuadShader(vs, fs); + this.material.shader = this.quadShader; this.quadRenderer = this.addComponent(MeshRenderer); this.quadRenderer.material = this.material; @@ -55,13 +42,6 @@ export class ViewQuad extends Object3D { // this.quadRenderer.renderOrder = 99999; this.quadRenderer.geometry = new PlaneGeometry(100, 100, 1, 1); - this.colorTexture = Engine3D.res.blackTexture; - - this.pass.setUniformFloat(`x`, 0); - this.pass.setUniformFloat(`y`, 0); - this.pass.setUniformFloat(`width`, 100); - this.pass.setUniformFloat(`height`, 100); - this.quadRenderer.material = this.material; this.quadRenderer[`__start`](); this.quadRenderer[`_enable`] = true; @@ -69,24 +49,20 @@ export class ViewQuad extends Object3D { // this.createRendererPassState(renderTargets, depth); // this.rendererPassState = WebGPUDescriptorPool.createRendererPassState(renderTargets, shaderState.multisample>0 ? false : true); this.rendererPassState = WebGPUDescriptorCreator.createRendererPassState(rtFrame, `load`); - if (shaderState.multisample > 0) { - this.rendererPassState.multisample = shaderState.multisample; + if (multisample > 0) { + this.rendererPassState.multisample = this.quadShader.getDefaultColorShader().shaderState.multisample; this.rendererPassState.multiTexture = webGPUContext.device.createTexture({ size: { width: webGPUContext.presentationSize[0], height: webGPUContext.presentationSize[1], }, - sampleCount: shaderState.multisample, + sampleCount: multisample, format: renderTexture.length > 0 ? renderTexture[0].format : webGPUContext.presentationFormat, usage: GPUTextureUsage.RENDER_ATTACHMENT, }) } } - public set colorTexture(tex: Texture) { - this.material.getPass(RendererType.COLOR)[0].setTexture(`baseMap`, tex); - } - /** * By inputting a map to viewQuad and setting corresponding * processing shaders, the corresponding results are output for off-screen rendering @@ -101,8 +77,8 @@ export class ViewQuad extends Object3D { let camera = view.camera; let encoder = GPUContext.beginRenderPass(command, viewQuad.rendererPassState); GPUContext.bindCamera(encoder, camera); - viewQuad.quadRenderer.nodeUpdate(view, RendererType.COLOR, viewQuad.rendererPassState, null); - viewQuad.quadRenderer.renderPass2(view, RendererType.COLOR, viewQuad.rendererPassState, null, encoder); + viewQuad.quadRenderer.nodeUpdate(view, PassType.COLOR, viewQuad.rendererPassState, null); + viewQuad.quadRenderer.renderPass2(view, PassType.COLOR, viewQuad.rendererPassState, null, encoder); GPUContext.endPass(encoder); } @@ -117,37 +93,13 @@ export class ViewQuad extends Object3D { */ public renderToViewQuad(view: View3D, viewQuad: ViewQuad, command: GPUCommandEncoder, colorTexture: Texture) { let camera = view.camera; - viewQuad.colorTexture = colorTexture; + + viewQuad.quadShader.setTexture('baseMap', colorTexture); let encoder = GPUContext.beginRenderPass(command, viewQuad.rendererPassState); GPUContext.bindCamera(encoder, camera); - // viewQuad.x = view.viewPort.x; - // viewQuad.y = view.viewPort.y; - // viewQuad.scaleX = view.viewPort.width; - // viewQuad.scaleY = view.viewPort.height; - // viewQuad.transform.updateWorldMatrix(true); - // encoder.setViewport( - // view.viewPort.x * webGPUContext.presentationSize[0], - // view.viewPort.y * webGPUContext.presentationSize[1], - // view.viewPort.width * webGPUContext.presentationSize[0], - // view.viewPort.height * webGPUContext.presentationSize[1], - // 0.0, 1.0); - // encoder.setScissorRect( - // view.viewPort.x * webGPUContext.presentationSize[0], - // view.viewPort.y * webGPUContext.presentationSize[0], - // view.viewPort.width * webGPUContext.presentationSize[0], - // view.viewPort.height * webGPUContext.presentationSize[1], - // ); - - // encoder.setScissorRect(view.viewPort.x, view.viewPort.y, 300, 150); - // encoder.setViewport(view.viewPort.x, view.viewPort.y, view.viewPort.width / (view.viewPort.width / view.viewPort.height), view.viewPort.height, 0.0, 1.0); - // encoder.setScissorRect(view.viewPort.x, view.viewPort.y, view.viewPort.width, view.viewPort.height); - - // encoder.setViewport(camera.viewPort.x, camera.viewPort.y, camera.viewPort.width, camera.viewPort.height, 0.0, 1.0); - // encoder.setScissorRect(camera.viewPort.x, camera.viewPort.y, camera.viewPort.width, camera.viewPort.height); - - viewQuad.quadRenderer.nodeUpdate(view, RendererType.COLOR, viewQuad.rendererPassState, null); - viewQuad.quadRenderer.renderPass2(view, RendererType.COLOR, viewQuad.rendererPassState, null, encoder); + viewQuad.quadRenderer.nodeUpdate(view, PassType.COLOR, viewQuad.rendererPassState, null); + viewQuad.quadRenderer.renderPass2(view, PassType.COLOR, viewQuad.rendererPassState, null, encoder); GPUContext.endPass(encoder); } } diff --git a/src/core/entities/Entity.ts b/src/core/entities/Entity.ts index f8c80d5a..ff6df208 100644 --- a/src/core/entities/Entity.ts +++ b/src/core/entities/Entity.ts @@ -308,6 +308,7 @@ export class Entity extends CEventDispatcher { } this.components.forEach((v, k) => { v.enable = false; + v.beforeDestroy(); v.destroy(); }); this.components.clear(); @@ -319,8 +320,8 @@ export class Entity extends CEventDispatcher { while (v.length > 0) { const element = v.shift(); element[`__start`](); + ComponentCollect.waitStartComponent.delete(element.object3D); } - ComponentCollect.waitStartComponent.delete(k); }); } } diff --git a/src/core/entities/Object3D.ts b/src/core/entities/Object3D.ts index 444be1be..c700111b 100644 --- a/src/core/entities/Object3D.ts +++ b/src/core/entities/Object3D.ts @@ -549,17 +549,17 @@ function DecorateObject3D(ctor: any, _?: any) { public get materialColor(): Color { let component = this.getComponent(MeshRenderer); - return component?.material?.defaultPass.baseColor; + return component?.material?.shader.getDefaultColorShader().baseColor; } public set materialColor(color: Color) { let material = this.getComponent(MeshRenderer)?.material; - material && (material.defaultPass.baseColor = color); + material && (material.shader.getDefaultColorShader().baseColor = color); } public notifyMaterialColorChange(materialIndex: number, key: string) { let materials = this.getComponent(MeshRenderer).materials; - materials?.[materialIndex]?.defaultPass.uniforms[key].onChange(); + materials?.[materialIndex]?.shader.getDefaultColorShader().uniforms[key].onChange(); } }; } \ No newline at end of file diff --git a/src/core/geometry/ExtrudeGeometry.ts b/src/core/geometry/ExtrudeGeometry.ts index c3a65c4a..05bff8a8 100644 --- a/src/core/geometry/ExtrudeGeometry.ts +++ b/src/core/geometry/ExtrudeGeometry.ts @@ -180,7 +180,10 @@ export class ExtrudeGeometry extends GeometryBase { indexStart: 0, indexCount: indices_arr.length, vertexStart: 0, + vertexCount: 0, + firstStart: 0, index: 0, + topology: 0, }); this.computeNormals(); diff --git a/src/core/geometry/GeometryBase.ts b/src/core/geometry/GeometryBase.ts index 385029c2..54962f05 100644 --- a/src/core/geometry/GeometryBase.ts +++ b/src/core/geometry/GeometryBase.ts @@ -8,12 +8,17 @@ import { GeometryIndicesBuffer } from "./GeometryIndicesBuffer"; import { GeometryVertexType } from "./GeometryVertexType"; import { VertexAttributeData } from "./VertexAttributeData"; import { ArrayBufferData } from "../../gfx/graphics/webGpu/core/buffer/ArrayBufferData"; +import { BlendShapeData } from "../../loader/parser/prefab/prefabData/BlendShapeData"; +import { Matrix4 } from "../../math/Matrix4"; -export type LodLevel = { +export type LODDescriptor = { indexStart: number; indexCount: number; vertexStart: number; + vertexCount: number; + firstStart: number; index: number; + topology: number; } @@ -22,7 +27,7 @@ export type LodLevel = { * @group Geometry */ export class SubGeometry { - public lodLevels: LodLevel[]; + public lodLevels: LODDescriptor[]; } @@ -35,14 +40,19 @@ export class GeometryBase { public name: string; public subGeometries: SubGeometry[] = []; public morphTargetsRelative: boolean; - public morphTargetDictionary: { value: string; key: number }; - private _bounds: BoundingBox; + public morphTargetDictionary: { [blenderName: string]: number }; + public skinNames: string[]; + public bindPose: Matrix4[]; + public blendShapeData: BlendShapeData; + public vertexDim: number; + private _bounds: BoundingBox; private _attributeMap: Map; private _attributes: string[]; private _indicesBuffer: GeometryIndicesBuffer; private _vertexBuffer: GeometryVertexBuffer; private _onChange: boolean = true; + private _wireframeLines: Vector3[]; constructor() { this.instanceID = UUID(); @@ -90,7 +100,7 @@ export class GeometryBase { this._bounds.max.z = -Number.MAX_VALUE; let attributes = this.getAttribute(VertexAttributeName.position); - if (attributes) { + if (attributes && attributes.data) { for (let i = 0; i < attributes.data.length / 3; i++) { const px = attributes.data[i * 3 + 0]; const py = attributes.data[i * 3 + 1]; @@ -127,9 +137,9 @@ export class GeometryBase { /** * add subGeometry from lod level - * @param lodLevels @see LodLevel + * @param lodLevels @see LODDescriptor */ - public addSubGeometry(...lodLevels: LodLevel[]) { + public addSubGeometry(...lodLevels: LODDescriptor[]) { let sub = new SubGeometry(); sub.lodLevels = lodLevels; this.subGeometries.push(sub); @@ -160,7 +170,7 @@ export class GeometryBase { } } - public setAttribute(attribute: string, data: ArrayBufferData) { + public setAttribute(attribute: VertexAttributeName | string, data: ArrayBufferData) { if (attribute == VertexAttributeName.indices) { this.setIndices(data); } else { @@ -173,35 +183,64 @@ export class GeometryBase { } } - public getAttribute(attribute: string): VertexAttributeData { + public getAttribute(attribute: VertexAttributeName | string): VertexAttributeData { return this._attributeMap.get(attribute) as VertexAttributeData; } - public hasAttribute(attribute: string): boolean { + public hasAttribute(attribute: VertexAttributeName | string): boolean { return this._attributeMap.has(attribute); } public genWireframe(): Vector3[] { - let positionAttribute = this.getAttribute(`position`); - let indexAttribute = this.getAttribute(`indices`); - if (indexAttribute && positionAttribute && indexAttribute.data.length > 0) { - let vertexData = positionAttribute.data; - let lines = []; - for (let i = 0; i < indexAttribute.data.length / 3; i++) { - const i1 = indexAttribute.data[i * 3 + 0]; - const i2 = indexAttribute.data[i * 3 + 1]; - const i3 = indexAttribute.data[i * 3 + 2]; - - let p1 = new Vector3(vertexData[i1 * 3 + 0], vertexData[i1 * 3 + 1], vertexData[i1 * 3 + 2]); - let p2 = new Vector3(vertexData[i2 * 3 + 0], vertexData[i2 * 3 + 1], vertexData[i2 * 3 + 2]); - let p3 = new Vector3(vertexData[i3 * 3 + 0], vertexData[i3 * 3 + 1], vertexData[i3 * 3 + 2]); - - lines.push(p1, p2); - lines.push(p2, p3); - lines.push(p3, p1); + if (this._wireframeLines) return this._wireframeLines; + if (this.geometryType == GeometryVertexType.split || this.geometryType == GeometryVertexType.compose) { + let positionAttribute = this.getAttribute(VertexAttributeName.position); + let indexAttribute = this.getAttribute(VertexAttributeName.indices); + if (indexAttribute && positionAttribute && indexAttribute.data.length > 0) { + let vertexData = positionAttribute.data; + let lines = []; + for (let i = 0; i < indexAttribute.data.length / 3; i++) { + const i1 = indexAttribute.data[i * 3 + 0]; + const i2 = indexAttribute.data[i * 3 + 1]; + const i3 = indexAttribute.data[i * 3 + 2]; + + let p1 = new Vector3(vertexData[i1 * 3 + 0], vertexData[i1 * 3 + 1], vertexData[i1 * 3 + 2]); + let p2 = new Vector3(vertexData[i2 * 3 + 0], vertexData[i2 * 3 + 1], vertexData[i2 * 3 + 2]); + let p3 = new Vector3(vertexData[i3 * 3 + 0], vertexData[i3 * 3 + 1], vertexData[i3 * 3 + 2]); + + lines.push(p1, p2); + lines.push(p2, p3); + lines.push(p3, p1); + } + this._wireframeLines = lines; + return lines; + } + } else if (this.geometryType == GeometryVertexType.compose_bin) { + let vertexAttribute = this.getAttribute(VertexAttributeName.all); + let strip = this.vertexDim; + + let indexAttribute = this.getAttribute(VertexAttributeName.indices); + if (indexAttribute && vertexAttribute && indexAttribute.data.length > 0) { + let vertexData = vertexAttribute.data; + let lines = []; + for (let i = 0; i < indexAttribute.data.length / 3; i++) { + const i1 = indexAttribute.data[i * 3 + 0]; // start by 0 + const i2 = indexAttribute.data[i * 3 + 1]; // start by 1 + const i3 = indexAttribute.data[i * 3 + 2]; // start by 2 + + let p1 = new Vector3(vertexData[i1 * strip + 0], vertexData[i1 * strip + 1], vertexData[i1 * strip + 2]); + let p2 = new Vector3(vertexData[i2 * strip + 0], vertexData[i2 * strip + 1], vertexData[i2 * strip + 2]); + let p3 = new Vector3(vertexData[i3 * strip + 0], vertexData[i3 * strip + 1], vertexData[i3 * strip + 2]); + + lines.push(p1, p2); + lines.push(p2, p3); + lines.push(p3, p1); + } + this._wireframeLines = lines; + return lines; } - return lines; } + return null; } diff --git a/src/core/geometry/GeometryVertexBuffer.ts b/src/core/geometry/GeometryVertexBuffer.ts index 76005495..23bef450 100644 --- a/src/core/geometry/GeometryVertexBuffer.ts +++ b/src/core/geometry/GeometryVertexBuffer.ts @@ -4,6 +4,7 @@ import { VertexAttributeData } from "./VertexAttributeData"; import { GeometryVertexType } from "./GeometryVertexType"; import { VertexBufferLayout, VertexAttribute } from "./VertexAttribute"; import { VertexAttributeSize } from "./VertexAttributeSize"; +import { VertexAttributeName } from "./VertexAttributeName"; export class GeometryVertexBuffer { @@ -33,6 +34,9 @@ export class GeometryVertexBuffer { case GeometryVertexType.compose: this.createComposeVertexBuffer(vertexDataInfos, shaderReflection); break; + case GeometryVertexType.compose_bin: + this.createComposBinVertexBuffer(vertexDataInfos, shaderReflection); + break; } } @@ -62,6 +66,7 @@ export class GeometryVertexBuffer { } vertexDataInfos.set(attributeInfo.name, vertexInfo); } + let len = vertexInfo.data.length / attributeLayout.stride; if (this.vertexCount != 0 && this.vertexCount != len) { console.error(" vertex count not match attribute count"); @@ -111,15 +116,69 @@ export class GeometryVertexBuffer { } vertexDataInfos.set(attributeInfo.name, vertexInfo); } - let len = vertexInfo.data.length / attributeLayout.stride; - if (this.vertexCount != 0 && this.vertexCount != len) { - console.error(" vertex count not match attribute count"); + if (vertexInfo.data) { + let len = vertexInfo.data.length / attributeLayout.stride; + if (this.vertexCount != 0 && this.vertexCount != len) { + console.error(" vertex count not match attribute count"); + } + this.vertexCount = len; } - this.vertexCount = len; + attributeOffset += attributeInfo.size; + } + + this._vertexBufferLayouts[0] = { + name: `composeStruct`, + arrayStride: attributeOffset * 4, + stepMode: `vertex`, + attributes: this._attributeSlotLayouts[0], + offset: 0, + size: this.vertexCount * attributeOffset * 4 + } + + this.vertexGPUBuffer = new VertexGPUBuffer(this.vertexCount * attributeOffset); + } + private createComposBinVertexBuffer(vertexDataInfos: Map, shaderReflection: ShaderReflection) { + this._attributeSlotLayouts[0] = []; + + let attributeOffset = 0; + for (let i = 0; i < shaderReflection.attributes.length; i++) { + const attributeInfo = shaderReflection.attributes[i]; + if (attributeInfo.name == `index`) continue; + if (attributeInfo.type == `builtin`) continue; + this._attributeLocation[attributeInfo.name] = attributeInfo.location; + + let attributeLayout: VertexAttribute = { + name: attributeInfo.name, + format: attributeInfo.format, + offset: attributeOffset * 4, + shaderLocation: attributeInfo.location, + stride: VertexAttributeSize[attributeInfo.format] + } + this._attributeSlotLayouts[0][attributeInfo.location] = attributeLayout; + + let vertexInfo = vertexDataInfos.get(attributeInfo.name); + if (!vertexInfo) { + vertexInfo = { + attribute: attributeInfo.name, + data: new Float32Array(attributeInfo.size * this.vertexCount) + } + vertexDataInfos.set(attributeInfo.name, vertexInfo); + } + if (vertexInfo.data) { + let len = vertexInfo.data.length / attributeLayout.stride; + if (this.vertexCount != 0 && this.vertexCount != len) { + console.error(" vertex count not match attribute count"); + } + this.vertexCount = len; + } attributeOffset += attributeInfo.size; } + let att_all = vertexDataInfos.get(VertexAttributeName.all); + let len = att_all.data.length / attributeOffset; + this.vertexCount = len; + this._vertexBufferLayouts[0] = { name: `composeStruct`, arrayStride: attributeOffset * 4, @@ -154,6 +213,9 @@ export class GeometryVertexBuffer { } } break; + case GeometryVertexType.compose_bin: + this.vertexGPUBuffer.node.setFloat32Array(0, vertexDataInfo.data as Float32Array); + break; } this.vertexGPUBuffer?.apply(); } @@ -186,6 +248,13 @@ export class GeometryVertexBuffer { } } break; + + case GeometryVertexType.compose_bin: + { + let attributeData = vertexDataInfos.get(VertexAttributeName.all); + this.vertexGPUBuffer.node.setFloat32Array(0, attributeData.data as Float32Array); + } + break; } this.vertexGPUBuffer.apply(); } diff --git a/src/core/geometry/GeometryVertexType.ts b/src/core/geometry/GeometryVertexType.ts index 618c36a8..82983336 100644 --- a/src/core/geometry/GeometryVertexType.ts +++ b/src/core/geometry/GeometryVertexType.ts @@ -2,4 +2,5 @@ export enum GeometryVertexType { split, compose, + compose_bin, } \ No newline at end of file diff --git a/src/core/geometry/VertexAttributeName.ts b/src/core/geometry/VertexAttributeName.ts index 43c05ce6..d412303d 100644 --- a/src/core/geometry/VertexAttributeName.ts +++ b/src/core/geometry/VertexAttributeName.ts @@ -8,6 +8,11 @@ export enum VertexAttributeName { TANGENT = 'TANGENT', TEXCOORD_1 = 'TEXCOORD_1', TEXCOORD_2 = 'TEXCOORD_2', + TEXCOORD_3 = 'TEXCOORD_3', + TEXCOORD_4 = 'TEXCOORD_4', + TEXCOORD_5 = 'TEXCOORD_5', + TEXCOORD_6 = 'TEXCOORD_6', + TEXCOORD_7 = 'TEXCOORD_7', color = 'color', joints0 = 'joints0', joints1 = 'joints1', @@ -17,4 +22,7 @@ export enum VertexAttributeName { indices = `indices`, vIndex = 'vIndex', a_morphPositions_0 = 'a_morphPositions_0', + + + all = 'all', } diff --git a/src/core/pool/memory/MemoryInfo.ts b/src/core/pool/memory/MemoryInfo.ts index 8b1bbb35..0dc8a5d3 100644 --- a/src/core/pool/memory/MemoryInfo.ts +++ b/src/core/pool/memory/MemoryInfo.ts @@ -150,8 +150,6 @@ export class MemoryInfo { this.dataBytes.setUint16(index * Uint16Array.BYTES_PER_ELEMENT, v, true); } - - public getUint16(index: number = 0): number { return this.dataBytes.getUint16(index * Uint16Array.BYTES_PER_ELEMENT, true); } @@ -172,10 +170,6 @@ export class MemoryInfo { } public setFloat32Array(index: number, data: Float32Array) { - // let buffer = this.dataBytes.buffer.slice(this.dataBytes.byteOffset, this.dataBytes.byteOffset + data.length * Float32Array.BYTES_PER_ELEMENT); - // let tmp = new Float32Array(buffer, index * Float32Array.BYTES_PER_ELEMENT); - // tmp.set(data); - let tmp = new Float32Array(this.dataBytes.buffer, this.dataBytes.byteOffset + index * Float32Array.BYTES_PER_ELEMENT, data.length); tmp.set(data); } diff --git a/src/core/tree/quad/IQuadNode.ts b/src/core/tree/quad/IQuadNode.ts new file mode 100644 index 00000000..9233e101 --- /dev/null +++ b/src/core/tree/quad/IQuadNode.ts @@ -0,0 +1,16 @@ +import { Plane3D } from "../../../math/Plane3D"; +import { QuadAABB } from "./QuadAABB"; + +export interface IQuadNode { + + initAABB(): void; + + isTriangle: boolean; + + aabb: QuadAABB; + + calcGlobalQuadAABB(): void; + + plane?: Plane3D; + +} diff --git a/src/core/tree/quad/QuadAABB.ts b/src/core/tree/quad/QuadAABB.ts new file mode 100644 index 00000000..aca56990 --- /dev/null +++ b/src/core/tree/quad/QuadAABB.ts @@ -0,0 +1,147 @@ +import { Vector3 } from "../../../math/Vector3"; + +export class QuadAABB { + + public minPosX: number = 0; + + public minPosY: number = 0; + + public maxPosX: number = 0; + + public maxPosY: number = 0; + + public testID: number = 0; + + public points: Array; + + private offsetPosition: Vector3; + + private static TINY: number = 0.000001; + + constructor() { + this.points = new Array(); + this.offsetPosition = new Vector3(0, 0, 0, 0); + this.clear(); + + } + + public setAABox(cx: number, cy: number, sideX: number, sideY: number): void { + this.minPosX = cx - sideX / 2 - QuadAABB.TINY; + this.maxPosX = cx + sideX / 2 + QuadAABB.TINY; + this.minPosY = cy - sideY / 2 - QuadAABB.TINY; + this.maxPosY = cy + sideY / 2 + QuadAABB.TINY; + + this.offsetPosition.setTo(0, 0, 0); + } + + public setOffset(vec: Vector3): void { + + this.maxPosX += vec.x - this.offsetPosition.x; + this.minPosX += vec.x - this.offsetPosition.x; + + this.minPosY += vec.z - this.offsetPosition.z; + this.maxPosY += vec.z - this.offsetPosition.z; + + this.offsetPosition.copyFrom(vec); + } + + public setContainRect(minX: number, minY: number, maxX: number, maxY: number): void { + if (this.minPosX > minX) this.minPosX = minX; + if (this.minPosY > minY) this.minPosY = minY; + if (this.maxPosX < maxX) this.maxPosX = maxX; + if (this.maxPosY < maxY) this.maxPosY = maxY; + } + + public clear(): void { + var huge: number = 1000000000; + this.minPosX = this.minPosY = huge; + this.maxPosX = this.maxPosY = -huge; + this.points.length = 0; + this.testID = 0; + this.offsetPosition.setTo(0, 0, 0); + } + + public addPoint(pos: Vector3): void { + if (this.points.indexOf(pos) == -1) { + if (pos.x < this.minPosX) + this.minPosX = pos.x - QuadAABB.TINY; + if (pos.x > this.maxPosX) + this.maxPosX = pos.x + QuadAABB.TINY; + if (pos.z < this.minPosY) + this.minPosY = pos.z - QuadAABB.TINY; + if (pos.z > this.maxPosY) + this.maxPosY = pos.z + QuadAABB.TINY; + + this.points.push(pos); + } + } + + public clone(): QuadAABB { + var aabb: QuadAABB = new QuadAABB(); + aabb.minPosX = this.minPosX; + aabb.minPosY = this.minPosY; + aabb.maxPosX = this.maxPosX; + aabb.maxPosY = this.maxPosY; + return aabb; + } + public get radius(): number { + return Math.sqrt((this.maxPosY - this.minPosY) * (this.maxPosY - this.minPosY) + (this.maxPosX - this.minPosX) * (this.maxPosX - this.minPosX)); + } + + public get sideX(): number { + return this.maxPosX - this.minPosX; + } + + public get sideY(): number { + return this.maxPosY - this.minPosY; + } + + public get centreX(): number { + return (this.maxPosX - this.minPosX) * 0.5 + this.minPosX; + } + + public get centreY(): number { + return (this.maxPosY - this.minPosY) * 0.5 + this.minPosY; + } + + public overlapTest(box: QuadAABB): boolean { + return ( + (this.minPosY >= box.maxPosY) || + (this.maxPosY <= box.minPosY) || + (this.minPosX >= box.maxPosX) || + (this.maxPosX <= box.minPosX)) ? false : true; + } + + public isPointInside(pos: Vector3): boolean { + return ((pos.x >= this.minPosX) && + (pos.x <= this.maxPosX) && + (pos.z >= this.minPosY) && + (pos.z <= this.maxPosY)); + } + + public isIntersectLineSegment(p1x: number, p1y: number, p2x: number, p2y: number): boolean { + var isIntersect: boolean = false; + // function p1-p2 + var A1: number = p1y - p2y; + var B1: number = p2x - p1x; + var C1: number = p1x * p2y - p2x * p1y; + // + var LineIntersectY: number = (-C1 - A1 * this.minPosX) / B1; + if (LineIntersectY <= this.maxPosY && LineIntersectY >= this.minPosY) + isIntersect = true; + LineIntersectY = (-C1 - A1 * this.maxPosX) / B1; + if (LineIntersectY <= this.maxPosY && LineIntersectY >= this.minPosY) + isIntersect = true; + var LineIntersectX: number = (-C1 - B1 * this.minPosY) / A1; + if (LineIntersectX <= this.maxPosX && LineIntersectX >= this.minPosX) + isIntersect = true; + LineIntersectX = (-C1 - B1 * this.maxPosY) / A1; + if (LineIntersectX <= this.maxPosX && LineIntersectX >= this.minPosX) + isIntersect = true; + return isIntersect; + } + + + + +} \ No newline at end of file diff --git a/src/core/tree/quad/QuadRoot.ts b/src/core/tree/quad/QuadRoot.ts new file mode 100644 index 00000000..2daa7af1 --- /dev/null +++ b/src/core/tree/quad/QuadRoot.ts @@ -0,0 +1,92 @@ +import { Vector3 } from "../../../math/Vector3"; +import { IQuadNode } from "./IQuadNode"; +import { QuadAABB } from "./QuadAABB"; +import { QuadTree } from "./QuadTree"; + +export class QuadRoot { + + private _maxNodesPerCell: number; + + private _minCellSize: number; + + private _quadTree: QuadTree; + + private _collisionNodesIdx: Array; + + private _segBox: QuadAABB; + + private _collisionNodes: Array; + + constructor(maxNodesPerCell: number = 10, minCellSize: number = 500) { + this._maxNodesPerCell = maxNodesPerCell; + this._minCellSize = minCellSize; + this._segBox = new QuadAABB; + this._collisionNodesIdx = new Array(); + this._collisionNodes = new Array(); + } + + public createQuadTree(nodes: Array): void { + + this._quadTree = new QuadTree(); + this._quadTree.initNodes(nodes); + this._quadTree.buildQuadTree(this._maxNodesPerCell, this._minCellSize); + } + + public getNodesByAABB(minX: number, minY: number, maxX: number, maxY: number): Array { + // 创建一个射线的boundingbox + this._segBox.clear(); + this._segBox.maxPosX = maxX; + this._segBox.maxPosY = maxY; + this._segBox.minPosX = minX; + this._segBox.minPosY = minY; + + // 获取Boundingbox中的nodes + this._collisionNodesIdx.length = 0; + this._collisionNodes.length = 0; + var numNodes: number = this._quadTree.getNodesIntersectingtAABox(this._collisionNodesIdx, this._segBox); + var quadNode: IQuadNode; + for (var i: number = 0; i < this._collisionNodesIdx.length; i++) { + quadNode = this._quadTree.getQuadNode(this._collisionNodesIdx[i]); + this._collisionNodes.push(quadNode); + } + return this._collisionNodes; + + } + + public getTriangleAtPoint(point: Vector3, threshold: number = 5): IQuadNode { + // 创建一个射线的boundingbox + this._segBox.clear(); + this._segBox.setAABox(point.x, point.z, 1, 1); + + this._collisionNodesIdx.length = 0; + this._collisionNodes.length = 0; + // 获取Boundingbox中的node的ID + var numTriangles: number = this._quadTree.getNodesIntersectingtAABox(this._collisionNodesIdx, this._segBox); + + // 检查那个三角与点(x,y)相交 + var minDistance: number = 0xffffffff; + var curDistance: number = 0; + var minTriangle: IQuadNode; + var quadNode: IQuadNode; + var triangle: IQuadNode; + var box: QuadAABB; + for (var i: number = 0; i < this._collisionNodesIdx.length; i++) { + quadNode = this._quadTree.getQuadNode(this._collisionNodesIdx[i]); + box = quadNode.aabb; + if (!Vector3.pointInsideTriangle(point, box.points[0], box.points[1], box.points[2])) { + continue; + } + triangle = quadNode; + curDistance = Math.abs(triangle.plane.distance(point)); + if (curDistance > threshold) + continue; + if (quadNode == null || curDistance <= minDistance) { + minTriangle = triangle; + minDistance = curDistance; + } + } + + return minTriangle; + } + +} diff --git a/src/core/tree/quad/QuadTree.ts b/src/core/tree/quad/QuadTree.ts new file mode 100644 index 00000000..b2f492b1 --- /dev/null +++ b/src/core/tree/quad/QuadTree.ts @@ -0,0 +1,293 @@ +import { Vector3 } from "../../../math/Vector3"; +import { IQuadNode } from "./IQuadNode"; +import { QuadAABB } from "./QuadAABB"; +import { QuadTreeCell } from "./QuadTreeCell"; + +export class QuadTree { + + private _cells: Array; + + private _rootCell: QuadTreeCell; + + private _quadNodes: Array; + + private _aabb: QuadAABB; + + private _cellsToTest: Array; + + private _testID: number; + + constructor() { + this._testID = 0; + this._cells = new Array(); + this._quadNodes = new Array(); + this._cellsToTest = new Array(); + this._aabb = new QuadAABB(); + } + + public getQuadNode(idx: number): IQuadNode { + return this._quadNodes[idx]; + } + + public clear(): void { + this._cells.length = 0; + this._quadNodes.length = 0; + } + + public initNodes(nodes: Array): void { + this.clear(); + var i: number = 0; + var count: number = nodes.length; + while (i < count) { + nodes[i].calcGlobalQuadAABB(); + this._quadNodes.push(nodes[i]); + i++; + } + + } + + public buildQuadTree(maxNodesPerCell: number, minCellSize: number): void { + this._aabb.clear(); + + for (var node of this._quadNodes) { + if (node.isTriangle) { + for (var vt of node.aabb.points) { + this._aabb.addPoint(vt); + } + } + else { + this._aabb.setContainRect(node.aabb.minPosX, node.aabb.minPosY, node.aabb.maxPosX, node.aabb.maxPosY); + } + } + + this._cells.length = 0; + this._rootCell = new QuadTreeCell(this._aabb); // 创建根节点 + this._cells.push(this._rootCell); + + var numTriangles: number = this._quadNodes.length; + for (var i: number = 0; i < numTriangles; i++) { + this._cells[0].nodeIndices[i] = i; // 先把所有的三角面放到根节点上 + } + + var cellsToProcess: Array = new Array(); + cellsToProcess.push(0); + + var iTri: number; + var cellIndex: number; + var childCell: QuadTreeCell; + while (cellsToProcess.length != 0) { + cellIndex = cellsToProcess.pop(); + if (this._cells[cellIndex].nodeIndices.length <= maxNodesPerCell + || this._cells[cellIndex].aabb.radius < minCellSize) { + continue; // 该cell中还可以放三角面 + } + + for (i = 0; i < QuadTreeCell.NUM_CHILDREN; i++) { + this._cells[cellIndex].childCellIndices[i] = this._cells.length; + cellsToProcess.push(this._cells.length); + this._cells.push(new QuadTreeCell(this.createAABox(this._cells[cellIndex].aabb, i))); + + childCell = this._cells[this._cells.length - 1]; + + // 父节点上的三角型往子节点中放 + numTriangles = this._cells[cellIndex].nodeIndices.length; + var pushCount: number = 0; + for (var j: number = 0; j < numTriangles; j++) { + iTri = this._cells[cellIndex].nodeIndices[j]; + + if (this.doesNodeIntersectCell(this._quadNodes[iTri], childCell)) { + pushCount++; + childCell.nodeIndices.push(iTri); + } + } + } + this._cells[cellIndex].nodeIndices.length = 0; + } + } + + private createAABox(aabb: QuadAABB, id: number): QuadAABB { + var centerX: number = aabb.centreX; + var centerY: number = aabb.centreY; + var dimX: number = aabb.sideX; + var dimY: number = aabb.sideY; + + var result: QuadAABB = new QuadAABB(); + switch (id) { + case 0: // 1象限 + result.setAABox(centerX + dimX / 4, centerY + dimY / 4, dimX / 2, dimY / 2); + break; + case 1: // 2象限 + result.setAABox(centerX - dimX / 4, centerY + dimY / 4, dimX / 2, dimY / 2); + break; + case 2: // 3象限 + result.setAABox(centerX - dimX / 4, centerY - dimY / 4, dimX / 2, dimY / 2); + break; + case 3: // 4象限 + result.setAABox(centerX + dimX / 4, centerY - dimY / 4, dimX / 2, dimY / 2); + break; + default: + result.setAABox(centerX + dimX / 4, centerY - dimY / 4, dimX / 2, dimY / 2); + break; + } + + return result; + } + + private doesNodeIntersectCell(node: IQuadNode, cell: QuadTreeCell): Boolean { + // boundingbox要重叠 + var box: QuadAABB = node.aabb; + if (!box.overlapTest(cell.aabb)) { + return false; + } + //如果不是三角形,则只需要检测aabb的相交 + if (!node.isTriangle) + return true; + + var points: Array = box.points; + var p1: Vector3 = points[0]; + var p2: Vector3 = points[1]; + var p3: Vector3 = points[2]; + + if (cell.aabb.isPointInside(p1) || + cell.aabb.isPointInside(p2) || + cell.aabb.isPointInside(p3)) { // 三角型有顶点在cell中 + return true; + } + + // cell的顶点在三角型中 + var isIntersect: Boolean = + this.pointInTriangle(cell.aabb.minPosX, cell.aabb.minPosY, p1, p2, p3) || + this.pointInTriangle(cell.aabb.minPosX, cell.aabb.maxPosY, p1, p2, p3) || + this.pointInTriangle(cell.aabb.maxPosX, cell.aabb.maxPosY, p1, p2, p3) || + this.pointInTriangle(cell.aabb.maxPosX, cell.aabb.minPosY, p1, p2, p3); + + if (isIntersect) + return true; + + + // 三角形的边是否与AABB的边相交 + isIntersect = cell.aabb.isIntersectLineSegment(p1.x, p1.z, p2.x, p2.z) || + cell.aabb.isIntersectLineSegment(p1.x, p1.z, p3.x, p3.z) || + cell.aabb.isIntersectLineSegment(p2.x, p2.z, p3.x, p3.z); + + return isIntersect; + } + + public getNodesIntersectingtAABox(result: Array, aabb: QuadAABB): number { + if (this._cells.length == 0) + return 0; + this._cellsToTest.length = 0; + this._cellsToTest.push(0); + + this.incrementTestCounter(); + + var cellIndex: number, nTris: number, cell: QuadTreeCell; + var nodeBox: QuadAABB; + var i: number = 0; + while (this._cellsToTest.length != 0) { + cellIndex = this._cellsToTest.pop(); + + cell = this._cells[cellIndex]; + + if (!aabb.overlapTest(cell.aabb)) { + continue; + } + + if (cell.isLeaf()) { + nTris = cell.nodeIndices.length; + for (i = 0; i < nTris; i++) { + nodeBox = this.getQuadNode(cell.nodeIndices[i]).aabb; + if (nodeBox.testID != this._testID) { + nodeBox.testID = this._testID; + if (aabb.overlapTest(nodeBox)) { + result.push(cell.nodeIndices[i]); + } + } + } + } else { + for (i = 0; i < QuadTreeCell.NUM_CHILDREN; i++) { + this._cellsToTest.push(cell.childCellIndices[i]); + } + } + } + return result.length; + + } + + private pointInTriangle(x: number, y: number, triP1: Vector3, triP2: Vector3, triP3: Vector3): boolean { + var p1: Vector3 = triP1; + var p2: Vector3 = triP2; + var p3: Vector3 = triP3; + + // 直线方程p1-p2 + var A1: number = p1.z - p2.z; + var B1: number = p2.x - p1.x; + var C1: number = p1.x * p2.z - p2.x * p1.z; + // 直线方程p2-p3 + var A2: number = p2.z - p3.z; + var B2: number = p3.x - p2.x; + var C2: number = p2.x * p3.z - p3.x * p2.z; + // 直线方程p3-p1 + var A3: number = p3.z - p1.z; + var B3: number = p1.x - p3.x; + var C3: number = p3.x * p1.z - p1.x * p3.z; + + var isInTri: boolean = false; + var D1: number = A1 * x + B1 * y + C1; + var D2: number = A2 * x + B2 * y + C2; + var D3: number = A3 * x + B3 * y + C3; + + const Tiny: number = 0.01; + if ((D1 >= -Tiny && D2 >= -Tiny && D3 >= -Tiny) || (D1 <= Tiny && D2 <= Tiny && D3 <= Tiny)) + isInTri = true; + + return isInTri; + } + + private incrementTestCounter(): void { + ++this._testID; + if (this._testID == 0) { + var numTriangles: number = this._quadNodes.length; + for (var i: number = 0; i < numTriangles; i++) { + this._quadNodes[i].aabb.testID = 0; + } + this._testID = 1; + } + } + + private logDeep: number = 0; + private logTree(cellIndex: number): void { + if (cellIndex < 0) + return; + + this.logDeep++; + + var cell: QuadTreeCell = this._cells[cellIndex]; + + var spaces: String = ""; + for (var si: number = 0; si < (this.logDeep - 1); si++) + spaces += "-|"; + + console.log(spaces + "i=" + cellIndex + " " + + cell.aabb.minPosX.toFixed(2) + " " + cell.aabb.maxPosX.toFixed(2) + " " + + cell.aabb.minPosY.toFixed(2) + " " + cell.aabb.maxPosY.toFixed(2)); + + var i: number; + for (i = 0; i < cell.nodeIndices.length; i++) { + if (cell.nodeIndices[i] >= 0) { + var tri: IQuadNode = this._quadNodes[cell.nodeIndices[i]]; + console.log(spaces + " t=" + cell.nodeIndices[i] + " " + + tri.aabb.minPosX.toFixed(2) + " " + tri.aabb.maxPosX.toFixed(2) + " " + + tri.aabb.minPosY.toFixed(2) + " " + tri.aabb.maxPosY.toFixed(2)); + + } + } + for (i = 0; i < cell.childCellIndices.length; i++) { + if (cell.childCellIndices[i] >= 0) { + this.logTree(cell.childCellIndices[i]); + } + } + this.logDeep--; + } + +} diff --git a/src/core/tree/quad/QuadTreeCell.ts b/src/core/tree/quad/QuadTreeCell.ts new file mode 100644 index 00000000..083bbcd9 --- /dev/null +++ b/src/core/tree/quad/QuadTreeCell.ts @@ -0,0 +1,48 @@ +import { Vector3 } from "../../../math/Vector3"; +import { QuadAABB } from "./QuadAABB"; + + +export class QuadTreeCell { + + public static NUM_CHILDREN: number = 4; + + public childCellIndices: Array; + + public nodeIndices: Array; + + public aabb: QuadAABB; + + public points: Array; + + constructor(aabox: QuadAABB) { + this.childCellIndices = new Array(); + this.childCellIndices.length = QuadTreeCell.NUM_CHILDREN; + + this.nodeIndices = new Array(); + + this.clear(); + + if (aabox) { + this.aabb = aabox.clone(); + } else { + this.aabb = new QuadAABB(); + } + } + + /** + * @language zh_CN + * Indicates if we contain triangles (if not then we should/might have children) + */ + public isLeaf(): boolean { + return this.childCellIndices[0] == -1; + } + + public clear(): void { + for (var i: number = 0; i < QuadTreeCell.NUM_CHILDREN; i++) { + this.childCellIndices[i] = -1; + } + this.nodeIndices.splice(0, this.nodeIndices.length); + } + + +} \ No newline at end of file diff --git a/src/gfx/generate/BrdfLUTGenerate.ts b/src/gfx/generate/BrdfLUTGenerate.ts index 80b2d2a0..64e2ae9f 100644 --- a/src/gfx/generate/BrdfLUTGenerate.ts +++ b/src/gfx/generate/BrdfLUTGenerate.ts @@ -1,4 +1,4 @@ -import { BRDFLUT } from '../../assets/shader/utils/BRDFLUT'; +import { BRDFLUT } from '../../assets/shader/compute/BRDFLUT'; import { VirtualTexture } from '../../textures/VirtualTexture'; import { ComputeShader } from '../graphics/webGpu/shader/ComputeShader'; import { GPUTextureFormat } from '../graphics/webGpu/WebGPUConst'; diff --git a/src/gfx/generate/PassGenerate.ts b/src/gfx/generate/PassGenerate.ts index 064b2d96..416d7312 100644 --- a/src/gfx/generate/PassGenerate.ts +++ b/src/gfx/generate/PassGenerate.ts @@ -1,44 +1,45 @@ import { RenderNode } from '../../components/renderer/RenderNode'; -// import { CastPointShadowMaterialPass } from '../../materials/multiPass/CastPointShadowMaterialPass'; -// import { CastShadowMaterialPass } from '../../materials/multiPass/CastShadowMaterialPass'; -// import { DepthMaterialPass } from '../../materials/multiPass/DepthMaterialPass'; -// import { GBufferPass } from '../../materials/multiPass/GBufferPass'; -// import { SkyGBufferPass } from '../../materials/multiPass/SkyGBufferPass'; import { RendererMaskUtil, RendererMask } from '../renderJob/passRenderer/state/RendererMask'; -import { RendererType } from '../renderJob/passRenderer/state/RendererType'; +import { PassType } from '../renderJob/passRenderer/state/RendererType'; import { GLTFType } from '../../loader/parser/gltf/GLTFType'; -import { CastPointShadowMaterialPass, CastShadowMaterialPass, DepthMaterialPass, GBufferPass, Material, RendererPassState, SkyGBufferPass } from '../..'; +import { Shader } from '../graphics/webGpu/shader/Shader'; +import { SkyGBufferPass } from '../../materials/multiPass/SkyGBufferPass'; +import { GBufferPass } from '../../materials/multiPass/GBufferPass'; +import { VertexAttributeName } from '../../core/geometry/VertexAttributeName'; +import { CastShadowMaterialPass } from '../../materials/multiPass/CastShadowMaterialPass'; +import { CastPointShadowMaterialPass } from '../../materials/multiPass/CastPointShadowMaterialPass'; +import { DepthMaterialPass } from '../../materials/multiPass/DepthMaterialPass'; /** * @internal * @group GFX */ export class PassGenerate { - public static createGIPass(renderNode: RenderNode, material: Material) { + public static createGIPass(renderNode: RenderNode, shader: Shader) { if (RendererMaskUtil.hasMask(renderNode.rendererMask, RendererMask.Sky)) { - let colorPass = material.getPass(RendererType.COLOR)[0]; - let pass = new SkyGBufferPass(); - pass.setTexture(`baseMap`, colorPass.getTexture('baseMap')); - - pass.cullMode = colorPass.cullMode; - pass.frontFace = colorPass.frontFace; + let pass0 = shader.passShader.get(PassType.GI); + if (!pass0) { + let colorPass = shader.getSubShaders(PassType.COLOR)[0]; + let pass = new SkyGBufferPass(); + pass.setTexture(`baseMap`, colorPass.getTexture('baseMap')); + pass.cullMode = colorPass.cullMode; + pass.frontFace = colorPass.frontFace; + shader.addRenderPass(pass, 0); + pass.preCompile(renderNode.geometry); + } - material.addPass(RendererType.GI, pass, 0); - pass.preCompile(renderNode.geometry); } else { - this.castGBufferPass(renderNode, material); + this.castGBufferPass(renderNode, shader); } } - public static castGBufferPass(renderNode: RenderNode, material: Material) { - // for (let i = 0; i < renderNode.materials.length; i++) { - // const mat = renderNode.materials[i]; - let colorPassList = material.getPass(RendererType.COLOR); + public static castGBufferPass(renderNode: RenderNode, shader: Shader) { + let colorPassList = shader.getDefaultShaders(); for (let jj = 0; jj < colorPassList.length; jj++) { const colorPass = colorPassList[jj]; - let giPassList = material.getPass(RendererType.GI); - if (!giPassList || giPassList.length < jj) { + let giPassList = shader.getSubShaders(PassType.GI); + if (!giPassList || giPassList.length == 0 || giPassList.length < jj) { let pass = new GBufferPass(); pass.setTexture('baseMap', colorPass.getTexture("baseMap")); pass.setTexture('normalMap', colorPass.getTexture("normalMap")); @@ -53,23 +54,22 @@ export class PassGenerate { pass.cullMode = colorPass.cullMode; pass.frontFace = colorPass.frontFace; pass.preCompile(renderNode.geometry); - material.addPass(RendererType.GI, pass); + shader.addRenderPass(pass); } } - // } } - public static createShadowPass(renderNode: RenderNode, material: Material) { + public static createShadowPass(renderNode: RenderNode, shader: Shader) { let use_skeleton = RendererMaskUtil.hasMask(renderNode.rendererMask, RendererMask.SkinnedMesh); - let useTangent = renderNode.geometry.hasAttribute('TANGENT'); + let useTangent = renderNode.geometry.hasAttribute(VertexAttributeName.TANGENT); let useMorphTargets = renderNode.geometry.hasAttribute(GLTFType.MORPH_POSITION_PREFIX + '0'); let useMorphNormals = renderNode.geometry.hasAttribute(GLTFType.MORPH_NORMAL_PREFIX + '0'); - let colorPassList = material.getPass(RendererType.COLOR); + let colorPassList = shader.getSubShaders(PassType.COLOR); for (let i = 0; i < colorPassList.length; i++) { const colorPass = colorPassList[i]; - let shadowPassList = material.getPass(RendererType.SHADOW); - if (!shadowPassList || shadowPassList.length < i) { + let shadowPassList = shader.getSubShaders(PassType.SHADOW); + if (!shadowPassList || shadowPassList.length < (i + 1)) { let shadowPass = new CastShadowMaterialPass(); shadowPass.setTexture(`baseMap`, colorPass.getTexture(`baseMap`)); shadowPass.setUniform(`alphaCutoff`, colorPass.getUniform(`alphaCutoff`)); @@ -95,11 +95,11 @@ export class PassGenerate { shadowPass.shaderState.cullMode = `back`; } shadowPass.preCompile(renderNode.geometry); - material.addPass(RendererType.SHADOW, shadowPass); + shader.addRenderPass(shadowPass); } - let castPointShadowPassList = material.getPass(RendererType.POINT_SHADOW); - if (!castPointShadowPassList) { + let castPointShadowPassList = shader.getSubShaders(PassType.POINT_SHADOW); + if (!castPointShadowPassList || castPointShadowPassList.length < (i + 1)) { let castPointShadowPass = new CastPointShadowMaterialPass(); castPointShadowPass.setTexture(`baseMap`, colorPass.getTexture(`baseMap`)); castPointShadowPass.setUniform(`alphaCutoff`, colorPass.getUniform(`alphaCutoff`)); @@ -121,53 +121,13 @@ export class PassGenerate { castPointShadowPass.shaderState.cullMode = `front`; castPointShadowPass.preCompile(renderNode.geometry); } - material.addPass(RendererType.POINT_SHADOW, castPointShadowPass); + shader.addRenderPass(castPointShadowPass); } } } - public static createReflectionPass(renderNode: RenderNode, material: Material) { - // let reflectionPass = material.renderShader.getPassShader(RendererType.REFLECTION); - // if (!reflectionPass) { - // reflectionPass = new ColorLitMaterial(); - // let baseMat = renderNode.materials[0]; - // reflectionPass.baseMap = baseMat.baseMap; - // let useTangent = renderNode.geometry.hasVertexAttribute('TANGENT'); - // let useMorphTargets = renderNode.geometry.hasVertexAttribute(GLTFType.MORPH_POSITION_PREFIX + '0'); - // let useMorphNormals = renderNode.geometry.hasVertexAttribute(GLTFType.MORPH_NORMAL_PREFIX + '0'); - - // let use_skeleton = RendererMaskUtil.hasMask(renderNode.rendererMask, RendererMask.SkinnedMesh); - - // let shader = reflectionPass.getShader(); - // shader.shaderState.cullMode = baseMat.getShader().cullMode; - // shader.shaderState.frontFace = baseMat.getShader().frontFace; - - // for (let j = 0; j < 1; j++) { - // const renderShader = reflectionPass.getShader(); - - // if (!useTangent) { - // renderShader.setDefine(`USE_TANGENT`, useTangent); - // } - // if (use_skeleton) { - // renderShader.setDefine(`USE_SKELETON`, use_skeleton); - // } - // if (useMorphTargets) { - // renderShader.setDefine(`USE_MORPHTARGETS`, useMorphTargets); - // } - // if (useMorphNormals) { - // renderShader.setDefine(`USE_MORPHNORMALS`, useMorphNormals); - // } - - // renderShader.preCompile(renderNode.geometry, reflectionPass); - // } - - // material.renderShader.setPassShader(RendererType.REFLECTION, reflectionPass); - // } - // material.addPass(RendererType.REFLECTION, reflectionPass, 0); - } - - public static createDepthPass(renderNode: RenderNode, material: Material) { - let colorListPass = material.getPass(RendererType.COLOR); + public static createDepthPass(renderNode: RenderNode, shader: Shader) { + let colorListPass = shader.getSubShaders(PassType.COLOR); let useTangent = renderNode.geometry.hasAttribute('TANGENT'); let useMorphTargets = renderNode.geometry.hasAttribute(GLTFType.MORPH_POSITION_PREFIX + '0'); let useMorphNormals = renderNode.geometry.hasAttribute(GLTFType.MORPH_NORMAL_PREFIX + '0'); @@ -175,7 +135,7 @@ export class PassGenerate { for (let i = 0; i < colorListPass.length; i++) { const colorPass = colorListPass[i]; - let depthPassList = material.getPass(RendererType.DEPTH); + let depthPassList = shader.getSubShaders(PassType.DEPTH); if (!depthPassList && colorPass.shaderState.useZ) { if (!depthPassList || depthPassList.length < i) { let depthPass = new DepthMaterialPass(); @@ -195,7 +155,7 @@ export class PassGenerate { depthPass.cullMode = colorPass.cullMode; depthPass.frontFace = colorPass.frontFace; depthPass.preCompile(renderNode.geometry); - material.addPass(RendererType.DEPTH, depthPass); + shader.addRenderPass(depthPass); } } } diff --git a/src/gfx/graphics/webGpu/Context3D.ts b/src/gfx/graphics/webGpu/Context3D.ts index 628dc6e6..8b0865df 100644 --- a/src/gfx/graphics/webGpu/Context3D.ts +++ b/src/gfx/graphics/webGpu/Context3D.ts @@ -1,8 +1,10 @@ +import { CEventDispatcher } from '../../../event/CEventDispatcher'; +import { CResizeEvent } from '../../../event/CResizeEvent'; import { CanvasConfig } from './CanvasConfig'; /** * @internal */ -class Context3D { +class Context3D extends CEventDispatcher { public adapter: GPUAdapter; public device: GPUDevice; public context: GPUCanvasContext; @@ -15,6 +17,7 @@ class Context3D { public canvasConfig: CanvasConfig; public super: number = 1.0; private _pixelRatio: number = 1.0; + canResize: boolean = true; // initSize: number[]; public get pixelRatio() { return this._pixelRatio; @@ -34,7 +37,6 @@ class Context3D { // check if external canvas has initial with and height style const _width = this.canvas.clientWidth, _height = this.canvas.clientHeight - this.resize(this.canvas.clientWidth, this.canvas.clientHeight) // set a initial style if size changed if (_width != this.canvas.clientWidth) this.canvas.style.width = _width + 'px' @@ -104,28 +106,25 @@ class Context3D { format: this.presentationFormat, usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT, alphaMode: 'premultiplied', - colorSpace: `display-p3`, + colorSpace: `srgb`, }); - - // resize canvas size, aspect - this.resize(this.canvas.clientWidth, this.canvas.clientHeight) - let timer: any - const resizeObserver = new ResizeObserver(() => { - clearTimeout(timer) - timer = setTimeout(() => { - this.resize(this.canvas.clientWidth, this.canvas.clientHeight) - }, 50) - }); - resizeObserver.observe(this.canvas); + this.updateSize(); return true; } - public resize(width: number, height: number) { - this.canvas.width = this.windowWidth = Math.floor(width * this.pixelRatio * this.super) - this.canvas.height = this.windowHeight = Math.floor(height * this.pixelRatio * this.super) - this.presentationSize[0] = this.windowWidth; - this.presentationSize[1] = this.windowHeight; - this.aspect = this.windowWidth / this.windowHeight; + public updateSize() { + let w = Math.floor(this.canvas.clientWidth * this.pixelRatio * this.super); + let h = Math.floor(this.canvas.clientHeight * this.pixelRatio * this.super); + if (w != this.windowWidth || h != this.windowHeight) { + // if (this.canvas.width != this.windowWidth || this.canvas.height != this.windowHeight) { + this.canvas.width = this.windowWidth = w; + this.canvas.height = this.windowHeight = h; + this.presentationSize[0] = this.windowWidth; + this.presentationSize[1] = this.windowHeight; + this.aspect = this.windowWidth / this.windowHeight; + if (this.canResize) + this.dispatchEvent(new CResizeEvent(CResizeEvent.RESIZE, { width: this.windowWidth, height: this.windowHeight })); + } } } diff --git a/src/gfx/graphics/webGpu/PipelinePool.ts b/src/gfx/graphics/webGpu/PipelinePool.ts index 0e0bc733..cbea888e 100644 --- a/src/gfx/graphics/webGpu/PipelinePool.ts +++ b/src/gfx/graphics/webGpu/PipelinePool.ts @@ -1,4 +1,4 @@ -import { PoolNode, RenderShader } from "../../.."; +import { PoolNode, RenderShaderPass } from "../../.."; export class PipelinePool { private static pipelineMap: Map = new Map(); diff --git a/src/gfx/graphics/webGpu/compute/PreIntegratedLutCompute.ts b/src/gfx/graphics/webGpu/compute/PreIntegratedLutCompute.ts new file mode 100644 index 00000000..0262c6c4 --- /dev/null +++ b/src/gfx/graphics/webGpu/compute/PreIntegratedLutCompute.ts @@ -0,0 +1,40 @@ +import { VirtualTexture } from '../../../../textures/VirtualTexture'; +import { GPUTextureFormat } from '../WebGPUConst'; +import { GPUContext } from '../../../renderJob/GPUContext'; +import { RenderShaderCompute } from './RenderShaderCompute'; +import { PreIntegratedLut } from '../../../../assets/shader/compute/PreIntegratedLut'; +import { MaterialDataUniformGPUBuffer } from '../core/buffer/MaterialDataUniformGPUBuffer'; +import { Shader } from '../shader/Shader'; +/** + * @internal + * @group GFX + */ +export class PreIntegratedLutCompute extends RenderShaderCompute { + + constructor(shader: Shader) { + super(PreIntegratedLut, shader); + } + + protected init() { + //create virtual texture + let texture = new VirtualTexture(256, 256, GPUTextureFormat.rgba8unorm, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING); + + //set storageTexture + this.compute.setStorageTexture('sssMap', texture); + this.sourceShader.setTexture("lutMap", texture); + + return texture; + } + + public onFrame() { + + //set worker size + this.compute.workerSizeX = 256 / 8; + this.compute.workerSizeY = 256 / 8; + + //active + let commandEncoder = GPUContext.beginCommandEncoder(); + GPUContext.computeCommand(commandEncoder, [this.compute]); + GPUContext.endCommandEncoder(commandEncoder); + } +} diff --git a/src/gfx/graphics/webGpu/compute/RenderShaderCompute.ts b/src/gfx/graphics/webGpu/compute/RenderShaderCompute.ts new file mode 100644 index 00000000..2b32a6f3 --- /dev/null +++ b/src/gfx/graphics/webGpu/compute/RenderShaderCompute.ts @@ -0,0 +1,35 @@ +import { Shader } from "../../../.."; +import { ComputeShader } from "../shader/ComputeShader"; + +export class RenderShaderCompute { + + protected sourceShader: Shader; + protected compute: ComputeShader; + + protected needUpdate: boolean = true; + + constructor(shaderStr: string, sourceShader: Shader) { + this.sourceShader = sourceShader; + this.compute = new ComputeShader(shaderStr); + this.init(); + } + + protected init() { + + } + + protected onOnce?() + + protected onFrame?() + + public onUpdate() { + if (this.onFrame) { + this.onFrame(); + } + + if (this.onOnce && this.needUpdate) { + this.needUpdate = false; + this.onFrame(); + } + } +} \ No newline at end of file diff --git a/src/gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup.ts b/src/gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup.ts index 03fc39a9..34b5d342 100644 --- a/src/gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup.ts +++ b/src/gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup.ts @@ -24,6 +24,16 @@ export class GlobalUniformGroup { private uniformByteLength: number; private matrixesByteLength: number; + private shadowMatrixRaw = new Float32Array(8 * 16); + private csmMatrixRaw = new Float32Array(CSM.Cascades * 16); + private csmShadowBias = new Float32Array(4); + + public shadowLights = new Float32Array(16); + public dirShadowStart = 0; + public dirShadowEnd = 0; + public pointShadowStart = 0; + public pointShadowEnd = 0; + /** * * @param matrixBindGroup global matrix bindgroup @@ -33,7 +43,8 @@ export class GlobalUniformGroup { this.usage = GPUBufferUsage.UNIFORM | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST; // ... + 8(shadow matrix) + 8(csm matrix) + 4(csm bias) + 4(csm scattering exp...) this.uniformGPUBuffer = new UniformGPUBuffer(32 * 4 * 4 + (3 * 4 * 4) + 8 * 16 + CSM.Cascades * 16 + 4 + 4); - this.uniformGPUBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE + this.uniformGPUBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE; + this.matrixBindGroup = matrixBindGroup; this.createBindGroup(); @@ -67,9 +78,7 @@ export class GlobalUniformGroup { }); } - private shadowMatrixRaw = new Float32Array(8 * 16); - private csmMatrixRaw = new Float32Array(CSM.Cascades * 16); - private csmShadowBias = new Float32Array(4); + public setCamera(camera: Camera3D) { this.uniformGPUBuffer.setMatrix(`_projectionMatrix`, camera.projectionMatrix); @@ -102,21 +111,19 @@ export class GlobalUniformGroup { } this.uniformGPUBuffer.setFloat32Array(`csmShadowBias`, this.csmShadowBias); this.uniformGPUBuffer.setFloat32Array(`csmMatrix`, this.csmMatrixRaw); - this.uniformGPUBuffer.setVector3(`CameraPos`, camera.transform.worldPosition); this.uniformGPUBuffer.setFloat(`frame`, Time.frame); this.uniformGPUBuffer.setFloat(`time`, Time.frame); this.uniformGPUBuffer.setFloat(`delta`, Time.delta); + // this.uniformGPUBuffer.setFloat(`shadowBias`, Engine3D.setting.shadow.shadowBias); this.uniformGPUBuffer.setFloat(`shadowBias`, camera.getShadowBias(shadowMapSize)); this.uniformGPUBuffer.setFloat(`skyExposure`, Engine3D.setting.sky.skyExposure); this.uniformGPUBuffer.setFloat(`renderPassState`, Engine3D.setting.render.renderPassState); this.uniformGPUBuffer.setFloat(`quadScale`, Engine3D.setting.render.quadScale); this.uniformGPUBuffer.setFloat(`hdrExposure`, Engine3D.setting.render.hdrExposure); - this.uniformGPUBuffer.setInt32(`renderState_left`, Engine3D.setting.render.renderState_left); this.uniformGPUBuffer.setInt32(`renderState_right`, Engine3D.setting.render.renderState_right); this.uniformGPUBuffer.setFloat(`renderState_split`, Engine3D.setting.render.renderState_split); - let mouseX = Engine3D.inputSystem.mouseX * webGPUContext.pixelRatio; let mouseY = Engine3D.inputSystem.mouseY * webGPUContext.pixelRatio; this.uniformGPUBuffer.setFloat(`mouseX`, mouseX); @@ -125,14 +132,16 @@ export class GlobalUniformGroup { this.uniformGPUBuffer.setFloat(`windowHeight`, webGPUContext.windowHeight); this.uniformGPUBuffer.setFloat(`near`, camera.near); this.uniformGPUBuffer.setFloat(`far`, camera.far); - this.uniformGPUBuffer.setFloat(`pointShadowBias`, Engine3D.setting.shadow.pointShadowBias); this.uniformGPUBuffer.setFloat(`shadowMapSize`, shadowMapSize); this.uniformGPUBuffer.setFloat(`shadowSoft`, Engine3D.setting.shadow.shadowSoft); this.uniformGPUBuffer.setFloat(`enableCSM`, camera.enableCSM ? 1 : 0); - this.uniformGPUBuffer.setFloat(`csmMargin`, Engine3D.setting.shadow.csmMargin); - + this.uniformGPUBuffer.setInt32(`nDirShadowStart`, this.dirShadowStart); + this.uniformGPUBuffer.setInt32(`nDirShadowEnd`, this.dirShadowEnd); + this.uniformGPUBuffer.setInt32(`nPointShadowStart`, this.pointShadowStart); + this.uniformGPUBuffer.setInt32(`nPointShadowEnd`, this.pointShadowEnd); + this.uniformGPUBuffer.setFloat32Array(`shadowLights`, this.shadowLights); this.uniformGPUBuffer.apply(); } @@ -153,7 +162,7 @@ export class GlobalUniformGroup { this.uniformGPUBuffer.setFloat(`frame`, Time.frame); this.uniformGPUBuffer.setFloat(`time`, Time.frame); this.uniformGPUBuffer.setFloat(`delta`, Time.delta); - this.uniformGPUBuffer.setFloat(`shadowBias`, 0.0001); + this.uniformGPUBuffer.setFloat(`shadowBias`, Engine3D.setting.shadow.shadowBias); this.uniformGPUBuffer.setFloat(`skyExposure`, Engine3D.setting.sky.skyExposure); this.uniformGPUBuffer.setFloat(`renderPassState`, Engine3D.setting.render.renderPassState); this.uniformGPUBuffer.setFloat(`quadScale`, Engine3D.setting.render.quadScale); @@ -178,12 +187,16 @@ export class GlobalUniformGroup { this.uniformGPUBuffer.setFloat(`enableCSM`, 0); this.uniformGPUBuffer.setFloat(`csmMargin`, Engine3D.setting.shadow.csmMargin); - + this.uniformGPUBuffer.setInt32(`nDirShadowStart`, this.dirShadowStart); + this.uniformGPUBuffer.setInt32(`nDirShadowEnd`, this.dirShadowEnd); + this.uniformGPUBuffer.setInt32(`nPointShadowStart`, this.pointShadowStart); + this.uniformGPUBuffer.setInt32(`nPointShadowEnd`, this.pointShadowEnd); + this.uniformGPUBuffer.setFloat32Array(`shadowLights`, this.shadowLights); this.uniformGPUBuffer.apply(); } - public addUniformNode() { } + public setShadowLight() { } } diff --git a/src/gfx/graphics/webGpu/core/buffer/ComputeGPUBuffer.ts b/src/gfx/graphics/webGpu/core/buffer/ComputeGPUBuffer.ts index f02d3e09..b86680e6 100644 --- a/src/gfx/graphics/webGpu/core/buffer/ComputeGPUBuffer.ts +++ b/src/gfx/graphics/webGpu/core/buffer/ComputeGPUBuffer.ts @@ -10,6 +10,6 @@ export class ComputeGPUBuffer extends GPUBufferBase { constructor(size: number, data?: Float32Array) { super(); this.bufferType = GPUBufferType.ComputeGPUBuffer; - this.createBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST, size, data); + this.createBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST, size, data, "ComputeGPUBuffer"); } } diff --git a/src/gfx/graphics/webGpu/core/buffer/GPUBufferBase.ts b/src/gfx/graphics/webGpu/core/buffer/GPUBufferBase.ts index d9e98fdb..bb6a6d7c 100644 --- a/src/gfx/graphics/webGpu/core/buffer/GPUBufferBase.ts +++ b/src/gfx/graphics/webGpu/core/buffer/GPUBufferBase.ts @@ -309,10 +309,6 @@ export class GPUBufferBase { // this.applyMapAsync(); } - public applyMapAsync() { - this.mapAsyncWrite(new Float32Array(this.memory.shareDataBuffer), this.memory.shareDataBuffer.byteLength / 4); - } - public mapAsyncWrite(mapAsyncArray: Float32Array, len: number) { // Upload data using mapAsync and a queue of staging buffers. let bytesLen = len; @@ -382,7 +378,7 @@ export class GPUBufferBase { } } - protected createBuffer(usage: GPUBufferUsageFlags, size: number, data?: ArrayBufferData) { + protected createBuffer(usage: GPUBufferUsageFlags, size: number, data?: ArrayBufferData, debugLabel?: string) { let device = webGPUContext.device; this.byteSize = size * 4; this.usage = usage; @@ -390,6 +386,7 @@ export class GPUBufferBase { this.destroy(); } this.buffer = device.createBuffer({ + label: debugLabel, size: this.byteSize, usage: usage, mappedAtCreation: false, @@ -424,6 +421,7 @@ export class GPUBufferBase { let device = webGPUContext.device; this.buffer = device.createBuffer({ + label: "StructStorageGPUBuffer", size: totalLength, // size: totalLength * 4, usage: usage, diff --git a/src/gfx/graphics/webGpu/core/buffer/IndicesGPUBuffer.ts b/src/gfx/graphics/webGpu/core/buffer/IndicesGPUBuffer.ts index cde486b4..ab6f0ea0 100644 --- a/src/gfx/graphics/webGpu/core/buffer/IndicesGPUBuffer.ts +++ b/src/gfx/graphics/webGpu/core/buffer/IndicesGPUBuffer.ts @@ -26,6 +26,7 @@ export class IndicesGPUBuffer extends GPUBufferBase { this.destroy(); } this.buffer = device.createBuffer({ + label: "IndicesGPUBuffer", size: this.byteSize, usage: usage, mappedAtCreation: false, diff --git a/src/gfx/graphics/webGpu/core/buffer/MaterialDataUniformGPUBuffer.ts b/src/gfx/graphics/webGpu/core/buffer/MaterialDataUniformGPUBuffer.ts index d47ab69c..69ad9332 100644 --- a/src/gfx/graphics/webGpu/core/buffer/MaterialDataUniformGPUBuffer.ts +++ b/src/gfx/graphics/webGpu/core/buffer/MaterialDataUniformGPUBuffer.ts @@ -31,7 +31,7 @@ export class MaterialDataUniformGPUBuffer extends GPUBufferBase { } len = Math.floor(len / 256 + 1) * 256; - this.createBuffer(GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, len / 4); + this.createBuffer(GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, len / 4, null, "MaterialDataUniformGPUBuffer"); for (const key in uniformNodes) { const node = uniformNodes[key]; if (!node) console.error(key, "is empty"); @@ -52,11 +52,6 @@ export class MaterialDataUniformGPUBuffer extends GPUBufferBase { */ public apply() { if (this.uniformNodes.length == 0) return; - // if (this.uniformNodes.length > 0 && this.uniformNodes[0].type == "IrradianceVolumeData") { - // if (this.uniformNodes[0].data["isVolumeFrameChange"]) { - // this._onChange = true; - // } - // } if (!this._onChange) return; for (const key in this.uniformNodes) { diff --git a/src/gfx/graphics/webGpu/core/buffer/MatrixGPUBuffer.ts b/src/gfx/graphics/webGpu/core/buffer/MatrixGPUBuffer.ts index 1054bef1..2ac8ccd6 100644 --- a/src/gfx/graphics/webGpu/core/buffer/MatrixGPUBuffer.ts +++ b/src/gfx/graphics/webGpu/core/buffer/MatrixGPUBuffer.ts @@ -17,7 +17,7 @@ export class MatrixGPUBuffer extends GPUBufferBase { super(); this.bufferType = GPUBufferType.StorageGPUBuffer; this.size = size; - this.createBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | usage, size, data); + this.createBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | usage, size, data, "MatrixGPUBuffer"); } public writeBufferByHeap(mapAsyncArray: Float32Array, len: number) { diff --git a/src/gfx/graphics/webGpu/core/buffer/StorageGPUBuffer.ts b/src/gfx/graphics/webGpu/core/buffer/StorageGPUBuffer.ts index d728a408..83cda847 100644 --- a/src/gfx/graphics/webGpu/core/buffer/StorageGPUBuffer.ts +++ b/src/gfx/graphics/webGpu/core/buffer/StorageGPUBuffer.ts @@ -11,7 +11,7 @@ export class StorageGPUBuffer extends GPUBufferBase { constructor(size: number, usage: number = 0, data?: ArrayBufferData) { super(); this.bufferType = GPUBufferType.StorageGPUBuffer; - this.createBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | usage, size, data); + this.createBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | usage, size, data, "StorageGPUBuffer"); // this.createBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, size, data); } } diff --git a/src/gfx/graphics/webGpu/core/buffer/UniformGPUBuffer.ts b/src/gfx/graphics/webGpu/core/buffer/UniformGPUBuffer.ts index 1ee4860a..3fe78db0 100644 --- a/src/gfx/graphics/webGpu/core/buffer/UniformGPUBuffer.ts +++ b/src/gfx/graphics/webGpu/core/buffer/UniformGPUBuffer.ts @@ -10,7 +10,7 @@ export class UniformGPUBuffer extends GPUBufferBase { constructor(size: number, data?: Float32Array) { super(); this.bufferType = GPUBufferType.UniformGPUBuffer; - this.createBuffer(GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC, size, data); + this.createBuffer(GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC, size, data, "UniformGPUBuffer"); } public genUniformNodes() { diff --git a/src/gfx/graphics/webGpu/core/buffer/VertexGPUBuffer.ts b/src/gfx/graphics/webGpu/core/buffer/VertexGPUBuffer.ts index 30dcb0f7..c09605e4 100644 --- a/src/gfx/graphics/webGpu/core/buffer/VertexGPUBuffer.ts +++ b/src/gfx/graphics/webGpu/core/buffer/VertexGPUBuffer.ts @@ -25,6 +25,7 @@ export class VertexGPUBuffer extends GPUBufferBase { this.destroy(); } this.buffer = device.createBuffer({ + label: "VertexGPUBuffer", size: this.byteSize, usage: usage, mappedAtCreation: false, diff --git a/src/gfx/graphics/webGpu/core/texture/Texture.ts b/src/gfx/graphics/webGpu/core/texture/Texture.ts index 8afe6cd1..13534184 100644 --- a/src/gfx/graphics/webGpu/core/texture/Texture.ts +++ b/src/gfx/graphics/webGpu/core/texture/Texture.ts @@ -1,6 +1,7 @@ -import { GPUAddressMode } from '../../WebGPUConst'; +import { GPUAddressMode, GPUFilterMode } from '../../WebGPUConst'; import { TextureMipmapGenerator } from './TextureMipmapGenerator'; import { webGPUContext } from '../../Context3D'; +import { TextureMipmapCompute } from './TextureMipmapCompute'; /** * Texture @@ -51,7 +52,7 @@ export class Texture implements GPUSamplerDescriptor { /** * GPUTextureUsage */ - public usage: number; + public usage: GPUFlagsConstant; /** * texture width @@ -203,9 +204,9 @@ export class Texture implements GPUSamplerDescriptor { this.height = height; this.numberLayer = numberLayer; - this.minFilter = 'linear'; - this.magFilter = 'linear'; - this.mipmapFilter = `linear`; + this.minFilter = GPUFilterMode.linear; + this.magFilter = GPUFilterMode.linear; + this.mipmapFilter = GPUFilterMode.linear; this.addressModeU = GPUAddressMode.repeat; this.addressModeV = GPUAddressMode.repeat; // this.visibility = GPUShaderStage.FRAGMENT; @@ -263,6 +264,8 @@ export class Texture implements GPUSamplerDescriptor { } else { this.viewDescriptor = { dimension: this.textureBindingLayout.viewDimension, + mipLevelCount: mipLevelCount, + baseMipLevel: 0 }; } } @@ -300,6 +303,7 @@ export class Texture implements GPUSamplerDescriptor { if (this.useMipmap) { TextureMipmapGenerator.webGPUGenerateMipmap(this); + // TextureMipmapCompute.createMipmap(this,this.mipmapCount); } } @@ -348,9 +352,16 @@ export class Texture implements GPUSamplerDescriptor { return this._sourceImageData; } + public getMipmapCount() { + let w = this.width; + let h = this.height; + let maxSize = Math.max(w, h); + return 1 + Math.log2(maxSize) | 0; + } + protected updateTextureDescription() { // let mipmapCount = this.useMipmap ? Math.floor(Math.log2(this.width)) : 1; - this.mipmapCount = Math.floor(this.useMipmap ? Math.log2(Math.min(this.width, this.height)) : 1); + this.mipmapCount = Math.floor(this.useMipmap ? this.getMipmapCount() : 1); this.createTextureDescriptor(this.width, this.height, this.mipmapCount, this.format); } @@ -532,4 +543,16 @@ export class Texture implements GPUSamplerDescriptor { } } + private static _texs: GPUTexture[] = []; + public static delayDestroyTexture(tex: GPUTexture) { + this._texs.push(tex); + } + + public static destroyTexture() { + if (this._texs.length > 0) { + while (this._texs.length > 0) { + this._texs.shift().destroy(); + } + } + } } diff --git a/src/gfx/graphics/webGpu/core/texture/TextureMipmapGenerator.ts b/src/gfx/graphics/webGpu/core/texture/TextureMipmapGenerator.ts index 1791ea2f..5dc44dd3 100644 --- a/src/gfx/graphics/webGpu/core/texture/TextureMipmapGenerator.ts +++ b/src/gfx/graphics/webGpu/core/texture/TextureMipmapGenerator.ts @@ -1,5 +1,6 @@ import { GPUContext } from '../../../../renderJob/GPUContext'; import { webGPUContext } from '../../Context3D'; +import { GPUFilterMode } from '../../WebGPUConst'; import { Texture } from './Texture'; /** * @internal @@ -80,6 +81,13 @@ export class TextureMipmapGenerator { return pipeline; } + public static getMipmapCount(texture: Texture) { + let w = texture.width; + let h = texture.height; + let maxSize = Math.max(w, h); + return 1 + Math.log2(maxSize) | 0; + } + // TextureDescriptor should be the descriptor that the texture was created with. // This version only works for basic 2D textures. public static webGPUGenerateMipmap(texture: Texture) { @@ -112,7 +120,7 @@ export class TextureMipmapGenerator { @fragment fn fragmentMain(@location(0) texCoord : vec2) -> @location(0) vec4 { - var outColor: vec4 = textureSample(img, imgSampler, texCoord); + var outColor: vec4 = textureSampleLevel(img, imgSampler, texCoord , 0.0 ); return outColor; } `, @@ -149,8 +157,8 @@ export class TextureMipmapGenerator { }); } else { sampler = gpuDevice.createSampler({ - minFilter: `linear`, - magFilter: `linear`, + minFilter: GPUFilterMode.linear, + magFilter: GPUFilterMode.linear, }); } diff --git a/src/gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator.ts b/src/gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator.ts index 3768d3ce..8f83a9fc 100644 --- a/src/gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator.ts +++ b/src/gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator.ts @@ -3,6 +3,7 @@ import { RTResourceConfig } from '../../../renderJob/config/RTResourceConfig'; import { GPUTextureFormat } from '../WebGPUConst'; import { webGPUContext } from '../Context3D'; import { RendererPassState } from '../../../renderJob/passRenderer/state/RendererPassState'; +import { CResizeEvent } from '../../../../event/CResizeEvent'; /** * @internal * @author sirxu @@ -24,27 +25,29 @@ export class WebGPUDescriptorCreator { rps.isOutTarget = rtFrame.isOutTarget; rps.depthCleanValue = rtFrame.depthCleanValue; rps.depthLoadOp = rtFrame.depthLoadOp; - if (rtFrame && rtFrame.attachments.length > 0) { - rps.renderTargets = rtFrame.attachments; - rps.rtTextureDescripts = rtFrame.rtDescriptors; + + if (rtFrame && rtFrame.renderTargets.length > 0) { + rps.renderTargets = rtFrame.renderTargets; + rps.rtTextureDescriptors = rtFrame.rtDescriptors; rps.renderPassDescriptor = WebGPUDescriptorCreator.getRenderPassDescriptor(rps); rps.renderBundleEncoderDescriptor = WebGPUDescriptorCreator.getRenderBundleDescriptor(rps); - rps.outAttachments = []; - for (let i = 0; i < rtFrame.attachments.length; i++) { - const element = rtFrame.attachments[i]; - rps.outAttachments[i] = { + rps.renderTargetTextures = []; + for (let i = 0; i < rtFrame.renderTargets.length; i++) { + const element = rtFrame.renderTargets[i]; + rps.renderTargetTextures[i] = { format: element.format, }; if (element.name.indexOf(RTResourceConfig.colorBufferTex_NAME) != -1) { rps.outColor = i; } } + } else { rps.renderPassDescriptor = WebGPUDescriptorCreator.getRenderPassDescriptor(rps, loadOp); rps.renderBundleEncoderDescriptor = WebGPUDescriptorCreator.getRenderBundleDescriptor(rps); // if(!rps.customSize){ - rps.outAttachments = [ + rps.renderTargetTextures = [ { format: webGPUContext.presentationFormat, }, @@ -74,7 +77,7 @@ export class WebGPUDescriptorCreator { size = [renderPassState.renderTargets[0].width, renderPassState.renderTargets[0].height]; for (let i = 0; i < renderPassState.renderTargets.length; i++) { const texture = renderPassState.renderTargets[i]; - const rtDesc = renderPassState.rtTextureDescripts[i]; + const rtDesc = renderPassState.rtTextureDescriptors[i]; attachMentTexture.push({ view: texture.getGPUView(), resolveTarget: undefined, diff --git a/src/gfx/graphics/webGpu/shader/ComputeShader.ts b/src/gfx/graphics/webGpu/shader/ComputeShader.ts index 9f5f5b43..88b57776 100644 --- a/src/gfx/graphics/webGpu/shader/ComputeShader.ts +++ b/src/gfx/graphics/webGpu/shader/ComputeShader.ts @@ -1,6 +1,6 @@ import { Texture } from '../core/texture/Texture'; import { webGPUContext } from '../Context3D'; -import { ShaderBase } from './ShaderBase'; +import { ShaderPassBase } from './ShaderPassBase'; import { ShaderReflection, ShaderReflectionVarInfo } from './value/ShaderReflectionInfo'; import { Preprocessor } from './util/Preprocessor'; import { Reference, Struct } from '../../../..'; @@ -13,7 +13,7 @@ import { UniformGPUBuffer } from '../core/buffer/UniformGPUBuffer'; * @author sirxu * compute shader kernel */ -export class ComputeShader extends ShaderBase { +export class ComputeShader extends ShaderPassBase { /** * Compute shader entry point name */ diff --git a/src/gfx/graphics/webGpu/shader/RenderShader.ts b/src/gfx/graphics/webGpu/shader/RenderShaderPass.ts similarity index 94% rename from src/gfx/graphics/webGpu/shader/RenderShader.ts rename to src/gfx/graphics/webGpu/shader/RenderShaderPass.ts index 24e6da9e..9a7c9249 100644 --- a/src/gfx/graphics/webGpu/shader/RenderShader.ts +++ b/src/gfx/graphics/webGpu/shader/RenderShaderPass.ts @@ -12,7 +12,7 @@ import { UniformNode } from "../core/uniforms/UniformNode"; import { Texture } from "../core/texture/Texture"; import { webGPUContext } from "../Context3D"; import { ShaderConverter } from "./converter/ShaderConverter"; -import { ShaderBase } from "./ShaderBase"; +import { ShaderPassBase } from "./ShaderPassBase"; import { ShaderStage } from "./ShaderStage"; import { Preprocessor } from "./util/Preprocessor"; import { ShaderReflection, ShaderReflectionVarInfo } from "./value/ShaderReflectionInfo"; @@ -25,9 +25,13 @@ import { Reference } from "../../../../util/Reference"; import { CSM } from "../../../../core/csm/CSM"; import { GPUCompareFunction, GPUCullMode } from "../WebGPUConst"; import { UniformValue } from "./value/UniformValue"; +import { PassType } from "../../../renderJob/passRenderer/state/RendererType"; +import { Vector4 } from "../../../../math/Vector4"; import { PipelinePool } from "../PipelinePool"; -export class RenderShader extends ShaderBase { +export class RenderShaderPass extends ShaderPassBase { + + public passType: PassType = PassType.COLOR; public useRz: boolean = false; @@ -61,10 +65,7 @@ export class RenderShader extends ShaderBase { */ public bindGroupLayouts: GPUBindGroupLayout[]; - /** - * Uniform data for materials - */ - public materialDataUniformBuffer: MaterialDataUniformGPUBuffer; + public envMap: Texture; @@ -79,6 +80,7 @@ export class RenderShader extends ShaderBase { protected _textureGroup: number = -1; protected _textureChange: boolean = false; protected _groupsShaderReflectionVarInfos: ShaderReflectionVarInfo[][]; + outBufferMask: Vector4; constructor(vs: string, fs: string) { super(); @@ -112,7 +114,6 @@ export class RenderShader extends ShaderBase { this._bufferDic.set(`materialUniform`, this.materialDataUniformBuffer); } - /** * Blend mode */ @@ -142,6 +143,20 @@ export class RenderShader extends ShaderBase { this.shaderState.cullMode = b; } + /** + * depthWriteEnabled mode + */ + public get depthWriteEnabled(): boolean { + return this.shaderState.depthWriteEnabled; + } + + public set depthWriteEnabled(value: boolean) { + if (this.shaderState.depthWriteEnabled != value) { + this._valueChange = true; + } + this.shaderState.depthWriteEnabled = value; + } + /** * get render face cull mode */ @@ -370,7 +385,7 @@ export class RenderShader extends ShaderBase { //*********************************/ //******************/ - if (renderPassState.outAttachments.length > 1) { + if (renderPassState.renderTargetTextures.length > 1) { this.defineValue[`USE_WORLDPOS`] = true; this.defineValue[`USEGBUFFER`] = true; } else { @@ -692,7 +707,22 @@ export class RenderShader extends ShaderBase { let bufferMesh = geometry; let shaderState = this.shaderState; - let targets = renderPassState.outAttachments; + //create color state + let targets: GPUColorTargetState[] = []; + for (const tex of renderPassState.renderTargetTextures) { + targets.push({ + format: tex.format, + }); + } + + //set color state + for (let i = 0; i < targets.length; i++) { + const rtTexState = targets[i]; + if (shaderState.writeMasks && shaderState.writeMasks.length > 0) { + rtTexState.writeMask = shaderState.writeMasks[i]; + } + } + if (renderPassState.outColor != -1) { let target = targets[renderPassState.outColor]; if (shaderState.blendMode != BlendMode.NONE) { @@ -807,6 +837,8 @@ export class RenderShader extends ShaderBase { private preDefine(geometry: GeometryBase) { // this.vertexAttributes = "" ; // check geometry vertex attributes + let useSecondUV = geometry.hasAttribute(VertexAttributeName.TEXCOORD_1); + let isSkeleton = geometry.hasAttribute(VertexAttributeName.joints0); let hasMorphTarget = geometry.hasAttribute(VertexAttributeName.a_morphPositions_0); @@ -819,8 +851,16 @@ export class RenderShader extends ShaderBase { let useLight = this.shaderState.useLight; - this.defineValue[`USE_SKELETON`] = isSkeleton; - this.defineValue[`USE_MORPHTARGETS`] = hasMorphTarget; + if (useSecondUV) { + this.defineValue[`USE_SECONDUV`] = true; + } + + if (isSkeleton && hasMorphTarget) { + this.defineValue[`USE_METAHUMAN`] = true; + } else { + this.defineValue[`USE_SKELETON`] = isSkeleton; + this.defineValue[`USE_MORPHTARGETS`] = hasMorphTarget; + } if (!('USE_TANGENT' in this.defineValue)) { this.defineValue[`USE_TANGENT`] = useTangent; @@ -908,14 +948,16 @@ export class RenderShader extends ShaderBase { } else { texture.destroy(false); let table = Reference.getInstance().getReference(texture); - let list = []; - table.forEach((v, k) => { - if (`name` in v) { - list.push(v[`name`]); - } else { - list.push(`NaN`); - } - }); + if (table) { + let list = []; + table.forEach((v, k) => { + if (`name` in v) { + list.push(v[`name`]); + } else { + list.push(`NaN`); + } + }); + } } } } @@ -963,7 +1005,7 @@ export class RenderShader extends ShaderBase { * @returns Returns the instance ID of the RenderShader */ public static createShader(vs: string, fs: string): string { - let shader = new RenderShader(vs, fs); + let shader = new RenderShaderPass(vs, fs); ShaderUtil.renderShader.set(shader.instanceID, shader); return shader.instanceID; } diff --git a/src/gfx/graphics/webGpu/shader/Shader.ts b/src/gfx/graphics/webGpu/shader/Shader.ts new file mode 100644 index 00000000..6fdb3997 --- /dev/null +++ b/src/gfx/graphics/webGpu/shader/Shader.ts @@ -0,0 +1,245 @@ +import { RenderShaderCompute } from "../compute/RenderShaderCompute"; +import { GPUBufferBase } from "../core/buffer/GPUBufferBase"; +import { StorageGPUBuffer } from "../core/buffer/StorageGPUBuffer"; +import { StructStorageGPUBuffer } from "../core/buffer/StructStorageGPUBuffer"; +import { UniformGPUBuffer } from "../core/buffer/UniformGPUBuffer"; +import { Texture } from "../core/texture/Texture"; +import { RenderShaderPass } from "./RenderShaderPass"; +import { UniformValue } from "./value/UniformValue"; +import { PassType } from "../../../renderJob/passRenderer/state/RendererType"; +import { Color } from "../../../../math/Color"; +import { Vector2 } from "../../../../math/Vector2"; +import { Vector3 } from "../../../../math/Vector3"; +import { Vector4 } from "../../../../math/Vector4"; +import { Struct } from "../../../../util/struct/Struct"; + +export class Shader { + + + public computes: RenderShaderCompute[]; + + public passShader: Map; + + constructor() { + this.computes = []; + this.passShader = new Map(); + } + + public addRenderPass(renderShader: RenderShaderPass, index: number = -1) { + let subShader: RenderShaderPass[] = this.passShader.get(renderShader.passType) || []; + if (index == -1) { + subShader.push(renderShader); + } else { + subShader.splice(index, -1, renderShader); + } + this.passShader.set(renderShader.passType, subShader); + } + + public removeShader(renderShader: RenderShaderPass, index: number = -1) { + let subShader: RenderShaderPass[] = this.passShader.get(renderShader.passType); + if (subShader) { + if (index == -1) { + let index = subShader.indexOf(renderShader); + if (index != -1) { + subShader.splice(index); + } + } else { + subShader.splice(index, 1); + } + } + } + + public removeShaderByIndex(passType: PassType, index: number = -1) { + let subShader: RenderShaderPass[] = this.passShader.get(passType); + if (subShader) { + if (index == -1) { + this.passShader.delete(passType); + } else { + subShader.splice(index, 1); + } + } + } + + public getSubShaders(passType: PassType): RenderShaderPass[] { + return this.passShader.get(passType) || []; + } + + public hasSubShaders(passType: PassType): boolean { + let subs = this.passShader.get(passType); + return subs.length > 0; + } + + public getDefaultShaders(): RenderShaderPass[] { + return this.passShader.get(PassType.COLOR); + } + + public getDefaultColorShader(): RenderShaderPass { + return this.passShader.get(PassType.COLOR)[0]; + } + + public setDefine(arg0: string, arg1: boolean) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setDefine(arg0, arg1); + } + } + } + + public deleteDefine(arg0: string) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.deleteDefine(arg0); + } + } + } + + public setUniform(arg0: string, arg1: UniformValue) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setUniform(arg0, arg1); + } + } + } + + public setUniformFloat(arg0: string, arg1: number) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setUniformFloat(arg0, arg1); + } + } + } + + public setUniformVector2(arg0: string, arg1: Vector2) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setUniformVector2(arg0, arg1); + } + } + } + + public setUniformVector3(arg0: string, arg1: Vector3) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setUniformVector3(arg0, arg1); + } + } + } + + public setUniformVector4(arg0: string, arg1: Vector4) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setUniformVector4(arg0, arg1); + } + } + } + + public setUniformColor(arg0: string, arg1: Color) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setUniformColor(arg0, arg1); + } + } + } + + public getUniform(arg0: string): any { + return this.getDefaultColorShader().getUniform(arg0); + } + + public getUniformFloat(arg0: string): number { + return this.getDefaultColorShader().getUniformFloat(arg0); + } + + public getUniformVector2(arg0: string): Vector2 { + return this.getDefaultColorShader().getUniformVector2(arg0); + } + + public getUniformVector3(arg0: string): Vector3 { + return this.getDefaultColorShader().getUniformVector3(arg0); + } + + public getUniformVector4(arg0: string): Vector4 { + return this.getDefaultColorShader().getUniformVector4(arg0); + } + + public getUniformColor(arg0: string): Color { + return this.getDefaultColorShader().getUniformColor(arg0); + } + + public setTexture(arg0: string, arg1: Texture) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setTexture(arg0, arg1); + } + } + this.setDefine(`USE_${arg0.toLocaleUpperCase()}`, true); + } + + public getTexture(arg0: string): Texture { + return this.getDefaultColorShader().textures[arg0]; + } + + public setUniformBuffer(arg0: string, arg1: UniformGPUBuffer) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setUniformBuffer(arg0, arg1); + } + } + } + + public getUniformBuffer(arg0: string): GPUBufferBase { + return this.getDefaultColorShader().getBuffer(arg0); + } + + public setStorageBuffer(arg0: string, arg1: StorageGPUBuffer) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setStorageBuffer(arg0, arg1); + } + } + } + + public getStorageBuffer(arg0: string): StorageGPUBuffer { + return this.getDefaultColorShader().getBuffer(arg0); + } + + public setStructStorageBuffer(arg0: string, arg1: StructStorageGPUBuffer) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setStructStorageBuffer(arg0, arg1); + } + } + } + + public getStructStorageBuffer(arg0: string): GPUBufferBase { + return this.getDefaultColorShader().getBuffer(arg0); + } + + public noticeValueChange() { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.noticeValueChange(); + } + } + } + + public destroy() { + this.getDefaultColorShader().destroy(); + } + + public clone() { + let newShader = new Shader(); + let sourceShaderPassList = this.getDefaultShaders(); + for (const shadePass of sourceShaderPassList) { + newShader.addRenderPass(shadePass); + } + return newShader; + } + + applyUniform() { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.applyUniform(); + } + } + } +} \ No newline at end of file diff --git a/src/gfx/graphics/webGpu/shader/ShaderBase.ts b/src/gfx/graphics/webGpu/shader/ShaderPassBase.ts similarity index 87% rename from src/gfx/graphics/webGpu/shader/ShaderBase.ts rename to src/gfx/graphics/webGpu/shader/ShaderPassBase.ts index d74313ec..a3a188dc 100644 --- a/src/gfx/graphics/webGpu/shader/ShaderBase.ts +++ b/src/gfx/graphics/webGpu/shader/ShaderPassBase.ts @@ -11,9 +11,10 @@ import { UniformGPUBuffer } from "../core/buffer/UniformGPUBuffer"; import { UniformNode } from "../core/uniforms/UniformNode"; import { ShaderReflection } from "./value/ShaderReflectionInfo"; import { UniformValue } from "./value/UniformValue"; +import { MaterialDataUniformGPUBuffer } from "../core/buffer/MaterialDataUniformGPUBuffer"; -export class ShaderBase { +export class ShaderPassBase { /** * Shader Unique instance id */ @@ -59,6 +60,11 @@ export class ShaderBase { */ public uniforms: { [name: string]: UniformNode }; + /** + * Uniform data for materials + */ + public materialDataUniformBuffer: MaterialDataUniformGPUBuffer; + protected _bufferDic: Map; protected _shaderChange: boolean = true; protected _valueChange: boolean = false; @@ -251,10 +257,40 @@ export class ShaderBase { return this.uniforms[name].data; } + public getUniformFloat(name: string): number { + return this.uniforms[name].data; + } + + public getUniformVector2(name: string): Vector2 { + return this.uniforms[name].data; + } + + public getUniformVector3(name: string): Vector3 { + return this.uniforms[name].data; + } + + public getUniformVector4(name: string): Vector4 { + return this.uniforms[name].data; + } + + public getUniformColor(name: string): Color { + return this.uniforms[name].color; + } + + public getBuffer(name: string): GPUBufferBase { + return this._bufferDic[name].data; + } + protected noticeBufferChange(name: string) { } + public applyUniform() { + if (this.materialDataUniformBuffer && this._valueChange) { + this.materialDataUniformBuffer.apply(); + } + } + /** * destroy */ diff --git a/src/gfx/graphics/webGpu/shader/util/ShaderUtil.ts b/src/gfx/graphics/webGpu/shader/util/ShaderUtil.ts index eb9aca29..4789055e 100644 --- a/src/gfx/graphics/webGpu/shader/util/ShaderUtil.ts +++ b/src/gfx/graphics/webGpu/shader/util/ShaderUtil.ts @@ -1,4 +1,4 @@ -import { RenderShader } from "../RenderShader"; +import { RenderShaderPass } from "../RenderShaderPass"; export type VertexPart = { name: string; @@ -21,10 +21,10 @@ export type FragmentPart = { export class ShaderUtil { public static renderShaderModulePool: Map; - public static renderShader: Map; + public static renderShader: Map; public static init() { this.renderShaderModulePool = new Map(); - this.renderShader = new Map(); + this.renderShader = new Map(); } } diff --git a/src/gfx/graphics/webGpu/shader/value/ShaderReflectionInfo.ts b/src/gfx/graphics/webGpu/shader/value/ShaderReflectionInfo.ts index edf88bef..26d4bb62 100644 --- a/src/gfx/graphics/webGpu/shader/value/ShaderReflectionInfo.ts +++ b/src/gfx/graphics/webGpu/shader/value/ShaderReflectionInfo.ts @@ -1,8 +1,8 @@ import { VertexAttributeSize } from '../../../../../core/geometry/VertexAttributeSize'; import { VertexFormat } from '../../../../../core/geometry/VertexFormat'; import { ComputeShader } from '../ComputeShader'; -import { RenderShader } from '../RenderShader'; -import { ShaderBase } from '../ShaderBase'; +import { RenderShaderPass } from '../RenderShaderPass'; +import { ShaderPassBase } from '../ShaderPassBase'; import { Preprocessor } from '../util/Preprocessor'; import { ShaderValue } from './ShaderValue'; @@ -78,7 +78,7 @@ export class ShaderReflection { } } - public static parser2(wgsl: string, shaderBase: ShaderBase) { + public static parser2(wgsl: string, shaderBase: ShaderPassBase) { if (!shaderBase.shaderReflection) shaderBase.shaderReflection = new ShaderReflection(); let shaderReflection = shaderBase.shaderReflection; if (wgsl.indexOf(`@vertex`) != -1) { @@ -140,14 +140,14 @@ export class ShaderReflection { } } - public static final(shaderBase: ShaderBase) { + public static final(shaderBase: ShaderPassBase) { let shaderReflection = shaderBase.shaderReflection; this._shaderReflectionMap.set(shaderBase.shaderVariant, shaderReflection); this.combineShaderReflectionVarInfo(shaderReflection, shaderReflection.vs_variables); this.combineShaderReflectionVarInfo(shaderReflection, shaderReflection.fs_variables); } - public static getShaderReflection2(code: string, shaderBase: ShaderBase) { + public static getShaderReflection2(code: string, shaderBase: ShaderPassBase) { if (shaderBase.shaderVariant != undefined) { let preShader = Preprocessor.parse(code, shaderBase.defineValue); ShaderReflection.parser2(preShader, shaderBase); @@ -188,7 +188,7 @@ export class ShaderReflection { return shaderVariant; } - public static genShaderVariant(shader: ShaderBase) { + public static genShaderVariant(shader: ShaderPassBase) { let shaderVariant = ''; for (const key in shader.uniforms) { shaderVariant += key + ':'; @@ -209,7 +209,7 @@ export class ShaderReflection { return shaderVariant; } - public static genRenderShaderVariant(renderShader: RenderShader) { + public static genRenderShaderVariant(renderShader: RenderShaderPass) { let shaderVariant = `RenderShader(${renderShader.vsName},${renderShader.fsName})`; shaderVariant += '|'; diff --git a/src/gfx/graphics/webGpu/shader/value/ShaderState.ts b/src/gfx/graphics/webGpu/shader/value/ShaderState.ts index f04413d1..eb301609 100644 --- a/src/gfx/graphics/webGpu/shader/value/ShaderState.ts +++ b/src/gfx/graphics/webGpu/shader/value/ShaderState.ts @@ -32,6 +32,7 @@ export class ShaderState { public splitTexture: boolean = false; public alphaCutoff: number; public useFragDepth: boolean = false; + public writeMasks: GPUColorWriteFlags[] = []; public setFromMapValues(values: Map) { if (values.has('blendMode')) { diff --git a/src/gfx/renderJob/GPUContext.ts b/src/gfx/renderJob/GPUContext.ts index 170fb8fc..4ff2857d 100644 --- a/src/gfx/renderJob/GPUContext.ts +++ b/src/gfx/renderJob/GPUContext.ts @@ -4,7 +4,7 @@ import { ProfilerUtil } from "../../util/ProfilerUtil"; import { webGPUContext } from "../graphics/webGpu/Context3D"; import { GlobalBindGroup } from "../graphics/webGpu/core/bindGroups/GlobalBindGroup"; import { ComputeShader } from "../graphics/webGpu/shader/ComputeShader"; -import { RenderShader } from "../graphics/webGpu/shader/RenderShader"; +import { RenderShaderPass } from "../graphics/webGpu/shader/RenderShaderPass"; import { RendererPassState } from "./passRenderer/state/RendererPassState"; /** @@ -13,7 +13,7 @@ import { RendererPassState } from "./passRenderer/state/RendererPassState"; export class GPUContext { public static lastGeometry: GeometryBase; public static lastPipeline: GPURenderPipeline; - public static lastShader: RenderShader; + public static lastShader: RenderShaderPass; public static drawCount: number = 0; public static renderPassCount: number = 0; public static geometryCount: number = 0; @@ -25,10 +25,10 @@ export class GPUContext { /** * renderPipeline before render need bind pipeline * @param encoder current GPURenderPassEncoder {@link GPURenderPassEncoder } {@link GPURenderBundleEncoder } - * @param renderShader render pass shader {@link RenderShader } + * @param renderShader render pass shader {@link RenderShaderPass } * @returns */ - public static bindPipeline(encoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderShader: RenderShader) { + public static bindPipeline(encoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderShader: RenderShaderPass) { if (GPUContext.lastShader != renderShader) { GPUContext.lastShader = renderShader; } else { diff --git a/src/gfx/renderJob/collect/EntityBatchCollect.ts b/src/gfx/renderJob/collect/EntityBatchCollect.ts index 992d9102..b2c7f6cd 100644 --- a/src/gfx/renderJob/collect/EntityBatchCollect.ts +++ b/src/gfx/renderJob/collect/EntityBatchCollect.ts @@ -1,5 +1,5 @@ import { RenderNode } from '../../../components/renderer/RenderNode'; -import { RendererType } from '../passRenderer/state/RendererType'; +import { PassType } from '../passRenderer/state/RendererType'; import { RenderGroup } from './RenderGroup'; /** * @internal @@ -18,12 +18,12 @@ export class EntityBatchCollect { g_key += node.geometry.instanceID; for (let i = 0; i < node.materials.length; i++) { const mat = node.materials[i]; - s_key += mat.defaultPass.shaderVariant; + s_key += mat.shader.getDefaultColorShader().shaderVariant; } let key = g_key + s_key; if (!this.renderGroup.has(key)) { this.renderGroup.set(key, { - bundleMap: new Map(), + bundleMap: new Map(), key: key, renderNodes: [], }); diff --git a/src/gfx/renderJob/collect/EntityCollect.ts b/src/gfx/renderJob/collect/EntityCollect.ts index 40988012..e1afaa4d 100644 --- a/src/gfx/renderJob/collect/EntityCollect.ts +++ b/src/gfx/renderJob/collect/EntityCollect.ts @@ -1,11 +1,13 @@ -import { Camera3D } from '../../..'; +import { Graphic3DMeshRenderer } from '../../..'; import { Engine3D } from '../../../Engine3D'; import { ILight } from '../../../components/lights/ILight'; import { RenderNode } from '../../../components/renderer/RenderNode'; +import { Camera3D } from '../../../core/Camera3D'; import { Scene3D } from '../../../core/Scene3D'; import { View3D } from '../../../core/View3D'; import { BoundingBox } from '../../../core/bound/BoundingBox'; +import { GeometryBase } from '../../../core/geometry/GeometryBase'; import { Octree } from '../../../core/tree/octree/Octree'; import { Vector3 } from '../../../math/Vector3'; import { zSorterUtil } from '../../../util/ZSorterUtil'; @@ -291,7 +293,7 @@ export class EntityCollect { } public getRenderShaderCollect(view: View3D) { - let viewList = this._renderShaderCollect.renderShaderUpdateList.get(view) || []; + let viewList = this._renderShaderCollect.renderShaderUpdateList.get(view); return viewList; } } diff --git a/src/gfx/renderJob/collect/RenderGroup.ts b/src/gfx/renderJob/collect/RenderGroup.ts index 33ec5b1b..9881c139 100644 --- a/src/gfx/renderJob/collect/RenderGroup.ts +++ b/src/gfx/renderJob/collect/RenderGroup.ts @@ -1,11 +1,11 @@ import { RenderNode } from '../../../components/renderer/RenderNode'; -import { RendererType } from '../passRenderer/state/RendererType'; +import { PassType } from '../passRenderer/state/RendererType'; /** * @internal * @group Post */ export type RenderGroup = { key: string; - bundleMap: Map; + bundleMap: Map; renderNodes: RenderNode[]; }; diff --git a/src/gfx/renderJob/collect/RenderShaderCollect.ts b/src/gfx/renderJob/collect/RenderShaderCollect.ts index 556cfd64..ba488ba9 100644 --- a/src/gfx/renderJob/collect/RenderShaderCollect.ts +++ b/src/gfx/renderJob/collect/RenderShaderCollect.ts @@ -51,11 +51,6 @@ export class RenderShaderCollect { const pass = colorPassList[i]; let key = `${node.geometry.instanceID + pass.instanceID}` rDic.delete(key); - // if (!nodeMap) { - // nodeMap = new Map(); - // rDic.set(key, nodeMap); - // } - // nodeMap.set(node.instanceID, node); } }); } diff --git a/src/gfx/renderJob/collect/ShadowLightsCollect.ts b/src/gfx/renderJob/collect/ShadowLightsCollect.ts index 823f3b44..38e40c50 100644 --- a/src/gfx/renderJob/collect/ShadowLightsCollect.ts +++ b/src/gfx/renderJob/collect/ShadowLightsCollect.ts @@ -1,12 +1,9 @@ -import { StorageGPUBuffer } from '../../..'; -import { Engine3D } from '../../../Engine3D'; import { ILight } from '../../../components/lights/ILight'; - import { LightType } from '../../../components/lights/LightData'; import { Scene3D } from '../../../core/Scene3D'; - +import { View3D } from '../../../core/View3D'; import { CameraUtil } from '../../../util/CameraUtil'; -import { UUID } from '../../../util/Global'; +import { GlobalBindGroup } from '../../graphics/webGpu/core/bindGroups/GlobalBindGroup'; /** * @internal * @group Lights @@ -18,33 +15,18 @@ export class ShadowLightsCollect { public static directionLightList: Map; public static pointLightList: Map; - public static shadowBuffer: Map; - public static shadowLights: Map;//Uint32Array = new Uint32Array(16); + public static shadowLights: Map; public static init() { this.directionLightList = new Map(); this.pointLightList = new Map(); - - this.shadowBuffer = new Map; - this.shadowLights = new Map; + this.shadowLights = new Map; } - public static createBuffer(scene: Scene3D) { - if (!this.shadowBuffer.has(scene)) { - let buffer = new StorageGPUBuffer(4 + 16); - buffer.visibility = GPUShaderStage.FRAGMENT; - this.shadowBuffer.set(scene, buffer); - - buffer.setInt32('nDirShadowStart', 0); - buffer.setInt32('nDirShadowEnd', 1); - buffer.setInt32('nPointShadowStart', 0); - buffer.setInt32('nPointShadowEnd', 0); - - let list = new Uint32Array(16); - this.shadowLights.set(scene, list); - - buffer.setUint32Array('shadowLights', list); - buffer.apply(); + public static createBuffer(view: View3D) { + if (!this.shadowLights.has(view.scene)) { + let list = new Float32Array(16); + this.shadowLights.set(view.scene, list); } } @@ -175,11 +157,11 @@ export class ShadowLightsCollect { } - public static update(scene3D: Scene3D) { - let shadowBuffer = this.shadowBuffer.get(scene3D); - let shadowLights = this.shadowLights.get(scene3D); - let directionLightList = ShadowLightsCollect.directionLightList.get(scene3D); - let pointLightList = ShadowLightsCollect.pointLightList.get(scene3D); + public static update(view: View3D) { + let globalUniform = GlobalBindGroup.getCameraGroup(view.camera); + let shadowLights = this.shadowLights.get(view.scene); + let directionLightList = ShadowLightsCollect.directionLightList.get(view.scene); + let pointLightList = ShadowLightsCollect.pointLightList.get(view.scene); let nDirShadowStart: number = 0; let nDirShadowEnd: number = 0; @@ -195,8 +177,8 @@ export class ShadowLightsCollect { } nDirShadowEnd = directionLightList.length; } - shadowBuffer.setInt32('nDirShadowStart', nDirShadowStart); - shadowBuffer.setInt32('nDirShadowEnd', nDirShadowEnd); + globalUniform.dirShadowStart = nDirShadowStart; + globalUniform.dirShadowEnd = nDirShadowEnd; if (pointLightList) { nPointShadowStart = nDirShadowEnd; @@ -208,10 +190,9 @@ export class ShadowLightsCollect { } nPointShadowEnd = nPointShadowStart + pointLightList.length; } - shadowBuffer.setInt32('nPointShadowStart', nPointShadowStart); - shadowBuffer.setInt32('nPointShadowEnd', nPointShadowEnd); - shadowBuffer.setUint32Array(`shadowLights`, shadowLights); - shadowBuffer.apply(); + globalUniform.pointShadowStart = nPointShadowStart; + globalUniform.pointShadowEnd = nPointShadowEnd; + globalUniform.shadowLights = shadowLights; } } diff --git a/src/gfx/renderJob/frame/GBufferFrame.ts b/src/gfx/renderJob/frame/GBufferFrame.ts index 2c40133f..c6976b3e 100644 --- a/src/gfx/renderJob/frame/GBufferFrame.ts +++ b/src/gfx/renderJob/frame/GBufferFrame.ts @@ -1,3 +1,4 @@ +import { Engine3D } from "../../.."; import { VirtualTexture } from "../../../textures/VirtualTexture"; import { webGPUContext } from "../../graphics/webGpu/Context3D"; import { GPUTextureFormat } from "../../graphics/webGpu/WebGPUConst"; @@ -8,57 +9,57 @@ import { RTResourceMap } from "./RTResourceMap"; export class GBufferFrame extends RTFrame { public static gBufferMap: Map = new Map(); - + public static bufferTexture: boolean = false; constructor() { super([], []); } crateGBuffer(key: string, rtWidth: number, rtHeight: number) { - let attachments = this.attachments; + let attachments = this.renderTargets; let reDescriptors = this.rtDescriptors; - // GPUTextureFormat.rgba16float, GPUTextureFormat.rgba8unorm, GPUTextureFormat.rgba8unorm let colorBufferTex = RTResourceMap.createRTTexture(key + RTResourceConfig.colorBufferTex_NAME, rtWidth, rtHeight, GPUTextureFormat.rgba16float, false); let positionBufferTex = RTResourceMap.createRTTexture(key + RTResourceConfig.positionBufferTex_NAME, rtWidth, rtHeight, GPUTextureFormat.rgba16float, false); let normalBufferTex = RTResourceMap.createRTTexture(key + RTResourceConfig.normalBufferTex_NAME, rtWidth, rtHeight, GPUTextureFormat.rgba8unorm, false); let materialBufferTex = RTResourceMap.createRTTexture(key + RTResourceConfig.materialBufferTex_NAME, rtWidth, rtHeight, GPUTextureFormat.rgba8unorm, false); - attachments.push(colorBufferTex); - attachments.push(positionBufferTex); - attachments.push(normalBufferTex); - attachments.push(materialBufferTex); + if (GBufferFrame.bufferTexture) { + attachments.push(colorBufferTex); + attachments.push(positionBufferTex); + attachments.push(normalBufferTex); + attachments.push(materialBufferTex); + } let colorRTDes = new RTDescriptor(); colorRTDes.loadOp = `clear`; - // colorRTDes.clearValue = [1,0,0,1]; - //depth24plus-stencil8 - let depthTexture = new VirtualTexture(rtWidth, rtHeight, GPUTextureFormat.depth32float, false); - // let depthTexture = new VirtualTexture(rtWidth, rtHeight, `depth24plus`, false); + let depthTexture = new VirtualTexture(rtWidth, rtHeight, GPUTextureFormat.depth24plus, false); depthTexture.name = `depthTexture`; let depthDec = new RTDescriptor(); depthDec.loadOp = `load`; this.depthTexture = depthTexture; - reDescriptors.push(colorRTDes); - reDescriptors.push(new RTDescriptor()); - reDescriptors.push(new RTDescriptor()); - reDescriptors.push(new RTDescriptor()); + if (GBufferFrame.bufferTexture) { + reDescriptors.push(colorRTDes); + reDescriptors.push(new RTDescriptor()); + reDescriptors.push(new RTDescriptor()); + reDescriptors.push(new RTDescriptor()); + } } public getColorMap() { - return this.attachments[0]; + return this.renderTargets[0]; } public getPositionMap() { - return this.attachments[1]; + return this.renderTargets[1]; } public getNormalMap() { - return this.attachments[2]; + return this.renderTargets[2]; } public getMaterialMap() { - return this.attachments[3]; + return this.renderTargets[3]; } /** diff --git a/src/gfx/renderJob/frame/ProbeGBufferFrame.ts b/src/gfx/renderJob/frame/ProbeGBufferFrame.ts index 6ee02c9a..9fa95d81 100644 --- a/src/gfx/renderJob/frame/ProbeGBufferFrame.ts +++ b/src/gfx/renderJob/frame/ProbeGBufferFrame.ts @@ -13,7 +13,7 @@ export class ProbeGBufferFrame extends RTFrame { } crateGBuffer(rtWidth: number, rtHeight: number) { - let attachments = this.attachments; + let attachments = this.renderTargets; let rtDescriptors = this.rtDescriptors; let positionMap = new VirtualTexture(rtWidth, rtHeight, GPUTextureFormat.rgba16float, false); positionMap.name = `positionMap`; diff --git a/src/gfx/renderJob/frame/RTFrame.ts b/src/gfx/renderJob/frame/RTFrame.ts index b0093e02..a06bd644 100644 --- a/src/gfx/renderJob/frame/RTFrame.ts +++ b/src/gfx/renderJob/frame/RTFrame.ts @@ -5,7 +5,7 @@ import { RTDescriptor } from "../../graphics/webGpu/descriptor/RTDescriptor"; export class RTFrame { public label: string; public customSize: boolean = false; - public attachments: VirtualTexture[]; + public renderTargets: VirtualTexture[]; public rtDescriptors: RTDescriptor[]; public zPreTexture: VirtualTexture; @@ -17,7 +17,7 @@ export class RTFrame { public isOutTarget: boolean = true; constructor(attachments: VirtualTexture[], rtDescriptors: RTDescriptor[], depthTexture?: VirtualTexture, zPreTexture?: VirtualTexture, isOutTarget: boolean = true) { - this.attachments = attachments; + this.renderTargets = attachments; this.rtDescriptors = rtDescriptors; this.depthTexture = depthTexture; this.zPreTexture = zPreTexture; @@ -25,7 +25,7 @@ export class RTFrame { } public clone2Frame(rtFrame: RTFrame) { - rtFrame.attachments.push(...this.attachments.concat()); + rtFrame.renderTargets.push(...this.renderTargets.concat()); for (let i = 0; i < this.rtDescriptors.length; i++) { const des = this.rtDescriptors[i]; let rtDes = new RTDescriptor(); diff --git a/src/gfx/renderJob/frame/RTResourceMap.ts b/src/gfx/renderJob/frame/RTResourceMap.ts index 3ed7f278..dbcaed69 100644 --- a/src/gfx/renderJob/frame/RTResourceMap.ts +++ b/src/gfx/renderJob/frame/RTResourceMap.ts @@ -47,14 +47,14 @@ export class RTResourceMap { return rt; } - public static createViewQuad(name: string, shaderVS: string, shaderFS: string, outRtTexture: VirtualTexture, shaderUniforms?: { [uniName: string]: UniformNode }, multisample: number = 0) { + public static createViewQuad(name: string, shaderVS: string, shaderFS: string, outRtTexture: VirtualTexture, multisample: number = 0) { let rtFrame = new RTFrame([ outRtTexture ], [ new RTDescriptor() ]); - let viewQuad = new ViewQuad(shaderVS, shaderFS, rtFrame, shaderUniforms, multisample); + let viewQuad = new ViewQuad(shaderVS, shaderFS, rtFrame, multisample); RTResourceMap.rtViewQuad.set(name, viewQuad); return viewQuad; } diff --git a/src/gfx/renderJob/jobs/ForwardRenderJob.ts b/src/gfx/renderJob/jobs/ForwardRenderJob.ts index f6d48913..99b1aedd 100644 --- a/src/gfx/renderJob/jobs/ForwardRenderJob.ts +++ b/src/gfx/renderJob/jobs/ForwardRenderJob.ts @@ -5,6 +5,10 @@ import { ColorPassRenderer } from '../passRenderer/color/ColorPassRenderer'; import { GBufferFrame } from '../frame/GBufferFrame'; import { RendererJob } from './RendererJob'; import { DDGIProbeRenderer } from '../passRenderer/ddgi/DDGIProbeRenderer'; +import { webGPUContext } from '../../graphics/webGpu/Context3D'; +import { RTResourceConfig } from '../config/RTResourceConfig'; +import { RTResourceMap } from '../frame/RTResourceMap'; +import { GPUTextureFormat } from '../../graphics/webGpu/WebGPUConst'; /** * Forward+ * Every time a forward rendering is performed, @@ -21,6 +25,7 @@ export class ForwardRenderJob extends RendererJob { public start(): void { super.start(); + let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); { let debugTextures = []; @@ -32,6 +37,11 @@ export class ForwardRenderJob extends RendererJob { colorPassRenderer.setRenderStates(rtFrame); + for (let i = 0; i < rtFrame.renderTargets.length; i++) { + const tex = rtFrame.renderTargets[i]; + debugTextures.push(tex); + } + if (Engine3D.setting.gi.enable) { let lightEntries = GlobalBindGroup.getLightEntries(this.view.scene); this.ddgiProbeRenderer = new DDGIProbeRenderer(lightEntries.irradianceVolume); diff --git a/src/gfx/renderJob/jobs/RenderMap.ts b/src/gfx/renderJob/jobs/RenderMap.ts index 44a04ea0..b0969e21 100644 --- a/src/gfx/renderJob/jobs/RenderMap.ts +++ b/src/gfx/renderJob/jobs/RenderMap.ts @@ -1,15 +1,15 @@ import { Camera3D } from "../../../core/Camera3D"; import { Scene3D } from "../../../core/Scene3D"; import { RendererBase } from "../passRenderer/RendererBase"; -import { RendererType } from "../passRenderer/state/RendererType"; +import { PassType } from "../passRenderer/state/RendererType"; export class RendererMap { - private map: Map; + private map: Map; private passRendererList: RendererBase[]; constructor() { - this.map = new Map(); + this.map = new Map(); this.passRendererList = []; } @@ -24,7 +24,7 @@ export class RendererMap { } } - public getRenderer(passType: RendererType): RendererBase { + public getRenderer(passType: PassType): RendererBase { return this.map.get(passType); } @@ -32,7 +32,7 @@ export class RendererMap { this.passRendererList.push(renderer); } - public getAllRenderer(): Map { + public getAllRenderer(): Map { return this.map; } diff --git a/src/gfx/renderJob/jobs/RendererJob.ts b/src/gfx/renderJob/jobs/RendererJob.ts index 8cb6a79d..ec8f2fdd 100644 --- a/src/gfx/renderJob/jobs/RendererJob.ts +++ b/src/gfx/renderJob/jobs/RendererJob.ts @@ -17,6 +17,7 @@ import { PostBase } from '../post/PostBase'; import { RendererBase } from '../passRenderer/RendererBase'; import { Ctor } from '../../../util/Global'; import { DDGIProbeRenderer } from '../passRenderer/ddgi/DDGIProbeRenderer'; +import { Texture } from '../../graphics/webGpu/core/texture/Texture'; /** * render jobs @@ -74,6 +75,7 @@ export class RendererJob { */ public pauseRender: boolean = false; public pickFire: PickFire; + public renderState: boolean = false; protected _view: View3D; /** @@ -124,6 +126,7 @@ export class RendererJob { * start render task */ public start() { + this.renderState = true; } // public get guiCanvas(): UICanvas { @@ -162,7 +165,10 @@ export class RendererJob { * @param post */ public addPost(post: PostBase): PostBase | PostBase[] { - if (!this.postRenderer) this.enablePost(GBufferFrame.getGBufferFrame('ColorPassGBuffer')); + if (!this.postRenderer) { + GBufferFrame.bufferTexture = true; + this.enablePost(GBufferFrame.getGBufferFrame('ColorPassGBuffer')); + } if (post instanceof PostBase) { this.postRenderer.attachPost(this.view, post); @@ -198,7 +204,7 @@ export class RendererJob { this.clusterLightingRender.render(view, this.occlusionSystem); if (this.shadowMapPassRenderer) { - ShadowLightsCollect.update(view.scene); + ShadowLightsCollect.update(view); this.shadowMapPassRenderer.render(view, this.occlusionSystem); } @@ -226,6 +232,7 @@ export class RendererJob { if (this.postRenderer && this.postRenderer.postList.length > 0) { this.postRenderer.render(view); } + } public debug() { diff --git a/src/gfx/renderJob/passRenderer/RenderContext.ts b/src/gfx/renderJob/passRenderer/RenderContext.ts index 875e8763..ff25bc0d 100644 --- a/src/gfx/renderJob/passRenderer/RenderContext.ts +++ b/src/gfx/renderJob/passRenderer/RenderContext.ts @@ -24,19 +24,23 @@ export class RenderContext { * continue renderer pass state * @returns */ - public beginContinueRendererPassState() { + public beginContinueRendererPassState(color_loadOp: GPULoadOp = 'load', depth_loadOp: GPULoadOp = 'load') { if (this.rendererPassStates.length > 0) { let splitRtFrame = this.rtFrame.clone(); for (const iterator of splitRtFrame.rtDescriptors) { iterator.loadOp = `load`; // iterator.storeOp = `discard`; } - splitRtFrame.depthLoadOp = "load"; - let splitRendererPassState = WebGPUDescriptorCreator.createRendererPassState(splitRtFrame); + splitRtFrame.depthLoadOp = depth_loadOp; + let splitRendererPassState = WebGPUDescriptorCreator.createRendererPassState(splitRtFrame, color_loadOp); this.rendererPassStates.push(splitRendererPassState); return splitRendererPassState; } else { - let splitRendererPassState = WebGPUDescriptorCreator.createRendererPassState(this.rtFrame); + // for (const iterator of this.rtFrame.rtDescriptors) { + // iterator.loadOp = color_loadOp; + // } + this.rtFrame.depthLoadOp = depth_loadOp; + let splitRendererPassState = WebGPUDescriptorCreator.createRendererPassState(this.rtFrame, color_loadOp); this.rendererPassStates.push(splitRendererPassState); return splitRendererPassState; } @@ -46,8 +50,14 @@ export class RenderContext { return this.rendererPassStates[this.rendererPassStates.length - 1]; } - public beginRenderPass() { - this.beginContinueRendererPassState(); + public beginOpaqueRenderPass() { + this.beginContinueRendererPassState('clear', 'clear'); + this.begineNewCommand(); + this.beginNewEncoder(); + } + + public beginTransparentRenderPass() { + this.beginContinueRendererPassState('load', 'load'); this.begineNewCommand(); this.beginNewEncoder(); } diff --git a/src/gfx/renderJob/passRenderer/RendererBase.ts b/src/gfx/renderJob/passRenderer/RendererBase.ts index 5e17c100..ae43b94a 100644 --- a/src/gfx/renderJob/passRenderer/RendererBase.ts +++ b/src/gfx/renderJob/passRenderer/RendererBase.ts @@ -14,10 +14,13 @@ import { EntityCollect } from "../collect/EntityCollect"; import { RTFrame } from "../frame/RTFrame"; import { OcclusionSystem } from "../occlusion/OcclusionSystem"; import { RendererPassState } from "./state/RendererPassState"; -import { RendererType } from "./state/RendererType"; +import { PassType } from "./state/RendererType"; import { RenderContext } from "./RenderContext"; import { ClusterLightingRender } from "./cluster/ClusterLightingRender"; import { ClusterLightingBuffer } from "./cluster/ClusterLightingBuffer"; +import { RTResourceMap } from "../frame/RTResourceMap"; +import { RTResourceConfig } from "../config/RTResourceConfig"; +import { webGPUContext } from "../../graphics/webGpu/Context3D"; /** @@ -33,14 +36,14 @@ export class RendererBase extends CEventDispatcher { protected renderContext: RenderContext; - protected _rendererType: RendererType; + protected _rendererType: PassType; protected _rtFrame: RTFrame; - public get passType(): RendererType { + public get passType(): PassType { return this._rendererType; } - public set passType(value: RendererType) { + public set passType(value: PassType) { this._rendererType = value; } @@ -63,6 +66,7 @@ export class RendererBase extends CEventDispatcher { } this.renderContext = new RenderContext(rtFrame); + } public setIrradiance(probeIrradianceMap: VirtualTexture, probeDepthMap: VirtualTexture) { diff --git a/src/gfx/renderJob/passRenderer/cluster/ClusterLightingRender.ts b/src/gfx/renderJob/passRenderer/cluster/ClusterLightingRender.ts index 481e5a8b..16ccd831 100644 --- a/src/gfx/renderJob/passRenderer/cluster/ClusterLightingRender.ts +++ b/src/gfx/renderJob/passRenderer/cluster/ClusterLightingRender.ts @@ -6,7 +6,7 @@ import { EntityCollect } from '../../collect/EntityCollect'; import { GPUContext } from '../../GPUContext'; import { OcclusionSystem } from '../../occlusion/OcclusionSystem'; import { RendererBase } from '../RendererBase'; -import { RendererType } from '../state/RendererType'; +import { PassType } from '../state/RendererType'; import { ILight } from '../../../../components/lights/ILight'; import { ClusterLightingBuffer } from './ClusterLightingBuffer'; import { ClusterBoundsSource_cs } from '../../../../assets/shader/cluster/ClusterBoundsSource_cs'; @@ -33,7 +33,7 @@ export class ClusterLightingRender extends RendererBase { constructor(view: View3D) { super(); - this.passType = RendererType.Cluster; + this.passType = PassType.Cluster; this.initCompute(view); } @@ -67,40 +67,40 @@ export class ClusterLightingRender extends RendererBase { this.resize = true; - GUIHelp.addButton("clusterBuffer", () => { - let od = this.clusterLightingBuffer.clusterBuffer.readBuffer(); - console.log(od); - let byteLength = 2 * 4; - for (let i = 0; i < numClusters; i++) { - const element = new Float32Array(od.buffer, i * byteLength * 4, byteLength); - let p0 = new Vector3(element[0], element[1], element[2], element[3]); - let p1 = new Vector3(element[4], element[5], element[6], element[7]); - view.graphic3D.drawBox(i + "-box", p0, p1, Color.random()); - } - }); - - GUIHelp.addButton("assignTable", () => { - let od = this.clusterLightingBuffer.assignTableBuffer.readBuffer(); - for (let i = 0; i < od.length / 4; i++) { - const count = od[i * 4 + 0]; - const start = od[i * 4 + 1]; - const e1 = od[i * 4 + 2]; - const e2 = od[i * 4 + 3]; - if (count >= 1) { - console.log(count); - } - - if ((start + count) > start + 1) { - console.log(count, start, e1, e2); - } - } - console.log(od); - }); - - GUIHelp.addButton("clustersUniformBuffer", () => { - let od = this.clusterLightingBuffer.clustersUniformBuffer.readBuffer(); - console.log(od); - }); + // GUIHelp.addButton("clusterBuffer", () => { + // let od = this.clusterLightingBuffer.clusterBuffer.readBuffer(); + // console.log(od); + // let byteLength = 2 * 4; + // for (let i = 0; i < numClusters; i++) { + // const element = new Float32Array(od.buffer, i * byteLength * 4, byteLength); + // let p0 = new Vector3(element[0], element[1], element[2], element[3]); + // let p1 = new Vector3(element[4], element[5], element[6], element[7]); + // view.graphic3D.drawBox(i + "-box", p0, p1, Color.random()); + // } + // }); + + // GUIHelp.addButton("assignTable", () => { + // let od = this.clusterLightingBuffer.assignTableBuffer.readBuffer(); + // for (let i = 0; i < od.length / 4; i++) { + // const count = od[i * 4 + 0]; + // const start = od[i * 4 + 1]; + // const e1 = od[i * 4 + 2]; + // const e2 = od[i * 4 + 3]; + // if (count >= 1) { + // console.log(count); + // } + + // if ((start + count) > start + 1) { + // console.log(count, start, e1, e2); + // } + // } + // console.log(od); + // }); + + // GUIHelp.addButton("clustersUniformBuffer", () => { + // let od = this.clusterLightingBuffer.clustersUniformBuffer.readBuffer(); + // console.log(od); + // }); } render(view: View3D, occlusionSystem: OcclusionSystem) { diff --git a/src/gfx/renderJob/passRenderer/color/ColorPassRenderer.ts b/src/gfx/renderJob/passRenderer/color/ColorPassRenderer.ts index b642d547..6d403766 100644 --- a/src/gfx/renderJob/passRenderer/color/ColorPassRenderer.ts +++ b/src/gfx/renderJob/passRenderer/color/ColorPassRenderer.ts @@ -4,11 +4,13 @@ import { View3D } from "../../../../core/View3D"; import { ProfilerUtil } from "../../../../util/ProfilerUtil"; import { GPUContext } from "../../GPUContext"; import { EntityCollect } from "../../collect/EntityCollect"; +import { RTResourceConfig } from "../../config/RTResourceConfig"; +import { RTResourceMap } from "../../frame/RTResourceMap"; import { OcclusionSystem } from "../../occlusion/OcclusionSystem"; import { RenderContext } from "../RenderContext"; import { RendererBase } from "../RendererBase"; import { ClusterLightingBuffer } from "../cluster/ClusterLightingBuffer"; -import { RendererType } from "../state/RendererType"; +import { PassType } from "../state/RendererType"; /** * @internal @@ -19,7 +21,7 @@ import { RendererType } from "../state/RendererType"; export class ColorPassRenderer extends RendererBase { constructor() { super(); - this.passType = RendererType.COLOR; + this.passType = PassType.COLOR; } public render(view: View3D, occlusionSystem: OcclusionSystem, clusterLightingBuffer?: ClusterLightingBuffer, maskTr: boolean = false) { @@ -38,7 +40,7 @@ export class ColorPassRenderer extends RendererBase { { ProfilerUtil.start("ColorPass Draw Opaque"); - this.renderContext.beginRenderPass(); + this.renderContext.beginOpaqueRenderPass(); let command = this.renderContext.command; let renderPassEncoder = this.renderContext.encoder; @@ -83,7 +85,7 @@ export class ColorPassRenderer extends RendererBase { { ProfilerUtil.start("ColorPass Draw Transparent"); - this.renderContext.beginRenderPass(); + this.renderContext.beginTransparentRenderPass(); let command = this.renderContext.command; let renderPassEncoder = this.renderContext.encoder; @@ -105,6 +107,13 @@ export class ColorPassRenderer extends RendererBase { graphic3DRenderNode.renderPass2(view, this._rendererType, this.splitRendererPassState, clusterLightingBuffer, renderPassEncoder); } + // let graphicsMesh = EntityCollect.instance.getGraphicMesh(view); + // for (const iterator of graphicsMesh) { + // let meshGroup = iterator; + // meshGroup.nodeUpdate(view, this._rendererType, this.splitRendererPassState, clusterLightingBuffer); + // meshGroup.renderPass2(view, this._rendererType, this.splitRendererPassState, clusterLightingBuffer, renderPassEncoder); + // } + this.renderContext.endRenderPass(); ProfilerUtil.end("ColorPass Draw Transparent"); @@ -114,8 +123,8 @@ export class ColorPassRenderer extends RendererBase { } public drawNodes(view: View3D, renderContext: RenderContext, nodes: RenderNode[], occlusionSystem: OcclusionSystem, clusterLightingBuffer: ClusterLightingBuffer) { - { - let viewRenderList = EntityCollect.instance.getRenderShaderCollect(view); + let viewRenderList = EntityCollect.instance.getRenderShaderCollect(view); + if (viewRenderList) { for (const renderList of viewRenderList) { let nodeMap = renderList[1]; for (const iterator of nodeMap) { diff --git a/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceComputePass.ts b/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceComputePass.ts index cc58cd42..a69acf5c 100644 --- a/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceComputePass.ts +++ b/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceComputePass.ts @@ -43,7 +43,7 @@ export class DDGIIrradianceComputePass { this.computeShader.setStorageBuffer(`depthRaysBuffer`, this.depthRaysBuffer); this.computeShader.setStorageBuffer(`probes`, this.volume.probesBuffer); - this.computeShader.setStorageBuffer(`uniformData`, this.volume.irradianceVolumeBuffer); + this.computeShader.setUniformBuffer(`uniformData`, this.volume.irradianceVolumeBuffer); this.computeShader.setStorageBuffer("models", GlobalBindGroup.modelMatrixBindGroup.matrixBufferDst); } diff --git a/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceVolume.ts b/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceVolume.ts index 1bab3631..342ba806 100644 --- a/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceVolume.ts +++ b/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceVolume.ts @@ -3,6 +3,7 @@ import { Vector3 } from "../../../../math/Vector3"; import { Probe } from "./Probe"; import { GlobalIlluminationSetting } from "../../../../setting/GlobalIlluminationSetting"; import { StorageGPUBuffer } from "../../../graphics/webGpu/core/buffer/StorageGPUBuffer"; +import { UniformGPUBuffer } from "../../../.."; /** * @internal * @group Post @@ -15,7 +16,7 @@ export class DDGIIrradianceVolume { private randomOrientation: Matrix4; private startPosition: Vector3 = new Vector3(); private isVolumeChange: boolean = true; - public irradianceVolumeBuffer: StorageGPUBuffer; + public irradianceVolumeBuffer: UniformGPUBuffer; //__make random direction private readonly directionDistance: number = 20; @@ -37,7 +38,7 @@ export class DDGIIrradianceVolume { this.setting = setting; this.randomOrientation = new Matrix4(false); this.randomOrientation.identity(); - this.irradianceVolumeBuffer = new StorageGPUBuffer(80); + this.irradianceVolumeBuffer = new UniformGPUBuffer(80); this.createFramesBuffer(); //center this.arroundPositions.push(this.centerDirection.clone()); diff --git a/src/gfx/renderJob/passRenderer/ddgi/DDGIMultiBouncePass.ts b/src/gfx/renderJob/passRenderer/ddgi/DDGIMultiBouncePass.ts index eb6bf5c6..f117be71 100644 --- a/src/gfx/renderJob/passRenderer/ddgi/DDGIMultiBouncePass.ts +++ b/src/gfx/renderJob/passRenderer/ddgi/DDGIMultiBouncePass.ts @@ -28,7 +28,7 @@ export class DDGIMultiBouncePass { this.computerShader = new ComputeShader(MultiBouncePass_cs); this.computerShader.setStorageTexture("outputBuffer", this.blendTexture); - this.computerShader.setStorageBuffer("uniformData", this.volume.irradianceVolumeBuffer); + this.computerShader.setUniformBuffer("uniformData", this.volume.irradianceVolumeBuffer); } public setInputs(inputs: VirtualTexture[]) { diff --git a/src/gfx/renderJob/passRenderer/ddgi/DDGIProbeRenderer.ts b/src/gfx/renderJob/passRenderer/ddgi/DDGIProbeRenderer.ts index db921b5d..201abaad 100644 --- a/src/gfx/renderJob/passRenderer/ddgi/DDGIProbeRenderer.ts +++ b/src/gfx/renderJob/passRenderer/ddgi/DDGIProbeRenderer.ts @@ -8,7 +8,7 @@ import { GPUContext } from '../../GPUContext'; import { ProbeGBufferFrame } from '../../frame/ProbeGBufferFrame'; import { OcclusionSystem } from '../../occlusion/OcclusionSystem'; import { RendererBase } from '../RendererBase'; -import { RendererType } from '../state/RendererType'; +import { PassType } from '../state/RendererType'; import { DDGIIrradianceComputePass } from './DDGIIrradianceComputePass'; import { DDGIIrradianceVolume } from './DDGIIrradianceVolume'; import { DDGIMultiBouncePass } from './DDGIMultiBouncePass'; @@ -62,7 +62,7 @@ export class DDGIProbeRenderer extends RendererBase { constructor(volume: DDGIIrradianceVolume) { super(); - this.passType = RendererType.GI; + this.passType = PassType.GI; this.volume = volume; let giSetting = volume.setting; @@ -79,9 +79,9 @@ export class DDGIProbeRenderer extends RendererBase { this.probeRenderResult = new ProbeRenderResult(); let probeGBufferFrame = new ProbeGBufferFrame(this.sizeW, this.sizeH); - this.positionMap = probeGBufferFrame.attachments[0]; - this.normalMap = probeGBufferFrame.attachments[1]; - this.colorMap = probeGBufferFrame.attachments[2]; + this.positionMap = probeGBufferFrame.renderTargets[0]; + this.normalMap = probeGBufferFrame.renderTargets[1]; + this.colorMap = probeGBufferFrame.renderTargets[2]; this.setRenderStates(probeGBufferFrame); } @@ -299,7 +299,7 @@ export class DDGIProbeRenderer extends RendererBase { if (execRender) { let probeList = EntityCollect.instance.getProbes(view.scene); this.renderContext.clean(); - this.renderContext.beginRenderPass(); + this.renderContext.beginOpaqueRenderPass(); this.tempProbeList.length = 0; let remainCount = Math.min(this.probeCountPerFrame, probeList.length); this.probeRenderResult.count = remainCount; diff --git a/src/gfx/renderJob/passRenderer/graphic/Graphic3DBatchRenderer.ts b/src/gfx/renderJob/passRenderer/graphic/Graphic3DBatchRenderer.ts index efef4ed6..cb109b45 100644 --- a/src/gfx/renderJob/passRenderer/graphic/Graphic3DBatchRenderer.ts +++ b/src/gfx/renderJob/passRenderer/graphic/Graphic3DBatchRenderer.ts @@ -5,7 +5,7 @@ import { Color } from "../../../../math/Color"; import { Vector3 } from "../../../../math/Vector3"; import { RendererMask } from "../state/RendererMask"; import { RendererPassState } from "../state/RendererPassState"; -import { RendererType } from "../state/RendererType"; +import { PassType } from "../state/RendererType"; import { ClusterLightingRender } from "../cluster/ClusterLightingRender"; import { Graphic3DFixedRenderPipeline } from "./Graphic3DFixedRenderPipeline"; import { GraphicConfig } from "./GraphicConfig"; @@ -82,7 +82,7 @@ export class Graphic3DBatchRenderer extends RenderNode { this._readyPipeline = true; } - public nodeUpdate(view: View3D, passType: RendererType, renderPassState: RendererPassState, clusterLightingBuffer?: ClusterLightingBuffer) { + public nodeUpdate(view: View3D, passType: PassType, renderPassState: RendererPassState, clusterLightingBuffer?: ClusterLightingBuffer) { // if(!this.enable || passType != RendererType.COLOR ) return ; if (this.mDirtyData) { this.mRenderPipeline.reset(); @@ -94,7 +94,7 @@ export class Graphic3DBatchRenderer extends RenderNode { return; } - public renderPass2(view: View3D, passType: RendererType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { + public renderPass2(view: View3D, passType: PassType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { // if(!this.enable || passType != RendererType.COLOR ) return ; this.mRenderPipeline.render(rendererPassState, encoder); } diff --git a/src/gfx/renderJob/passRenderer/graphic/Graphic3DFixedRenderPipeline.ts b/src/gfx/renderJob/passRenderer/graphic/Graphic3DFixedRenderPipeline.ts index 084b80ea..70067ffd 100644 --- a/src/gfx/renderJob/passRenderer/graphic/Graphic3DFixedRenderPipeline.ts +++ b/src/gfx/renderJob/passRenderer/graphic/Graphic3DFixedRenderPipeline.ts @@ -56,7 +56,8 @@ export class Graphic3DFixedRenderPipeline { } let remainLength = this.mDataBuffer.length - this.mOffset; - this.mDataBuffer.set(data.slice(0, remainLength), this.mOffset); + // this.mDataBuffer.set(data.slice(0, remainLength), this.mOffset); + this.mDataBuffer.set(data, this.mOffset,); this.mOffset += remainLength; data = data.slice(remainLength); } @@ -86,10 +87,10 @@ export class Graphic3DFixedRenderPipeline { const device = webGPUContext.device; if (!this.mRenderPipeline) { - let targets = rendererPassState.outAttachments; + let targets = rendererPassState.renderTargetTextures; if (rendererPassState.outColor != -1) { let target = targets[rendererPassState.outColor]; - target.blend = BlendFactor.getBlend(BlendMode.NONE); + target.blend = BlendFactor.getBlend(BlendMode.ALPHA); } this.mRenderPipelineLayout = device.createPipelineLayout({ @@ -111,7 +112,7 @@ export class Graphic3DFixedRenderPipeline { }, primitive: { topology: this.mGPUPrimitiveTopology, - cullMode: GPUCullMode.back, + cullMode: GPUCullMode.none, frontFace: 'ccw', }, }; diff --git a/src/gfx/renderJob/passRenderer/graphic/Graphic3DRender.ts b/src/gfx/renderJob/passRenderer/graphic/Graphic3DRender.ts index 8e9b42ac..686c8eaf 100644 --- a/src/gfx/renderJob/passRenderer/graphic/Graphic3DRender.ts +++ b/src/gfx/renderJob/passRenderer/graphic/Graphic3DRender.ts @@ -248,9 +248,9 @@ export class Graphic3D extends Object3D { this.mFillRender.fillShapeData(uuid, 'fill', color, [ origin, new Vector3(origin.x + width, origin.y, origin.z), - new Vector3(origin.x + width, origin.y + height, origin.z), - new Vector3(origin.x + width, origin.y + height, origin.z), - new Vector3(origin.x, origin.y + height, origin.z), + new Vector3(origin.x + width, origin.y, origin.z + height), + new Vector3(origin.x + width, origin.y, origin.z + height), + new Vector3(origin.x, origin.y, origin.z + height), origin ]); } @@ -300,10 +300,11 @@ export class Graphic3D extends Object3D { * @param transform The Transform that needs to be bound * @param color The color of the wire frame */ - public drawMeshWireframe(uuid: string, geometry: GeometryBase, transform: Transform, color: Color = Color.COLOR_WHITE) { + public drawMeshWireframe(uuid: string, geometry: GeometryBase, transform: Transform, color: Color = Color.COLOR_WHITE, forceUpdate: boolean = false) { if (geometry) this.createCustomShape(uuid, transform ? transform : this.transform).fillShapeData( geometry.genWireframe(), - color + color, + forceUpdate ); } diff --git a/src/gfx/renderJob/passRenderer/graphic/Graphics3DShape.ts b/src/gfx/renderJob/passRenderer/graphic/Graphics3DShape.ts index 49e6497f..d075a26f 100644 --- a/src/gfx/renderJob/passRenderer/graphic/Graphics3DShape.ts +++ b/src/gfx/renderJob/passRenderer/graphic/Graphics3DShape.ts @@ -99,7 +99,7 @@ export class Graphics3DShape { this.fillShapeData(points, color); } - public fillShapeData(points: Vector3[], colors: Color | Color[]) { + public fillShapeData(points: Vector3[], colors: Color | Color[], forceUpdate: boolean = false) { if (!this.shapeData) { this.shapeData = new Float32Array(GraphicConfig.ShapeVertexSize * points.length); } else if (this.count + GraphicConfig.ShapeVertexSize * points.length >= this.shapeData.length) { @@ -108,25 +108,27 @@ export class Graphics3DShape { this.shapeData = tmp; } - const shapeData = this.shapeData; - for (let i = 0; i < points.length; ++i) { - const point = points[i]; - shapeData[this.count++] = point.x; - shapeData[this.count++] = point.y; - shapeData[this.count++] = point.z; - shapeData[this.count++] = this.transformIndex; + if (forceUpdate || this.dirtyData == false) { + const shapeData = this.shapeData; + for (let i = 0; i < points.length; ++i) { + const point = points[i]; + shapeData[this.count++] = point.x; + shapeData[this.count++] = point.y; + shapeData[this.count++] = point.z; + shapeData[this.count++] = this.transformIndex; - if (colors instanceof Color) { - shapeData[this.count++] = colors.r; - shapeData[this.count++] = colors.g; - shapeData[this.count++] = colors.b; - shapeData[this.count++] = colors.a; - } else { - const color = colors[i]; - shapeData[this.count++] = color.r; - shapeData[this.count++] = color.g; - shapeData[this.count++] = color.b; - shapeData[this.count++] = color.a; + if (colors instanceof Color) { + shapeData[this.count++] = colors.r; + shapeData[this.count++] = colors.g; + shapeData[this.count++] = colors.b; + shapeData[this.count++] = colors.a; + } else { + const color = colors[i]; + shapeData[this.count++] = color.r; + shapeData[this.count++] = color.g; + shapeData[this.count++] = color.b; + shapeData[this.count++] = color.a; + } } } diff --git a/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMesh.ts b/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMesh.ts new file mode 100644 index 00000000..5f35d318 --- /dev/null +++ b/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMesh.ts @@ -0,0 +1,20 @@ +import { Scene3D } from "../../../../../core/Scene3D"; +import { Object3D } from "../../../../../core/entities/Object3D"; +import { GeometryBase } from "../../../../../core/geometry/GeometryBase"; +import { BitmapTexture2DArray } from "../../../../../textures/BitmapTexture2DArray"; +import { Graphic3DMeshRenderer } from "./Graphic3DMeshRenderer"; + +export class Graphic3DMesh { + public static meshMap: Map = new Map(); + public static meshDrawGroup: Map = new Map(); + public static draw(scene: Scene3D, geo: GeometryBase, texture: BitmapTexture2DArray, count: number): Graphic3DMeshRenderer { + if (!this.meshMap.has(geo)) { + let object = new Object3D(); + let renderNode = object.addComponent(Graphic3DMeshRenderer); + renderNode.create(geo, texture, count); + this.meshMap.set(geo, renderNode); + scene.addChild(object); + return renderNode; + } + } +} \ No newline at end of file diff --git a/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts b/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts new file mode 100644 index 00000000..82ca2a14 --- /dev/null +++ b/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts @@ -0,0 +1,55 @@ +import { MeshRenderer } from "../../../../../components/renderer/MeshRenderer"; +import { View3D } from "../../../../../core/View3D"; +import { Object3D } from "../../../../../core/entities/Object3D"; +import { GeometryBase } from "../../../../../core/geometry/GeometryBase"; +import { UnLitTexArrayMaterial } from "../../../../../materials/UnLitTexArrayMaterial"; +import { BitmapTexture2DArray } from "../../../../../textures/BitmapTexture2DArray"; +import { GeometryUtil } from "../../../../../util/GeometryUtil"; +import { StorageGPUBuffer } from "../../../../graphics/webGpu/core/buffer/StorageGPUBuffer"; + +export class Graphic3DMeshRenderer extends MeshRenderer { + public transformBuffer: StorageGPUBuffer; + public sourceGeometry: GeometryBase; + public texture: BitmapTexture2DArray; + public object3Ds: Object3D[]; + + private _onChange: boolean = false; + public init(): void { + super.init(); + } + + public create(source: GeometryBase, tex: BitmapTexture2DArray, num: number) { + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = tex; + this.material = mat; + + this.transformBuffer = new StorageGPUBuffer(num * 2, 0); + this.material.setStorageBuffer("graphicBuffer", this.transformBuffer); + + this.object3Ds = []; + for (let i = 0; i < num; i++) { + const element = new Object3D(); + this.object3Ds.push(element); + this.object3D.addChild(element); + + this.transformBuffer.setFloat("matrix_" + i, element.transform.worldMatrix.index); + this.transformBuffer.setFloat("texId_" + i, 1); + } + + this.transformBuffer.apply(); + this.geometry = GeometryUtil.mergeNumber(source, num); + } + + public setTextureID(i: number, id: number) { + this.transformBuffer.setFloat("texId_" + i, id); + this._onChange = true; + } + + public onUpdate(view?: View3D) { + if (this._onChange) { + this._onChange = false; + this.transformBuffer.apply(); + } + } + +} \ No newline at end of file diff --git a/src/gfx/renderJob/passRenderer/post/PostRenderer.ts b/src/gfx/renderJob/passRenderer/post/PostRenderer.ts index 8d4bec11..27ecbf35 100644 --- a/src/gfx/renderJob/passRenderer/post/PostRenderer.ts +++ b/src/gfx/renderJob/passRenderer/post/PostRenderer.ts @@ -7,7 +7,7 @@ import { GPUContext } from "../../GPUContext"; import { RTFrame } from "../../frame/RTFrame"; import { PostBase } from "../../post/PostBase"; import { RendererBase } from "../RendererBase"; -import { RendererType } from "../state/RendererType"; +import { PassType } from "../state/RendererType"; /** @@ -20,7 +20,7 @@ export class PostRenderer extends RendererBase { constructor() { super(); - this._rendererType = RendererType.POST; + this._rendererType = PassType.POST; this.postList = []; @@ -29,7 +29,7 @@ export class PostRenderer extends RendererBase { public initRenderer() { ShaderLib.register("FullQuad_vert_wgsl", FullQuad_vert_wgsl); - this.finalQuadView = new ViewQuad(`Quad_vert_wgsl`, `Quad_frag_wgsl`, new RTFrame([], []), null, null, false); + this.finalQuadView = new ViewQuad(`Quad_vert_wgsl`, `Quad_frag_wgsl`, new RTFrame([], []), 0, false); } public attachPost(view: View3D, post: PostBase) { diff --git a/src/gfx/renderJob/passRenderer/preDepth/PreDepthPassRenderer.ts b/src/gfx/renderJob/passRenderer/preDepth/PreDepthPassRenderer.ts index 633787d1..321c5213 100644 --- a/src/gfx/renderJob/passRenderer/preDepth/PreDepthPassRenderer.ts +++ b/src/gfx/renderJob/passRenderer/preDepth/PreDepthPassRenderer.ts @@ -14,7 +14,7 @@ import { RTResourceMap } from "../../frame/RTResourceMap"; import { OcclusionSystem } from "../../occlusion/OcclusionSystem"; import { RendererBase } from "../RendererBase"; import { ClusterLightingBuffer } from "../cluster/ClusterLightingBuffer"; -import { RendererType } from "../state/RendererType"; +import { PassType } from "../state/RendererType"; import { ZCullingCompute } from "./ZCullingCompute"; /** @@ -28,7 +28,7 @@ export class PreDepthPassRenderer extends RendererBase { zCullingCompute: ZCullingCompute; constructor() { super(); - this.passType = RendererType.DEPTH; + this.passType = PassType.DEPTH; let size = webGPUContext.presentationSize; let scale = 1; diff --git a/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts b/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts index 5b349716..8815cbaf 100644 --- a/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts +++ b/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts @@ -19,9 +19,10 @@ import { Time } from '../../../../util/Time'; import { RTDescriptor } from '../../../graphics/webGpu/descriptor/RTDescriptor'; import { WebGPUDescriptorCreator } from '../../../graphics/webGpu/descriptor/WebGPUDescriptorCreator'; import { RendererPassState } from '../state/RendererPassState'; -import { RendererType } from '../state/RendererType'; +import { PassType } from '../state/RendererType'; import { ILight } from '../../../../components/lights/ILight'; -import { Reference } from '../../../..'; +import { ShadowTexture } from '../../../../textures/ShadowTexture'; +import { Reference } from '../../../../util/Reference'; type CubeShadowMapInfo = { cubeCamera: CubeCamera, @@ -43,7 +44,7 @@ export class PointLightShadowRenderer extends RendererBase { public shadowSize: number = 1024; constructor() { super(); - this.passType = RendererType.POINT_SHADOW; + this.passType = PassType.POINT_SHADOW; // this.shadowSize = Engine3D.setting.shadow.pointShadowSize; this._shadowCameraDic = new Map(); @@ -60,11 +61,11 @@ export class PointLightShadowRenderer extends RendererBase { } else { let camera = new PointShadowCubeCamera(view.camera.near, view.camera.far, 90, true); camera.label = lightBase.name; - let depths: VirtualTexture[] = []; + let depths: ShadowTexture[] = []; let rendererPassStates: RendererPassState[] = []; for (let i = 0; i < 6; i++) { - let depthTexture = new VirtualTexture(this.shadowSize, this.shadowSize, this.cubeArrayTexture.format, false); + let depthTexture = new ShadowTexture(this.shadowSize, this.shadowSize, this.cubeArrayTexture.format, false); let rtFrame = new RTFrame([this.colorTexture], [new RTDescriptor()]); depthTexture.name = `shadowDepthTexture_` + lightBase.name + i + "_face"; rtFrame.depthTexture = depthTexture; @@ -75,8 +76,7 @@ export class PointLightShadowRenderer extends RendererBase { rendererPassStates[i] = rendererPassState; depths[i] = depthTexture; - Engine3D.getRenderJob(view).postRenderer.setDebugTexture([depthTexture]); - Engine3D.getRenderJob(view).debug(); + Engine3D.getRenderJob(view).postRenderer?.setDebugTexture([depthTexture]); } cubeShadowMapInfo = { cubeCamera: camera, diff --git a/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts b/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts index 6b43dca9..9f2ed6bb 100644 --- a/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts +++ b/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts @@ -15,12 +15,13 @@ import { ShadowLightsCollect } from "../../collect/ShadowLightsCollect"; import { RTFrame } from "../../frame/RTFrame"; import { OcclusionSystem } from "../../occlusion/OcclusionSystem"; import { RendererPassState } from "../state/RendererPassState"; -import { RendererType } from "../state/RendererType"; +import { PassType } from "../state/RendererType"; import { RendererBase } from "../RendererBase"; import { ClusterLightingBuffer } from "../cluster/ClusterLightingBuffer"; import { Reference } from "../../../../util/Reference"; import { Texture } from "../../../graphics/webGpu/core/texture/Texture"; import { CSM } from "../../../../core/csm/CSM"; +import { ShadowTexture } from "../../../../textures/ShadowTexture"; /** * @internal @@ -35,7 +36,7 @@ export class ShadowMapPassRenderer extends RendererBase { constructor() { super(); this.setShadowMap(Engine3D.setting.shadow.shadowSize, CSM.Cascades); - this.passType = RendererType.SHADOW; + this.passType = PassType.SHADOW; } setShadowMap(size: number, cascades: number) { @@ -45,7 +46,7 @@ export class ShadowMapPassRenderer extends RendererBase { for (let i = 0; i < 8; i++) { let rtFrame = new RTFrame([], []); - const tex = new VirtualTexture(size, size, GPUTextureFormat.depth32float, false); + const tex = new ShadowTexture(size, size, GPUTextureFormat.depth32float, false); tex.name = `shadowDepthTexture_${i}`; rtFrame.depthTexture = tex; rtFrame.label = "shadowRender"; diff --git a/src/gfx/renderJob/passRenderer/state/RendererPassState.ts b/src/gfx/renderJob/passRenderer/state/RendererPassState.ts index 46ee9a45..0a584154 100644 --- a/src/gfx/renderJob/passRenderer/state/RendererPassState.ts +++ b/src/gfx/renderJob/passRenderer/state/RendererPassState.ts @@ -15,13 +15,10 @@ export class RendererPassState { public customSize: boolean = false; public zPreTexture: VirtualTexture = null; public depthTexture: VirtualTexture = null; - public outAttachments: GPUColorTargetState[]; + public renderTargetTextures: GPUColorTargetState[]; public outColor: number = -1; public renderTargets: Texture[]; - public rtTextureDescripts: RTDescriptor[]; - // public depthFormat: GPUTextureFormat = 'depth24plus'; - // public depthFormat: GPUTextureFormat = 'depth32float'; - // public depthTexture: GPUTexture; + public rtTextureDescriptors: RTDescriptor[]; public irradianceBuffer: Texture[]; public multisample: number = 0; public multiTexture: GPUTexture; diff --git a/src/gfx/renderJob/passRenderer/state/RendererType.ts b/src/gfx/renderJob/passRenderer/state/RendererType.ts index 09bb584a..d85c9d92 100644 --- a/src/gfx/renderJob/passRenderer/state/RendererType.ts +++ b/src/gfx/renderJob/passRenderer/state/RendererType.ts @@ -1,7 +1,7 @@ /** * @internal */ -export enum RendererType { +export enum PassType { COLOR = 1 << 0, NORMAL = 1 << 1, POSITION = 1 << 2, diff --git a/src/gfx/renderJob/post/BloomPost.ts b/src/gfx/renderJob/post/BloomPost.ts new file mode 100644 index 00000000..e68aecb9 --- /dev/null +++ b/src/gfx/renderJob/post/BloomPost.ts @@ -0,0 +1,280 @@ +import { VirtualTexture } from '../../../textures/VirtualTexture'; +import { UniformGPUBuffer } from '../../graphics/webGpu/core/buffer/UniformGPUBuffer'; +import { WebGPUDescriptorCreator } from '../../graphics/webGpu/descriptor/WebGPUDescriptorCreator'; +import { ComputeShader } from '../../graphics/webGpu/shader/ComputeShader'; +import { GPUTextureFormat } from '../../graphics/webGpu/WebGPUConst'; +import { webGPUContext } from '../../graphics/webGpu/Context3D'; +import { GPUContext } from '../GPUContext'; +import { RendererPassState } from '../passRenderer/state/RendererPassState'; +import { PostBase } from './PostBase'; +import { Engine3D } from '../../../Engine3D'; +import { View3D } from '../../../core/View3D'; +import { RTDescriptor } from '../../graphics/webGpu/descriptor/RTDescriptor'; +import { RTFrame } from '../frame/RTFrame'; +import { downSample, post, threshold, upSample } from '../../../assets/shader/compute/BloomEffect_cs'; + +/** + * Bloom Effects + * ``` + * bloom setting + * let cfg = {@link Engine3D.setting.render.postProcessing.bloom}; + *``` + * @group Post Effects + */ +export class BloomPost extends PostBase { + /** + * @internal + */ + RT_BloomUp: VirtualTexture[]; + RT_BloomDown: VirtualTexture[]; + RT_threshold: VirtualTexture; + /** + * @internal + */ + rendererPassState: RendererPassState; + /** + * @internal + */ + thresholdCompute: ComputeShader; + downSampleComputes: ComputeShader[]; + upSampleComputes: ComputeShader[]; + postCompute: ComputeShader; + /** + * @internal + */ + bloomSetting: UniformGPUBuffer; + /** + * @internal + */ + rtFrame: RTFrame; + + constructor() { + super(); + } + + /** + * @internal + */ + onAttach(view: View3D,) { + Engine3D.setting.render.postProcessing.bloom.enable = true; + this.createGUI(); + } + /** + * @internal + */Render + onDetach(view: View3D,) { + Engine3D.setting.render.postProcessing.bloom.enable = false; + this.removeGUI(); + } + + private createGUI() { + } + + private removeGUI() { + } + + public get downSampleBlurSize(): number { + return Engine3D.setting.render.postProcessing.bloom.downSampleBlurSize; + } + public set downSampleBlurSize(value: number) { + Engine3D.setting.render.postProcessing.bloom.downSampleBlurSize = value; + } + + + public get downSampleBlurSigma(): number { + return Engine3D.setting.render.postProcessing.bloom.downSampleBlurSigma; + } + public set downSampleBlurSigma(value: number) { + Engine3D.setting.render.postProcessing.bloom.downSampleBlurSigma = value; + } + + public get upSampleBlurSize(): number { + return Engine3D.setting.render.postProcessing.bloom.upSampleBlurSize; + } + public set upSampleBlurSize(value: number) { + Engine3D.setting.render.postProcessing.bloom.upSampleBlurSize = value; + } + + public get upSampleBlurSigma(): number { + return Engine3D.setting.render.postProcessing.bloom.upSampleBlurSigma; + } + public set upSampleBlurSigma(value: number) { + Engine3D.setting.render.postProcessing.bloom.upSampleBlurSigma = value; + } + + public get luminanceThreshole(): number { + return Engine3D.setting.render.postProcessing.bloom.luminanceThreshole; + } + public set luminanceThreshole(value: number) { + Engine3D.setting.render.postProcessing.bloom.luminanceThreshole = value; + } + + public get bloomIntensity(): number { + return Engine3D.setting.render.postProcessing.bloom.bloomIntensity; + } + public set bloomIntensity(value: number) { + Engine3D.setting.render.postProcessing.bloom.bloomIntensity = value; + } + + private createThreshouldCompute() { + this.thresholdCompute = new ComputeShader(threshold); + + this.autoSetColorTexture('inTex', this.thresholdCompute); + this.thresholdCompute.setStorageTexture(`outTex`, this.RT_threshold); + this.thresholdCompute.setUniformBuffer('bloomCfg', this.bloomSetting); + this.thresholdCompute.workerSizeX = Math.ceil(this.RT_threshold.width / 8); + this.thresholdCompute.workerSizeY = Math.ceil(this.RT_threshold.height / 8); + this.thresholdCompute.workerSizeZ = 1; + } + + private createDownSampleComputes() { + let setting = Engine3D.setting.render.postProcessing.bloom; + const N = setting.downSampleStep; // 下采样次数 + this.downSampleComputes = []; + + for (let i = 0; i < N; i++) { + let compute = new ComputeShader(downSample); + let dstTexture = this.RT_BloomDown[i]; + let srcTexture = i == 0 ? this.RT_threshold : this.RT_BloomDown[i - 1]; + compute.setSamplerTexture(`inTex`, srcTexture); + compute.setStorageTexture(`outTex`, dstTexture); + compute.setUniformBuffer('bloomCfg', this.bloomSetting); + compute.workerSizeX = Math.ceil(dstTexture.width / 8); + compute.workerSizeY = Math.ceil(dstTexture.height / 8); + compute.workerSizeZ = 1; + + this.downSampleComputes.push(compute); + + // Graphics.Blit(RT_BloomDown[i - 1], RT_BloomDown[i], new Material(Shader.Find("Shaders/downSample"))); + } + } + + private createUpSampleComputes() { + let setting = Engine3D.setting.render.postProcessing.bloom; + const N = setting.downSampleStep; // 下采样次数 + this.upSampleComputes = []; + { + let compute = new ComputeShader(upSample); + let dstTexture = this.RT_BloomUp[0]; + let srcTexture = this.RT_BloomDown[N - 2]; + compute.setSamplerTexture(`_MainTex`, srcTexture); + compute.setSamplerTexture(`_PrevMip`, this.RT_BloomDown[N - 1]); + compute.setStorageTexture(`outTex`, dstTexture); + compute.setUniformBuffer('bloomCfg', this.bloomSetting); + compute.workerSizeX = Math.ceil(dstTexture.width / 8); + compute.workerSizeY = Math.ceil(dstTexture.height / 8); + compute.workerSizeZ = 1; + + this.upSampleComputes.push(compute); + } + for (let i = 1; i < N - 1; i++) { + let compute = new ComputeShader(upSample); + let dstTexture = this.RT_BloomUp[i]; + let srcTexture = this.RT_BloomDown[N - 2 - i]; + compute.setSamplerTexture(`_MainTex`, srcTexture); + compute.setSamplerTexture(`_PrevMip`, this.RT_BloomUp[i - 1]); + compute.setStorageTexture(`outTex`, dstTexture); + compute.setUniformBuffer('bloomCfg', this.bloomSetting); + compute.workerSizeX = Math.ceil(dstTexture.width / 8); + compute.workerSizeY = Math.ceil(dstTexture.height / 8); + compute.workerSizeZ = 1; + + this.upSampleComputes.push(compute); + + // Graphics.Blit(RT_BloomDown[i - 1], RT_BloomDown[i], new Material(Shader.Find("Shaders/downSample"))); + } + } + + private createPostCompute() { + let setting = Engine3D.setting.render.postProcessing.bloom; + const N = setting.downSampleStep; // 融合结果 + + this.postCompute = new ComputeShader(post); + + this.autoSetColorTexture('_MainTex', this.postCompute); + this.postCompute.setSamplerTexture(`_BloomTex`, this.RT_BloomUp[N - 2]); + this.postCompute.setStorageTexture(`outTex`, this.RT_threshold); + this.postCompute.setUniformBuffer('bloomCfg', this.bloomSetting); + + this.postCompute.workerSizeX = Math.ceil(this.RT_threshold.width / 8); + this.postCompute.workerSizeY = Math.ceil(this.RT_threshold.height / 8); + this.postCompute.workerSizeZ = 1; + } + + + private createResource() { + let setting = Engine3D.setting.render.postProcessing.bloom; + + this.bloomSetting = new UniformGPUBuffer(4 * 2); //vector4 * 2 + + let presentationSize = webGPUContext.presentationSize; + let screenWidth = presentationSize[0]; + let screenHeight = presentationSize[1]; + + this.RT_threshold = new VirtualTexture(screenWidth, screenHeight, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); + + const N = setting.downSampleStep; // 下采样次数 + { + let downSize = 2; + this.RT_BloomDown = []; + + // 创建下纹理 + for (let i = 0; i < N; i++) { + let w = Math.ceil(screenWidth / downSize); + let h = Math.ceil(screenHeight / downSize); + this.RT_BloomDown[i] = new VirtualTexture(w, h, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); + downSize *= 2; + } + } + + { + // 创建上采样纹理 + this.RT_BloomUp = []; + for (let i = 0; i < N - 1; i++) { + let w = this.RT_BloomDown[N - 2 - i].width; + let h = this.RT_BloomDown[N - 2 - i].height; + this.RT_BloomUp[i] = new VirtualTexture(w, h, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); + } + } + + let bloomDesc = new RTDescriptor(); + bloomDesc.loadOp = `load`; + + // this.rtFrame = new RTFrame([this.RT_threshold], [bloomDesc]); + // this.rtFrame = new RTFrame([this.RT_BloomDown[4]], [bloomDesc]); + // this.rtFrame = new RTFrame([this.RT_BloomUp[5]], [bloomDesc]); + this.rtFrame = new RTFrame([this.RT_threshold], [bloomDesc]); + } + + /** + * @internal + */ + render(view: View3D, command: GPUCommandEncoder) { + if (!this.thresholdCompute) { + this.createResource(); + this.createThreshouldCompute(); + + this.createDownSampleComputes(); + this.createUpSampleComputes(); + this.createPostCompute(); + + this.rendererPassState = WebGPUDescriptorCreator.createRendererPassState(this.rtFrame, null); + this.rendererPassState.label = "Bloom"; + } + let cfg = Engine3D.setting.render.postProcessing.bloom; + + this.bloomSetting.setFloat('downSampleStep', cfg.downSampleStep); + this.bloomSetting.setFloat('downSampleBlurSize', cfg.downSampleBlurSize); + this.bloomSetting.setFloat('downSampleBlurSigma', cfg.downSampleBlurSigma); + this.bloomSetting.setFloat('upSampleBlurSize', cfg.upSampleBlurSize); + this.bloomSetting.setFloat('upSampleBlurSigma', cfg.upSampleBlurSigma); + this.bloomSetting.setFloat('luminanceThreshole', cfg.luminanceThreshole); + this.bloomSetting.setFloat('bloomIntensity', cfg.bloomIntensity); + + this.bloomSetting.apply(); + + GPUContext.computeCommand(command, [this.thresholdCompute, ...this.downSampleComputes, ...this.upSampleComputes, this.postCompute]); + GPUContext.lastRenderPassState = this.rendererPassState; + } + +} diff --git a/src/gfx/renderJob/post/DepthOfFieldPost.ts b/src/gfx/renderJob/post/DepthOfFieldPost.ts index 79177990..fc92a435 100644 --- a/src/gfx/renderJob/post/DepthOfFieldPost.ts +++ b/src/gfx/renderJob/post/DepthOfFieldPost.ts @@ -129,8 +129,8 @@ export class DepthOfFieldPost extends PostBase { blurCompute.setUniformBuffer('blurSetting', blurSetting); let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); - blurCompute.setSamplerTexture(RTResourceConfig.positionBufferTex_NAME, rtFrame.attachments[1]); - blurCompute.setSamplerTexture(RTResourceConfig.normalBufferTex_NAME, rtFrame.attachments[2]); + blurCompute.setSamplerTexture(RTResourceConfig.positionBufferTex_NAME, rtFrame.renderTargets[1]); + blurCompute.setSamplerTexture(RTResourceConfig.normalBufferTex_NAME, rtFrame.renderTargets[2]); let input = i % 2 == 0 ? this.blurTexture1 : this.blurTexture2; let output = i % 2 == 1 ? this.blurTexture1 : this.blurTexture2; diff --git a/src/gfx/renderJob/post/FXAAPost.ts b/src/gfx/renderJob/post/FXAAPost.ts index fe2ed8bc..031cf277 100644 --- a/src/gfx/renderJob/post/FXAAPost.ts +++ b/src/gfx/renderJob/post/FXAAPost.ts @@ -4,8 +4,6 @@ import { Vector2 } from '../../../math/Vector2'; import { UniformNode } from '../../graphics/webGpu/core/uniforms/UniformNode'; import { GPUTextureFormat } from '../../graphics/webGpu/WebGPUConst'; import { webGPUContext } from '../../graphics/webGpu/Context3D'; -import { RTResourceConfig } from '../config/RTResourceConfig'; -import { RTResourceMap } from '../frame/RTResourceMap'; import { PostBase } from './PostBase'; import { View3D } from '../../../core/View3D'; import { FXAAShader } from '../../..'; @@ -21,17 +19,13 @@ export class FXAAPost extends PostBase { constructor() { super(); let presentationSize = webGPUContext.presentationSize; - RTResourceMap.createRTTexture(RTResourceConfig.colorBufferTex_NAME, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float, false); ShaderLib.register("FXAA_Shader", FXAAShader); - let shaderUniforms = { - u_texel: new UniformNode(new Vector2(1.0 / presentationSize[0], 1.0 / presentationSize[1])), - u_strength: new UniformNode(4), - }; - let rt = this.createRTTexture(`FXAAPost`, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float); - this.createViewQuad(`fxaa`, 'FXAA_Shader', rt, shaderUniforms); + let quad = this.createViewQuad(`fxaa`, 'FXAA_Shader', rt); + quad.quadShader.setUniform("u_texel", new Vector2(1.0 / presentationSize[0], 1.0 / presentationSize[1])); + quad.quadShader.setUniform("u_strength", 4); } /** * @internal diff --git a/src/gfx/renderJob/post/GTAOPost.ts b/src/gfx/renderJob/post/GTAOPost.ts index 2fddb75e..049cb45e 100644 --- a/src/gfx/renderJob/post/GTAOPost.ts +++ b/src/gfx/renderJob/post/GTAOPost.ts @@ -180,9 +180,9 @@ export class GTAOPost extends PostBase { this.gtaoCompute.setStorageBuffer('aoBuffer', this.aoBuffer); let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); //setting.usePosFloat32 ? RTResourceMap.getTexture(RTResourceConfig.positionBufferTex_NAME): - let posTexture = rtFrame.attachments[1]; + let posTexture = rtFrame.renderTargets[1]; this.gtaoCompute.setSamplerTexture(`posTex`, posTexture); - this.gtaoCompute.setSamplerTexture(`normalTex`, rtFrame.attachments[2]); + this.gtaoCompute.setSamplerTexture(`normalTex`, rtFrame.renderTargets[2]); this.autoSetColorTexture('inTex', this.gtaoCompute); this.gtaoCompute.setStorageTexture(`outTex`, this.gtaoTexture); @@ -265,4 +265,4 @@ export class GTAOPost extends PostBase { GPUContext.computeCommand(command, [this.gtaoCompute]); GPUContext.lastRenderPassState = this.rendererPassState; } -} +} \ No newline at end of file diff --git a/src/gfx/renderJob/post/GlobalFog.ts b/src/gfx/renderJob/post/GlobalFog.ts index 459e8c8e..7c8c163b 100644 --- a/src/gfx/renderJob/post/GlobalFog.ts +++ b/src/gfx/renderJob/post/GlobalFog.ts @@ -39,25 +39,28 @@ export class GlobalFog extends PostBase { ShaderLib.register("GlobalFog_shader", GlobalFog_shader); let shaderUniforms = { - fogColor: new UniformNode(new Color(globalFog.fogColor.r, globalFog.fogColor.g, globalFog.fogColor.b, globalFog.fogColor.a)), - fogType: new UniformNode(globalFog.fogType), - fogHeightScale: new UniformNode(globalFog.fogHeightScale), - start: new UniformNode(globalFog.start), - end: new UniformNode(globalFog.end), - density: new UniformNode(globalFog.density), - ins: new UniformNode(globalFog.ins), - falloff: new UniformNode(globalFog.falloff), - rayLength: new UniformNode(globalFog.rayLength), - scatteringExponent: new UniformNode(globalFog.scatteringExponent), - dirHeightLine: new UniformNode(globalFog.dirHeightLine), - skyFactor: new UniformNode(globalFog.skyFactor), - skyRoughness: new UniformNode(globalFog.skyRoughness), - overrideSkyFactor: new UniformNode(globalFog.overrideSkyFactor), isSkyHDR: new UniformNode(0), }; this.rtTexture = this.createRTTexture(`GlobalFog`, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float); - this.viewQuad = this.createViewQuad(`GlobalFog`, 'GlobalFog_shader', this.rtTexture, shaderUniforms); + this.viewQuad = this.createViewQuad(`GlobalFog`, 'GlobalFog_shader', this.rtTexture); + let shader = this.viewQuad.quadShader; + + shader.setUniformColor("fogColor", new Color(globalFog.fogColor.r, globalFog.fogColor.g, globalFog.fogColor.b, globalFog.fogColor.a)); + shader.setUniform("fogType", globalFog.fogType); + shader.setUniform("fogHeightScale", globalFog.fogHeightScale); + shader.setUniform("start", globalFog.start); + shader.setUniform("end", globalFog.end); + shader.setUniform("density", globalFog.density); + shader.setUniform("ins", globalFog.ins); + shader.setUniform("falloff", globalFog.falloff); + shader.setUniform("rayLength", globalFog.rayLength); + shader.setUniform("scatteringExponent", globalFog.scatteringExponent); + shader.setUniform("dirHeightLine", globalFog.dirHeightLine); + shader.setUniform("skyFactor", globalFog.skyFactor); + shader.setUniform("skyRoughness", globalFog.skyRoughness); + shader.setUniform("overrideSkyFactor", globalFog.overrideSkyFactor); + shader.setUniform("isSkyHDR", 0); let ptex = rtFrame.getPositionMap(); let ntex = rtFrame.getNormalMap(); @@ -79,56 +82,56 @@ export class GlobalFog extends PostBase { public set fogType(v: number) { this._globalFog.fogType = v; - this.viewQuad.uniforms['fogType'].value = v; + this.viewQuad.quadShader.setUniform('fogType', v); } public get fogType() { return this._globalFog.fogType; } public set fogHeightScale(v: number) { this._globalFog.fogHeightScale = v; - this.viewQuad.uniforms['fogHeightScale'].value = v; + this.viewQuad.quadShader.setUniform('fogHeightScale', v); } public get fogHeightScale() { - return this.viewQuad.uniforms['fogHeightScale'].value; + return this.viewQuad.quadShader.getUniform('fogHeightScale'); } public set start(v: number) { this._globalFog.start = v; - this.viewQuad.uniforms['start'].value = v; + this.viewQuad.quadShader.setUniform('start', v); } public get start() { - return this.viewQuad.uniforms['start'].value; + return this.viewQuad.quadShader.getUniform('start'); } public set end(v: number) { this._globalFog.end = v; - this.viewQuad.uniforms['end'].value = v; + this.viewQuad.quadShader.setUniform('end', v); } public get end() { - return this.viewQuad.uniforms['end'].value; + return this.viewQuad.quadShader.getUniform('end'); } public set ins(v: number) { this._globalFog.ins = v; - this.viewQuad.uniforms['ins'].value = v; + this.viewQuad.quadShader.setUniform('ins', v); } public get ins() { - return this.viewQuad.uniforms['ins'].value; + return this.viewQuad.quadShader.getUniform('ins'); } public set density(v: number) { this._globalFog.density = v; - this.viewQuad.uniforms['density'].value = v; + this.viewQuad.quadShader.setUniform('density', v); } public get density() { - return this.viewQuad.uniforms['density'].value; + return this.viewQuad.quadShader.getUniform('density'); } public set skyRoughness(v: number) { this._globalFog.skyRoughness = v; - this.viewQuad.uniforms['skyRoughness'].value = v; + this.viewQuad.quadShader.setUniform('skyRoughness', v); } public get skyRoughness() { return this._globalFog.skyRoughness; } public set skyFactor(v: number) { this._globalFog.skyFactor = v; - this.viewQuad.uniforms['skyFactor'].value = v; + this.viewQuad.quadShader.setUniform('skyFactor', v); } public get skyFactor() { return this._globalFog.skyFactor; @@ -136,7 +139,7 @@ export class GlobalFog extends PostBase { public set overrideSkyFactor(v: number) { this._globalFog.overrideSkyFactor = v; - this.viewQuad.uniforms['overrideSkyFactor'].value = v; + this.viewQuad.quadShader.setUniform('overrideSkyFactor', v); } public get overrideSkyFactor() { return this._globalFog.overrideSkyFactor; @@ -154,22 +157,21 @@ export class GlobalFog extends PostBase { */ public set fogColor(value: Color) { this._globalFog.fogColor.copyFrom(value); - this.viewQuad.uniforms['fogColor'].color = value; - this.viewQuad.uniforms['fogColor'].onChange(); + this.viewQuad.quadShader.setUniformColor('fogColor', value); } public set falloff(v: number) { this._globalFog.falloff = v; - this.viewQuad.uniforms['falloff'].value = v; + this.viewQuad.quadShader.setUniform('falloff', v); } public get falloff() { - return this.viewQuad.uniforms['falloff'].value; + return this.viewQuad.quadShader.getUniform('falloff'); } public set rayLength(v: number) { this._globalFog.rayLength = v; - this.viewQuad.uniforms['rayLength'].value = v; + this.viewQuad.quadShader.setUniform('rayLength', v); } public get rayLength() { @@ -178,7 +180,7 @@ export class GlobalFog extends PostBase { public set scatteringExponent(v: number) { this._globalFog.scatteringExponent = v; - this.viewQuad.uniforms['scatteringExponent'].value = v; + this.viewQuad.quadShader.setUniform('scatteringExponent', v); } public get scatteringExponent() { @@ -187,7 +189,7 @@ export class GlobalFog extends PostBase { public set dirHeightLine(v: number) { this._globalFog.dirHeightLine = v; - this.viewQuad.uniforms['dirHeightLine'].value = v; + this.viewQuad.quadShader.setUniform('dirHeightLine', v); } public get dirHeightLine() { @@ -198,7 +200,7 @@ export class GlobalFog extends PostBase { * @internal */ public setInputTexture(positionMap: VirtualTexture, normalMap: VirtualTexture) { - const pass = this.viewQuad.pass; + const pass = this.viewQuad.quadShader; pass.setTexture('positionMap', positionMap); pass.setTexture('normalMap', normalMap); this._lastSkyTexture = this.getSkyTexture(); @@ -217,7 +219,7 @@ export class GlobalFog extends PostBase { * @internal */ render(view: View3D, command: GPUCommandEncoder) { - const pass = this.viewQuad.pass; + const pass = this.viewQuad.quadShader; let skyTexture = this.getSkyTexture(); if (skyTexture != this._lastSkyTexture) { this._lastSkyTexture = skyTexture; diff --git a/src/gfx/renderJob/post/GodRayPost.ts b/src/gfx/renderJob/post/GodRayPost.ts index 7c3b1f4d..e59cadab 100644 --- a/src/gfx/renderJob/post/GodRayPost.ts +++ b/src/gfx/renderJob/post/GodRayPost.ts @@ -87,8 +87,8 @@ export class GodRayPost extends PostBase { let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); - this.godRayCompute.setSamplerTexture(`posTex`, rtFrame.attachments[1]); - this.godRayCompute.setSamplerTexture(`normalTex`, rtFrame.attachments[2]); + this.godRayCompute.setSamplerTexture(`posTex`, rtFrame.renderTargets[1]); + this.godRayCompute.setSamplerTexture(`normalTex`, rtFrame.renderTargets[2]); this.autoSetColorTexture('inTex', this.godRayCompute); this.godRayCompute.setStorageTexture(`outTex`, this.godRayTexture); diff --git a/src/gfx/renderJob/post/HDRBloomPost.ts b/src/gfx/renderJob/post/HDRBloomPost.ts deleted file mode 100644 index f2762783..00000000 --- a/src/gfx/renderJob/post/HDRBloomPost.ts +++ /dev/null @@ -1,189 +0,0 @@ -import { ViewQuad } from '../../../core/ViewQuad'; -import { Engine3D } from '../../../Engine3D'; -import { Vector2 } from '../../../math/Vector2'; -import { UniformNode } from '../../graphics/webGpu/core/uniforms/UniformNode'; -import { GPUTextureFormat } from '../../graphics/webGpu/WebGPUConst'; -import { webGPUContext } from '../../graphics/webGpu/Context3D'; -import { GPUContext } from '../GPUContext'; -import { RTResourceConfig } from '../config/RTResourceConfig'; -import { RTResourceMap } from '../frame/RTResourceMap'; -import { PostBase } from './PostBase'; -import { View3D } from '../../../core/View3D'; -import { Color, RendererType } from '../../..'; -/** - * HDR Bloom effect - * ``` - * @group Post Effects - */ -export class HDRBloomPost extends PostBase { - private brightnessView: ViewQuad; - private compositeView: ViewQuad; - private blurList: { ql: ViewQuad; qr: ViewQuad }[]; - /** - * @internal - */ - public blurX: number = 1; - /** - * @internal - */ - public blurY: number = 1; - constructor() { - super(); - const bloomSetting = Engine3D.setting.render.postProcessing.bloom; - - bloomSetting.enable = true; - - let presentationSize = webGPUContext.presentationSize; - let outTextures = this.createRTTexture('HDRBloomPost-outTextures', presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float, false); - RTResourceMap.createRTTexture(RTResourceConfig.colorBufferTex_NAME, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float, false); - - { - let brightnessTextures = this.createRTTexture('brightnessTextures', presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float, false); - - this.brightnessView = this.createViewQuad(`brightnessView`, `Bloom_Brightness_frag_wgsl`, brightnessTextures, { - luminosityThreshold: new UniformNode(bloomSetting.luminosityThreshold), - }); - } - - let blurMip = 5; - let sizeW = presentationSize[0]; - let sizeH = presentationSize[1]; - this.blurList = []; - for (let i = 0; i < blurMip; i++) { - let tex_l = this.createRTTexture(`tex_l${i}`, sizeW, sizeH, GPUTextureFormat.rgba16float); - let tex_r = this.createRTTexture(`tex_r${i}`, sizeW, sizeH, GPUTextureFormat.rgba16float); - - let ql = this.createViewQuad(`ql${i}`, `Bloom_blur_frag_wgsl`, tex_l, { - texSize: new UniformNode(new Vector2(sizeW * 2, sizeH * 2)), - hScale: new UniformNode(i), - vScale: new UniformNode(i), - horizontal: new UniformNode(0.5), - }); - - let qr = this.createViewQuad(`qr${i}`, `Bloom_blur_frag_wgsl`, tex_r, { - texSize: new UniformNode(new Vector2(sizeW * 2, sizeH * 2)), - hScale: new UniformNode(i), - vScale: new UniformNode(i), - horizontal: new UniformNode(1.0), - }); - - this.blurList.push({ - ql: ql, - qr: qr, - }); - - sizeW /= 2; - sizeH /= 2; - } - - { - this.compositeView = this.createViewQuad(`compositeView`, `Bloom_composite_frag_wgsl`, outTextures, { - tintColor: new UniformNode(new Color(1, 1, 1)), - bloomStrength: new UniformNode(bloomSetting.strength), - exposure: new UniformNode(bloomSetting.exposure), - bloomRadius: new UniformNode(1), - }); - } - - this.blurX = bloomSetting.blurX; - this.blurY = bloomSetting.blurY; - this.luminosityThreshold = bloomSetting.luminosityThreshold; - this.strength = bloomSetting.strength; - this.radius = bloomSetting.radius; - } - - onAttach(view: View3D): void { - this.debug(); - } - - onDetach(view: View3D): void { - } - - public debug() { - } - - public get tintColor(): Color { - return this.compositeView.uniforms['tintColor'].color; - } - - public set tintColor(color: Color) { - this.compositeView.uniforms['tintColor'].color = color; - } - - public get strength() { - return this.compositeView.uniforms['bloomStrength'].value; - } - - public set strength(value: number) { - this.compositeView.uniforms['bloomStrength'].value = value; - } - - public get exposure() { - return this.compositeView.uniforms['exposure'].value; - } - - public set exposure(value: number) { - this.compositeView.uniforms['exposure'].value = value; - } - - - public get radius() { - return this.compositeView.uniforms['bloomRadius'].value; - } - - public set radius(value: number) { - this.compositeView.uniforms['bloomRadius'].value = value; - } - - public get luminosityThreshold(): number { - return this.brightnessView.uniforms['luminosityThreshold'].value; - } - - public set luminosityThreshold(value: number) { - this.brightnessView.uniforms['luminosityThreshold'].value = value; - } - - /** - * @internal - */ - render(view: View3D, command: GPUCommandEncoder) { - // let command = GPUContext.beginCommandEncoder(); - { - let colorTexture = this.getOutTexture(); - { - this.brightnessView.renderToViewQuad(view, this.brightnessView, command, colorTexture); - } - { - let tex = this.brightnessView.rendererPassState.renderTargets[0]; - for (let i = 0; i < this.blurList.length; i++) { - let ql = this.blurList[i].ql; - let qr = this.blurList[i].qr; - - ql.pass.setUniformFloat(`horizontal`, 0.5); - ql.pass.setUniformFloat(`vScale`, i * this.blurX); - - ql.renderToViewQuad(view, ql, command, tex); - tex = ql.rendererPassState.renderTargets[0]; - - qr.pass.setUniformFloat(`horizontal`, 2.0); - qr.pass.setUniformFloat(`hScale`, i * this.blurY); - - qr.renderToViewQuad(view, qr, command, tex); - tex = qr.rendererPassState.renderTargets[0]; - } - } - - { - let pass = this.compositeView.pass; - pass.setTexture(`blurTex1`, this.blurList[0].qr.rendererPassState.renderTargets[0]); - pass.setTexture(`blurTex2`, this.blurList[1].qr.rendererPassState.renderTargets[0]); - pass.setTexture(`blurTex3`, this.blurList[2].qr.rendererPassState.renderTargets[0]); - pass.setTexture(`blurTex4`, this.blurList[3].qr.rendererPassState.renderTargets[0]); - pass.setTexture(`blurTex5`, this.blurList[4].qr.rendererPassState.renderTargets[0]); - - this.compositeView.renderToViewQuad(view, this.compositeView, command, colorTexture); - } - } - // GPUContext.endCommandEncoder(command); - } -} diff --git a/src/gfx/renderJob/post/PostBase.ts b/src/gfx/renderJob/post/PostBase.ts index 10e151f3..7c1b9cba 100644 --- a/src/gfx/renderJob/post/PostBase.ts +++ b/src/gfx/renderJob/post/PostBase.ts @@ -1,4 +1,3 @@ -import { Scene3D } from '../../../core/Scene3D'; import { ViewQuad } from '../../../core/ViewQuad'; import { VirtualTexture } from '../../../textures/VirtualTexture'; import { Texture } from '../../graphics/webGpu/core/texture/Texture'; @@ -34,8 +33,8 @@ export class PostBase { return rt; } - protected createViewQuad(name: string, shaderName: string, outRtTexture: VirtualTexture, shaderUniforms?: { [uniName: string]: UniformNode }, msaa: number = 0) { - let viewQuad = RTResourceMap.createViewQuad(name, 'Quad_vert_wgsl', shaderName, outRtTexture, shaderUniforms, msaa); + protected createViewQuad(name: string, shaderName: string, outRtTexture: VirtualTexture, msaa: number = 0) { + let viewQuad = RTResourceMap.createViewQuad(name, 'Quad_vert_wgsl', shaderName, outRtTexture, msaa); this.rtViewQuad.set(name, viewQuad); return viewQuad; } diff --git a/src/gfx/renderJob/post/SSRPost.ts b/src/gfx/renderJob/post/SSRPost.ts index 5fedce16..2746ccdb 100644 --- a/src/gfx/renderJob/post/SSRPost.ts +++ b/src/gfx/renderJob/post/SSRPost.ts @@ -169,8 +169,8 @@ export class SSRPost extends PostBase { let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); this.SSR_RayTraceCompute.setSamplerTexture("zBufferTexture", rtFrame.getPositionMap()); - this.SSR_RayTraceCompute.setSamplerTexture(RTResourceConfig.normalBufferTex_NAME, rtFrame.attachments[2]); - this.SSR_RayTraceCompute.setSamplerTexture(RTResourceConfig.materialBufferTex_NAME, rtFrame.attachments[3]); + this.SSR_RayTraceCompute.setSamplerTexture(RTResourceConfig.normalBufferTex_NAME, rtFrame.renderTargets[2]); + this.SSR_RayTraceCompute.setSamplerTexture(RTResourceConfig.materialBufferTex_NAME, rtFrame.renderTargets[3]); if (EntityCollect.instance.sky instanceof SkyRenderer) this.SSR_RayTraceCompute.setSamplerTexture(`prefilterMap`, EntityCollect.instance.sky.map); diff --git a/src/index.ts b/src/index.ts index 845da1b6..70fff56e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,6 +6,8 @@ export * from "./assets/shader/anim/SkeletonAnimation_shader" export * from "./assets/shader/cluster/ClusterBoundsSource_cs" export * from "./assets/shader/cluster/ClusterLighting_cs" export * from "./assets/shader/compute/BLUR_CsShader" +export * from "./assets/shader/compute/BRDFLUT" +export * from "./assets/shader/compute/BloomEffect_cs" export * from "./assets/shader/compute/BlurEffectCreator_cs" export * from "./assets/shader/compute/DDGIIrradiance_Cs" export * from "./assets/shader/compute/DDGILighting_CSShader" @@ -21,6 +23,7 @@ export * from "./assets/shader/compute/OutLineBlendColor_cs" export * from "./assets/shader/compute/OutlineCalcOutline_cs" export * from "./assets/shader/compute/Outline_cs" export * from "./assets/shader/compute/Picker_cs" +export * from "./assets/shader/compute/PreIntegratedLut" export * from "./assets/shader/compute/SSAO_cs" export * from "./assets/shader/compute/SSR_BlendColor_cs" export * from "./assets/shader/compute/SSR_IS_cs" @@ -47,6 +50,7 @@ export * from "./assets/shader/core/struct/ClusterLight" export * from "./assets/shader/core/struct/ColorPassFragmentOutput" export * from "./assets/shader/core/struct/FragmentVarying" export * from "./assets/shader/core/struct/ShadingInput" +export * from "./assets/shader/core/struct/VertexAttributeIndexShader" export * from "./assets/shader/core/struct/VertexAttributes" export * from "./assets/shader/glsl/Quad_glsl" export * from "./assets/shader/glsl/Sky_glsl" @@ -54,7 +58,9 @@ export * from "./assets/shader/glsl/post/LUT_glsl" export * from "./assets/shader/graphic/Graphic3DShader_fs" export * from "./assets/shader/graphic/Graphic3DShader_vs" export * from "./assets/shader/lighting/BRDF_frag" +export * from "./assets/shader/lighting/BsDF_frag" export * from "./assets/shader/lighting/BxDF_frag" +export * from "./assets/shader/lighting/Hair_frag" export * from "./assets/shader/lighting/IESProfiles_frag" export * from "./assets/shader/lighting/IrradianceVolumeData_frag" export * from "./assets/shader/lighting/Irradiance_frag" @@ -63,13 +69,16 @@ export * from "./assets/shader/lighting/UnLit_frag" export * from "./assets/shader/materials/ColorLitShader" export * from "./assets/shader/materials/GIProbeShader" export * from "./assets/shader/materials/GlassShader" -export * from "./assets/shader/materials/LambertShader" -export * from "./assets/shader/materials/LitShader" +export * from "./assets/shader/materials/Hair_shader" +export * from "./assets/shader/materials/Lambert_shader" +export * from "./assets/shader/materials/Lit_shader" export * from "./assets/shader/materials/OutlinePass" export * from "./assets/shader/materials/PBRLItShader" +export * from "./assets/shader/materials/PBRLitSSSShader" export * from "./assets/shader/materials/PavementShader" export * from "./assets/shader/materials/PointShadowDebug" export * from "./assets/shader/materials/UnLit" +export * from "./assets/shader/materials/UnLitTextureArray" export * from "./assets/shader/materials/program/BxdfDebug_frag" export * from "./assets/shader/materials/program/Clearcoat_frag" export * from "./assets/shader/materials/program/ClusterDebug_frag" @@ -82,13 +91,11 @@ export * from "./assets/shader/materials/uniforms/VideoUniform_frag" export * from "./assets/shader/math/FastMathShader" export * from "./assets/shader/math/MathShader" export * from "./assets/shader/math/MatrixShader" -export * from "./assets/shader/post/Bloom_shader" export * from "./assets/shader/post/FXAAShader" export * from "./assets/shader/post/GlobalFog_shader" export * from "./assets/shader/quad/Quad_shader" export * from "./assets/shader/sky/AtmosphericScatteringSky_shader" export * from "./assets/shader/sky/CubeSky_Shader" -export * from "./assets/shader/utils/BRDFLUT" export * from "./assets/shader/utils/ColorUtil" export * from "./assets/shader/utils/GenerayRandomDir" export * from "./components/AtmosphericComponent" @@ -98,6 +105,7 @@ export * from "./components/ComponentBase" export * from "./components/IComponent" export * from "./components/SkeletonAnimationComponent" export * from "./components/Transform" +export * from "./components/anim/AnimatorComponent" export * from "./components/anim/OAnimationEvent" export * from "./components/anim/curveAnim/AnimationMonitor" export * from "./components/anim/curveAnim/AttributeAnimCurve" @@ -160,6 +168,7 @@ export * from "./components/lights/DirectLight" export * from "./components/lights/GILighting" export * from "./components/lights/IESProfiles" export * from "./components/lights/ILight" +export * from "./components/lights/Light" export * from "./components/lights/LightBase" export * from "./components/lights/LightData" export * from "./components/lights/PointLight" @@ -167,9 +176,11 @@ export * from "./components/lights/SpotLight" export * from "./components/post/PostProcessingComponent" export * from "./components/renderer/GlobalIlluminationComponent" export * from "./components/renderer/InstanceDrawComponent" +export * from "./components/renderer/MeshFilter" export * from "./components/renderer/MeshRenderer" export * from "./components/renderer/RenderNode" export * from "./components/renderer/SkinnedMeshRenderer" +export * from "./components/renderer/SkinnedMeshRenderer2" export * from "./components/renderer/SkyRenderer" export * from "./components/shape/BoxColliderShape" export * from "./components/shape/CapsuleColliderShape" @@ -213,6 +224,11 @@ export * from "./core/tree/kdTree/KDTreeNode" export * from "./core/tree/kdTree/KDTreeSpace" export * from "./core/tree/octree/Octree" export * from "./core/tree/octree/OctreeEntity" +export * from "./core/tree/quad/IQuadNode" +export * from "./core/tree/quad/QuadAABB" +export * from "./core/tree/quad/QuadRoot" +export * from "./core/tree/quad/QuadTree" +export * from "./core/tree/quad/QuadTreeCell" export * from "./event/CEvent" export * from "./event/CEventDispatcher" export * from "./event/CEventListener" @@ -236,6 +252,8 @@ export * from "./gfx/graphics/webGpu/CanvasConfig" export * from "./gfx/graphics/webGpu/Context3D" export * from "./gfx/graphics/webGpu/PipelinePool" export * from "./gfx/graphics/webGpu/WebGPUConst" +export * from "./gfx/graphics/webGpu/compute/PreIntegratedLutCompute" +export * from "./gfx/graphics/webGpu/compute/RenderShaderCompute" export * from "./gfx/graphics/webGpu/core/bindGroups/GlobalBindGroup" export * from "./gfx/graphics/webGpu/core/bindGroups/GlobalBindGroupLayout" export * from "./gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup" @@ -262,8 +280,9 @@ export * from "./gfx/graphics/webGpu/core/uniforms/UniformNode" export * from "./gfx/graphics/webGpu/descriptor/RTDescriptor" export * from "./gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator" export * from "./gfx/graphics/webGpu/shader/ComputeShader" -export * from "./gfx/graphics/webGpu/shader/RenderShader" -export * from "./gfx/graphics/webGpu/shader/ShaderBase" +export * from "./gfx/graphics/webGpu/shader/RenderShaderPass" +export * from "./gfx/graphics/webGpu/shader/Shader" +export * from "./gfx/graphics/webGpu/shader/ShaderPassBase" export * from "./gfx/graphics/webGpu/shader/ShaderStage" export * from "./gfx/graphics/webGpu/shader/converter/GLSLLexer" export * from "./gfx/graphics/webGpu/shader/converter/GLSLLexerToken" @@ -320,6 +339,8 @@ export * from "./gfx/renderJob/passRenderer/graphic/Graphic3DLineBatchRenderer" export * from "./gfx/renderJob/passRenderer/graphic/Graphic3DRender" export * from "./gfx/renderJob/passRenderer/graphic/GraphicConfig" export * from "./gfx/renderJob/passRenderer/graphic/Graphics3DShape" +export * from "./gfx/renderJob/passRenderer/graphic/new/Graphic3DMesh" +export * from "./gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer" export * from "./gfx/renderJob/passRenderer/post/PostRenderer" export * from "./gfx/renderJob/passRenderer/preDepth/PreDepthPassRenderer" export * from "./gfx/renderJob/passRenderer/preDepth/ZCullingCompute" @@ -328,12 +349,12 @@ export * from "./gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer" export * from "./gfx/renderJob/passRenderer/state/RendererMask" export * from "./gfx/renderJob/passRenderer/state/RendererPassState" export * from "./gfx/renderJob/passRenderer/state/RendererType" +export * from "./gfx/renderJob/post/BloomPost" export * from "./gfx/renderJob/post/DepthOfFieldPost" export * from "./gfx/renderJob/post/FXAAPost" export * from "./gfx/renderJob/post/GTAOPost" export * from "./gfx/renderJob/post/GlobalFog" export * from "./gfx/renderJob/post/GodRayPost" -export * from "./gfx/renderJob/post/HDRBloomPost" export * from "./gfx/renderJob/post/OutlinePost" export * from "./gfx/renderJob/post/PostBase" export * from "./gfx/renderJob/post/SSRPost" @@ -356,6 +377,7 @@ export * from "./loader/parser/FontParser" export * from "./loader/parser/I3DMParser" export * from "./loader/parser/OBJParser" export * from "./loader/parser/ParserBase" +export * from "./loader/parser/ParserFormat" export * from "./loader/parser/RGBEParser" export * from "./loader/parser/b3dm/B3DMLoader" export * from "./loader/parser/b3dm/B3DMLoaderBase" @@ -390,6 +412,33 @@ export * from "./loader/parser/gltf/extends/KHR_texture_basisu" export * from "./loader/parser/gltf/extends/KHR_texture_transform" export * from "./loader/parser/i3dm/I3DMLoader" export * from "./loader/parser/i3dm/I3DMLoaderBase" +export * from "./loader/parser/prefab/PrefabAvatarParser" +export * from "./loader/parser/prefab/PrefabMaterialParser" +export * from "./loader/parser/prefab/PrefabMeshParser" +export * from "./loader/parser/prefab/PrefabParser" +export * from "./loader/parser/prefab/PrefabStringUtil" +export * from "./loader/parser/prefab/PrefabTextureParser" +export * from "./loader/parser/prefab/mats/MaterialUtilities" +export * from "./loader/parser/prefab/mats/shader/LitHairShader" +export * from "./loader/parser/prefab/mats/shader/LitSSSShader" +export * from "./loader/parser/prefab/mats/shader/LitShader" +export * from "./loader/parser/prefab/mats/shader/QuadShader" +export * from "./loader/parser/prefab/mats/shader/SkyShader" +export * from "./loader/parser/prefab/mats/shader/StandShader" +export * from "./loader/parser/prefab/mats/shader/UnLitShader" +export * from "./loader/parser/prefab/mats/shader/UnLitTexArrayShader" +export * from "./loader/parser/prefab/prefabData/APatch" +export * from "./loader/parser/prefab/prefabData/BlendShapeData" +export * from "./loader/parser/prefab/prefabData/BlendShapeFrameData" +export * from "./loader/parser/prefab/prefabData/BlendShapePropertyData" +export * from "./loader/parser/prefab/prefabData/KVData" +export * from "./loader/parser/prefab/prefabData/PrefabAvatarData" +export * from "./loader/parser/prefab/prefabData/PrefabBoneData" +export * from "./loader/parser/prefab/prefabData/PrefabMeshData" +export * from "./loader/parser/prefab/prefabData/PrefabNode" +export * from "./loader/parser/prefab/prefabData/PrefabTextureData" +export * from "./loader/parser/prefab/prefabData/ValueParser" +export * from "./loader/parser/prefab/prefabData/ValueType" export * from "./loader/parser/tileRenderer/TileSet" export * from "./loader/parser/tileRenderer/TilesRenderer" export * from "./materials/BlendMode" @@ -401,17 +450,20 @@ export * from "./materials/LitMaterial" export * from "./materials/Material" export * from "./materials/MaterialRegister" export * from "./materials/PhysicMaterial" -export * from "./materials/PointMaterial" export * from "./materials/SkyMaterial" export * from "./materials/UnLitMaterial" +export * from "./materials/UnLitTexArrayMaterial" export * from "./materials/multiPass/CastPointShadowMaterialPass" export * from "./materials/multiPass/CastShadowMaterialPass" export * from "./materials/multiPass/DepthMaterialPass" export * from "./materials/multiPass/GBufferPass" export * from "./materials/multiPass/SkyGBufferPass" export * from "./math/AnimationCurve" +export * from "./math/AnimationCurveClip" +export * from "./math/AnimationCurveT" export * from "./math/Bezier2D" export * from "./math/Bezier3D" +export * from "./math/BiMap" export * from "./math/Color" export * from "./math/CubicBezierCurve" export * from "./math/CubicBezierPath" @@ -420,10 +472,13 @@ export * from "./math/Line" export * from "./math/MathUtil" export * from "./math/Matrix3" export * from "./math/Matrix4" +export * from "./math/OrderMap" export * from "./math/Orientation3D" export * from "./math/ParticleMath" export * from "./math/ParticleSystemCurves" export * from "./math/Plane" +export * from "./math/Plane3D" +export * from "./math/PlaneClassification" export * from "./math/PolynomialCurve" export * from "./math/Polynomials" export * from "./math/Quaternion" @@ -437,9 +492,28 @@ export * from "./math/UV" export * from "./math/Vector2" export * from "./math/Vector3" export * from "./math/Vector4" +export * from "./math/enum/FrameCache" +export * from "./math/enum/Keyframe" +export * from "./math/enum/T/KeyframeT" +export * from "./math/enum/T/ValueOp" +export * from "./math/enum/WrapTimeMode" +export * from "./math/navigation/DoubleArray" +export * from "./math/navigation/Navi3DAstar" +export * from "./math/navigation/Navi3DConst" +export * from "./math/navigation/Navi3DEdge" +export * from "./math/navigation/Navi3DFunnel" +export * from "./math/navigation/Navi3DMaskType" +export * from "./math/navigation/Navi3DMergeVertex" +export * from "./math/navigation/Navi3DMesh" +export * from "./math/navigation/Navi3DPoint" +export * from "./math/navigation/Navi3DPoint2D" +export * from "./math/navigation/Navi3DPointFat" +export * from "./math/navigation/Navi3DRouter" +export * from "./math/navigation/Navi3DTriangle" export * from "./setting/EngineSetting" export * from "./setting/GlobalIlluminationSetting" export * from "./setting/LightSetting" +export * from "./setting/LoaderSetting" export * from "./setting/MaterialSetting" export * from "./setting/OcclusionQuerySetting" export * from "./setting/PickSetting" @@ -457,6 +531,7 @@ export * from "./shape/BoxGeometry" export * from "./shape/CylinderGeometry" export * from "./shape/PlaneGeometry" export * from "./shape/SphereGeometry" +export * from "./shape/StripeGeometry" export * from "./shape/TorusGeometry" export * from "./textures/AtmosphericScatteringSky" export * from "./textures/BitmapTexture2D" @@ -470,6 +545,7 @@ export * from "./textures/Float32ArrayTexture" export * from "./textures/HDRTexture" export * from "./textures/HDRTextureCube" export * from "./textures/LDRTextureCube" +export * from "./textures/ShadowTexture" export * from "./textures/SolidColorSky" export * from "./textures/TextureCubeFaceData" export * from "./textures/Uint16Texture" @@ -477,7 +553,7 @@ export * from "./textures/Uint8ArrayTexture" export * from "./textures/VirtualTexture" export * from "./util/AxisObject" export * from "./util/BoundUtil" -export * from "./util/BytesStream" +export * from "./util/BytesArray" export * from "./util/CameraUtil" export * from "./util/Convert" export * from "./util/GeometryUtil" @@ -487,6 +563,7 @@ export * from "./util/Object3DUtil" export * from "./util/ProfilerUtil" export * from "./util/Reference" export * from "./util/SerializeDecoration" +export * from "./util/StorageUtil" export * from "./util/StringUtil" export * from "./util/Time" export * from "./util/Vector3Ex" diff --git a/src/loader/FileLoader.ts b/src/loader/FileLoader.ts index c5609b47..52157c9e 100644 --- a/src/loader/FileLoader.ts +++ b/src/loader/FileLoader.ts @@ -1,7 +1,8 @@ import { LoaderBase } from './LoaderBase'; import { LoaderFunctions } from './LoaderFunctions'; import { ParserBase } from './parser/ParserBase'; -import { Ctor } from "../util/Global"; +import { Ctor, Parser } from "../util/Global"; +import { ParserFormat } from './parser/ParserFormat'; /** * @internal @@ -16,9 +17,9 @@ export class FileLoader extends LoaderBase { * @see LoaderFunctions * @returns */ - public async load(url: string, c: Ctor, loaderFunctions?: LoaderFunctions, userData?: any): Promise { - switch (c[`format`]) { - case `bin`: + public async load(url: string, c: Parser, loaderFunctions?: LoaderFunctions, userData?: any): Promise { + switch (c.format) { + case ParserFormat.BIN: { return new Promise(async (succ, fail) => { this.loadBinData(url, loaderFunctions).then(async (data) => { @@ -37,8 +38,7 @@ export class FileLoader extends LoaderBase { }) }); } - break; - case `json`: + case ParserFormat.JSON: { return new Promise((succ, fail) => { this.loadJson(url, loaderFunctions) @@ -56,8 +56,7 @@ export class FileLoader extends LoaderBase { }); }); } - break; - case `text`: + case ParserFormat.TEXT: { return new Promise((succ, fail) => { this.loadTxt(url, loaderFunctions) @@ -79,7 +78,6 @@ export class FileLoader extends LoaderBase { }); }); } - break; default: break; } diff --git a/src/loader/parser/AtlasParser.ts b/src/loader/parser/AtlasParser.ts index e5da83db..606609ba 100644 --- a/src/loader/parser/AtlasParser.ts +++ b/src/loader/parser/AtlasParser.ts @@ -3,9 +3,10 @@ import { GUITexture } from "../../components/gui/core/GUITexture"; import { Engine3D } from "../../Engine3D"; import { Texture } from "../../gfx/graphics/webGpu/core/texture/Texture"; import { ParserBase } from "../../loader/parser/ParserBase"; +import { ParserFormat } from "./ParserFormat"; export class AtlasParser extends ParserBase { - static format: string = 'text'; + static format: ParserFormat = ParserFormat.TEXT; private _json: any; private _texture: Texture; diff --git a/src/loader/parser/B3DMParser.ts b/src/loader/parser/B3DMParser.ts index 2a23e9db..77eacf90 100644 --- a/src/loader/parser/B3DMParser.ts +++ b/src/loader/parser/B3DMParser.ts @@ -1,8 +1,9 @@ import { Object3D } from '../../core/entities/Object3D'; import { ParserBase } from './ParserBase'; +import { ParserFormat } from './ParserFormat'; export class B3DMParser extends ParserBase { - static format: string = 'bin'; + static format: ParserFormat = ParserFormat.JSON; public async parseBuffer(buffer: ArrayBuffer) { let loader = new B3DMLoader(); diff --git a/src/loader/parser/FontParser.ts b/src/loader/parser/FontParser.ts index 80d18038..7a99d448 100644 --- a/src/loader/parser/FontParser.ts +++ b/src/loader/parser/FontParser.ts @@ -3,6 +3,7 @@ import { fonts } from "../../assets/Fonts"; import { GUISprite } from "../../components/gui/core/GUISprite"; import { GUITexture } from "../../components/gui/core/GUITexture"; import { ParserBase } from "./ParserBase"; +import { ParserFormat } from "./ParserFormat"; export class FontInfo { public face: string = ''; @@ -49,7 +50,7 @@ export class FontChar { } export class FontParser extends ParserBase { - static format: string = 'text'; + static format: ParserFormat = ParserFormat.TEXT; public static parseSprite(guiTexture: GUITexture[], fontData: FontInfo) { for (const key in fontData.fontChar) { diff --git a/src/loader/parser/I3DMParser.ts b/src/loader/parser/I3DMParser.ts index f1b402a8..15efafd4 100644 --- a/src/loader/parser/I3DMParser.ts +++ b/src/loader/parser/I3DMParser.ts @@ -1,9 +1,9 @@ import { ParserBase } from './ParserBase'; +import { ParserFormat } from './ParserFormat'; import { I3DMLoader } from "./i3dm/I3DMLoader"; export class I3DMParser extends ParserBase { - static format: string = 'bin'; - + static format: ParserFormat = ParserFormat.BIN; async parseBuffer(buffer: ArrayBuffer) { let loader = new I3DMLoader(); loader.adjustmentTransform = this.userData; diff --git a/src/loader/parser/OBJParser.ts b/src/loader/parser/OBJParser.ts index 3bed3534..6661f108 100644 --- a/src/loader/parser/OBJParser.ts +++ b/src/loader/parser/OBJParser.ts @@ -7,6 +7,7 @@ import { LitMaterial } from '../../materials/LitMaterial'; import { StringUtil } from '../../util/StringUtil'; import { FileLoader } from '../FileLoader'; import { ParserBase } from './ParserBase'; +import { ParserFormat } from './ParserFormat'; type MatData = { @@ -54,7 +55,7 @@ type Face = { * @group Loader */ export class OBJParser extends ParserBase { - static format: string = 'text'; + static format: ParserFormat = ParserFormat.TEXT; private textData: string = ''; private source_vertices: number[][]; @@ -346,7 +347,10 @@ export class OBJParser extends ParserBase { indexStart: 0, indexCount: geoData.indeice_arr.length, vertexStart: 0, + vertexCount: 0, + firstStart: 0, index: 0, + topology: 0, }); let mat = new LitMaterial(); diff --git a/src/loader/parser/ParserBase.ts b/src/loader/parser/ParserBase.ts index 052abaca..63be235b 100644 --- a/src/loader/parser/ParserBase.ts +++ b/src/loader/parser/ParserBase.ts @@ -1,12 +1,13 @@ import { Texture } from '../../gfx/graphics/webGpu/core/texture/Texture'; import { LoaderFunctions } from '../LoaderFunctions'; +import { ParserFormat } from './ParserFormat'; /** * @internal * @group Loader */ export class ParserBase { - static format: string = 'bin'; + static format: ParserFormat = ParserFormat.BIN; public baseUrl: string; public initUrl: string; public loaderFunctions?: LoaderFunctions; diff --git a/src/loader/parser/ParserFormat.ts b/src/loader/parser/ParserFormat.ts new file mode 100644 index 00000000..ba34b29f --- /dev/null +++ b/src/loader/parser/ParserFormat.ts @@ -0,0 +1,5 @@ +export enum ParserFormat { + TEXT, + BIN, + JSON +} \ No newline at end of file diff --git a/src/loader/parser/RGBEParser.ts b/src/loader/parser/RGBEParser.ts index 36c64e6b..b1fed387 100644 --- a/src/loader/parser/RGBEParser.ts +++ b/src/loader/parser/RGBEParser.ts @@ -38,7 +38,7 @@ export class RGBEHeader { * @group Loader */ export class RGBEParser extends ParserBase { - static format: string = 'bin'; + // static format: string = 'bin'; private _rgbeArray: Uint8Array; private _width: number; private _height: number; diff --git a/src/loader/parser/gltf/GLBParser.ts b/src/loader/parser/gltf/GLBParser.ts index 0608b965..b5814a27 100644 --- a/src/loader/parser/gltf/GLBParser.ts +++ b/src/loader/parser/gltf/GLBParser.ts @@ -1,5 +1,6 @@ import { BitmapTexture2D } from '../../../textures/BitmapTexture2D'; import { ParserBase } from '../ParserBase'; +import { ParserFormat } from '../ParserFormat'; import { GLTF_Info } from './GLTFInfo'; import { GLTFSubParser } from './GLTFSubParser'; @@ -29,7 +30,7 @@ export class GLBChunk { * @group Loader */ export class GLBParser extends ParserBase { - static format: string = 'bin'; + static format: ParserFormat = ParserFormat.BIN; private _gltf: GLTF_Info; diff --git a/src/loader/parser/gltf/GLTFParser.ts b/src/loader/parser/gltf/GLTFParser.ts index 73c34281..5a66d884 100644 --- a/src/loader/parser/gltf/GLTFParser.ts +++ b/src/loader/parser/gltf/GLTFParser.ts @@ -1,6 +1,7 @@ import { StringUtil } from '../../../util/StringUtil'; import { FileLoader } from '../../FileLoader'; import { ParserBase } from '../ParserBase'; +import { ParserFormat } from '../ParserFormat'; import { GLTF_Info } from './GLTFInfo'; import { GLTFSubParser } from './GLTFSubParser'; @@ -10,7 +11,7 @@ import { GLTFSubParser } from './GLTFSubParser'; * @group Loader */ export class GLTFParser extends ParserBase { - static format: string = 'json'; + static format: ParserFormat = ParserFormat.JSON; private _gltf: GLTF_Info; public async parseJson(obj: object) { diff --git a/src/loader/parser/gltf/GLTFSubParserConverter.ts b/src/loader/parser/gltf/GLTFSubParserConverter.ts index 24a3d408..07d95f5b 100644 --- a/src/loader/parser/gltf/GLTFSubParserConverter.ts +++ b/src/loader/parser/gltf/GLTFSubParserConverter.ts @@ -177,73 +177,59 @@ export class GLTFSubParserConverter { if (primitive.material) { const { baseColorTexture, baseColorFactor, metallicFactor, roughnessFactor, doubleSided, metallicRoughnessTexture, normalTexture, occlusionTexture, emissiveTexture, emissiveFactor, enableBlend, alphaCutoff } = primitive.material; - let physicMaterial = (newMat = this.applyMaterialExtensions(primitive.material, newMat) as PhysicMaterial); + let physicMaterial = (newMat = this.applyMaterialExtensions(primitive.material, newMat)); if (`enableBlend` in primitive.material) { if (primitive.material[`enableBlend`]) { physicMaterial.blendMode = BlendMode.NORMAL; - physicMaterial.depthWriteEnabled = false; } else { physicMaterial.blendMode = BlendMode.NONE; } - - if (primitive.material.defines) { - if (primitive.material.defines.indexOf(`ALPHA_BLEND`) != -1) { - physicMaterial.blendMode = BlendMode.ALPHA; - physicMaterial.transparent = true; - physicMaterial.depthWriteEnabled = false; - } - } } - if (`alphaCutoff` in primitive.material && alphaCutoff > 0) { - physicMaterial.alphaCutoff = alphaCutoff; + if (`alphaCutoff` in primitive.material && alphaCutoff > 0 && alphaCutoff < 1) { + physicMaterial.setUniformFloat("alphaCutoff", alphaCutoff); physicMaterial.blendMode = BlendMode.NORMAL; physicMaterial.transparent = true; - physicMaterial.depthWriteEnabled = false; + // physicMaterial.depthWriteEnabled = false; } - if (primitive.material.transformUV1) physicMaterial.uvTransform_1 = primitive.material.transformUV1; - if (primitive.material.transformUV2) physicMaterial.uvTransform_2 = primitive.material.transformUV2; - - physicMaterial.baseColor = new Color(baseColorFactor[0], baseColorFactor[1], baseColorFactor[2], baseColorFactor[3]); - - physicMaterial.roughness = roughnessFactor; - - physicMaterial.metallic = metallicFactor; - + if (primitive.material.transformUV1) { + physicMaterial.setUniformVector4("uvTransform_1", primitive.material.transformUV1); + } + if (primitive.material.transformUV2) { + physicMaterial.setUniformVector4("uvTransform_2", primitive.material.transformUV2); + } + physicMaterial.setUniformColor("baseColor", new Color(baseColorFactor[0], baseColorFactor[1], baseColorFactor[2], baseColorFactor[3])); + physicMaterial.setUniformFloat("roughness", roughnessFactor); + physicMaterial.setUniformFloat("metallic", metallicFactor); + physicMaterial.setUniformFloat("ao", 1); physicMaterial.doubleSide = doubleSided; - physicMaterial.ao = 1; - if (baseColorTexture) { - physicMaterial.baseMap = baseColorTexture; + physicMaterial.setTexture("baseMap", baseColorTexture); } if (normalTexture) { - physicMaterial.normalMap = normalTexture; + physicMaterial.setTexture("normalMap", normalTexture); } if (metallicRoughnessTexture) { - physicMaterial.maskMap = metallicRoughnessTexture; + physicMaterial.setTexture("maskMap", metallicRoughnessTexture); } if (occlusionTexture && (metallicRoughnessTexture != occlusionTexture)) { - physicMaterial.aoMap = occlusionTexture; + physicMaterial.setTexture("aoMap", occlusionTexture); } if (emissiveTexture) { - physicMaterial.emissiveMap = emissiveTexture; + physicMaterial.setTexture("emissiveMap", emissiveTexture); } if (emissiveFactor && (emissiveFactor[0] > 0 || emissiveFactor[1] > 0 || emissiveFactor[2] > 0)) { - if (physicMaterial.emissiveMap) { - if (physicMaterial.emissiveMap == Engine3D.res.blackTexture) { - physicMaterial.emissiveMap = Engine3D.res.whiteTexture; - } + if (!physicMaterial.shader.getTexture("emissiveMap")) { + physicMaterial.shader.setTexture("emissiveMap", Engine3D.res.whiteTexture); } - let emissiveFactorA = emissiveFactor[3] ? emissiveFactor[3] : 1.0; - physicMaterial.emissiveColor = new Color(emissiveFactor[0], emissiveFactor[1], emissiveFactor[2], emissiveFactorA); - physicMaterial.emissiveIntensity = 1; + physicMaterial.setUniformColor("emissiveColor", new Color(emissiveFactor[0], emissiveFactor[1], emissiveFactor[2], emissiveFactor[3])); } } } @@ -412,6 +398,9 @@ export class GLTFSubParserConverter { indexCount: indicesAttribute.data.length, vertexStart: 0, index: 0, + vertexCount: 0, + firstStart: 0, + topology: 0 } ) return geometry; diff --git a/src/loader/parser/gltf/GLTFSubParserSkeleton.ts b/src/loader/parser/gltf/GLTFSubParserSkeleton.ts index eb8f0fdc..cd130572 100644 --- a/src/loader/parser/gltf/GLTFSubParserSkeleton.ts +++ b/src/loader/parser/gltf/GLTFSubParserSkeleton.ts @@ -46,37 +46,48 @@ export class GLTFSubParserSkeleton { } count++; let joint = skeleton.getJointByName(node.name); - switch (property) { - case 'scale': - for (var nFrame: number = 0; nFrame < numFrame; nFrame++) { - var srcOffset = nFrame * outputAccessor.numComponents; - var dstOffset = skeletonPoseLength * nFrame + 12 * joint.index; - bufferData[dstOffset + 0] = outputAccessor.data[srcOffset + 0]; // x - bufferData[dstOffset + 1] = outputAccessor.data[srcOffset + 1]; // y - bufferData[dstOffset + 2] = outputAccessor.data[srcOffset + 2]; // z - bufferData[dstOffset + 3] = 1; - } - break; - case 'rotation': - for (var nFrame: number = 0; nFrame < numFrame; nFrame++) { - var srcOffset = nFrame * outputAccessor.numComponents; - var dstOffset = skeletonPoseLength * nFrame + 12 * joint.index + 4; - bufferData[dstOffset + 0] = outputAccessor.data[srcOffset + 0]; // x - bufferData[dstOffset + 1] = outputAccessor.data[srcOffset + 1]; // y - bufferData[dstOffset + 2] = outputAccessor.data[srcOffset + 2]; // z - bufferData[dstOffset + 3] = outputAccessor.data[srcOffset + 3]; // w - } - break; - case 'translation': - for (var nFrame: number = 0; nFrame < numFrame; nFrame++) { - var srcOffset = nFrame * outputAccessor.numComponents; - var dstOffset = skeletonPoseLength * nFrame + 12 * joint.index + 8; - bufferData[dstOffset + 0] = outputAccessor.data[srcOffset + 0]; // x - bufferData[dstOffset + 1] = outputAccessor.data[srcOffset + 1]; // y - bufferData[dstOffset + 2] = outputAccessor.data[srcOffset + 2]; // z - bufferData[dstOffset + 3] = inputAccessor.data[nFrame * inputAccessor.numComponents]; - } - break; + if (!joint) { + switch (property) { + case 'scale': + break; + case 'rotation': + break; + case 'translation': + break; + } + } else { + switch (property) { + case 'scale': + for (var nFrame: number = 0; nFrame < numFrame; nFrame++) { + var srcOffset = nFrame * outputAccessor.numComponents; + var dstOffset = skeletonPoseLength * nFrame + 12 * joint.index; + bufferData[dstOffset + 0] = outputAccessor.data[srcOffset + 0]; // x + bufferData[dstOffset + 1] = outputAccessor.data[srcOffset + 1]; // y + bufferData[dstOffset + 2] = outputAccessor.data[srcOffset + 2]; // z + bufferData[dstOffset + 3] = 1; + } + break; + case 'rotation': + for (var nFrame: number = 0; nFrame < numFrame; nFrame++) { + var srcOffset = nFrame * outputAccessor.numComponents; + var dstOffset = skeletonPoseLength * nFrame + 12 * joint.index + 4; + bufferData[dstOffset + 0] = outputAccessor.data[srcOffset + 0]; // x + bufferData[dstOffset + 1] = outputAccessor.data[srcOffset + 1]; // y + bufferData[dstOffset + 2] = outputAccessor.data[srcOffset + 2]; // z + bufferData[dstOffset + 3] = outputAccessor.data[srcOffset + 3]; // w + } + break; + case 'translation': + for (var nFrame: number = 0; nFrame < numFrame; nFrame++) { + var srcOffset = nFrame * outputAccessor.numComponents; + var dstOffset = skeletonPoseLength * nFrame + 12 * joint.index + 8; + bufferData[dstOffset + 0] = outputAccessor.data[srcOffset + 0]; // x + bufferData[dstOffset + 1] = outputAccessor.data[srcOffset + 1]; // y + bufferData[dstOffset + 2] = outputAccessor.data[srcOffset + 2]; // z + bufferData[dstOffset + 3] = inputAccessor.data[nFrame * inputAccessor.numComponents]; + } + break; + } } } diff --git a/src/loader/parser/gltf/extends/KHR_materials_clearcoat.ts b/src/loader/parser/gltf/extends/KHR_materials_clearcoat.ts index 3d895738..e8e5aa01 100644 --- a/src/loader/parser/gltf/extends/KHR_materials_clearcoat.ts +++ b/src/loader/parser/gltf/extends/KHR_materials_clearcoat.ts @@ -11,7 +11,7 @@ export class KHR_materials_clearcoat { public static apply(gltf: any, dmaterial: any, tMaterial: any) { let extensions = dmaterial.extensions; if (extensions && extensions[`KHR_materials_clearcoat`]) { - (tMaterial as Material).defaultPass.setDefine('USE_CLEARCOAT', true); + (tMaterial as Material).shader.getDefaultColorShader().setDefine('USE_CLEARCOAT', true); let KHR_materials_clearcoat = extensions[`KHR_materials_clearcoat`]; if (`clearcoatFactor` in KHR_materials_clearcoat) { diff --git a/src/loader/parser/prefab/PrefabAvatarParser.ts b/src/loader/parser/prefab/PrefabAvatarParser.ts new file mode 100644 index 00000000..f291feee --- /dev/null +++ b/src/loader/parser/prefab/PrefabAvatarParser.ts @@ -0,0 +1,56 @@ +import { Engine3D } from "../../../Engine3D"; +import { GeometryBase, LODDescriptor } from "../../../core/geometry/GeometryBase"; +import { GeometryVertexType } from "../../../core/geometry/GeometryVertexType"; +import { VertexAttributeName } from "../../../core/geometry/VertexAttributeName"; +import { BytesArray } from "../../../util/BytesArray"; +import { ParserBase } from "../ParserBase"; +import { ParserFormat } from "../ParserFormat"; +import { PrefabParser } from "./PrefabParser"; +import { PrefabAvatarData } from "./prefabData/PrefabAvatarData"; + + +export class PrefabAvatarParser extends ParserBase { + static format: ParserFormat = ParserFormat.BIN; + public static parser(bytesStream: BytesArray, prefabParser: PrefabParser) { + let avatarCount = bytesStream.readInt32(); + for (let j = 0; j < avatarCount; j++) { + let prefabAvatarData = new PrefabAvatarData(); + prefabAvatarData.formBytes(bytesStream.readBytesArray()); + Engine3D.res.addObj(prefabAvatarData.name, prefabAvatarData); + } + } + + /** + * Verify parsing validity + * @param ret + * @returns + */ + public verification(): boolean { + if (this.data) { + return true; + } + throw new Error('verify failed.'); + } + +} + +let MeshVertexAttribute = { + "Position": VertexAttributeName.position, + "Normal": VertexAttributeName.normal, + "Color": VertexAttributeName.color, + "Tangent": VertexAttributeName.TANGENT, + "TexCoord0": VertexAttributeName.uv, + "TexCoord1": VertexAttributeName.TEXCOORD_1, + "TexCoord2": VertexAttributeName.TEXCOORD_2, + "TexCoord3": VertexAttributeName.TEXCOORD_2, + "TexCoord4": VertexAttributeName.TEXCOORD_4, + "TexCoord5": VertexAttributeName.TEXCOORD_5, + "TexCoord6": VertexAttributeName.TEXCOORD_6, + "TexCoord7": VertexAttributeName.TEXCOORD_7, + "BlendIndices": VertexAttributeName.joints0, + "BlendWeight": VertexAttributeName.weights0, +} + + + + diff --git a/src/loader/parser/prefab/PrefabMaterialParser.ts b/src/loader/parser/prefab/PrefabMaterialParser.ts new file mode 100644 index 00000000..900e99b5 --- /dev/null +++ b/src/loader/parser/prefab/PrefabMaterialParser.ts @@ -0,0 +1,171 @@ +import { BitmapTexture2D, BlendMode, Engine3D } from "../../.."; +import { LitMaterial } from "../../../materials/LitMaterial"; +import { Material } from "../../../materials/Material"; +import { Color } from "../../../math/Color"; +import { BytesArray } from "../../../util/BytesArray"; +import { ParserBase } from "../ParserBase"; +import { ParserFormat } from "../ParserFormat"; +import { PrefabParser } from "./PrefabParser"; +import { MaterialUtilities } from "./mats/MaterialUtilities"; +import { KV } from "./prefabData/KVData"; +import { PrefabTextureData } from "./prefabData/PrefabTextureData"; + + +export class PrefabMaterialParser extends ParserBase { + static format: ParserFormat = ParserFormat.TEXT; + + public static parserMaterial(bytesStream: BytesArray, prefabParser: PrefabParser) { + let matCount = bytesStream.readInt32(); + for (let i = 0; i < matCount; i++) { + let matBytes = bytesStream.readBytesArray(); + + let matName = matBytes.readUTF(); + let id = matBytes.readUTF(); + let renderType = matBytes.readUTF(); + let defines = matBytes.readStringArray(); + let uvTransform_1 = matBytes.readVector4(); + let uvTransform_2 = matBytes.readVector4(); + let shaderName = matBytes.readUTF(); + let properties: KV[] = []; + let textures: PrefabTextureData[] = []; + let propertyCount = matBytes.readInt32(); + for (let j = 0; j < propertyCount; j++) { + let kv: KV = new KV(); + kv.formBytes(matBytes); + properties.push(kv); + } + + let textureCount = matBytes.readInt32(); + for (let j = 0; j < textureCount; j++) { + let texBytes = matBytes.readBytesArray(); + let textureData = new PrefabTextureData(); + textureData.property = texBytes.readUTF(); + textureData.name = texBytes.readUTF(); + textureData.texture = Engine3D.res.getTexture(textureData.name) as BitmapTexture2D; + textureData.texelSize = texBytes.readVector2(); + textureData.wrapModeU = texBytes.readUnit32(); + textureData.wrapModeV = texBytes.readUnit32(); + textureData.wrapModeW = texBytes.readUnit32(); + textureData.wrapMode = texBytes.readUnit32(); + textureData.anisoLevel = texBytes.readUnit32(); + textureData.dimension = texBytes.readUnit32(); + textureData.filterMode = texBytes.readUnit32(); + textures.push(textureData); + } + + let mat = MaterialUtilities.GetMaterial(shaderName); + mat.name = matName; + // mat.uvTransform_1 = uvTransform_1; + // mat.uvTransform_2 = uvTransform_2; + // mat.roughness = 1; + // mat.metallic = 1; + // mat.alphaCutoff = 0.5; + + // mat.blendMode = renderType == "Opaque" ? BlendMode.NONE : BlendMode.ALPHA; + + for (let i = 0; i < defines.length; i++) { + const define = defines[i]; + mat.shader.setDefine(define, true); + } + + MaterialUtilities.applyMaterialTexture(mat, textures); + MaterialUtilities.applyMaterialProperties(mat, properties); + + // for (let k = 0; k < properties.length; k++) { + // const kv = properties[k]; + + // // mat.setu(texInfo.property, texInfo.texture); + // // if (kv.key in Material_transformer.prototype) { + // // Material_transformer.prototype[kv.key](kv, mat); + // // } + // } + + Engine3D.res.addMat(id, mat); + } + } + + + /** + * Verify parsing validity + * @param ret + * @returns + */ + public verification(): boolean { + if (this.data) { + return true; + } + throw new Error('verify failed.'); + } +} + + +class Texture_transformer { + public _MainTex(tex: PrefabTextureData, material: Material) { + material.shader.setDefine("USE_SRGB_ALBEDO", true); + return { + property: "baseMap", + value: tex.texture + }; + } + + public _MetallicGlossMap(tex: PrefabTextureData) { + return { + property: "maskMap", + value: tex.texture + }; + } + + public _BumpMap(tex: PrefabTextureData) { + return { + property: "normalMap", + value: tex.texture + }; + } + + public _OcclusionMap(tex: PrefabTextureData, mat: LitMaterial) { + mat.shader.setDefine("USE_AOTEX", true); + mat.ao = 1.0; + return { + property: "aoMap", + value: tex.texture + }; + } +} + +class Material_transformer { + _Color(kv: KV, material: LitMaterial) { + material.baseColor = kv.getValue(); + } + + // _Glossiness(kv: KV, material: LitMaterial) { + // let str = kv.value.replaceAll("[", ""); + // str = str.replaceAll("]", ""); + // let alpha = 1.0 - parseFloat(str); + // let roughness = alpha * alpha * alpha * alpha; + // // material.roughness = roughness; + // } + //return 1 + Math.log2(maxSize) | 0; + + _GlossMapScale(kv: KV, material: LitMaterial) { + material.roughness = kv.getValue()[0]; + } + + _Metallic(kv: KV, material: LitMaterial) { + if (!material.maskMap) { + material.metallic = kv.getValue()[0]; + } else { + material.metallic = 1.0; + } + } + + _SmoothnessTextureChannel(kv: KV, material: LitMaterial) { + let channel = kv.getValue(); + let type = channel == 0 ? `USE_ROUGHNESS_A` : "USE_ALBEDO_A"; + let type2 = `USE_METALLIC_R`; + material.shader.setDefine(type, true); + material.shader.setDefine(type2, true); + } +} + +let TextureChannel = ["A", "R", "G", "B"] + diff --git a/src/loader/parser/prefab/PrefabMeshParser.ts b/src/loader/parser/prefab/PrefabMeshParser.ts new file mode 100644 index 00000000..d78fce4d --- /dev/null +++ b/src/loader/parser/prefab/PrefabMeshParser.ts @@ -0,0 +1,182 @@ +import { Engine3D } from "../../../Engine3D"; +import { GeometryBase, LODDescriptor } from "../../../core/geometry/GeometryBase"; +import { GeometryVertexType } from "../../../core/geometry/GeometryVertexType"; +import { VertexAttributeName } from "../../../core/geometry/VertexAttributeName"; +import { BytesArray } from "../../../util/BytesArray"; +import { ParserBase } from "../ParserBase"; +import { ParserFormat } from "../ParserFormat"; +import { PrefabParser } from "./PrefabParser"; +import { BlendShapeData } from "./prefabData/BlendShapeData"; +import { PrefabMeshData } from "./prefabData/PrefabMeshData"; + + +export class PrefabMeshParser extends ParserBase { + static format: ParserFormat = ParserFormat.BIN; + + public async parseBuffer(buffer: ArrayBuffer) { + } + + public static parserMeshs(bytesStream: BytesArray, prefabParser: PrefabParser) { + + + let meshCount = bytesStream.readInt32(); + for (let j = 0; j < meshCount; j++) { + let prefabMesh = new PrefabMeshData(); + let meshBytesArray = bytesStream.readBytesArray();; + prefabMesh.meshName = meshBytesArray.readUTF(); + prefabMesh.meshID = meshBytesArray.readUTF(); + + let useTangent = meshBytesArray.readFloat32() > 0; + let useColor = meshBytesArray.readFloat32() > 0; + let useSecondUV = meshBytesArray.readFloat32() > 0; + let useSkeleton = meshBytesArray.readFloat32() > 0; + let useBlendShape = meshBytesArray.readFloat32() > 0; + + if (useSkeleton) { + prefabMesh.bones = meshBytesArray.readStringArray(); + prefabMesh.bindPose = meshBytesArray.readMatrix44Array(); + } + + if (useBlendShape) { + prefabMesh.blendShapeData = new BlendShapeData(); + prefabMesh.blendShapeData.formBytes(meshBytesArray); + } + + let vertexBlock = meshBytesArray.readBytesArray(); + let vertexBuffer = meshBytesArray.readBytesArray(); + + let attCount = vertexBlock.readInt32(); + let vertex_dim = 0; + let attributes = []; + for (let i = 0; i < attCount; i++) { + attributes[i] = {}; + attributes[i].att = MeshVertexAttribute[vertexBlock.readUTF()]; + attributes[i].dim = vertexBlock.readInt32(); + vertex_dim += attributes[i].dim; + attributes[i].format = vertexBlock.readUTF(); + } + + prefabMesh.vertexCount = vertexBlock.readInt32(); + prefabMesh.vertexBuffer = vertexBuffer.getFloat32Array(); + + let tmpIndices = meshBytesArray.readInt32Array(); + let subMesh: LODDescriptor[] = []; + let subMeshCount = meshBytesArray.readInt32(); + for (let jj = 0; jj < subMeshCount; jj++) { + let subMesh_topology = meshBytesArray.readInt32(); + let subMesh_indexStart = meshBytesArray.readInt32(); + let subMesh_indexCount = meshBytesArray.readInt32(); + let subMesh_baseVertex = meshBytesArray.readInt32(); + let subMesh_firstVertex = meshBytesArray.readInt32(); + let subMesh_vertexCount = meshBytesArray.readInt32(); + let subMesh_boundMin = meshBytesArray.readVector3(); + let subMesh_boundMax = meshBytesArray.readVector3(); + let subDes: LODDescriptor = { + indexStart: subMesh_indexStart, + indexCount: subMesh_indexCount, + vertexStart: subMesh_baseVertex, + vertexCount: subMesh_vertexCount, + firstStart: subMesh_firstVertex, + topology: subMesh_topology, + index: jj + } + subMesh.push(subDes); + } + + + if (tmpIndices.length > 65535) { + prefabMesh.indices = new Uint32Array(tmpIndices); + } else { + prefabMesh.indices = new Uint16Array(tmpIndices); + } + + let geometry = new GeometryBase(); + geometry.vertexDim = vertex_dim; + geometry.geometryType = GeometryVertexType.compose_bin; + geometry.setIndices(prefabMesh.indices); + geometry.setAttribute(VertexAttributeName.all, prefabMesh.vertexBuffer); + if (useSkeleton) { + geometry.skinNames = prefabMesh.bones; + geometry.bindPose = prefabMesh.bindPose; + } + if (useBlendShape) { + geometry.blendShapeData = prefabMesh.blendShapeData; + geometry.morphTargetsRelative = true; + geometry.morphTargetDictionary = {}; + for (let i = 0; i < prefabMesh.blendShapeData.blendCount; i++) { + // if (i == 0) { + // for (let index = 0; index < prefabMesh.blendShapeData.blendShapePropertyDatas[i].blendPositionList.length; index++) { + // if (prefabMesh.blendShapeData.blendShapePropertyDatas[i].blendPositionList[index] != 0) { + // console.error("has"); + // } + // } + // } + geometry.setAttribute("a_morphPositions_" + i, prefabMesh.blendShapeData.blendShapePropertyDatas[i].blendPositionList); + geometry.setAttribute("a_morphNormals_" + i, prefabMesh.blendShapeData.blendShapePropertyDatas[i].blendNormalList); + for (let i = 0; i < prefabMesh.blendShapeData.blendCount; i++) { + let blendName = prefabMesh.blendShapeData.shapeNames[i]; + let blendIndex = prefabMesh.blendShapeData.shapeIndexs[i]; + geometry.morphTargetDictionary[blendName] = blendIndex; + } + } + + + // geometry.setAttribute("a_morphPositions_0", prefabMesh.blendShapeData.positionList); + // geometry.setAttribute("a_morphNormals_0", prefabMesh.blendShapeData.normalList); + // geometry.morphTargetsRelative = true; + // geometry.morphTargetDictionary = {}; + // for (let i = 0; i < prefabMesh.blendShapeData.blendCount; i++) { + // let blendName = prefabMesh.blendShapeData.shapeNames[i]; + // let blendIndex = prefabMesh.blendShapeData.shapeIndexs[i]; + // geometry.morphTargetDictionary[blendName] = blendIndex; + // } + } + for (let ii = 0; ii < attributes.length; ii++) { + const element = attributes[ii].att; + geometry.setAttribute(element, null);//3 + } + + for (let kk = 0; kk < subMesh.length; kk++) { + const element = subMesh[kk]; + geometry.addSubGeometry(element); + } + + geometry.name = prefabMesh.meshName; + Engine3D.res.addGeometry(prefabMesh.meshID, geometry); + } + } + + /** + * Verify parsing validity + * @param ret + * @returns + */ + public verification(): boolean { + if (this.data) { + return true; + } + throw new Error('verify failed.'); + } + +} + +let MeshVertexAttribute = { + "Position": VertexAttributeName.position, + "Normal": VertexAttributeName.normal, + "Color": VertexAttributeName.color, + "Tangent": VertexAttributeName.TANGENT, + "TexCoord0": VertexAttributeName.uv, + "TexCoord1": VertexAttributeName.TEXCOORD_1, + "TexCoord2": VertexAttributeName.TEXCOORD_2, + "TexCoord3": VertexAttributeName.TEXCOORD_2, + "TexCoord4": VertexAttributeName.TEXCOORD_4, + "TexCoord5": VertexAttributeName.TEXCOORD_5, + "TexCoord6": VertexAttributeName.TEXCOORD_6, + "TexCoord7": VertexAttributeName.vIndex, + "BlendIndices": VertexAttributeName.joints0, + "BlendWeight": VertexAttributeName.weights0, +} + + + + diff --git a/src/loader/parser/prefab/PrefabParser.ts b/src/loader/parser/prefab/PrefabParser.ts new file mode 100644 index 00000000..0fb2ce52 --- /dev/null +++ b/src/loader/parser/prefab/PrefabParser.ts @@ -0,0 +1,98 @@ +import { Engine3D } from "../../../Engine3D"; +import { MeshFilter } from "../../../components/renderer/MeshFilter"; +import { SkinnedMeshRenderer } from "../../../components/renderer/SkinnedMeshRenderer"; +import { Object3D } from "../../../core/entities/Object3D"; +import { GeometryBase } from "../../../core/geometry/GeometryBase"; +import { Material } from "../../../materials/Material"; +import { Quaternion } from "../../../math/Quaternion"; +import { Vector3 } from "../../../math/Vector3"; +import { BitmapTexture2D } from "../../../textures/BitmapTexture2D"; +import { BytesArray } from "../../../util/BytesArray"; +import { GetComponentClass } from "../../../util/SerializeDecoration"; +import { ParserBase } from "../ParserBase"; +import { ParserFormat } from "../ParserFormat"; +import { PrefabAvatarParser } from "./PrefabAvatarParser"; +import { PrefabMaterialParser } from "./PrefabMaterialParser"; +import { PrefabMeshParser } from "./PrefabMeshParser"; +import { PrefabTextureParser } from "./PrefabTextureParser"; +import { LitSSSShader } from "./mats/shader/LitSSSShader"; +import { LitShader } from "./mats/shader/LitShader"; +import { PrefabAvatarData } from "./prefabData/PrefabAvatarData"; +import { PrefabNode } from "./prefabData/PrefabNode"; + +LitShader; +LitSSSShader; +export class PrefabParser extends ParserBase { + public static useWebp: boolean = true; + static format: ParserFormat = ParserFormat.BIN; + public avatarDic: { [name: string]: PrefabAvatarData }; + public nodeData: PrefabNode; + public async parseBuffer(buffer: ArrayBuffer) { + this.avatarDic = {}; + + let bytesStream = new BytesArray(buffer, 0); + + await PrefabTextureParser.parserTexture(bytesStream, this, this.loaderFunctions); + + PrefabAvatarParser.parser(bytesStream, this); + + PrefabMeshParser.parserMeshs(bytesStream, this); + + PrefabMaterialParser.parserMaterial(bytesStream, this); + + this.nodeData = this.parserPrefabNode(bytesStream); + + this.data = this.data = this.parserNodeTree(this.nodeData); + } + + private parserPrefabNode(bytesStream: BytesArray) { + let rootNodeData = PrefabNode.parser(bytesStream); + return rootNodeData; + } + + private parserNodeTree(nodeData: PrefabNode) { + let root = new Object3D(); + root.localPosition = Vector3.serialize(nodeData.position); + root.localQuaternion = Quaternion.serialize(nodeData.rotation); + root.localScale = Vector3.serialize(nodeData.scale); + root.name = nodeData.name; + if (nodeData.comDatas) { + for (let i = 0; i < nodeData.comDatas.length; i++) { + const comData = nodeData.comDatas[i]; + let com = null; + let comClass = GetComponentClass(comData.comName); + if (comClass) { + com = root.getOrAddComponent(comClass); + for (let j = 0; j < comData.data.length; j++) { + const kv = comData.data[j]; + if (kv.key in com) { + com[kv.key] = kv.getValue(); + } + } + } else { + // console.warn("no component", comData.comName); + } + } + } + + if (nodeData.child && nodeData.child.length > 0) { + for (let j = 0; j < nodeData.child.length; j++) { + let child = this.parserNodeTree(nodeData.child[j]); + root.addChild(child); + } + } + return root; + } + + /** + * Verify parsing validity + * @param ret + * @returns + */ + public verification(): boolean { + if (this.data) { + return true; + } + throw new Error('verify failed.'); + } +} diff --git a/src/loader/parser/prefab/PrefabStringUtil.ts b/src/loader/parser/prefab/PrefabStringUtil.ts new file mode 100644 index 00000000..140f2db9 --- /dev/null +++ b/src/loader/parser/prefab/PrefabStringUtil.ts @@ -0,0 +1,63 @@ +import { Quaternion } from "../../.."; + +export class PrefabStringUtil { + + public static getNumber(st: string) { + let v = parseFloat(st); + return v; + } + + public static getInt(st: string) { + let v = parseInt(st); + return v; + } + + public static getBoolean(st: string) { + let v = st == "true" ? true : false; + return v; + } + + public static getNumberArray(st: string) { + let v = st.replaceAll("[", ""); + v = v.replaceAll("]", ""); + let list = v.split(","); + let ret: number[] = []; + for (let i = 0; i < list.length; i++) { + const element = parseFloat(list[i]); + ret.push(element); + } + return v; + } + + public static getStringArray(st: string) { + let v = st.replaceAll("[", ""); + v = v.replaceAll("]", ""); + let list = v.split(","); + let ret: string[] = []; + for (let i = 0; i < list.length; i++) { + const element = (list[i]); + ret.push(element); + } + return ret; + } + + public static getVector2(st: string) { + + } + + public static getVector3(st: string) { + + } + + public static getVector4(st: string) { + + } + + public static getQuaternion(st: string) { + + } + + public static getColor(st: string) { + + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/PrefabTextureParser.ts b/src/loader/parser/prefab/PrefabTextureParser.ts new file mode 100644 index 00000000..78deaaf3 --- /dev/null +++ b/src/loader/parser/prefab/PrefabTextureParser.ts @@ -0,0 +1,46 @@ +import { Engine3D } from "../../../Engine3D"; +import { BitmapTexture2D } from "../../../textures/BitmapTexture2D"; +import { BytesArray } from "../../../util/BytesArray"; +import { LoaderFunctions } from "../../LoaderFunctions"; +import { ParserBase } from "../ParserBase"; +import { ParserFormat } from "../ParserFormat"; +import { PrefabParser } from "./PrefabParser"; + + +export class PrefabTextureParser extends ParserBase { + static format: ParserFormat = ParserFormat.TEXT; + + public static async parserTexture(bytesStream: BytesArray, prefabParser: PrefabParser, loaderFunctions: LoaderFunctions) { + let preTextureCount = bytesStream.readInt32(); + + let textures = []; + for (let i = 0; i < preTextureCount; i++) { + let texName = bytesStream.readUTF(); + if (PrefabParser.useWebp) { + texName = texName.replace("png", "webp"); + texName = texName.replace("jpb", "webp"); + textures.push(prefabParser.baseUrl + `webp\/` + texName); + } else { + textures.push(prefabParser.baseUrl + texName); + } + + } + + let textureList = await Engine3D.res.loadBitmapTextures(textures, Engine3D.setting.loader.numConcurrent, loaderFunctions, true); + for (const tex of textureList) { + Engine3D.res.addTexture(tex.name, tex); + } + } + + /** + * Verify parsing validity + * @param ret + * @returns + */ + public verification(): boolean { + if (this.data) { + return true; + } + throw new Error('verify failed.'); + } +} diff --git a/src/loader/parser/prefab/mats/MaterialUtilities.ts b/src/loader/parser/prefab/mats/MaterialUtilities.ts new file mode 100644 index 00000000..7f65c967 --- /dev/null +++ b/src/loader/parser/prefab/mats/MaterialUtilities.ts @@ -0,0 +1,139 @@ +import { Color, Vector2, Vector3, Vector4 } from "../../../.."; +import { Material } from "../../../../materials/Material"; +import { GetShader } from "../../../../util/SerializeDecoration"; +import { KV } from "../prefabData/KVData"; +import { PrefabTextureData } from "../prefabData/PrefabTextureData"; +import { ValueEnumType } from "../prefabData/ValueType"; + +export class MaterialUtilities { + + public static GetMaterial(shaderName: string) { + let name = shaderName; + // let name = "UnLitShader"; + let list = name.split("/"); + name = list[list.length - 1]; + + list = name.split("."); + name = list[list.length - 1]; + + let shader = GetShader(name); + if (shader) { + let material = new Material(); + material.shader = new shader(); + return material; + } else { + throw new console.error("not found shader, shader name is " + name); + + } + } + + public static applyMaterialTexture(mat: Material, textures: PrefabTextureData[]) { + for (let ii = 0; ii < textures.length; ii++) { + const texInfo = textures[ii]; + if (texInfo.property in mat) { + mat[texInfo.property] = texInfo.texture; + } else if (texInfo.property in mat.shader) { + mat.shader[texInfo.property] = texInfo.texture; + } else { + mat.setTexture(texInfo.property, texInfo.texture); + } + } + } + + public static applyMaterialProperties(mat: Material, properties: KV[]) { + for (let ii = 0; ii < properties.length; ii++) { + const propertyInfo = properties[ii]; + const key = propertyInfo.key; + // let transformInfo = mat.shader[propertyInfo.key]; + // if (transformInfo != null) { + switch (propertyInfo.type) { + case ValueEnumType.color: + case ValueEnumType.color32: + { + let value = propertyInfo.getValue(); + if (key in mat) { + mat[key] = value; + } else if (key in mat.shader) { + mat.shader[key] = value; + } else { + mat.setUniformColor(key, value); + } + } + break; + case ValueEnumType.single: + case ValueEnumType.float: + case ValueEnumType.int: + case ValueEnumType.int16: + case ValueEnumType.int32: + case ValueEnumType.int32: + case ValueEnumType.uint: + case ValueEnumType.uint32: + case ValueEnumType.uint64: + { + let value = propertyInfo.getValue(); + if (key in mat) { + mat[key] = value; + } else if (key in mat.shader) { + mat.shader[key] = value; + } else { + mat.setUniformFloat(key, value); + } + } + break; + case ValueEnumType.singleArray: + { + let value = propertyInfo.getValue()[0]; + if (key in mat) { + mat[key] = value; + } else if (key in mat.shader) { + mat.shader[key] = value; + } else { + mat.setUniformFloat(key, value); + } + } + break; + case ValueEnumType.vector2: + case ValueEnumType.vector2Int: + { + let value = propertyInfo.getValue(); + if (key in mat) { + mat[key] = value; + } else if (key in mat.shader) { + mat.shader[key] = value; + } else { + mat.setUniformVector2(key, value); + } + } + break; + case ValueEnumType.vector3: + { + let value = propertyInfo.getValue(); + if (key in mat) { + mat[key] = value; + } else if (key in mat.shader) { + mat.shader[key] = value; + } else { + mat.setUniformVector3(key, value); + } + } + break; + case ValueEnumType.vector4: + { + let value = propertyInfo.getValue(); + if (key in mat) { + mat[key] = value; + } else if (key in mat.shader) { + mat.shader[key] = value; + } else { + mat.setUniformVector4(key, value); + } + } + break; + default: + break; + // } + } + } + } + +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/LitHairShader.ts b/src/loader/parser/prefab/mats/shader/LitHairShader.ts new file mode 100644 index 00000000..94383506 --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/LitHairShader.ts @@ -0,0 +1,220 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { ShaderLib } from "../../../../../assets/shader/ShaderLib"; +import { GPUCullMode } from "../../../../../gfx/graphics/webGpu/WebGPUConst"; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { BlendMode } from "../../../../../materials/BlendMode"; +import { Color } from "../../../../../math/Color"; +import { Vector4 } from "../../../../../math/Vector4"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; +import { Hair_shader_op, Hair_shader_tr, RenderShaderPass, PassType } from "../../../../.."; + + +@RegisterShader +export class LitHairShader extends Shader { + + constructor() { + super(); + + this.create_opPass(); + // this.create_trPass(); + + this.setDefine('USEC', true); + this.setDefine('USE_BRDF', true); + this.setDefine('USE_AO_R', true); + this.setDefine('USE_ROUGHNESS_G', true); + this.setDefine('USE_METALLIC_B', true); + this.setDefine('USE_ALPHA_A', true); + this.setDefine('USE_HAIR', true); + this.setDefine('USE_CUSTOMUNIFORM', true); + this.setDefine('USE_HAIRCOLOR', true); + + this.setDefault(); + this.debug(); + } + + private create_opPass() { + ShaderLib.register("HairShader_op", Hair_shader_op); + let colorShader = new RenderShaderPass('HairShader_op', 'HairShader_op'); + this.addRenderPass(colorShader); + + colorShader.setShaderEntry(`VertMain`, `FragMain`) + let shaderState = colorShader.shaderState; + shaderState.acceptShadow = true; + shaderState.castShadow = true; + shaderState.receiveEnv = true; + shaderState.acceptGI = true; + shaderState.useLight = true; + shaderState.blendMode = BlendMode.NONE; + shaderState.cullMode = GPUCullMode.none; + shaderState.writeMasks[0] = GPUColorWrite.ALL; + } + + private create_trPass() { + ShaderLib.register("HairShader_tr", Hair_shader_tr); + let colorShader = new RenderShaderPass('HairShader_tr', 'HairShader_tr'); + this.addRenderPass(colorShader); + + colorShader.setShaderEntry(`VertMain`, `FragMain`) + let shaderState = colorShader.shaderState; + shaderState.acceptShadow = true; + shaderState.castShadow = true; + shaderState.receiveEnv = true; + shaderState.acceptGI = true; + shaderState.useLight = true; + shaderState.depthWriteEnabled = false; + shaderState.blendMode = BlendMode.NORMAL; + shaderState.cullMode = GPUCullMode.none; + + shaderState.writeMasks[0] = GPUColorWrite.ALL; + shaderState.writeMasks[1] = 0; + shaderState.writeMasks[2] = 0; + shaderState.writeMasks[3] = 0; + } + + public debug() { + GUIHelp.addFolder("Hair"); + GUIHelp.addColor({ HairColorStart: new Color() }, "HairColorStart").onChange((v) => { + let c = new Color(); + c.copyFromArray(v); + this._HairColor0 = c; + }); + + GUIHelp.addColor({ HairColorEnd: new Color() }, "HairColorEnd").onChange((v) => { + let c = new Color(); + c.copyFromArray(v); + this._HairColor1 = c; + }); + + GUIHelp.addColor({ specularColor: new Color() }, "specularColor").onChange((v) => { + let c = new Color(); + c.copyFromArray(v); + this._SpecularColor = c; + }); + + GUIHelp.add({ roughness: 1 }, "roughness", 0.0, 1.0).onChange((v) => { + this._Roughness = v; + }); + GUIHelp.add({ metallic: 1 }, "metallic", 0.0, 1.0).onChange((v) => { + this._Metallic = v; + }); + + GUIHelp.add({ alphaCutoff: 1 }, "alphaCutoff", 0.0, 1.0).onChange((v) => { + this._AlphaCutoff = v; + }); + + GUIHelp.add({ backlit: 1 }, "backlit", 0.0, 1.0, 0.0001).onChange((v) => { + this._BackLit = v; + }); + + GUIHelp.add({ area: 0.1 }, "area", 0.0, 1.0, 0.0001).onChange((v) => { + this._Area = v; + }); + GUIHelp.endFolder(); + } + + public setDefault() { + this.setUniformFloat(`shadowBias`, 0.00035); + this.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + this.setUniformColor(`baseColor0`, new Color(3 / 255, 2 / 255, 2 / 255)); + this.setUniformColor(`baseColor1`, new Color(2 / 255, 2 / 255, 2 / 255)); + this.setUniformColor(`emissiveColor`, new Color(1, 1, 1)); + this.setUniformVector4(`materialF0`, new Vector4(0.04, 0.04, 0.04, 1)); + this.setUniformColor(`specularColor`, new Color(36 / 255, 36 / 255, 36 / 255)); + this.setUniformFloat(`envIntensity`, 1); + this.setUniformFloat(`normalScale`, 1); + this.setUniformFloat(`roughness`, 0.1); + this.setUniformFloat(`metallic`, 0.3); + this.setUniformFloat(`ao`, 1.0); + this.setUniformFloat(`roughness_min`, 0.0); + this.setUniformFloat(`roughness_max`, 1.0); + this.setUniformFloat(`metallic_min`, 0.0); + this.setUniformFloat(`metallic_max`, 1.0); + this.setUniformFloat(`emissiveIntensity`, 0.0); + this.setUniformFloat(`alphaCutoff`, 0.1); + this.setUniformFloat(`ior`, 1.5); + this.setUniformFloat(`backlit`, 0.3987); + this.setUniformFloat(`area`, 0.0615); + } + + + public set _MainTex(value: Texture) { + this.setTexture("baseMap", value); + } + + public set _IDMap(value: Texture) { + this.setTexture("idMap", value); + } + + public set _DepthMap(value: Texture) { + this.setTexture("depthMap", value); + } + + public set _RootMap(value: Texture) { + this.setTexture("rootMap", value); + } + + public set _AlphaMap(value: Texture) { + this.setTexture("alphaMap", value); + } + + public set _UVTransform(value: Vector4) { + this.setUniformVector4("transformUV1", value); + } + + public set _Metallic(value: number) { + this.setUniformFloat("metallic", value); + } + + public set _Roughness(value: number) { + this.setUniformFloat("roughness", value); + } + + public set _HairColor0(value: Color) { + this.setUniformColor("baseColor0", value); + } + + public set _HairColor1(value: Color) { + this.setUniformColor("baseColor1", value); + } + + public set _SpecularColor(value: Color) { + this.setUniformColor("specularColor", value); + } + + public set _AlphaCutoff(value: number) { + this.setUniformFloat("alphaCutoff", value); + } + + public set _BackLit(value: number) { + this.setUniformFloat("backlit", value); + } + + public set _Area(value: number) { + this.setUniformFloat("area", value); + } + + + public set _DoubleSidedEnable(value: number) { + let subShader = this.getSubShaders(PassType.COLOR)[0]; + subShader.shaderState.cullMode = value ? GPUCullMode.none : subShader.shaderState.cullMode; + } + + public set _SurfaceType(value: number) { + if (value == 0) { + // this.blendMode = BlendMode.NONE; + } else { + // this.blendMode = BlendMode.ALPHA; + } + } + + public set _AlphaCutoffEnable(value: number) { + if (value == 0) { + this.setDefine('USE_ALPHACUT', false); + } else { + this.setDefine('USE_ALPHACUT', true); + } + } + +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/LitSSSShader.ts b/src/loader/parser/prefab/mats/shader/LitSSSShader.ts new file mode 100644 index 00000000..8682bbf4 --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/LitSSSShader.ts @@ -0,0 +1,178 @@ +import { Color } from "../../../../../math/Color"; +import { Vector4 } from "../../../../../math/Vector4"; +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; +import { PBRLitSSSShader } from "../../../../../assets/shader/materials/PBRLitSSSShader"; +import { ShaderLib } from "../../../../../assets/shader/ShaderLib"; +import { PreIntegratedLutCompute } from "../../../../../gfx/graphics/webGpu/compute/PreIntegratedLutCompute"; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { GPUCullMode } from "../../../../../gfx/graphics/webGpu/WebGPUConst"; +import { BlendMode } from "../../../../../materials/BlendMode"; +import { RenderShaderPass } from "../../../../../gfx/graphics/webGpu/shader/RenderShaderPass"; + + +@RegisterShader +export class LitSSSShader extends Shader { + + constructor() { + super(); + + ShaderLib.register("PBRLitSSSShader", PBRLitSSSShader); + let colorShader = new RenderShaderPass('PBRLitSSSShader', 'PBRLitSSSShader'); + colorShader.setShaderEntry(`VertMain`, `FragMain`) + this.addRenderPass(colorShader); + + let shaderState = colorShader.shaderState; + shaderState.acceptShadow = true; + shaderState.castShadow = true; + shaderState.receiveEnv = true; + shaderState.acceptGI = true; + shaderState.useLight = true; + this.setDefine('USE_BRDF', true); + this.setDefine('USE_AO_R', true); + this.setDefine('USE_ROUGHNESS_G', true); + this.setDefine('USE_METALLIC_B', true); + this.setDefine('USE_ALPHA_A', true); + this.setDefine('USE_CUSTOMUNIFORM', true); + this.setDefault(); + this.debug(); + + this.computes = [ + new PreIntegratedLutCompute(this) + ] + } + + public debug() { + GUIHelp.addFolder("face"); + GUIHelp.addColor({ SkinColor: new Color() }, "SkinColor").onChange((v) => { + let newColor = new Color(); + newColor.copyFromArray(v); + this._SkinColor = newColor; + }); + GUIHelp.add({ skinPower: 1 }, "skinPower", 0.0, 10.0).onChange((v) => { + this._SkinPower = v; + }); + GUIHelp.add({ skinColorIns: 1 }, "skinColorIns", 0.0, 10.0).onChange((v) => { + this._SkinColorIns = v; + }); + GUIHelp.add({ roughness: 1 }, "roughness", 0.0, 1.0).onChange((v) => { + this._Roughness = v; + }); + GUIHelp.add({ metallic: 1 }, "metallic", 0.0, 1.0).onChange((v) => { + this._Metallic = v; + }); + GUIHelp.add({ curveFactor: 1 }, "curveFactor", 0.0, 10.0).onChange((v) => { + this.curveFactor = v; + }); + + GUIHelp.endFolder(); + } + + public setDefault() { + this.setUniformFloat(`shadowBias`, 0.00035); + this.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + this.setUniformColor(`baseColor`, new Color()); + this.setUniformColor(`emissiveColor`, new Color(1, 1, 1)); + this.setUniformVector4(`materialF0`, new Vector4(0.04, 0.04, 0.04, 1)); + this.setUniformColor(`specularColor`, new Color(0.04, 0.04, 0.04)); + this.setUniformFloat(`envIntensity`, 1); + this.setUniformFloat(`normalScale`, 1); + this.setUniformFloat(`roughness`, 1.0); + this.setUniformFloat(`metallic`, 0.0); + this.setUniformFloat(`ao`, 1.0); + this.setUniformFloat(`roughness_min`, 0.0); + this.setUniformFloat(`roughness_max`, 1.0); + this.setUniformFloat(`metallic_min`, 0.0); + this.setUniformFloat(`metallic_max`, 1.0); + this.setUniformFloat(`emissiveIntensity`, 0.0); + this.setUniformFloat(`alphaCutoff`, 0.0); + this.setUniformFloat(`ior`, 1.5); + this.setUniformFloat(`clearcoatFactor`, 0.0); + this.setUniformFloat(`clearcoatRoughnessFactor`, 0.0); + this.setUniformColor(`clearcoatColor`, new Color(1, 1, 1)); + this.setUniformFloat(`clearcoatWeight`, 0.0); + + this.setUniformColor(`skinColor`, new Color(1, 0, 0)); + this.setUniformFloat(`skinPower`, 3.4); + this.setUniformFloat(`skinColorIns`, 0.5); + this.setUniformFloat(`curveFactor`, 1.0); + } + + public set _MainTex(value: Texture) { + this.setTexture("baseMap", value); + } + + public set _BumpMap(value: Texture) { + this.setTexture("normalMap", value); + } + + public set _SSSMap(value: Texture) { + this.setTexture("sssMap", value); + } + + public set _MaskTex(value: Texture) { + this.setTexture("maskMap", value); + } + + public set _UVTransform(value: Vector4) { + this.setUniformVector4("transformUV1", value); + } + + public set _Metallic(value: number) { + this.setUniformFloat("metallic", value); + } + + public set _Roughness(value: number) { + this.setUniformFloat("roughness", value); + } + + + public set _MainColor(value: Color) { + this.setUniformColor("baseColor", value); + } + + public set _AlphaCutoff(value: number) { + this.setUniformFloat("alphaCutoff", value); + } + + public set _DoubleSidedEnable(value: number) { + let shader = this.getDefaultColorShader(); + shader.shaderState.cullMode = value ? GPUCullMode.none : shader.shaderState.cullMode; + } + + public set _SkinColor(value: Color) { + this.setUniformColor("skinColor", value); + } + + public set _SkinPower(value: number) { + this.setUniformFloat("skinPower", value); + } + + public set _SkinColorIns(value: number) { + this.setUniformFloat("skinColorIns", value); + } + + public set curveFactor(value: number) { + this.setUniformFloat("curveFactor", value); + } + + public set _SurfaceType(value: number) { + let shader = this.getDefaultColorShader(); + if (value == 0) { + shader.blendMode = BlendMode.NONE; + } else { + shader.blendMode = BlendMode.ALPHA; + } + } + + public set _AlphaCutoffEnable(value: number) { + if (value == 0) { + this.setDefine('USE_ALPHACUT', false); + } else { + this.setDefine('USE_ALPHACUT', true); + } + } + +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/LitShader.ts b/src/loader/parser/prefab/mats/shader/LitShader.ts new file mode 100644 index 00000000..c6612406 --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/LitShader.ts @@ -0,0 +1,121 @@ +import { Engine3D } from "../../../../.."; +import { GPUCullMode } from "../../../../../gfx/graphics/webGpu/WebGPUConst"; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../../../../../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { BlendMode } from "../../../../../materials/BlendMode"; +import { Color } from "../../../../../math/Color"; +import { Vector4 } from "../../../../../math/Vector4"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; + + +@RegisterShader +export class LitShader extends Shader { + + constructor() { + super(); + + let colorShader = new RenderShaderPass('PBRLItShader', 'PBRLItShader'); + colorShader.setShaderEntry(`VertMain`, `FragMain`) + this.addRenderPass(colorShader); + + let shaderState = colorShader.shaderState; + shaderState.acceptShadow = true; + shaderState.castShadow = true; + shaderState.receiveEnv = true; + shaderState.acceptGI = true; + shaderState.useLight = true; + this.setDefine('USE_BRDF', true); + this.setDefine('USE_AO_R', true); + this.setDefine('USE_ROUGHNESS_G', true); + this.setDefine('USE_METALLIC_B', true); + this.setDefine('USE_ALPHA_A', true); + + this.setDefault(); + } + + public setDefault() { + this.setUniformFloat(`shadowBias`, 0.00035); + this.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + this.setUniformColor(`baseColor`, new Color()); + this.setUniformColor(`emissiveColor`, new Color(0, 0, 0)); + this.setUniformVector4(`materialF0`, new Vector4(0.04, 0.04, 0.04, 1)); + this.setUniformColor(`specularColor`, new Color(0.04, 0.04, 0.04)); + this.setUniformFloat(`envIntensity`, 1); + this.setUniformFloat(`normalScale`, 1); + this.setUniformFloat(`roughness`, 1.0); + this.setUniformFloat(`metallic`, 0.0); + this.setUniformFloat(`ao`, 1.0); + this.setUniformFloat(`roughness_min`, 0.0); + this.setUniformFloat(`roughness_max`, 1.0); + this.setUniformFloat(`metallic_min`, 0.0); + this.setUniformFloat(`metallic_max`, 1.0); + this.setUniformFloat(`emissiveIntensity`, 0.0); + this.setUniformFloat(`alphaCutoff`, 0.0); + this.setUniformFloat(`ior`, 1.5); + this.setUniformFloat(`clearcoatFactor`, 0.0); + this.setUniformFloat(`clearcoatRoughnessFactor`, 0.0); + this.setUniformColor(`clearcoatColor`, new Color(1, 1, 1)); + this.setUniformFloat(`clearcoatWeight`, 0.0); + + this._MainTex = Engine3D.res.grayTexture; + this._BumpMap = Engine3D.res.normalTexture; + this._MaskTex = Engine3D.res.maskTexture; + } + + public set _MainTex(value: Texture) { + this.setTexture("baseMap", value); + } + + public set _BumpMap(value: Texture) { + this.setTexture("normalMap", value); + } + + public set _MaskTex(value: Texture) { + this.setTexture("maskMap", value); + } + + public set _UVTransform(value: Vector4) { + this.setUniformVector4("transformUV1", value); + } + + public set _Metallic(value: number) { + this.setUniformFloat("metallic", value); + } + + public set _Roughness(value: number) { + this.setUniformFloat("roughness", value); + } + + public set _MainColor(value: Color) { + this.setUniformColor("baseColor", value); + } + + public set _AlphaCutoff(value: number) { + this.setUniformFloat("alphaCutoff", value); + } + + public set _DoubleSidedEnable(value: number) { + let subShader = this.getDefaultColorShader(); + subShader.shaderState.cullMode = value ? GPUCullMode.none : subShader.shaderState.cullMode; + } + + public set _SurfaceType(value: number) { + let subShader = this.getDefaultColorShader(); + if (value == 0) { + subShader.blendMode = BlendMode.NONE; + } else { + subShader.blendMode = BlendMode.ALPHA; + } + } + + public set _AlphaCutoffEnable(value: number) { + if (value == 0) { + this.setDefine('USE_ALPHACUT', false); + } else { + this.setDefine('USE_ALPHACUT', true); + } + } + +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/QuadShader.ts b/src/loader/parser/prefab/mats/shader/QuadShader.ts new file mode 100644 index 00000000..706aeb7c --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/QuadShader.ts @@ -0,0 +1,34 @@ +import { Engine3D } from "../../../../../Engine3D"; +import { GPUCompareFunction, GPUCullMode } from "../../../../../gfx/graphics/webGpu/WebGPUConst"; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../../../../../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { BlendMode } from "../../../../../materials/BlendMode"; +import { Color } from "../../../../../math/Color"; +import { Vector4 } from "../../../../../math/Vector4"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; + + +@RegisterShader +export class QuadShader extends Shader { + + constructor(vs: string = 'QuadGlsl_vs', fs: string = 'QuadGlsl_fs') { + super(); + + let colorShader = new RenderShaderPass(vs, fs); + this.addRenderPass(colorShader); + + let shaderState = colorShader.shaderState; + colorShader.blendMode = BlendMode.NONE; + shaderState.frontFace = `cw`; + shaderState.depthWriteEnabled = false; + shaderState.depthCompare = GPUCompareFunction.always; + shaderState.multisample = 0; + + this.setTexture("baseMap", Engine3D.res.blackTexture); + this.setUniformFloat(`x`, 0); + this.setUniformFloat(`y`, 0); + this.setUniformFloat(`width`, 100); + this.setUniformFloat(`height`, 100); + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/SkyShader.ts b/src/loader/parser/prefab/mats/shader/SkyShader.ts new file mode 100644 index 00000000..27d4a618 --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/SkyShader.ts @@ -0,0 +1,30 @@ +import { GPUCompareFunction, GPUCullMode } from "../../../../../gfx/graphics/webGpu/WebGPUConst"; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../../../../../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { BlendMode } from "../../../../../materials/BlendMode"; +import { Color } from "../../../../../math/Color"; +import { Vector3 } from "../../../../../math/Vector3"; +import { Vector4 } from "../../../../../math/Vector4"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; + + +@RegisterShader +export class SkyShader extends Shader { + + constructor() { + super(); + let colorShader = new RenderShaderPass('sky_vs_frag_wgsl', 'sky_fs_frag_wgsl'); + this.addRenderPass(colorShader); + + colorShader.setUniformVector3(`eyesPos`, new Vector3()); + colorShader.setUniformFloat(`exposure`, 1.0); + colorShader.setUniformFloat(`roughness`, 0.0); + + let shaderState = colorShader.shaderState; + shaderState.frontFace = `cw`; + shaderState.cullMode = GPUCullMode.back; + shaderState.depthWriteEnabled = false; + shaderState.depthCompare = GPUCompareFunction.less; + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/StandShader.ts b/src/loader/parser/prefab/mats/shader/StandShader.ts new file mode 100644 index 00000000..2dc3f3ea --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/StandShader.ts @@ -0,0 +1,485 @@ +import { Engine3D, PassType } from "../../../../.."; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../../../../../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { Color } from "../../../../../math/Color"; +import { Vector4 } from "../../../../../math/Vector4"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; + + +@RegisterShader +export class StandShader extends Shader { + + constructor() { + super(); + + let colorShader = new RenderShaderPass('PBRLItShader', 'PBRLItShader'); + colorShader.setShaderEntry(`VertMain`, `FragMain`) + colorShader.passType = PassType.COLOR; + this.addRenderPass(colorShader); + + let shaderState = colorShader.shaderState; + shaderState.acceptShadow = true; + shaderState.castShadow = true; + shaderState.receiveEnv = true; + shaderState.acceptGI = true; + shaderState.useLight = true; + this.setDefine('USE_BRDF', true); + this.setDefine('USE_AO_R', true); + this.setDefine('USE_ROUGHNESS_G', true); + this.setDefine('USE_METALLIC_B', true); + this.setDefine('USE_ALPHA_A', true); + + this.setDefault(); + } + + public setDefault() { + this.setUniformFloat(`shadowBias`, 0.00035); + this.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + this.setUniformColor(`baseColor`, new Color(0.75, 0.75, 0.75, 1.0)); + this.setUniformColor(`emissiveColor`, new Color(0, 0, 0)); + this.setUniformVector4(`materialF0`, new Vector4(0.04, 0.04, 0.04, 1)); + this.setUniformColor(`specularColor`, new Color(0.04, 0.04, 0.04)); + this.setUniformFloat(`envIntensity`, 1); + this.setUniformFloat(`normalScale`, 1); + this.setUniformFloat(`roughness`, 1.0); + this.setUniformFloat(`metallic`, 1.0); + this.setUniformFloat(`ao`, 1.0); + this.setUniformFloat(`roughness_min`, 0.0); + this.setUniformFloat(`roughness_max`, 1.0); + this.setUniformFloat(`metallic_min`, 0.0); + this.setUniformFloat(`metallic_max`, 1.0); + this.setUniformFloat(`emissiveIntensity`, 0.0); + this.setUniformFloat(`alphaCutoff`, 0.0); + this.setUniformFloat(`ior`, 1.5); + this.setUniformFloat(`clearcoatFactor`, 0.0); + this.setUniformFloat(`clearcoatRoughnessFactor`, 0.0); + this.setUniformColor(`clearcoatColor`, new Color(1, 1, 1)); + this.setUniformFloat(`clearcoatWeight`, 0.0); + + this.baseMap = Engine3D.res.whiteTexture; + this.normalMap = Engine3D.res.normalTexture; + this.maskMap = Engine3D.res.maskTexture; + } + + public get baseMap(): Texture { + return this.getDefaultColorShader().getTexture(`baseMap`); + } + + public set baseMap(value: Texture) { + this.getDefaultColorShader().setTexture(`baseMap`, value); + } + + public get baseColor(): Color { + return this.getDefaultColorShader().getUniform(`baseColor`); + } + + public set baseColor(value: Color) { + this.getDefaultColorShader().setUniformColor(`baseColor`, value); + } + + public get normalMap(): Texture { + return this.getDefaultColorShader().getTexture(`normalMap`); + } + + public set normalMap(value: Texture) { + this.getDefaultColorShader().setTexture(`normalMap`, value); + } + + public get doubleSide(): boolean { + return this.getDefaultColorShader().doubleSide; + } + public set doubleSide(value: boolean) { + this.getDefaultColorShader().doubleSide = value; + } + + public get alphaCutoff(): any { + return this.getDefaultColorShader().shaderState.alphaCutoff; + } + public set alphaCutoff(value: any) { + this.getDefaultColorShader().setDefine("USE_ALPHACUT", true); + this.getDefaultColorShader().shaderState.alphaCutoff = value; + this.getDefaultColorShader().setUniform(`alphaCutoff`, value); + } + + public get emissiveColor(): Color { + return this.getDefaultColorShader().getUniform(`emissiveColor`); + } + + public set emissiveColor(value: Color) { + this.getDefaultColorShader().setUniform(`emissiveColor`, value); + } + + public get emissiveIntensity(): number { + return this.getDefaultColorShader().getUniform(`emissiveIntensity`); + } + + public set emissiveIntensity(value: number) { + this.getDefaultColorShader().setUniform(`emissiveIntensity`, value); + } + + /** + * get transformUV1 + */ + public get uvTransform_1(): Vector4 { + return this.getDefaultColorShader().uniforms[`transformUV1`].vector4; + } + + /** + * set transformUV1 + */ + public set uvTransform_1(value: Vector4) { + // this.getDefaultColorShader().uniforms[`transformUV1`].v4 = value; + this.getDefaultColorShader().setUniform(`transformUV1`, value); + } + + /** + * get transformUV2 + */ + public get uvTransform_2(): Vector4 { + return this.getDefaultColorShader().uniforms[`transformUV2`].vector4; + } + + /** + * set transformUV2 + */ + public set uvTransform_2(value: Vector4) { + // this.getDefaultColorShader().uniforms[`transformUV2`].v4 = value; + this.getDefaultColorShader().setUniform(`transformUV2`, value); + } + + public get depthWriteEnabled(): boolean { + return this.getDefaultColorShader().shaderState.depthWriteEnabled; + } + public set depthWriteEnabled(value: boolean) { + this.getDefaultColorShader().shaderState.depthWriteEnabled = value; + } + + /** + * get reflectivity + */ + public get materialF0(): Vector4 { + return this.getDefaultColorShader().uniforms[`materialF0`].vector4; + } + + /** + * set reflectivity + */ + public set materialF0(value: Vector4) { + this.getDefaultColorShader().setUniform(`materialF0`, value); + } + + /** + * get specularColor + */ + public get specularColor(): Color { + return this.getDefaultColorShader().uniforms[`specularColor`].color; + } + + /**specularColor + * set reflectivity + */ + public set specularColor(value: Color) { + this.getDefaultColorShader().setUniform(`specularColor`, value); + } + + /** + * get roughness + */ + public get roughness(): number { + return this.getDefaultColorShader().uniforms[`roughness`].value; + } + + /** + * set roughness + */ + public set roughness(value: number) { + this.getDefaultColorShader().setUniform(`roughness`, value); + } + + /** + * get metallic + */ + public get metallic(): number { + return this.getDefaultColorShader().uniforms[`metallic`].value; + } + + /** + * set metallic + */ + public set metallic(value: number) { + this.getDefaultColorShader().setUniform(`metallic`, value); + } + + /** + * get Ambient Occlussion, dealing with the effect of ambient light on object occlusion + */ + public get ao(): number { + return this.getDefaultColorShader().uniforms[`ao`].value; + } + + /** + * set Ambient Occlussion, dealing with the effect of ambient light on object occlusion + */ + public set ao(value: number) { + this.getDefaultColorShader().setUniform(`ao`, value); + } + + /** + * get min metallic + */ + public get metallic_min(): number { + return this.getDefaultColorShader().uniforms[`metallic_min`].value; + } + + /** + * set min metallic + */ + public set metallic_min(value: number) { + this.getDefaultColorShader().setUniform(`metallic_min`, value); + } + + /** + * get max metallic + */ + public get metallic_max(): number { + return this.getDefaultColorShader().uniforms[`metallic_max`].value; + } + + /** + * set max metallic + */ + public set metallic_max(value: number) { + this.getDefaultColorShader().setUniform(`metallic_max`, value); + } + + /** + * get min roughness + */ + public get roughness_min(): number { + return this.getDefaultColorShader().uniforms[`roughness_min`].value; + } + + /** + * set min roughness + */ + public set roughness_min(value: number) { + this.getDefaultColorShader().setUniform(`roughness_min`, value); + } + + /** + * get max roughness + */ + public get roughness_max(): number { + return this.getDefaultColorShader().uniforms[`roughness_max`].value; + } + + /** + * set max roughness + */ + public set roughness_max(value: number) { + this.getDefaultColorShader().setUniform(`roughness_max`, value); + } + + /** + * Get the influence of Normal mapping on materials + */ + public get normalScale(): number { + return this.getDefaultColorShader().uniforms[`normalScale`].value; + } + + /** + * Set the influence of Normal mapping on materials + */ + public set normalScale(value: number) { + this.getDefaultColorShader().setUniform(`normalScale`, value); + } + + /** + * get Mask Map + * R_chanel -> AoMap + * G_chanel -> Roughness + * B_chanel -> Metallic + * A_chanel -> C + */ + public get maskMap(): Texture { + return this.getDefaultColorShader().textures[`maskMap`]; + } + + /** + * set Mask Map + * R_chanel -> AoMap + * G_chanel -> Roughness + * B_chanel -> Metallic + * A_chanel -> C + */ + public set maskMap(value: Texture) { + // USE_MR + // USE_ORMC + // USE_RMOC + // USE_CRMC + this.getDefaultColorShader().setDefine(`USE_MR`, true); + this.getDefaultColorShader().setTexture(`maskMap`, value); + } + + /** + * set Ambient Occlussion Map, dealing with the effect of ambient light on object occlusion + */ + public set aoMap(value: Texture) { + if (!value) return; + this.getDefaultColorShader().setTexture(`aoMap`, value); + if (value != Engine3D.res.whiteTexture) { + this.getDefaultColorShader().setDefine(`USE_AOTEX`, true); + } + } + + /** + * get Ambient Occlussion Map, dealing with the effect of ambient light on object occlusion + */ + public get aoMap(): Texture { + return this.getDefaultColorShader().textures[`aoMap`]; + } + + /** + * set clearCoatRoughnessMap + */ + public set clearCoatRoughnessMap(value: Texture) { + if (!value) return; + console.log("USE_CLEARCOAT_ROUGHNESS"); + + this.getDefaultColorShader().setTexture(`clearCoatRoughnessMap`, value); + this.getDefaultColorShader().setDefine(`USE_CLEARCOAT_ROUGHNESS`, true); + } + + /** + * get clearCoatRoughnessMap + */ + public get clearCoatRoughnessMap(): Texture { + return this.getDefaultColorShader().textures[`clearCoatRoughnessMap`]; + } + + /** + * get brdf query map + */ + public get brdfLUT(): Texture { + return this.getDefaultColorShader().textures[`brdfLUT`]; + } + + /** + * set brdf query map + */ + public set brdfLUT(value: Texture) { + this.getDefaultColorShader().setTexture(`brdfLUT`, value); + this.getDefaultColorShader().setTexture(`brdflutMap`, value); + } + + /** + * get emissive map + */ + public get emissiveMap(): Texture { + return this.getDefaultColorShader().textures[`emissiveMap`]; + } + + /** + * set emissive map + */ + public set emissiveMap(value: Texture) { + this.getDefaultColorShader().setTexture(`emissiveMap`, value); + } + + /** + * set intensity of environment light or color of sampled by texture + */ + public set envIntensity(value: number) { + this.getDefaultColorShader().setUniformFloat(`envIntensity`, value); + } + + /** + * get intensity of environment light or color of sampled by texture + */ + public get envIntensity() { + return this.getDefaultColorShader().uniforms[`envIntensity`].value; + } + + /** + * set factor of refractive + */ + public set ior(value: number) { + this.getDefaultColorShader().setUniformFloat(`ior`, value); + } + + /** + * get factor of refractive + */ + public get ior(): number { + return this.getDefaultColorShader().uniforms[`ior`].value; + } + + /** + * valid USE_CLEARCOAT define in shader + */ + public useCleanCoat() { + this.getDefaultColorShader().setDefine("USE_CLEARCOAT", true); + } + + /** + * Set the factor of the clearcoat + */ + public set clearcoatFactor(value: number) { + this.getDefaultColorShader().setUniformFloat(`clearcoatFactor`, value); + this.useCleanCoat(); + } + + /** + * get the factor of the clearcoat + */ + public get clearcoatFactor(): number { + return this.getDefaultColorShader().uniforms[`clearcoatFactor`].value; + } + + /** + * set the factor of the clearcoat Roughness + */ + public set clearcoatRoughnessFactor(value: number) { + this.getDefaultColorShader().setUniformFloat(`clearcoatRoughnessFactor`, value); + this.useCleanCoat(); + } + + /** + * get the factor of the clearcoat Roughness + */ + public get clearcoatRoughnessFactor(): number { + return this.getDefaultColorShader().uniforms[`clearcoatRoughnessFactor`].value; + } + + /** + * set the weight of the clearcoat + */ + public set clearcoatWeight(value: number) { + this.getDefaultColorShader().setUniformFloat(`clearcoatWeight`, value); + this.useCleanCoat(); + } + + /** + * get the weight of the clearcoat + */ + public get clearcoatWeight(): number { + return this.getDefaultColorShader().uniforms[`clearcoatWeight`].value; + } + + /** + * get the color of the clearcoat + */ + public set clearcoatColor(value: Color) { + this.getDefaultColorShader().setUniformColor(`clearcoatColor`, value); + this.useCleanCoat(); + } + + /** + * set the color of the clearcoat + */ + public get clearcoatColor(): Color { + return this.getDefaultColorShader().uniforms[`clearcoatColor`].color; + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/UnLitShader.ts b/src/loader/parser/prefab/mats/shader/UnLitShader.ts new file mode 100644 index 00000000..4ccd4ce5 --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/UnLitShader.ts @@ -0,0 +1,98 @@ +import { Engine3D } from "../../../../../Engine3D"; +import { GPUCullMode } from "../../../../../gfx/graphics/webGpu/WebGPUConst"; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../../../../../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { BlendMode } from "../../../../../materials/BlendMode"; +import { Color } from "../../../../../math/Color"; +import { Vector4 } from "../../../../../math/Vector4"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; + + +@RegisterShader +export class UnLitShader extends Shader { + + constructor() { + super(); + let colorShader = new RenderShaderPass('UnLit', 'UnLit'); + colorShader.setShaderEntry(`VertMain`, `FragMain`) + this.addRenderPass(colorShader); + + let shaderState = colorShader.shaderState; + shaderState.acceptShadow = false; + shaderState.castShadow = false; + shaderState.receiveEnv = false; + shaderState.acceptGI = false; + shaderState.useLight = false; + this.setDefine('USE_BRDF', true); + this.setDefine('USE_AO_R', true); + this.setDefine('USE_ROUGHNESS_G', true); + this.setDefine('USE_METALLIC_B', true); + this.setDefine('USE_ALPHA_A', true); + + this.setDefault(); + } + + public setDefault() { + this.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + this.setUniformColor(`baseColor`, new Color()); + this.setUniformFloat(`alphaCutoff`, 0.0); + } + + public set _MainTex(value: Texture) { + this.setTexture("baseMap", value); + } + + public set _BumpMap(value: Texture) { + this.setTexture("normalMap", value); + } + + public set _MaskTex(value: Texture) { + this.setTexture("maskMap", value); + } + + public set _UVTransform(value: Vector4) { + this.setUniformVector4("transformUV1", value); + } + + public set _Metallic(value: number) { + this.setUniformFloat("metallic", value); + } + + public set _Roughness(value: number) { + this.setUniformFloat("roughness", value); + } + + + public set _MainColor(value: Color) { + this.setUniformColor("baseColor", value); + } + + public set _AlphaCutoff(value: number) { + this.setUniformFloat("alphaCutoff", value); + } + + public set _DoubleSidedEnable(value: number) { + let defaultShader = this.getDefaultColorShader(); + defaultShader.shaderState.cullMode = value ? GPUCullMode.none : defaultShader.shaderState.cullMode; + } + + public set _SurfaceType(value: number) { + let defaultShader = this.getDefaultColorShader(); + if (value == 0) { + defaultShader.blendMode = BlendMode.NONE; + } else { + defaultShader.blendMode = BlendMode.ALPHA; + } + } + + public set _AlphaCutoffEnable(value: number) { + if (value == 0) { + this.setDefine('USE_ALPHACUT', false); + } else { + this.setDefine('USE_ALPHACUT', true); + } + } + +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/UnLitTexArrayShader.ts b/src/loader/parser/prefab/mats/shader/UnLitTexArrayShader.ts new file mode 100644 index 00000000..9b8ac7b1 --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/UnLitTexArrayShader.ts @@ -0,0 +1,103 @@ +import { Engine3D } from "../../../../../Engine3D"; +import { GPUCullMode } from "../../../../../gfx/graphics/webGpu/WebGPUConst"; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../../../../../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { BlendMode } from "../../../../../materials/BlendMode"; +import { Color } from "../../../../../math/Color"; +import { Vector4 } from "../../../../../math/Vector4"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; +import { UnLitTextureArray } from "../../../../../assets/shader/materials/UnLitTextureArray"; +import { ShaderLib } from "../../../../../assets/shader/ShaderLib"; +import { VertexAttributeIndexShader } from "../../../../../assets/shader/core/struct/VertexAttributeIndexShader"; + + +@RegisterShader +export class UnLitTexArrayShader extends Shader { + + constructor() { + super(); + + ShaderLib.register("VertexAttributeIndexShader", VertexAttributeIndexShader); + ShaderLib.register("UnLitTextureArray", UnLitTextureArray); + let colorShader = new RenderShaderPass('UnLitTextureArray', 'UnLitTextureArray'); + colorShader.setShaderEntry(`VertMain`, `FragMain`) + this.addRenderPass(colorShader); + + let shaderState = colorShader.shaderState; + shaderState.acceptShadow = false; + shaderState.castShadow = false; + shaderState.receiveEnv = false; + shaderState.acceptGI = false; + shaderState.useLight = false; + this.setDefine('USE_BRDF', true); + this.setDefine('USE_AO_R', true); + this.setDefine('USE_ROUGHNESS_G', true); + this.setDefine('USE_METALLIC_B', true); + this.setDefine('USE_ALPHA_A', true); + this.setDefault(); + } + + public setDefault() { + this.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + this.setUniformColor(`baseColor`, new Color()); + this.setUniformFloat(`alphaCutoff`, 0.0); + } + + public set _MainTex(value: Texture) { + this.setTexture("baseMap", value); + } + + public set _BumpMap(value: Texture) { + this.setTexture("normalMap", value); + } + + public set _MaskTex(value: Texture) { + this.setTexture("maskMap", value); + } + + public set _UVTransform(value: Vector4) { + this.setUniformVector4("transformUV1", value); + } + + public set _Metallic(value: number) { + this.setUniformFloat("metallic", value); + } + + public set _Roughness(value: number) { + this.setUniformFloat("roughness", value); + } + + + public set _MainColor(value: Color) { + this.setUniformColor("baseColor", value); + } + + public set _AlphaCutoff(value: number) { + this.setUniformFloat("alphaCutoff", value); + } + + public set _DoubleSidedEnable(value: number) { + let defaultShader = this.getDefaultColorShader(); + defaultShader.shaderState.cullMode = value ? GPUCullMode.none : defaultShader.shaderState.cullMode; + } + + public set _SurfaceType(value: number) { + let defaultShader = this.getDefaultColorShader(); + if (value == 0) { + defaultShader.blendMode = BlendMode.NONE; + } else { + defaultShader.blendMode = BlendMode.ALPHA; + } + } + + public set _AlphaCutoffEnable(value: number) { + if (value == 0) { + this.setDefine('USE_ALPHACUT', false); + } else { + this.setDefine('USE_ALPHACUT', true); + } + } + +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/APatch.ts b/src/loader/parser/prefab/prefabData/APatch.ts new file mode 100644 index 00000000..3c91b196 --- /dev/null +++ b/src/loader/parser/prefab/prefabData/APatch.ts @@ -0,0 +1,34 @@ +import { Vector3, View3D } from "../../../.."; +import { ComponentBase } from "../../../../components/ComponentBase"; +import { Color } from "../../../../math/Color"; +import { Vector2 } from "../../../../math/Vector2"; +import { RegisterComponent } from "../../../../util/SerializeDecoration"; + +@RegisterComponent +export class APatch extends ComponentBase { + public size: Vector2; + public blockSize: number; + public walk: Color; + public obs: Color; + + public colors: Color[]; + + public aPaths: number[]; + + public onGraphic(view?: View3D) { + return; + + // for (let i = this.size.x ; i > 0 ; i--) { + for (let i = 0; i < this.size.x; i++) { + for (let j = 0; j < this.size.y; j++) { + let index = j * this.size.x + (i); + let data = this.aPaths[index]; + let color = this.colors[data] ; + + let pos = new Vector3(-i * this.blockSize + this.object3D.x , 0 + this.object3D.y , j * this.blockSize+ this.object3D.z); + view.graphic3D.drawFillRect(`${i}-${j}` , pos , this.blockSize , this.blockSize, color ); + } + } + + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/BlendShapeData.ts b/src/loader/parser/prefab/prefabData/BlendShapeData.ts new file mode 100644 index 00000000..b71f8638 --- /dev/null +++ b/src/loader/parser/prefab/prefabData/BlendShapeData.ts @@ -0,0 +1,44 @@ +import { BytesArray } from "../../../../util/BytesArray"; +import { BlendShapePropertyData } from "./BlendShapePropertyData"; + +export class BlendShapeData { + public vertexCount: number; + public shapeNames: string[]; + public shapeIndexs: number[]; + + public blendCount: number; + + // public positionList: Float32Array; + // public normalList: Float32Array; + + public blendShapePropertyDatas: BlendShapePropertyData[]; + public blendShapeMap: Map; + + public formBytes(byteArray: BytesArray) { + this.blendShapeMap = new Map(); + this.blendShapePropertyDatas = []; + let bytes = byteArray.readBytesArray(); + + this.vertexCount = bytes.readInt32(); + this.shapeNames = bytes.readStringArray(); + this.shapeIndexs = bytes.readIntArray(); + + this.blendCount = bytes.readInt32(); + + // let posCount = bytes.readInt32(); + // this.positionList = bytes.readFloat32Array(posCount * 3); + // let normalCount = bytes.readInt32(); + // this.normalList = bytes.readFloat32Array(normalCount * 3); + + + for (let i = 0; i < this.blendCount; i++) { + let propertyData = new BlendShapePropertyData(); + propertyData.formBytes(bytes); + + this.blendShapePropertyDatas.push(propertyData); + this.blendShapeMap.set(propertyData.shapeName, propertyData); + } + return byteArray; + } + +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/BlendShapeFrameData.ts b/src/loader/parser/prefab/prefabData/BlendShapeFrameData.ts new file mode 100644 index 00000000..07bc055c --- /dev/null +++ b/src/loader/parser/prefab/prefabData/BlendShapeFrameData.ts @@ -0,0 +1,27 @@ +import { Vector3 } from "../../../../math/Vector3"; +import { BytesArray } from "../../../../util/BytesArray"; + +export class BlendShapeFrameData { + + public weight: number; + + // public deltaVertices: Vector3[]; + // public deltaNormals: Vector3[]; + // public deltaTangents: Vector3[]; + + public deltaVertices: Float32Array; + public deltaNormals: Float32Array; + public deltaTangents: Float32Array; + + formBytes(byteArray: BytesArray) { + let bytes = byteArray.readBytesArray(); + this.weight = bytes.readFloat32(); + let len = 0; + len = bytes.readInt32(); + this.deltaVertices = bytes.readFloat32Array(len * 3); + len = bytes.readInt32(); + this.deltaNormals = bytes.readFloat32Array(len * 3); + len = bytes.readInt32(); + this.deltaTangents = bytes.readFloat32Array(len * 3); + } +} diff --git a/src/loader/parser/prefab/prefabData/BlendShapePropertyData.ts b/src/loader/parser/prefab/prefabData/BlendShapePropertyData.ts new file mode 100644 index 00000000..75ac1ed8 --- /dev/null +++ b/src/loader/parser/prefab/prefabData/BlendShapePropertyData.ts @@ -0,0 +1,24 @@ +import { BytesArray } from "../../../.."; +import { BlendShapeFrameData } from "./BlendShapeFrameData"; + +export class BlendShapePropertyData { + public shapeName: string; + public shapeIndex: number; + public frameCount: number; + // public blendShapeFrameDatas: BlendShapeFrameData[]; + public blendPositionList = new Float32Array(); + public blendNormalList = new Float32Array(); + public formBytes(byteArray: BytesArray) { + let bytes = byteArray.readBytesArray(); + + this.shapeName = bytes.readUTF(); + this.shapeIndex = bytes.readInt32(); + this.frameCount = bytes.readInt32(); + + let len = bytes.readInt32(); + this.blendPositionList = bytes.readFloat32Array(len * 3); + + let len2 = bytes.readInt32(); + this.blendNormalList = bytes.readFloat32Array(len2 * 3); + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/KVData.ts b/src/loader/parser/prefab/prefabData/KVData.ts new file mode 100644 index 00000000..dd7eb533 --- /dev/null +++ b/src/loader/parser/prefab/prefabData/KVData.ts @@ -0,0 +1,24 @@ +import { BytesArray } from "../../../../util/BytesArray"; +import { ValueParser } from "./ValueParser"; +import { ValueEnumType } from "./ValueType"; + + + +export class KV { + + public key: string; + public type: ValueEnumType; + private _data: any; + + public getValue(): T { + return this._data as T; + } + + formBytes(matBytes: BytesArray) { + this.key = matBytes.readUTF(); + let { t, v } = ValueParser.parser(matBytes); + this.type = t; + this._data = v; + } +} + diff --git a/src/loader/parser/prefab/prefabData/PrefabAvatarData.ts b/src/loader/parser/prefab/prefabData/PrefabAvatarData.ts new file mode 100644 index 00000000..3d26d0b6 --- /dev/null +++ b/src/loader/parser/prefab/prefabData/PrefabAvatarData.ts @@ -0,0 +1,23 @@ +import { BytesArray } from "../../../../util/BytesArray"; +import { PrefabBoneData } from "./PrefabBoneData"; + +export class PrefabAvatarData { + public name: string; + public count: number; + public boneData: PrefabBoneData[]; + public boneMap: Map; + public formBytes(bytes: BytesArray) { + this.boneData = []; + this.boneMap = new Map(); + + this.name = bytes.readUTF(); + this.count = bytes.readInt32(); + for (let i = 0; i < this.count; i++) { + let boneData = new PrefabBoneData(); + boneData.formBytes(bytes.readBytesArray()); + this.boneData[i] = boneData; + + this.boneMap.set(boneData.boneName, boneData); + } + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/PrefabBoneData.ts b/src/loader/parser/prefab/prefabData/PrefabBoneData.ts new file mode 100644 index 00000000..75a1269f --- /dev/null +++ b/src/loader/parser/prefab/prefabData/PrefabBoneData.ts @@ -0,0 +1,32 @@ +import { Quaternion } from "../../../../math/Quaternion"; +import { Vector3 } from "../../../../math/Vector3"; +import { BytesArray } from "../../../../util/BytesArray"; + +export class PrefabBoneData { + public boneName: string; + public bonePath: string; + public parentBoneName: string; + public boneID: number; + public parentBoneID: number; + public instanceID: string; + public parentInstanceID: string; + public t: Vector3; + public q: Quaternion; + public s: Vector3; + + public formBytes(bytes: BytesArray) { + this.boneName = bytes.readUTF(); + this.bonePath = bytes.readUTF(); + this.parentBoneName = bytes.readUTF(); + + this.boneID = bytes.readInt32(); + this.parentBoneID = bytes.readInt32(); + + this.instanceID = bytes.readUTF(); + this.parentInstanceID = bytes.readUTF(); + + this.t = bytes.readVector3(); + this.q = bytes.readQuaternion(); + this.s = bytes.readVector3(); + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/PrefabMeshData.ts b/src/loader/parser/prefab/prefabData/PrefabMeshData.ts new file mode 100644 index 00000000..3ddee497 --- /dev/null +++ b/src/loader/parser/prefab/prefabData/PrefabMeshData.ts @@ -0,0 +1,18 @@ +import { Matrix4 } from "../../../.."; +import { BlendShapeData } from "./BlendShapeData"; + +export class PrefabMeshData { + public name: string; + public meshName: string; + public meshID: string; + public vertexCount: number; + public vertexStrip: number; + public vertexBuffer: Float32Array; + public indices: Uint16Array | Uint32Array; + + public attributes: { attribute: string, dim: number, pos: number }[]; + + public bones: string[]; + public bindPose: Matrix4[]; + public blendShapeData: BlendShapeData; +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/PrefabNode.ts b/src/loader/parser/prefab/prefabData/PrefabNode.ts new file mode 100644 index 00000000..ab4e23ec --- /dev/null +++ b/src/loader/parser/prefab/prefabData/PrefabNode.ts @@ -0,0 +1,67 @@ +import { Quaternion } from "../../../../math/Quaternion"; +import { Vector3 } from "../../../../math/Vector3"; +import { BytesArray } from "../../../../util/BytesArray"; +import { KV } from "./KVData"; + +export class ComData { + comName: string; + data: KV[]; + + public static parser(bytesArray: BytesArray): ComData { + let comBuffer = bytesArray.readBytesArray(); + + let comData = new ComData(); + comData.comName = comBuffer.readUTF(); + comData.data = []; + + let count = comBuffer.readInt32(); + for (let i = 0; i < count; i++) { + let kv = new KV(); + kv.formBytes(comBuffer); + comData.data.push(kv); + } + return comData; + } +} + +export class PrefabNode { + name: string; + + parentName: string; + + position: Vector3; + + rotation: Quaternion; + + scale: Vector3; + + comDatas: ComData[]; + + child: PrefabNode[]; + + public static parser(bytesArray: BytesArray) { + let nodeBytes = bytesArray.readBytesArray(); + + let prefabNode = new PrefabNode(); + prefabNode.name = nodeBytes.readUTF(); + prefabNode.parentName = nodeBytes.readUTF(); + prefabNode.position = nodeBytes.readVector3(); + prefabNode.rotation = nodeBytes.readQuaternion(); + prefabNode.scale = nodeBytes.readVector3(); + prefabNode.comDatas = []; + prefabNode.child = []; + + let comCount = nodeBytes.readInt32(); + for (let i = 0; i < comCount; i++) { + const comData = ComData.parser(nodeBytes); + prefabNode.comDatas.push(comData); + } + + let childCount = nodeBytes.readInt32(); + for (let i = 0; i < childCount; i++) { + const childNodeData = PrefabNode.parser(nodeBytes); + prefabNode.child.push(childNodeData); + } + return prefabNode; + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/PrefabTextureData.ts b/src/loader/parser/prefab/prefabData/PrefabTextureData.ts new file mode 100644 index 00000000..f3541ce0 --- /dev/null +++ b/src/loader/parser/prefab/prefabData/PrefabTextureData.ts @@ -0,0 +1,16 @@ +import { BitmapTexture2D, Vector2 } from "../../../.."; + +export class PrefabTextureData { + + public property: string; + public name: string; + public texture: BitmapTexture2D; + public texelSize: Vector2; + public wrapModeU: number; + public wrapModeV: number; + public wrapModeW: number; + public wrapMode: number; + public anisoLevel: number; + public dimension: number; + public filterMode: number; +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/ValueParser.ts b/src/loader/parser/prefab/prefabData/ValueParser.ts new file mode 100644 index 00000000..9f96623a --- /dev/null +++ b/src/loader/parser/prefab/prefabData/ValueParser.ts @@ -0,0 +1,135 @@ +import { GeometryBase, Material, PropertyAnimationClip, Texture } from "../../../.."; +import { Engine3D } from "../../../../Engine3D"; +import { Joint } from "../../../../components/anim/skeletonAnim/Joint"; +import { Skeleton } from "../../../../components/anim/skeletonAnim/Skeleton"; +import { Color } from "../../../../math/Color"; +import { Quaternion } from "../../../../math/Quaternion"; +import { Vector2 } from "../../../../math/Vector2"; +import { Vector3 } from "../../../../math/Vector3"; +import { Vector4 } from "../../../../math/Vector4"; +import { BytesArray } from "../../../../util/BytesArray"; +import { ValueEnumType } from "./ValueType"; + +export type CurveValueType = string | number | Vector2 | Vector3 | Vector4 | Quaternion | Color | boolean | Texture | Material | string[] | number[] | Float32Array | GeometryBase | Skeleton | PropertyAnimationClip[]; + +export class ValueParser { + public static parser(bytes: BytesArray): { t: ValueEnumType, v: CurveValueType } { + let type = bytes.readInt32(); + switch (type) { + case ValueEnumType.single: + return { t: ValueEnumType.single, v: bytes.readFloat32() }; + case ValueEnumType.boolean: + return { t: ValueEnumType.boolean, v: bytes.readBoolean() }; + case ValueEnumType.int: + return { t: ValueEnumType.int, v: bytes.readInt32() }; + case ValueEnumType.int16: + return { t: ValueEnumType.int16, v: bytes.readInt16() }; + case ValueEnumType.int32: + return { t: ValueEnumType.int32, v: bytes.readInt32() }; + case ValueEnumType.float: + return { t: ValueEnumType.float, v: bytes.readFloat32() }; + case ValueEnumType.long: + return { t: ValueEnumType.long, v: bytes.readFloat64() }; + case ValueEnumType.uint: + return { t: ValueEnumType.uint, v: bytes.readUnit32() }; + case ValueEnumType.uint32: + return { t: ValueEnumType.uint32, v: bytes.readUnit32() }; + case ValueEnumType.uint64: + return { t: ValueEnumType.uint64, v: bytes.readUnit32() }; + case ValueEnumType.double: + return { t: ValueEnumType.double, v: bytes.readFloat64() }; + case ValueEnumType.string: + return { t: ValueEnumType.string, v: bytes.readUTF() }; + case ValueEnumType.singleArray: + return { t: ValueEnumType.singleArray, v: bytes.readFloatArray() }; + case ValueEnumType.stringArray: + return { t: ValueEnumType.stringArray, v: bytes.readStringArray() }; + case ValueEnumType.floatArray: + return { t: ValueEnumType.floatArray, v: bytes.readFloatArray() }; + case ValueEnumType.vector2: + return { t: ValueEnumType.vector2, v: bytes.readVector2() }; + case ValueEnumType.vector3: + return { t: ValueEnumType.vector3, v: bytes.readVector3() }; + case ValueEnumType.vector4: + return { t: ValueEnumType.vector4, v: bytes.readVector4() }; + case ValueEnumType.color: + return { t: ValueEnumType.color, v: bytes.readColor() }; + case ValueEnumType.color32: + return { t: ValueEnumType.color32, v: bytes.readColor() }; + case ValueEnumType.animationCurve: + return { t: ValueEnumType.animationCurve, v: null } + case ValueEnumType.quaternion: + return { t: ValueEnumType.quaternion, v: bytes.readQuaternion() }; + case ValueEnumType.matrix4x4: + return { t: ValueEnumType.matrix4x4, v: null }; + case ValueEnumType.mesh: + { + let id = bytes.readUTF(); + let mesh = Engine3D.res.getGeometry(id); + return { t: ValueEnumType.mesh, v: mesh }; + } + case ValueEnumType.texture: + { + let id = bytes.readUTF(); + let texture = Engine3D.res.getTexture(id); + return { t: ValueEnumType.texture, v: texture }; + } + case ValueEnumType.material: + { + let id = bytes.readUTF(); + let mat = Engine3D.res.getMat(id); + return { t: ValueEnumType.material, v: mat }; + } + case ValueEnumType.materials: + { + let str = bytes.readStringArray(); + let mats = []; + for (let i = 0; i < str.length; i++) { + const element = str[i]; + let mat = Engine3D.res.getMat(element); + mats.push(mat); + } + return { t: ValueEnumType.materials, v: mats }; + } + + case ValueEnumType.skeleton: + break; + case ValueEnumType.animClip: + { + let animClipDatas: PropertyAnimationClip[] = []; + let animClipCount = bytes.readInt32(); + for (let i = 0; i < animClipCount; i++) { + let animationClipData = new PropertyAnimationClip(); + animationClipData.formBytes(bytes); + animClipDatas.push(animationClipData); + } + return { t: ValueEnumType.animClip, v: animClipDatas }; + } + case ValueEnumType.vector2Int: + return { t: ValueEnumType.vector2Int, v: bytes.readVector2int() }; + break; + case ValueEnumType.int32List: + return { t: ValueEnumType.int32List, v: bytes.readInt32List() }; + break; + case ValueEnumType.colorList: + let len = bytes.readInt32(); + let list = [] ; + for (let i = 0; i < len ; i++) { + const element = ValueParser.parser(bytes).v as Color; + list.push(element); + } + return { t: ValueEnumType.colorList, v: list }; + break; + case ValueEnumType.color32List: + let len2 = bytes.readInt32(); + let list2 = [] ; + for (let i = 0; i < len2 ; i++) { + const element = ValueParser.parser(bytes).v as Color; + list2.push(element); + } + return { t: ValueEnumType.color32List, v: list2 }; + break; + } + } + +} diff --git a/src/loader/parser/prefab/prefabData/ValueType.ts b/src/loader/parser/prefab/prefabData/ValueType.ts new file mode 100644 index 00000000..d8e85d8f --- /dev/null +++ b/src/loader/parser/prefab/prefabData/ValueType.ts @@ -0,0 +1,37 @@ + + +export enum ValueEnumType { + single, + boolean, + int, + int16, + int32, + float, + long, + uint, + uint32, + uint64, + double, + string, + singleArray, + stringArray, + floatArray, + vector2, + vector3, + vector4, + color, + color32, + animationCurve, + quaternion, + matrix4x4, + mesh, + texture, + material, + materials, + skeleton, + animClip, + vector2Int, + int32List, + colorList, + color32List, +} \ No newline at end of file diff --git a/src/materials/BlendMode.ts b/src/materials/BlendMode.ts index 880fb13e..9806770f 100644 --- a/src/materials/BlendMode.ts +++ b/src/materials/BlendMode.ts @@ -124,9 +124,9 @@ export class BlendFactor { blend.color.operation = 'add'; break; case BlendMode.NORMAL: - blend.color.srcFactor = 'one'; - blend.color.dstFactor = 'one-minus-src-alpha'; - blend.color.operation = 'add'; + blend.color.srcFactor = `src-alpha`; + blend.color.dstFactor = `one-minus-src-alpha`; + blend.color.operation = `add`; break; case BlendMode.SOFT_ADD: blend.color.srcFactor = `one`; diff --git a/src/materials/ColorLitMaterial.ts b/src/materials/ColorLitMaterial.ts index 455edf54..7311568f 100644 --- a/src/materials/ColorLitMaterial.ts +++ b/src/materials/ColorLitMaterial.ts @@ -1,15 +1,14 @@ -import { RenderShader } from '..'; +import { Material, RenderShaderPass, PassType, Shader } from '..'; import { Engine3D } from '../Engine3D'; import { ShaderLib } from '../assets/shader/ShaderLib'; import { ColorLitShader } from '../assets/shader/materials/ColorLitShader'; import { Color } from '../math/Color'; -import { PhysicMaterial } from './PhysicMaterial'; /** * ColorLitMaterial * @group Material */ -export class ColorLitMaterial extends PhysicMaterial { +export class ColorLitMaterial extends Material { static count = 0; /** * @constructor @@ -17,9 +16,13 @@ export class ColorLitMaterial extends PhysicMaterial { constructor() { super(); - ShaderLib.register("ColorLitShader", ColorLitShader.Ori_AllShader); + ShaderLib.register("ColorLitShader", ColorLitShader); + + this.shader = new Shader() + let renderShader = new RenderShaderPass(`ColorLitShader`, `ColorLitShader`); + renderShader.passType = PassType.COLOR; + this.shader.addRenderPass(renderShader); - let renderShader = new RenderShader(`ColorLitShader`, `ColorLitShader`); renderShader.setDefine("USE_BRDF", true); renderShader.setShaderEntry(`VertMain`, `FragMain`) renderShader.setUniformColor(`baseColor`, new Color()); diff --git a/src/materials/GIProbeMaterial.ts b/src/materials/GIProbeMaterial.ts index 7e7cd1ff..54a60274 100644 --- a/src/materials/GIProbeMaterial.ts +++ b/src/materials/GIProbeMaterial.ts @@ -1,9 +1,10 @@ -import { RenderShader } from '..'; +import { PassType, Shader } from '..'; import { GIProbeShader } from '../assets/shader/materials/GIProbeShader'; import { ShaderLib } from '../assets/shader/ShaderLib'; import { Engine3D } from '../Engine3D'; +import { RenderShaderPass } from '../gfx/graphics/webGpu/shader/RenderShaderPass'; import { Vector4 } from '../math/Vector4'; -import { PhysicMaterial } from './PhysicMaterial'; +import { Material } from './Material'; /** * @internal @@ -16,36 +17,34 @@ export enum GIProbeMaterialType { Other = 3, } -export class GIProbeMaterial extends PhysicMaterial { +export class GIProbeMaterial extends Material { static count = 0; constructor(type: GIProbeMaterialType = GIProbeMaterialType.CastGI, index: number = 0) { super(); ShaderLib.register("GIProbeShader", GIProbeShader); - this.defaultPass = new RenderShader('GIProbeShader', 'GIProbeShader'); + let newShader = new Shader(); - this.defaultPass.setDefine('USE_BRDF', true); - this.defaultPass.setShaderEntry(`VertMain`, `FragMain`); - this.defaultPass.setUniformVector4('probeUniform', new Vector4(index, type, 0, 0)); - let shaderState = this.defaultPass.shaderState; + let colorShader = new RenderShaderPass('GIProbeShader', 'GIProbeShader'); + colorShader.passType = PassType.COLOR; + newShader.addRenderPass(colorShader); + + colorShader.setDefine('USE_BRDF', true); + colorShader.setShaderEntry(`VertMain`, `FragMain`); + colorShader.setUniformVector4('probeUniform', new Vector4(index, type, 0, 0)); + let shaderState = colorShader.shaderState; shaderState.acceptShadow = false; shaderState.castShadow = false; shaderState.receiveEnv = false; shaderState.acceptGI = false; shaderState.useLight = false; - let bdrflutTex = Engine3D.res.getTexture(`BRDFLUT`); - this.brdfLUT = bdrflutTex; + newShader.setTexture("baseMap", Engine3D.res.whiteTexture); + newShader.setTexture("normalMap", Engine3D.res.normalTexture); + newShader.setTexture("emissiveMap", Engine3D.res.blackTexture); - this.baseMap = Engine3D.res.whiteTexture; - this.normalMap = Engine3D.res.normalTexture; - // this.aoMap = defaultTexture.whiteTexture; - // this.maskMap = defaultTexture.maskTexture; - // this.maskMap = defaultTexture.grayTexture; - // shader.setDefine(`USE_ARMC`, false); - this.emissiveMap = Engine3D.res.blackTexture; + this.shader = newShader; } - debug() { } } diff --git a/src/materials/GlassMaterial.ts b/src/materials/GlassMaterial.ts index 477b9468..f4388a84 100644 --- a/src/materials/GlassMaterial.ts +++ b/src/materials/GlassMaterial.ts @@ -1,16 +1,17 @@ import { ShaderLib } from '../assets/shader/ShaderLib'; import { Engine3D } from '../Engine3D'; -import { Vector4 } from '../math/Vector4'; - -import { registerMaterial } from './MaterialRegister'; import { GlassShader } from '../assets/shader/materials/GlassShader'; -import { Material, PhysicMaterial, RenderShader } from '..'; +import { Material } from './Material'; +import { Shader } from '../gfx/graphics/webGpu/shader/Shader'; +import { RenderShaderPass } from '../gfx/graphics/webGpu/shader/RenderShaderPass'; +import { PassType } from '../gfx/renderJob/passRenderer/state/RendererType'; + /** * GlassMaterial * an rendering material implemented by simulating glass surfaces * @group Material */ -export class GlassMaterial extends PhysicMaterial { +export class GlassMaterial extends Material { /** * @constructor @@ -18,63 +19,55 @@ export class GlassMaterial extends PhysicMaterial { constructor() { super(); ShaderLib.register("GlassShader", GlassShader); - let colorPass = new RenderShader('GlassShader', 'GlassShader'); - this.defaultPass = colorPass; - colorPass.setDefine("USE_BRDF", true); - colorPass.setShaderEntry(`VertMain`, `FragMain`) + this.shader = new Shader(); - let shaderState = colorPass.shaderState; + let colorShader = new RenderShaderPass('GlassShader', 'GlassShader'); + colorShader.passType = PassType.COLOR; + colorShader.setDefine("USE_BRDF", true); + colorShader.setShaderEntry(`VertMain`, `FragMain`) + + let shaderState = colorShader.shaderState; shaderState.acceptShadow = true; shaderState.castShadow = true; shaderState.receiveEnv = true; shaderState.acceptGI = true; shaderState.useLight = true; - let bdrflutTex = Engine3D.res.getTexture(`BRDFLUT`); - this.brdfLUT = bdrflutTex; - - this.baseMap = Engine3D.res.whiteTexture; - this.normalMap = Engine3D.res.normalTexture; - // this.aoMap = defaultTexture.whiteTexture; - // this.maskMap = defaultTexture.maskTexture; - // this.maskMap = defaultTexture.grayTexture; - // shader.setDefine(`USE_ARMC`, false); - this.emissiveMap = Engine3D.res.blackTexture; - + this.shader.setTexture("baseMap", Engine3D.res.whiteTexture); + this.shader.setTexture("normalMap", Engine3D.res.normalTexture); + this.shader.setTexture("emissiveMap", Engine3D.res.blackTexture); } - clone(): this { - console.log(`clone material ${this.name}`); + // clone(): this { + // console.log(`clone material ${this.name}`); - let ret = new GlassMaterial(); - ret.baseMap = this.baseMap; - ret.normalMap = this.normalMap; - ret.aoMap = this.aoMap; - if (this.maskMap) ret.maskMap = this.maskMap; - ret.emissiveMap = this.emissiveMap; - this.uvTransform_1 && (ret.uvTransform_1 = new Vector4().copyFrom(this.uvTransform_1)); - this.uvTransform_2 && (ret.uvTransform_2 = new Vector4().copyFrom(this.uvTransform_2)); - ret.baseColor = this.baseColor.clone(); - ret.emissiveColor = this.emissiveColor.clone(); - this.materialF0 && (ret.materialF0 = new Vector4().copyFrom(this.materialF0)); - ret.envIntensity = this.envIntensity; - ret.normalScale = this.normalScale; - ret.roughness = this.roughness; - ret.metallic = this.metallic; - ret.ao = this.ao; - ret.roughness_min = this.roughness_min; - ret.roughness_max = this.roughness_max; - ret.metallic_min = this.metallic_min; - ret.metallic_max = this.metallic_max; - ret.emissiveIntensity = this.emissiveIntensity; - ret.alphaCutoff = this.alphaCutoff; - ret.ior = this.ior; - ret.clearcoatFactor = this.clearcoatFactor; - ret.clearcoatRoughnessFactor = this.clearcoatRoughnessFactor; - return ret as this; - } + // let ret = new GlassMaterial(); + // ret.baseMap = this.baseMap; + // ret.normalMap = this.normalMap; + // ret.aoMap = this.aoMap; + // if (this.maskMap) ret.maskMap = this.maskMap; + // ret.emissiveMap = this.emissiveMap; + // this.uvTransform_1 && (ret.uvTransform_1 = new Vector4().copyFrom(this.uvTransform_1)); + // this.uvTransform_2 && (ret.uvTransform_2 = new Vector4().copyFrom(this.uvTransform_2)); + // ret.baseColor = this.baseColor.clone(); + // ret.emissiveColor = this.emissiveColor.clone(); + // this.materialF0 && (ret.materialF0 = new Vector4().copyFrom(this.materialF0)); + // ret.envIntensity = this.envIntensity; + // ret.normalScale = this.normalScale; + // ret.roughness = this.roughness; + // ret.metallic = this.metallic; + // ret.ao = this.ao; + // ret.roughness_min = this.roughness_min; + // ret.roughness_max = this.roughness_max; + // ret.metallic_min = this.metallic_min; + // ret.metallic_max = this.metallic_max; + // ret.emissiveIntensity = this.emissiveIntensity; + // ret.alphaCutoff = this.alphaCutoff; + // ret.ior = this.ior; + // ret.clearcoatFactor = this.clearcoatFactor; + // ret.clearcoatRoughnessFactor = this.clearcoatRoughnessFactor; + // return ret as this; + // } } - -registerMaterial('GlassMaterial', GlassMaterial); \ No newline at end of file diff --git a/src/materials/LambertMaterial.ts b/src/materials/LambertMaterial.ts index a82ed9f3..a0f6c4ab 100644 --- a/src/materials/LambertMaterial.ts +++ b/src/materials/LambertMaterial.ts @@ -1,12 +1,11 @@ -import { LambertShader, Material, RendererType, RenderShader } from '..'; +import { Lambert_shader, Material, PassType, RenderShaderPass, Shader } from '..'; import { ShaderLib } from '../assets/shader/ShaderLib'; import { Engine3D } from '../Engine3D'; import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; import { Color } from '../math/Color'; import { Vector4 } from '../math/Vector4'; -import { registerMaterial } from "./MaterialRegister"; /** * Lambert Mateiral @@ -19,13 +18,14 @@ export class LambertMaterial extends Material { */ constructor() { super(); - let colorPass = new RenderShader(`LambertShader`, `LambertShader`); + let colorPass = new RenderShaderPass(`LambertShader`, `LambertShader`); colorPass.setShaderEntry(`VertMain`, `FragMain`) - + colorPass.passType = PassType.COLOR; colorPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); colorPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); colorPass.setUniformColor(`baseColor`, new Color(1, 1, 1, 1)); colorPass.setUniformFloat(`alphaCutoff`, 0.5); + let shaderState = colorPass.shaderState; shaderState.acceptShadow = false; shaderState.castShadow = false; @@ -33,46 +33,38 @@ export class LambertMaterial extends Material { shaderState.acceptGI = false; shaderState.useLight = false; - // let shaderState = shader.shaderState; - // shaderState.acceptShadow = true; - // shaderState.castShadow = true; - // shaderState.receiveEnv = false; - // shaderState.acceptGI = false; - // shaderState.useLight = true; - - // default value - // this.baseMap = Engine3D.res.whiteTexture; - // this.emissiveMap = Engine3D.res.blackTexture; - this.defaultPass = colorPass; + let newShader = new Shader(); + newShader.addRenderPass(colorPass); + this.shader = newShader; this.baseMap = Engine3D.res.grayTexture; } /** * set base color map texture */ - set baseMap(tex: Texture) { - this.defaultPass.setTexture(`baseMap`, tex); + public set baseMap(tex: Texture) { + this.shader.setTexture(`baseMap`, tex); } /** * get base color map texture */ - get baseMap() { - return this.defaultPass.getTexture(`baseMap`); + public get baseMap() { + return this.shader.getTexture(`baseMap`); } /** * set base color (tint color) */ - set baseColor(color: Color) { - this.defaultPass.setUniformColor(`baseColor`, color); + public set baseColor(color: Color) { + this.shader.setUniformColor(`baseColor`, color); } /** * get base color (tint color) */ - get baseColor() { - return this.defaultPass.uniforms[`baseColor`].color; + public get baseColor() { + return this.shader.getUniformColor("baseColor"); } /** @@ -89,5 +81,4 @@ export class LambertMaterial extends Material { public set shadowMap(texture: Texture) { //not need shadowMap texture } - } \ No newline at end of file diff --git a/src/materials/LitMaterial.ts b/src/materials/LitMaterial.ts index 1e0bc92c..1a15c7be 100644 --- a/src/materials/LitMaterial.ts +++ b/src/materials/LitMaterial.ts @@ -1,69 +1,158 @@ -import { Material } from ".."; import { Engine3D } from "../Engine3D"; -import { RenderShader } from "../gfx/graphics/webGpu/shader/RenderShader"; -import { RendererType } from "../gfx/renderJob/passRenderer/state/RendererType"; +import { Texture } from "../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { StandShader } from "../loader/parser/prefab/mats/shader/StandShader"; +import { Color } from "../math/Color"; +import { Material } from "./Material"; import { PhysicMaterial } from "./PhysicMaterial"; -export class LitMaterial extends PhysicMaterial { +export class LitMaterial extends Material { + constructor() { super(); - let colorPass = new RenderShader('PBRLItShader', 'PBRLItShader'); - this.defaultPass = colorPass; + let shader = new StandShader(); + this.shader = shader; + } - colorPass.setShaderEntry(`VertMain`, `FragMain`) - let shaderState = colorPass.shaderState; - shaderState.acceptShadow = true; - shaderState.castShadow = true; - shaderState.receiveEnv = true; - shaderState.acceptGI = true; - shaderState.useLight = true; + public clone(): Material { + let litMaterial = new LitMaterial(); - let bdrflutTex = Engine3D.res.getTexture(`BRDFLUT`); - this.brdfLUT = bdrflutTex; - colorPass.setDefine('USE_BRDF', true); + let colorPass = litMaterial.shader.getDefaultColorShader(); + let sourceShader = this.shader.getDefaultColorShader(); + colorPass.defineValue = { ...sourceShader.defineValue } + colorPass.setUniform(`shadowBias`, sourceShader.getUniform(`shadowBias`)); + colorPass.setUniform(`transformUV1`, sourceShader.getUniform(`transformUV1`)); + colorPass.setUniform(`transformUV2`, sourceShader.getUniform(`transformUV2`)); + colorPass.setUniform(`baseColor`, sourceShader.getUniform(`baseColor`)); + colorPass.setUniform(`specularColor`, sourceShader.getUniform(`specularColor`)); + colorPass.setUniform(`emissiveColor`, sourceShader.getUniform(`emissiveColor`)); + colorPass.setUniform(`materialF0`, sourceShader.getUniform(`materialF0`)); + colorPass.setUniform(`envIntensity`, sourceShader.getUniform(`envIntensity`)); + colorPass.setUniform(`normalScale`, sourceShader.getUniform(`normalScale`)); + colorPass.setUniform(`roughness`, sourceShader.getUniform(`roughness`)); + colorPass.setUniform(`metallic`, sourceShader.getUniform(`metallic`)); + colorPass.setUniform(`ao`, sourceShader.getUniform(`ao`)); + colorPass.setUniform(`roughness_min`, sourceShader.getUniform(`roughness_min`)); + colorPass.setUniform(`roughness_max`, sourceShader.getUniform(`roughness_max`)); + colorPass.setUniform(`metallic_min`, sourceShader.getUniform(`metallic_min`)); + colorPass.setUniform(`metallic_max`, sourceShader.getUniform(`metallic_max`)); + colorPass.setUniform(`emissiveIntensity`, sourceShader.getUniform(`emissiveIntensity`)); + colorPass.setUniform(`alphaCutoff`, sourceShader.getUniform(`alphaCutoff`)); + colorPass.setUniform(`ior`, sourceShader.getUniform(`ior`)); + colorPass.setUniform(`clearcoatFactor`, sourceShader.getUniform(`clearcoatFactor`)); + colorPass.setUniform(`clearcoatRoughnessFactor`, sourceShader.getUniform(`clearcoatRoughnessFactor`)); + colorPass.setUniform(`clearcoatColor`, sourceShader.getUniform(`clearcoatColor`)); + colorPass.setUniform(`clearcoatWeight`, sourceShader.getUniform(`clearcoatWeight`)); - this.setDefault(); + colorPass.setTexture(`baseMap`, sourceShader.getTexture(`baseMap`)); + colorPass.setTexture(`normalMap`, sourceShader.getTexture(`normalMap`)); + colorPass.setTexture(`emissiveMap`, sourceShader.getTexture(`emissiveMap`)); + colorPass.setTexture(`aoMap`, sourceShader.getTexture(`aoMap`)); + colorPass.setTexture(`maskMap`, sourceShader.getTexture(`maskMap`)); + return litMaterial; + } - this.baseMap = Engine3D.res.whiteTexture; - this.normalMap = Engine3D.res.normalTexture; - this.emissiveMap = Engine3D.res.blackTexture; + public set baseMap(texture: Texture) { + this.shader.setTexture(`baseMap`, texture); + } - this.alphaCutoff = 0.5; + public get baseMap() { + return this.shader.getTexture(`baseMap`); } - public clone(): Material { - let litMaterial = new LitMaterial(); + public set maskMap(texture: Texture) { + this.shader.setTexture(`maskMap`, texture); + } - let colorPass = litMaterial.defaultPass; - colorPass.setUniform(`shadowBias`, this.defaultPass.getUniform(`shadowBias`)); - colorPass.setUniform(`transformUV1`, this.defaultPass.getUniform(`transformUV1`)); - colorPass.setUniform(`transformUV2`, this.defaultPass.getUniform(`transformUV2`)); - colorPass.setUniform(`baseColor`, this.defaultPass.getUniform(`baseColor`)); - colorPass.setUniform(`emissiveColor`, this.defaultPass.getUniform(`emissiveColor`)); - colorPass.setUniform(`materialF0`, this.defaultPass.getUniform(`materialF0`)); - colorPass.setUniform(`envIntensity`, this.defaultPass.getUniform(`envIntensity`)); - colorPass.setUniform(`normalScale`, this.defaultPass.getUniform(`normalScale`)); - colorPass.setUniform(`roughness`, this.defaultPass.getUniform(`roughness`)); - colorPass.setUniform(`metallic`, this.defaultPass.getUniform(`metallic`)); - colorPass.setUniform(`ao`, this.defaultPass.getUniform(`ao`)); - colorPass.setUniform(`roughness_min`, this.defaultPass.getUniform(`roughness_min`)); - colorPass.setUniform(`roughness_max`, this.defaultPass.getUniform(`roughness_max`)); - colorPass.setUniform(`metallic_min`, this.defaultPass.getUniform(`metallic_min`)); - colorPass.setUniform(`metallic_max`, this.defaultPass.getUniform(`metallic_max`)); - colorPass.setUniform(`emissiveIntensity`, this.defaultPass.getUniform(`emissiveIntensity`)); - colorPass.setUniform(`alphaCutoff`, this.defaultPass.getUniform(`alphaCutoff`)); - colorPass.setUniform(`ior`, this.defaultPass.getUniform(`ior`)); - colorPass.setUniform(`clearcoatFactor`, this.defaultPass.getUniform(`clearcoatFactor`)); - colorPass.setUniform(`clearcoatRoughnessFactor`, this.defaultPass.getUniform(`clearcoatRoughnessFactor`)); - colorPass.setUniform(`clearcoatColor`, this.defaultPass.getUniform(`clearcoatColor`)); - colorPass.setUniform(`clearcoatWeight`, this.defaultPass.getUniform(`clearcoatWeight`)); - - colorPass.setTexture(`baseMap`, this.defaultPass.getTexture(`baseMap`)); - colorPass.setTexture(`normalMap`, this.defaultPass.getTexture(`normalMap`)); - colorPass.setTexture(`emissiveMap`, this.defaultPass.getTexture(`emissiveMap`)); - colorPass.setTexture(`aoMap`, this.defaultPass.getTexture(`aoMap`)); - colorPass.setTexture(`maskMap`, this.defaultPass.getTexture(`maskMap`)); - return litMaterial; + public get maskMap() { + return this.shader.getTexture(`maskMap`); + } + + + public set normalMap(texture: Texture) { + this.shader.setTexture(`normalMap`, texture); + } + + public get normalMap() { + return this.shader.getTexture(`normalMap`); + } + + public set emissiveMap(texture: Texture) { + this.shader.setTexture(`emissiveMap`, texture); + } + + public get emissiveMap() { + return this.shader.getTexture(`emissiveMap`); + } + + public set aoMap(texture: Texture) { + this.shader.setTexture(`aoMap`, texture); + } + + public get aoMap() { + return this.shader.getTexture(`aoMap`); + } + + public set alphaCutoff(value: number) { + this.shader.setUniform(`alphaCutoff`, value); + } + + public get alphaCutoff() { + return this.shader.getUniform(`alphaCutoff`); + } + + /** + * set base color (tint color) + */ + public set baseColor(color: Color) { + this.shader.setUniformColor(`baseColor`, color); + } + + /** + * get base color (tint color) + */ + public get baseColor() { + return this.shader.getUniformColor("baseColor"); + } + + public get roughness(): number { + return this.shader.getUniformFloat("roughness"); + } + + public set roughness(value: number) { + this.shader.setUniformFloat("roughness", value); + } + + public get metallic(): number { + return this.shader.getUniformFloat("metallic"); + } + + public set metallic(value: number) { + this.shader.setUniformFloat("metallic", value); + } + + public get emissiveColor(): Color { + return this.shader.getUniformColor("emissiveColor"); + } + + public set emissiveColor(value: Color) { + this.shader.setUniformColor("emissiveColor", value); + } + + public get emissiveIntensity(): number { + return this.shader.getUniformFloat("emissiveIntensity"); + } + + public set emissiveIntensity(value: number) { + this.shader.setUniformFloat("emissiveIntensity", value); + } + + public get ao(): number { + return this.shader.getUniform(`ao`); + } + + public set ao(value: number) { + this.shader.setUniform(`ao`, value); } } \ No newline at end of file diff --git a/src/materials/Material.ts b/src/materials/Material.ts index 07c0e0f0..b88ee5dc 100644 --- a/src/materials/Material.ts +++ b/src/materials/Material.ts @@ -1,109 +1,109 @@ -import { BlendMode, GPUCompareFunction } from ".."; -import { RenderShader } from "../gfx/graphics/webGpu/shader/RenderShader"; -import { RendererType } from "../gfx/renderJob/passRenderer/state/RendererType"; +import { StorageGPUBuffer } from "../gfx/graphics/webGpu/core/buffer/StorageGPUBuffer"; +import { UniformGPUBuffer } from "../gfx/graphics/webGpu/core/buffer/UniformGPUBuffer"; +import { Texture } from "../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { PassType } from "../gfx/renderJob/passRenderer/state/RendererType"; +import { Shader } from "../gfx/graphics/webGpu/shader/Shader"; +import { Color } from "../math/Color"; +import { Vector2 } from "../math/Vector2"; +import { Vector3 } from "../math/Vector3"; +import { Vector4 } from "../math/Vector4"; +import { BlendMode } from "./BlendMode"; export class Material { - /** - * - * name of this material - */ - public name: string; - /** * * Material Unique Identifier */ public instanceID: string; - public enable: boolean = true; + /** + * + * name of this material + */ + public name: string; - private _defaultPass: RenderShader; + public enable: boolean = true; - private _renderPasses: Map; + private _defaultSubShader: RenderShaderPass; - private _depthCompare: GPUCompareFunction = GPUCompareFunction.less; + protected _shader: Shader; constructor() { - this._renderPasses = new Map(); - } - - public get depthCompare(): GPUCompareFunction { - return this._depthCompare; } - public set depthCompare(value: GPUCompareFunction) { - this._depthCompare = value; - this._defaultPass.depthCompare = value; - } - - public get defaultPass(): RenderShader { - return this._defaultPass; + public set shader(shader: Shader) { + this._shader = shader; + this._defaultSubShader = shader.getDefaultShaders()[0]; } - public set defaultPass(value: RenderShader) { - this._defaultPass = value; - this.addPass(RendererType.COLOR, value); + public get shader(): Shader { + return this._shader; } public get doubleSide(): boolean { - return this._defaultPass.doubleSide; + return this._defaultSubShader.doubleSide; } public set doubleSide(value: boolean) { - this._defaultPass.doubleSide = value; + this._defaultSubShader.doubleSide = value; } public get castShadow(): boolean { - let colorPass = this.defaultPass; - return colorPass.shaderState.castShadow; + return this._defaultSubShader.shaderState.castShadow; } public set castShadow(value: boolean) { - let colorPass = this.defaultPass; - colorPass.shaderState.castShadow = value; + this._defaultSubShader.shaderState.castShadow = value; } public get blendMode(): BlendMode { - let colorPass = this.defaultPass; - return colorPass.blendMode; + return this._defaultSubShader.blendMode; } public set blendMode(value: BlendMode) { - let colorPass = this.defaultPass; - colorPass.blendMode = value; + this._defaultSubShader.blendMode = value; + } + + public get depthCompare(): GPUCompareFunction { + return this._defaultSubShader.depthCompare; + } + + public set depthCompare(value: GPUCompareFunction) { + this._defaultSubShader.depthCompare = value; } public get transparent(): boolean { - let colorPass = this.defaultPass; - return colorPass.shaderState.transparent; + return this._defaultSubShader.shaderState.transparent; } public set transparent(value: boolean) { - let colorPass = this.defaultPass; - colorPass.shaderState.transparent = value; + this._defaultSubShader.shaderState.transparent = value; if (value) { - colorPass.renderOrder = 3000; + this._defaultSubShader.renderOrder = 3000; } } public get cullMode(): GPUCullMode { - let colorPass = this.defaultPass; - return colorPass.cullMode; + return this._defaultSubShader.cullMode; } public set cullMode(value: GPUCullMode) { - let colorPass = this.defaultPass; - colorPass.cullMode = value; + this._defaultSubShader.cullMode = value; } - /** - * @param passType - * @returns - */ - public hasPass(passType: RendererType) { - return this._renderPasses.has(passType); + public get depthWriteEnabled(): boolean { + return this._defaultSubShader.depthWriteEnabled; + } + + public set depthWriteEnabled(value: boolean) { + this._defaultSubShader.depthWriteEnabled = value; + } + + public set useBillboard(value: boolean) { + this._defaultSubShader.setDefine("USE_BILLBOARD", value); } /** @@ -111,44 +111,16 @@ export class Material { * @param passType * @returns */ - public getPass(passType: RendererType) { - return this._renderPasses.get(passType); + public getPass(passType: PassType) { + return this._shader.getSubShaders(passType); } /** * get all color render pass * @returns */ - public getAllPass(): RenderShader[] { - return this._renderPasses.get(RendererType.COLOR); - } - - public addPass(passType: RendererType, pass: RenderShader, index: number = -1): RenderShader[] { - if (!this._renderPasses.has(passType)) this._renderPasses.set(passType, []); - - let passList = this._renderPasses.get(passType); - if (passType == RendererType.COLOR && passList.length == 0) { - this._defaultPass = pass; - } - - let has = passList.indexOf(pass) != -1; - if (!has) { - if (index == -1) { - passList.push(pass); - } else { - passList.splice(index, -1, pass); - } - } - return passList; - } - - public removePass(passType: RendererType, index: number) { - if (this._renderPasses.has(passType)) { - let list = this._renderPasses.get(passType); - if (index < list.length) { - list.splice(index, 1); - } - } + public getAllPass(): RenderShaderPass[] { + return this._shader.getSubShaders(PassType.COLOR); } /** @@ -156,20 +128,92 @@ export class Material { * @returns Material */ public clone() { - return null; + let newMat = new Material(); + newMat.shader = this.shader.clone(); + return newMat; } + destroy(force: boolean) { - for (const iterator of this._renderPasses) { - let passList = iterator[1]; - for (const pass of passList) { - for (const textureName in pass.textures) { - if (textureName.indexOf("defaultOri") == -1) { - let texture = pass.textures[textureName]; - texture.destroy(force); - } - } - } - } + this._shader.destroy(); + this._shader = null; + } + + + public setDefine(define: string, value: boolean) { + this.shader.setDefine(define, value); + } + + public setTexture(propertyName: string, texture: Texture) { + this._shader.setTexture(propertyName, texture); + } + + public setStorageBuffer(propertyName: string, buffer: StorageGPUBuffer) { + this._shader.setStorageBuffer(propertyName, buffer); + } + + public setUniformBuffer(propertyName: string, buffer: UniformGPUBuffer) { + this._shader.setStorageBuffer(propertyName, buffer); + } + + + public setUniformFloat(propertyName: string, value: number) { + this._shader.setUniformFloat(propertyName, value); + } + + public setUniformVector2(propertyName: string, value: Vector2) { + this._shader.setUniformVector2(propertyName, value); + } + + public setUniformVector3(propertyName: string, value: Vector3) { + this._shader.setUniformVector3(propertyName, value); + } + + public setUniformVector4(propertyName: string, value: Vector4) { + this._shader.setUniformVector4(propertyName, value); + } + + public setUniformColor(propertyName: string, value: Color) { + this._shader.setUniformColor(propertyName, value); + } + + public getUniformFloat(str: string) { + return this._shader.getUniform(str).data; + } + + public getUniformV2(str: string): Vector2 { + return this._shader.getUniformVector2(str); + } + + public getUniformV3(str: string): Vector3 { + return this._shader.getUniformVector3(str); + } + + public getUniformV4(str: string): Vector4 { + return this._shader.getUniformVector4(str); + } + + public getUniformColor(str: string) { + return this._shader.getUniformColor(str); + } + + public getTexture(str: string) { + return this._shader.getTexture(str); + } + + public getStorageBuffer(str: string) { + return this._shader.getStorageBuffer(str); + } + + public getStructStorageBuffer(str: string) { + return this._shader.getStructStorageBuffer(str); + } + + public getUniformBuffer(str: string) { + return this._shader.getUniformBuffer(str); + } + + public applyUniform() { + this._shader.applyUniform(); } } \ No newline at end of file diff --git a/src/materials/PhysicMaterial.ts b/src/materials/PhysicMaterial.ts index 06c59757..856a825d 100644 --- a/src/materials/PhysicMaterial.ts +++ b/src/materials/PhysicMaterial.ts @@ -1,7 +1,5 @@ import { Engine3D } from '../Engine3D'; import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; -import { RenderShader } from '../gfx/graphics/webGpu/shader/RenderShader'; -import { RendererType } from '../gfx/renderJob/passRenderer/state/RendererType'; import { Color } from '../math/Color'; import { Vector4 } from '../math/Vector4'; import { Material } from './Material'; @@ -14,19 +12,36 @@ export class PhysicMaterial extends Material { constructor() { super(); + this.init(); } + private init() { + let bdrflutTex = Engine3D.res.getTexture(`BRDFLUT`); + this.brdfLUT = bdrflutTex; + + this.setDefault(); + this.baseMap = Engine3D.res.whiteTexture; + this.normalMap = Engine3D.res.normalTexture; + this.emissiveMap = Engine3D.res.blackTexture; + this.alphaCutoff = 0.5; + } + + // public get shader(): RenderShader { + // return this._shader; + // } + /** * Set the render shader default value */ public setDefault() { - let colorPass = this.defaultPass; + let colorPass = this.shader.getDefaultColorShader(); colorPass.setUniformFloat(`shadowBias`, 0.00035); colorPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); colorPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); colorPass.setUniformColor(`baseColor`, new Color()); colorPass.setUniformColor(`emissiveColor`, new Color(1, 1, 1)); colorPass.setUniformVector4(`materialF0`, new Vector4(0.04, 0.04, 0.04, 1)); + colorPass.setUniformColor(`specularColor`, new Color(0.04, 0.04, 0.04)); colorPass.setUniformFloat(`envIntensity`, 1); colorPass.setUniformFloat(`normalScale`, 1); colorPass.setUniformFloat(`roughness`, 1.0); @@ -47,222 +62,236 @@ export class PhysicMaterial extends Material { public get baseMap(): Texture { - return this.defaultPass.getTexture(`baseMap`); + return this.shader.getDefaultColorShader().getTexture(`baseMap`); } public set baseMap(value: Texture) { - this.defaultPass.setTexture(`baseMap`, value); + this.shader.getDefaultColorShader().setTexture(`baseMap`, value); } public get baseColor(): Color { - return this.defaultPass.getUniform(`baseColor`); + return this.shader.getDefaultColorShader().getUniform(`baseColor`); } public set baseColor(value: Color) { - this.defaultPass.setUniformColor(`baseColor`, value); + this.shader.getDefaultColorShader().setUniformColor(`baseColor`, value); } public get normalMap(): Texture { - return this.defaultPass.getTexture(`normalMap`); + return this.shader.getDefaultColorShader().getTexture(`normalMap`); } public set normalMap(value: Texture) { - this.defaultPass.setTexture(`normalMap`, value); + this.shader.getDefaultColorShader().setTexture(`normalMap`, value); } public get doubleSide(): boolean { - return this.defaultPass.doubleSide; + return this.shader.getDefaultColorShader().doubleSide; } public set doubleSide(value: boolean) { - this.defaultPass.doubleSide = value; + this.shader.getDefaultColorShader().doubleSide = value; } public get alphaCutoff(): any { - return this.defaultPass.shaderState.alphaCutoff; + return this.shader.getDefaultColorShader().shaderState.alphaCutoff; } public set alphaCutoff(value: any) { - this.defaultPass.setDefine("USE_ALPHACUT", true); - this.defaultPass.shaderState.alphaCutoff = value; - this.defaultPass.setUniform(`alphaCutoff`, value); + this.shader.getDefaultColorShader().setDefine("USE_ALPHACUT", true); + this.shader.getDefaultColorShader().shaderState.alphaCutoff = value; + this.shader.getDefaultColorShader().setUniform(`alphaCutoff`, value); } public get emissiveColor(): Color { - return this.defaultPass.getUniform(`emissiveColor`); + return this.shader.getDefaultColorShader().getUniform(`emissiveColor`); } public set emissiveColor(value: Color) { - this.defaultPass.setUniform(`emissiveColor`, value); + this.shader.getDefaultColorShader().setUniform(`emissiveColor`, value); } public get emissiveIntensity(): number { - return this.defaultPass.getUniform(`emissiveIntensity`); + return this.shader.getDefaultColorShader().getUniform(`emissiveIntensity`); } public set emissiveIntensity(value: number) { - this.defaultPass.setUniform(`emissiveIntensity`, value); + this.shader.getDefaultColorShader().setUniform(`emissiveIntensity`, value); } /** * get transformUV1 */ public get uvTransform_1(): Vector4 { - return this.defaultPass.uniforms[`transformUV1`].vector4; + return this.shader.getDefaultColorShader().uniforms[`transformUV1`].vector4; } /** * set transformUV1 */ public set uvTransform_1(value: Vector4) { - // this.defaultPass.uniforms[`transformUV1`].v4 = value; - this.defaultPass.setUniformVector4(`transformUV1`, value); + // this.shader.getDefaultColorShader().uniforms[`transformUV1`].v4 = value; + this.shader.getDefaultColorShader().setUniform(`transformUV1`, value); } /** * get transformUV2 */ public get uvTransform_2(): Vector4 { - return this.defaultPass.uniforms[`transformUV2`].vector4; + return this.shader.getDefaultColorShader().uniforms[`transformUV2`].vector4; } /** * set transformUV2 */ public set uvTransform_2(value: Vector4) { - // this.defaultPass.uniforms[`transformUV2`].v4 = value; - this.defaultPass.setUniformVector4(`transformUV2`, value); + // this.shader.getDefaultColorShader().uniforms[`transformUV2`].v4 = value; + this.shader.getDefaultColorShader().setUniform(`transformUV2`, value); } public get depthWriteEnabled(): boolean { - return this.defaultPass.shaderState.depthWriteEnabled; + return this.shader.getDefaultColorShader().shaderState.depthWriteEnabled; } public set depthWriteEnabled(value: boolean) { - this.defaultPass.shaderState.depthWriteEnabled = value; + this.shader.getDefaultColorShader().shaderState.depthWriteEnabled = value; } /** * get reflectivity */ public get materialF0(): Vector4 { - return this.defaultPass.uniforms[`materialF0`].vector4; + return this.shader.getDefaultColorShader().uniforms[`materialF0`].vector4; } /** * set reflectivity */ public set materialF0(value: Vector4) { - this.defaultPass.setUniformVector4(`materialF0`, value); + this.shader.getDefaultColorShader().setUniform(`materialF0`, value); + } + + /** + * get specularColor + */ + public get specularColor(): Color { + return this.shader.getDefaultColorShader().uniforms[`specularColor`].color; + } + + /**specularColor + * set reflectivity + */ + public set specularColor(value: Color) { + this.shader.getDefaultColorShader().setUniform(`specularColor`, value); } /** * get roughness */ public get roughness(): number { - return this.defaultPass.uniforms[`roughness`].value; + return this.shader.getDefaultColorShader().uniforms[`roughness`].value; } /** * set roughness */ public set roughness(value: number) { - this.defaultPass.setUniformFloat(`roughness`, value); + this.shader.getDefaultColorShader().setUniform(`roughness`, value); } /** * get metallic */ public get metallic(): number { - return this.defaultPass.uniforms[`metallic`].value; + return this.shader.getDefaultColorShader().uniforms[`metallic`].value; } /** * set metallic */ public set metallic(value: number) { - this.defaultPass.setUniformFloat(`metallic`, value); + this.shader.getDefaultColorShader().setUniform(`metallic`, value); } /** * get Ambient Occlussion, dealing with the effect of ambient light on object occlusion */ public get ao(): number { - return this.defaultPass.uniforms[`ao`].value; + return this.shader.getDefaultColorShader().uniforms[`ao`].value; } /** * set Ambient Occlussion, dealing with the effect of ambient light on object occlusion */ public set ao(value: number) { - this.defaultPass.setUniformFloat(`ao`, value); + this.shader.getDefaultColorShader().setUniform(`ao`, value); } /** * get min metallic */ public get metallic_min(): number { - return this.defaultPass.uniforms[`metallic_min`].value; + return this.shader.getDefaultColorShader().uniforms[`metallic_min`].value; } /** * set min metallic */ public set metallic_min(value: number) { - this.defaultPass.setUniformFloat(`metallic_min`, value); + this.shader.getDefaultColorShader().setUniform(`metallic_min`, value); } /** * get max metallic */ public get metallic_max(): number { - return this.defaultPass.uniforms[`metallic_max`].value; + return this.shader.getDefaultColorShader().uniforms[`metallic_max`].value; } /** * set max metallic */ public set metallic_max(value: number) { - this.defaultPass.setUniformFloat(`metallic_max`, value); + this.shader.getDefaultColorShader().setUniform(`metallic_max`, value); } /** * get min roughness */ public get roughness_min(): number { - return this.defaultPass.uniforms[`roughness_min`].value; + return this.shader.getDefaultColorShader().uniforms[`roughness_min`].value; } /** * set min roughness */ public set roughness_min(value: number) { - this.defaultPass.setUniformFloat(`roughness_min`, value); + this.shader.getDefaultColorShader().setUniform(`roughness_min`, value); } /** * get max roughness */ public get roughness_max(): number { - return this.defaultPass.uniforms[`roughness_max`].value; + return this.shader.getDefaultColorShader().uniforms[`roughness_max`].value; } /** * set max roughness */ public set roughness_max(value: number) { - this.defaultPass.setUniformFloat(`roughness_max`, value); + this.shader.getDefaultColorShader().setUniform(`roughness_max`, value); } /** * Get the influence of Normal mapping on materials */ public get normalScale(): number { - return this.defaultPass.uniforms[`normalScale`].value; + return this.shader.getDefaultColorShader().uniforms[`normalScale`].value; } /** * Set the influence of Normal mapping on materials */ public set normalScale(value: number) { - this.defaultPass.setUniformFloat(`normalScale`, value); + this.shader.getDefaultColorShader().setUniform(`normalScale`, value); } /** @@ -273,7 +302,7 @@ export class PhysicMaterial extends Material { * A_chanel -> C */ public get maskMap(): Texture { - return this.defaultPass.textures[`maskMap`]; + return this.shader.getDefaultColorShader().textures[`maskMap`]; } /** @@ -285,9 +314,11 @@ export class PhysicMaterial extends Material { */ public set maskMap(value: Texture) { // USE_MR - // USE_ARMC - this.defaultPass.setDefine(`USE_MR`, true); - this.defaultPass.setTexture(`maskMap`, value); + // USE_ORMC + // USE_RMOC + // USE_CRMC + this.shader.getDefaultColorShader().setDefine(`USE_MR`, true); + this.shader.getDefaultColorShader().setTexture(`maskMap`, value); } /** @@ -295,9 +326,9 @@ export class PhysicMaterial extends Material { */ public set aoMap(value: Texture) { if (!value) return; - this.defaultPass.setTexture(`aoMap`, value); + this.shader.getDefaultColorShader().setTexture(`aoMap`, value); if (value != Engine3D.res.whiteTexture) { - this.defaultPass.setDefine(`USE_AOTEX`, true); + this.shader.getDefaultColorShader().setDefine(`USE_AOTEX`, true); } } @@ -305,7 +336,7 @@ export class PhysicMaterial extends Material { * get Ambient Occlussion Map, dealing with the effect of ambient light on object occlusion */ public get aoMap(): Texture { - return this.defaultPass.textures[`aoMap`]; + return this.shader.getDefaultColorShader().textures[`aoMap`]; } /** @@ -315,86 +346,86 @@ export class PhysicMaterial extends Material { if (!value) return; console.log("USE_CLEARCOAT_ROUGHNESS"); - this.defaultPass.setTexture(`clearCoatRoughnessMap`, value); - this.defaultPass.setDefine(`USE_CLEARCOAT_ROUGHNESS`, true); + this.shader.getDefaultColorShader().setTexture(`clearCoatRoughnessMap`, value); + this.shader.getDefaultColorShader().setDefine(`USE_CLEARCOAT_ROUGHNESS`, true); } /** * get clearCoatRoughnessMap */ public get clearCoatRoughnessMap(): Texture { - return this.defaultPass.textures[`clearCoatRoughnessMap`]; + return this.shader.getDefaultColorShader().textures[`clearCoatRoughnessMap`]; } /** * get brdf query map */ public get brdfLUT(): Texture { - return this.defaultPass.textures[`brdfLUT`]; + return this.shader.getDefaultColorShader().textures[`brdfLUT`]; } /** * set brdf query map */ public set brdfLUT(value: Texture) { - this.defaultPass.setTexture(`brdfLUT`, value); - this.defaultPass.setTexture(`brdflutMap`, value); + this.shader.getDefaultColorShader().setTexture(`brdfLUT`, value); + this.shader.getDefaultColorShader().setTexture(`brdflutMap`, value); } /** * get emissive map */ public get emissiveMap(): Texture { - return this.defaultPass.textures[`emissiveMap`]; + return this.shader.getDefaultColorShader().textures[`emissiveMap`]; } /** * set emissive map */ public set emissiveMap(value: Texture) { - this.defaultPass.setTexture(`emissiveMap`, value); + this.shader.getDefaultColorShader().setTexture(`emissiveMap`, value); } /** * set intensity of environment light or color of sampled by texture */ public set envIntensity(value: number) { - this.defaultPass.setUniformFloat(`envIntensity`, value); + this.shader.getDefaultColorShader().setUniformFloat(`envIntensity`, value); } /** * get intensity of environment light or color of sampled by texture */ public get envIntensity() { - return this.defaultPass.uniforms[`envIntensity`].value; + return this.shader.getDefaultColorShader().uniforms[`envIntensity`].value; } /** * set factor of refractive */ public set ior(value: number) { - this.defaultPass.setUniformFloat(`ior`, value); + this.shader.getDefaultColorShader().setUniformFloat(`ior`, value); } /** * get factor of refractive */ public get ior(): number { - return this.defaultPass.uniforms[`ior`].value; + return this.shader.getDefaultColorShader().uniforms[`ior`].value; } /** * valid USE_CLEARCOAT define in shader */ public useCleanCoat() { - this.defaultPass.setDefine("USE_CLEARCOAT", true); + this.shader.getDefaultColorShader().setDefine("USE_CLEARCOAT", true); } /** * Set the factor of the clearcoat */ public set clearcoatFactor(value: number) { - this.defaultPass.setUniformFloat(`clearcoatFactor`, value); + this.shader.getDefaultColorShader().setUniformFloat(`clearcoatFactor`, value); this.useCleanCoat(); } @@ -402,14 +433,14 @@ export class PhysicMaterial extends Material { * get the factor of the clearcoat */ public get clearcoatFactor(): number { - return this.defaultPass.uniforms[`clearcoatFactor`].value; + return this.shader.getDefaultColorShader().uniforms[`clearcoatFactor`].value; } /** * set the factor of the clearcoat Roughness */ public set clearcoatRoughnessFactor(value: number) { - this.defaultPass.setUniformFloat(`clearcoatRoughnessFactor`, value); + this.shader.getDefaultColorShader().setUniformFloat(`clearcoatRoughnessFactor`, value); this.useCleanCoat(); } @@ -417,14 +448,14 @@ export class PhysicMaterial extends Material { * get the factor of the clearcoat Roughness */ public get clearcoatRoughnessFactor(): number { - return this.defaultPass.uniforms[`clearcoatRoughnessFactor`].value; + return this.shader.getDefaultColorShader().uniforms[`clearcoatRoughnessFactor`].value; } /** * set the weight of the clearcoat */ public set clearcoatWeight(value: number) { - this.defaultPass.setUniformFloat(`clearcoatWeight`, value); + this.shader.getDefaultColorShader().setUniformFloat(`clearcoatWeight`, value); this.useCleanCoat(); } @@ -432,14 +463,14 @@ export class PhysicMaterial extends Material { * get the weight of the clearcoat */ public get clearcoatWeight(): number { - return this.defaultPass.uniforms[`clearcoatWeight`].value; + return this.shader.getDefaultColorShader().uniforms[`clearcoatWeight`].value; } /** * get the color of the clearcoat */ public set clearcoatColor(value: Color) { - this.defaultPass.setUniformColor(`clearcoatColor`, value); + this.shader.getDefaultColorShader().setUniformColor(`clearcoatColor`, value); this.useCleanCoat(); } @@ -447,6 +478,6 @@ export class PhysicMaterial extends Material { * set the color of the clearcoat */ public get clearcoatColor(): Color { - return this.defaultPass.uniforms[`clearcoatColor`].color; + return this.shader.getDefaultColorShader().uniforms[`clearcoatColor`].color; } } diff --git a/src/materials/PointMaterial.ts b/src/materials/PointMaterial.ts deleted file mode 100644 index 3cc1a8ed..00000000 --- a/src/materials/PointMaterial.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Material, RenderShader } from '..'; -import { Engine3D } from '../Engine3D'; -import { ShaderLib } from '../assets/shader/ShaderLib'; -import { PointShadowDebug } from '../assets/shader/materials/PointShadowDebug'; -import { UnLit } from '../assets/shader/materials/UnLit'; -import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; -import { Color } from '../math/Color'; -import { Vector4 } from '../math/Vector4'; -import { registerMaterial } from "./MaterialRegister"; - -/** - * PointMaterial - * @group Material - */ -export class PointMaterial extends Material { - /** - * @constructor - */ - constructor() { - super(); - ShaderLib.register("UnLitShader", UnLit); - ShaderLib.register("PointShadowDebug", PointShadowDebug); - - let colorPass = new RenderShader(`UnLitShader`, `PointShadowDebug`); - this.defaultPass = colorPass; - colorPass.setShaderEntry(`VertMain`, `FragMain`) - - colorPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); - colorPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); - colorPass.setUniformColor(`baseColor`, new Color()); - colorPass.setUniformFloat(`alphaCutoff`, 0.5); - let shaderState = colorPass.shaderState; - shaderState.acceptShadow = false; - shaderState.receiveEnv = false; - shaderState.acceptGI = false; - shaderState.useLight = false; - - // default value - this.baseMap = Engine3D.res.whiteTexture; - } - - /** - * set environment texture, usually referring to cubemap - */ - public set baseMap(texture: Texture) { - //not need env texture - this.defaultPass.setTexture(`baseMap`, texture); - } - - /** - * set environment texture, usually referring to cubemap - */ - public set envMap(texture: Texture) { - //not need env texture - } - - /** - * set shadow map - */ - public set shadowMap(texture: Texture) { - //not need shadowMap texture - } - - debug() { - } -} \ No newline at end of file diff --git a/src/materials/SkyMaterial.ts b/src/materials/SkyMaterial.ts index 66cec265..0bc7c7d5 100644 --- a/src/materials/SkyMaterial.ts +++ b/src/materials/SkyMaterial.ts @@ -1,9 +1,7 @@ -import { ShaderUtil } from ".."; import { Engine3D } from "../Engine3D"; -import { GPUCompareFunction, GPUCullMode } from "../gfx/graphics/webGpu/WebGPUConst"; import { Texture } from "../gfx/graphics/webGpu/core/texture/Texture"; -import { RenderShader } from "../gfx/graphics/webGpu/shader/RenderShader"; -import { RendererType } from "../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../gfx/renderJob/passRenderer/state/RendererType"; +import { SkyShader } from "../loader/parser/prefab/mats/shader/SkyShader"; import { Vector3 } from "../math/Vector3"; import { Material } from "./Material"; @@ -16,28 +14,21 @@ export class SkyMaterial extends Material { constructor() { super(); - let colorPass = new RenderShader('sky_vs_frag_wgsl', 'sky_fs_frag_wgsl'); - this.defaultPass = colorPass; - colorPass.setUniformVector3(`eyesPos`, new Vector3()); - colorPass.setUniformFloat(`exposure`, 1.0); - colorPass.setUniformFloat(`roughness`, 0.0); - - let shaderState = colorPass.shaderState; - shaderState.frontFace = `cw`; - shaderState.cullMode = GPUCullMode.back; - shaderState.depthWriteEnabled = false; - shaderState.depthCompare = GPUCompareFunction.less; - + this.shader = new SkyShader(); + this.shader.setUniformVector3(`eyesPos`, new Vector3()); + this.shader.setUniformFloat(`exposure`, 1.0); + this.shader.setUniformFloat(`roughness`, 0.5); } /** * Set base map(main map) */ public set baseMap(texture: Texture) { - this.defaultPass.setTexture(`baseMap`, texture); + this.setTexture(`baseMap`, texture); const key = 'IS_HDR_SKY'; - if (this.defaultPass.defineValue[key] != texture?.isHDRTexture) { - this.defaultPass.setDefine(key, texture?.isHDRTexture ? true : false); + let defaultShader = this._shader.getDefaultShaders()[0]; + if (defaultShader.defineValue[key] != texture?.isHDRTexture) { + this._shader.setDefine(key, texture?.isHDRTexture ? true : false); } } @@ -45,7 +36,8 @@ export class SkyMaterial extends Material { * Get base map(main map) // */ public get baseMap(): Texture { - return this.defaultPass.getTexture(`baseMap`); + let defaultShader = this._shader.getDefaultColorShader(); + return defaultShader.getTexture(`baseMap`); } public set envMap(texture: Texture) { @@ -64,9 +56,11 @@ export class SkyMaterial extends Material { } public get roughness() { - return this.defaultPass.uniforms[`roughness`].value; + let defaultShader = this._shader.getDefaultColorShader(); + return defaultShader.uniforms[`roughness`].value; } public set roughness(value: number) { - if (`roughness` in this.defaultPass.uniforms) this.defaultPass.uniforms[`roughness`].value = value; + let defaultShader = this._shader.getDefaultColorShader(); + if (`roughness` in defaultShader.uniforms) defaultShader.uniforms[`roughness`].value = value; } } diff --git a/src/materials/UnLitMaterial.ts b/src/materials/UnLitMaterial.ts index eba5212c..ac508c98 100644 --- a/src/materials/UnLitMaterial.ts +++ b/src/materials/UnLitMaterial.ts @@ -1,10 +1,11 @@ import { Engine3D } from '../Engine3D'; import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; -import { RenderShader } from '../gfx/graphics/webGpu/shader/RenderShader'; +import { RenderShaderPass } from '../gfx/graphics/webGpu/shader/RenderShaderPass'; import { Color } from '../math/Color'; import { Vector4 } from '../math/Vector4'; import { Material } from './Material'; -import { RendererType } from '../gfx/renderJob/passRenderer/state/RendererType'; +import { PassType } from '../gfx/renderJob/passRenderer/state/RendererType'; +import { Shader, UnLitShader } from '..'; /** * Unlit Mateiral @@ -17,55 +18,31 @@ export class UnLitMaterial extends Material { */ constructor() { super(); - let colorPass = new RenderShader(`UnLit`, `UnLit`); - this.defaultPass = colorPass; - colorPass.setShaderEntry(`VertMain`, `FragMain`) - - colorPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); - colorPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); - colorPass.setUniformColor(`baseColor`, new Color(1, 1, 1, 1)); - colorPass.setUniformFloat(`alphaCutoff`, 0.5); - let shaderState = colorPass.shaderState; - shaderState.acceptShadow = false; - shaderState.castShadow = false; - shaderState.receiveEnv = false; - shaderState.acceptGI = false; - shaderState.useLight = false; - - // let shaderState = shader.shaderState; - // shaderState.acceptShadow = true; - // shaderState.castShadow = true; - // shaderState.receiveEnv = false; - // shaderState.acceptGI = false; - // shaderState.useLight = true; - + this.shader = new UnLitShader(); // default value - // this.emissiveMap = Engine3D.res.blackTexture; - this.defaultPass = colorPass; - // this.baseMap = Engine3D.res.grayTexture; this.baseMap = Engine3D.res.whiteTexture; } public set baseMap(texture: Texture) { - this.defaultPass.setTexture(`baseMap`, texture); + this.shader.setTexture(`baseMap`, texture); } public get baseMap() { - return this.defaultPass.getTexture(`baseMap`); + return this.shader.getTexture(`baseMap`); } /** * set base color (tint color) */ public set baseColor(color: Color) { - this.defaultPass.setUniformColor(`baseColor`, color); + this.shader.setUniformColor(`baseColor`, color); } /** * get base color (tint color) */ public get baseColor() { - return this.defaultPass.uniforms[`baseColor`].color; + return this.shader.getUniformColor("baseColor"); } /** diff --git a/src/materials/UnLitTexArrayMaterial.ts b/src/materials/UnLitTexArrayMaterial.ts new file mode 100644 index 00000000..889d4b6a --- /dev/null +++ b/src/materials/UnLitTexArrayMaterial.ts @@ -0,0 +1,61 @@ +import { Engine3D } from '../Engine3D'; +import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; +import { RenderShaderPass } from '../gfx/graphics/webGpu/shader/RenderShaderPass'; +import { UnLitTexArrayShader } from '../loader/parser/prefab/mats/shader/UnLitTexArrayShader'; +import { Color } from '../math/Color'; +import { Vector4 } from '../math/Vector4'; +import { Material } from './Material'; + +/** + * Unlit Mateiral + * A non glossy surface material without specular highlights. + * @group Material + */ +export class UnLitTexArrayMaterial extends Material { + /** + * @constructor + */ + constructor() { + super(); + this.shader = new UnLitTexArrayShader(); + // default value + this.baseMap = Engine3D.res.whiteTexture; + } + + public set baseMap(texture: Texture) { + this.shader.setTexture(`baseMap`, texture); + } + + public get baseMap() { + return this.shader.getTexture(`baseMap`); + } + + /** + * set base color (tint color) + */ + public set baseColor(color: Color) { + this.shader.setUniformColor(`baseColor`, color); + } + + /** + * get base color (tint color) + */ + public get baseColor() { + return this.shader.getUniformColor("baseColor"); + } + + // /** + // * set environment texture, usually referring to cubemap + // */ + // public set envMap(texture: Texture) { + // //not need env texture + // } + + /** + * @internal + * set shadow map + */ + public set shadowMap(texture: Texture) { + //not need shadowMap texture + } +} diff --git a/src/materials/multiPass/CastPointShadowMaterialPass.ts b/src/materials/multiPass/CastPointShadowMaterialPass.ts index 49d7eb1d..e7b5903b 100644 --- a/src/materials/multiPass/CastPointShadowMaterialPass.ts +++ b/src/materials/multiPass/CastPointShadowMaterialPass.ts @@ -1,4 +1,5 @@ -import { RenderShader } from "../../gfx/graphics/webGpu/shader/RenderShader"; +import { RenderShaderPass } from "../../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { PassType } from "../../gfx/renderJob/passRenderer/state/RendererType"; import { Vector3 } from "../../math/Vector3"; /** @@ -6,9 +7,10 @@ import { Vector3 } from "../../math/Vector3"; * CastPointShadowMaterialPass * @group Material */ -export class CastPointShadowMaterialPass extends RenderShader { +export class CastPointShadowMaterialPass extends RenderShaderPass { constructor() { super(`castPointShadowMap_vert`, `shadowCastMap_frag`); + this.passType = PassType.POINT_SHADOW; this.setShaderEntry("main", "main"); this.setUniformFloat("cameraFar", 5000); this.setUniformVector3("lightWorldPos", Vector3.ZERO); diff --git a/src/materials/multiPass/CastShadowMaterialPass.ts b/src/materials/multiPass/CastShadowMaterialPass.ts index 691bb0f3..97b3047d 100644 --- a/src/materials/multiPass/CastShadowMaterialPass.ts +++ b/src/materials/multiPass/CastShadowMaterialPass.ts @@ -1,4 +1,5 @@ -import { RenderShader, Texture } from '../..'; +import { RenderShaderPass } from '../../gfx/graphics/webGpu/shader/RenderShaderPass'; +import { PassType } from '../../gfx/renderJob/passRenderer/state/RendererType'; import { Vector3 } from '../../math/Vector3'; /** @@ -6,9 +7,10 @@ import { Vector3 } from '../../math/Vector3'; * CastShadowMaterialPass * @group Material */ -export class CastShadowMaterialPass extends RenderShader { +export class CastShadowMaterialPass extends RenderShaderPass { constructor() { super(`shadowCastMap_vert`, `directionShadowCastMap_frag`); + this.passType = PassType.SHADOW; this.setShaderEntry("main"); this.setUniformFloat("cameraFar", 5000); this.setUniformVector3("lightWorldPos", Vector3.ZERO); @@ -20,9 +22,4 @@ export class CastShadowMaterialPass extends RenderShader { this.setDefine(`USE_ALPHACUT`, true); // this.alphaCutoff = 0.5 ; } - - public setTexture(name: string, texture: Texture) { - // texture.visibility = GPUShaderStage.COMPUTE | GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT; - super.setTexture(name, texture); - } } diff --git a/src/materials/multiPass/DepthMaterialPass.ts b/src/materials/multiPass/DepthMaterialPass.ts index d9ada6a3..d1d27cbb 100644 --- a/src/materials/multiPass/DepthMaterialPass.ts +++ b/src/materials/multiPass/DepthMaterialPass.ts @@ -1,4 +1,4 @@ -import { RenderShader } from '../..'; +import { RenderShaderPass, PassType } from '../..'; /** @@ -6,9 +6,10 @@ import { RenderShader } from '../..'; * DepthMaterialPass * @group Material */ -export class DepthMaterialPass extends RenderShader { +export class DepthMaterialPass extends RenderShaderPass { constructor() { super(`ZPass_shader_vs`, `ZPass_shader_vs`); + this.passType = PassType.DEPTH; this.setShaderEntry("main"); this.useRz = false; let shaderState = this.shaderState; diff --git a/src/materials/multiPass/GBufferPass.ts b/src/materials/multiPass/GBufferPass.ts index d232224f..8765f466 100644 --- a/src/materials/multiPass/GBufferPass.ts +++ b/src/materials/multiPass/GBufferPass.ts @@ -1,21 +1,21 @@ import { Color } from '../../math/Color'; import { BlendMode } from '../BlendMode'; import { Engine3D } from '../../Engine3D'; -import { RenderShader } from '../../gfx/graphics/webGpu/shader/RenderShader'; +import { RenderShaderPass } from '../../gfx/graphics/webGpu/shader/RenderShaderPass'; +import { PassType } from '../..'; /** * @internal * GBufferPass * @group Material */ -export class GBufferPass extends RenderShader { +export class GBufferPass extends RenderShaderPass { transparency: number; constructor() { super(`gbuffer_vs`, `gbuffer_fs`); this.setShaderEntry(`VertMain`, `FragMain`) - let shaderState = this.shaderState; - // shaderState.cullMode = `none`; + this.passType = PassType.GI; this.setUniformColor(`baseColor`, new Color()); this.setUniformColor(`emissiveColor`, new Color()); diff --git a/src/materials/multiPass/SkyGBufferPass.ts b/src/materials/multiPass/SkyGBufferPass.ts index 5308e30f..33d30cd0 100644 --- a/src/materials/multiPass/SkyGBufferPass.ts +++ b/src/materials/multiPass/SkyGBufferPass.ts @@ -1,14 +1,19 @@ -import { RenderShader, SkyGBuffer_pass } from '../..'; +import { Vector3 } from '../..'; import { GPUCompareFunction, GPUCullMode } from '../../gfx/graphics/webGpu/WebGPUConst'; +import { RenderShaderPass } from '../../gfx/graphics/webGpu/shader/RenderShaderPass'; +import { PassType } from '../../gfx/renderJob/passRenderer/state/RendererType'; /** * @internal * @group Material */ -export class SkyGBufferPass extends RenderShader { +export class SkyGBufferPass extends RenderShaderPass { constructor() { super(`sky_vs_frag_wgsl`, `SkyGBuffer_fs`); + this.passType = PassType.GI; + + this.setUniformVector3(`eyesPos`, new Vector3()); this.setUniformFloat(`exposure`, 1.0); this.setUniformFloat(`roughness`, 0.0); diff --git a/src/math/AnimationCurve.ts b/src/math/AnimationCurve.ts index 672c575f..4853bb93 100644 --- a/src/math/AnimationCurve.ts +++ b/src/math/AnimationCurve.ts @@ -1,62 +1,7 @@ import { PingPong, RepeatSE } from './MathUtil'; - -/** - * Time Warp Mode - * @PingPong value min -> max -> min - * @Repeat value = value % repeatSpace - * @Clamp value = max(min( value , 1 ) , 0 ) - */ -export enum WrapTimeMode { - PingPong = 0, - Repeat = 1, - Clamp = 2, -} - -/** - * @group Math - */ -export class Keyframe { - public serializedVersion: string = '2'; - public time: number; - public value: number; - public inSlope: number = 0; - public outSlope: number = 0; - public tangentMode: number = 0; - - constructor(time: number = 0, value: number = 0) { - this.time = time; - this.value = value; - } - - public unSerialized(data: any) { - this.serializedVersion = data['serializedVersion']; - this.time = data['time']; - this.value = data['value']; - this.tangentMode = data['tangentMode']; - this.inSlope = data['inSlope'] == 'Infinity' ? NaN : data['inSlope']; - this.outSlope = data['outSlope'] == 'Infinity' ? NaN : data['outSlope']; - } - - public unSerialized2(data: any) { - this.serializedVersion = data['serializedVersion']; - this.time = data['time']; - this.value = data['value']; - this.tangentMode = data['tangentMode']; - this.inSlope = data['inTangent'] == 'Infinity' ? NaN : data['inTangent']; - this.outSlope = data['outTangent'] == 'Infinity' ? NaN : data['outTangent']; - } -} - -/** - * @internal - * @group Math - */ -export class FrameCache { - public index: number; //= lhsIndex; - public time: number; // = lhs.time + timeOffset; - public timeEnd: number; // = rhs.time + timeOffset; - public coeff: number[] = []; //= lhsIndex; -} +import { FrameCache } from './enum/FrameCache'; +import { WrapTimeMode } from './enum/WrapTimeMode'; +import { Keyframe } from './enum/Keyframe'; /** * Animation Cureve @@ -288,7 +233,11 @@ export class AnimationCurve { private calcTotalTime() { let maxTime = 0; for (let curve of this.curve) { - maxTime = Math.max(maxTime, curve.time); + if (curve) { + maxTime = Math.max(maxTime, curve.time); + } else { + console.error(curve); + } } this._totalTime = maxTime; } diff --git a/src/math/AnimationCurveClip.ts b/src/math/AnimationCurveClip.ts new file mode 100644 index 00000000..2caa150a --- /dev/null +++ b/src/math/AnimationCurveClip.ts @@ -0,0 +1,65 @@ +import { PingPong, RepeatSE } from './MathUtil'; +import { FrameCache } from './enum/FrameCache'; +import { WrapTimeMode } from './enum/WrapTimeMode'; +import { Keyframe } from './enum/Keyframe'; +import { AnimationCurve, AnimationCurveT, BytesArray, KeyframeT } from '..'; + +/** + * Animation Cureve + * has frame list data + * @group Math + */ +export class PropertyAnimationClip { + public clipName: string; + public loopTime: boolean; + public startTime: number; + public stopTime: number; + public sampleRate: number; + public useSkeletonPos: boolean; + public useSkeletonScale: boolean; + public positionCurves: Map = new Map(); + public rotationCurves: Map = new Map(); + public scaleCurves: Map = new Map(); + public floatCurves: Map = new Map(); + + public formBytes(bytes: BytesArray) { + this.clipName = bytes.readUTF(); + this.loopTime = bytes.readInt32() ? false : true; + this.startTime = bytes.readFloat32(); + this.stopTime = bytes.readFloat32(); + this.sampleRate = bytes.readInt32(); + this.useSkeletonPos = bytes.readInt32() > 0; + this.useSkeletonScale = bytes.readInt32() > 0; + if (this.useSkeletonPos) { + let positionCurvesCount = bytes.readInt32(); + for (let i = 0; i < positionCurvesCount; i++) { + let curveData = new AnimationCurveT(); + curveData.formBytes(bytes); + this.positionCurves.set(curveData.path, curveData); + } + } + + let rotationCurvesCount = bytes.readInt32(); + for (let i = 0; i < rotationCurvesCount; i++) { + let curveData = new AnimationCurveT(); + curveData.formBytes(bytes); + this.rotationCurves.set(curveData.path, curveData); + } + + if (this.useSkeletonScale) { + let scaleCurvesCount = bytes.readInt32(); + for (let i = 0; i < scaleCurvesCount; i++) { + let curveData = new AnimationCurveT(); + curveData.formBytes(bytes); + this.scaleCurves.set(curveData.path, curveData); + } + } + + let floatCurvesCount = bytes.readInt32(); + for (let i = 0; i < floatCurvesCount; i++) { + let curveData = new AnimationCurveT(); + curveData.formBytes(bytes); + this.floatCurves.set(curveData.attribute, curveData); + } + } +} diff --git a/src/math/AnimationCurveT.ts b/src/math/AnimationCurveT.ts new file mode 100644 index 00000000..789e5607 --- /dev/null +++ b/src/math/AnimationCurveT.ts @@ -0,0 +1,151 @@ +import { PingPong, RepeatSE, swap } from './MathUtil'; +import { FrameCache } from './enum/FrameCache'; +import { WrapTimeMode } from './enum/WrapTimeMode'; +import { Keyframe } from './enum/Keyframe'; +import { AnimationCurve, BytesArray, KeyframeT, Quaternion, Vector2, Vector3, Vector4 } from '..'; + +export type CurveValueT = number | Vector2 | Vector3 | Vector4 | Quaternion; +/** + * Animation Cureve + * has frame list data + * @group Math + */ +export class AnimationCurveT { + public path: string; + public attribute: string; + public propertys: string[]; + public preInfinity: number; + public postInfinity: number; + public rotationOrder: number; + public m_curves: AnimationCurve[]; + private k: number = 0; + + private _cacheValue: any; + private _kValue: CurveValueT; + + constructor(k: number = 1) { + this.k = k; + this.m_curves = []; + this.check(); + } + + private check() { + for (let i = 0; i < this.k; i++) { + this.m_curves[i] ||= new AnimationCurve(); + } + switch (this.k) { + case 1: + this._cacheValue = 0; + break; + case 2: + this._cacheValue = new Vector2(); + break; + case 3: + this._cacheValue = new Vector3(); + break; + case 4: + this._cacheValue = new Vector4(); + break; + default: + break; + } + } + + /** + * return this curve use total time + */ + public get totalTime() { + return this.m_curves[0].totalTime; + } + + /** + * add keyFrame to curve keyframe last and calcTotalTime + * @param keyFrame {@link Keyframe} sea: one key frame data + */ + public addKeyFrame(keyFrame: KeyframeT) { + for (let i = 0; i < this.k; i++) { + this.m_curves[i].addKeyFrame(keyFrame.getK(i)); + } + } + + /** + * remove keyframe from this curve + * @param keyFrame {@link Keyframe} + */ + public removeKeyFrame(keyFrame: KeyframeT) { + for (let i = 0; i < this.k; i++) { + this.m_curves[i].removeKeyFrame(keyFrame.getK(i)); + } + } + + /** + * get caculate frames value + * @param time + * @returns + */ + public getValue(time: number): CurveValueT { + switch (this.k) { + case 1: + this._cacheValue = this.m_curves[0].getValue(time); + break; + case 2: + this._cacheValue.x = this.m_curves[0].getValue(time); + this._cacheValue.y = this.m_curves[1].getValue(time); + break; + case 3: + this._cacheValue.x = this.m_curves[0].getValue(time); + this._cacheValue.y = this.m_curves[1].getValue(time); + this._cacheValue.z = this.m_curves[2].getValue(time); + break; + case 4: + this._cacheValue.x = this.m_curves[0].getValue(time); + this._cacheValue.y = this.m_curves[1].getValue(time); + this._cacheValue.z = this.m_curves[2].getValue(time); + this._cacheValue.w = this.m_curves[3].getValue(time); + break; + default: + break; + } + return this._cacheValue; + } + + /** + * get has Keyframe list count + * @returns int + */ + public getKeyCount(): number { + return this.m_curves[0].getKeyCount(); + } + + /** + * Get a Keyframe Data by Index + * @param index must int + * @returns Keyframe {@link Keyframe} + */ + public getKey(index: number): Keyframe[] { + let list = []; + for (let i = 0; i < this.k; i++) { + list.push(this.m_curves[i].getKey(index)); + } + return list; + } + + public formBytes(bytes: BytesArray) { + this.path = bytes.readUTF(); + this.k = bytes.readInt32(); + this.check(); + + this.attribute = bytes.readUTF(); + + this.propertys = this.attribute.split("."); + this.preInfinity = bytes.readInt32(); + this.postInfinity = bytes.readInt32(); + this.rotationOrder = bytes.readInt32(); + let curvesCount = bytes.readInt32(); + for (let i = 0; i < curvesCount; i++) { + let keyframe = new KeyframeT(0); + keyframe.formBytes(bytes); + this.addKeyFrame(keyframe); + } + } +} diff --git a/src/math/BiMap.ts b/src/math/BiMap.ts new file mode 100644 index 00000000..95cb605d --- /dev/null +++ b/src/math/BiMap.ts @@ -0,0 +1,43 @@ +//双向map +export class BiMap extends Map{ + private readonly negtive: Map; + constructor(iterable?: Iterable | null,) { + super(iterable); + this.negtive = new Map(); + if (iterable) { + for (let item of iterable) { + this.negtive.set(item[1], item[0]); + } + } + } + delete(key: K): boolean { + if (this.has(key)) { + let value = this.get(key); + this.negtive.delete(value); + return super.delete(key); + } + return false; + } + + getKey(value: V): K { + return this.negtive.get(value); + } + + deleteValue(value: V) { + let k = this.negtive.get(value); + k && this.delete(k); + return this.negtive.delete(value); + } + + set(key: K, value: V): this { + super.set(key, value); + this.negtive.set(value, key); + return this; + } + + clear(): void { + this.negtive.clear(); + super.clear(); + } + +} \ No newline at end of file diff --git a/src/math/OrderMap.ts b/src/math/OrderMap.ts new file mode 100644 index 00000000..b48e45ef --- /dev/null +++ b/src/math/OrderMap.ts @@ -0,0 +1,63 @@ +export class OrderMap extends Map{ + public readonly valueList: V[]; + public readonly keyList: K[]; + public isChange: boolean = true; + constructor(iterable?: Iterable | null, recordKey?: boolean, recordValue?: boolean) { + super(iterable); + if (recordKey) this.keyList = []; + if (recordValue) this.valueList = []; + + if (iterable) { + for (let item of iterable) { + this.valueList?.push(item[1]); + this.keyList?.push(item[0]); + } + } + } + + delete(key: K): boolean { + if (this.has(key)) { + let value = this.get(key); + this.valueList && this.deleteValue(value); + + this.keyList && this.deleteKey(key); + + this.isChange = true; + return super.delete(key); + } + return false; + } + + private deleteValue(value: V): this { + let index = this.valueList.indexOf(value); + if (index >= 0) { + this.valueList.splice(index, 1); + } + return this; + } + + private deleteKey(key: K): this { + let index = this.keyList.indexOf(key); + if (index >= 0) { + this.keyList.splice(index, 1); + } + return this; + } + + set(key: K, value: V): this { + this.delete(key); + this.keyList?.push(key); + this.valueList?.push(value); + super.set(key, value); + this.isChange = true; + return this; + } + + clear(): void { + if (this.valueList) this.valueList.length = 0; + if (this.keyList) this.keyList.length = 0; + this.isChange = true; + super.clear(); + } + +} \ No newline at end of file diff --git a/src/math/ParticleSystemCurves.ts b/src/math/ParticleSystemCurves.ts index 9978dfaa..1fd9c5ec 100644 --- a/src/math/ParticleSystemCurves.ts +++ b/src/math/ParticleSystemCurves.ts @@ -1,8 +1,9 @@ -import { AnimationCurve, FrameCache } from './AnimationCurve'; +import { AnimationCurve } from './AnimationCurve'; import { lerp } from './MathUtil'; import { Polynomial, PolynomialCurve } from './PolynomialCurve'; import { quadraticPolynomialRootsGeneric } from './Polynomials'; import { Vector2 } from './Vector2'; +import { FrameCache } from './enum/FrameCache'; /** * @internal diff --git a/src/math/Plane3D.ts b/src/math/Plane3D.ts new file mode 100644 index 00000000..5f8c532d --- /dev/null +++ b/src/math/Plane3D.ts @@ -0,0 +1,248 @@ +import { Vector3 } from ".."; +import { PlaneClassification } from "./PlaneClassification"; + +/** +* @language zh_CN +* @class Plane3D +* @classdesc +* Plane3D 类 3D空间中的平面表示数据 +* 由a,b,c,d4个分量组成 在三维空间中定义了一个平面 Ax + By + Cz + D = 0 +* @includeExample geom/Plane3D.ts +* @version +* @platform Web,Native +*/ +export class Plane3D { + /** + * @language en_US + * The A coefficient of this plane. (Also the x dimension of the plane normal) + */ + /** + * @language zh_CN + * 平面中的a分量 + * @platform Web,Native + */ + public a: number; + + /** + * @language en_US + * The B coefficient of this plane. (Also the y dimension of the plane normal) + */ + /** + * @language zh_CN + * 平面中的b分量 + * @platform Web,Native + */ + public b: number; + + /** + * @language en_US + * The C coefficient of this plane. (Also the z dimension of the plane normal) + */ + /** + * @language zh_CN + * 平面中的c分量 + * @platform Web,Native + */ + public c: number; + + /** + * @language en_US + * The D coefficient of this plane. (Also the inverse dot product between normal and point) + */ + /** + * @language zh_CN + * 平面中的d分量 + * @platform Web,Native + */ + public d: number; + + // indicates the alignment of the plane + /** + * @private + */ + public static ALIGN_ANY: number = 0; + + /** + * @private + */ + public static ALIGN_XY_AXIS: number = 1; + + /** + * @private + */ + public static ALIGN_YZ_AXIS: number = 2; + + /** + * @private + */ + public static ALIGN_XZ_AXIS: number = 3; + + /** + * @language en_US + * Create a Plane3D with ABCD coefficients + */ + /** + * @language zh_CN + * 创建一个平面实例 + * @param a + * @param b + * @param c + * @param d + * @platform Web,Native + */ + constructor(a: number = 0, b: number = 0, c: number = 0, d: number = 0) { + this.a = a; + this.b = b; + this.c = c; + this.d = d; + } + + /** + * @language zh_CN + * 填充平面的各分量的值 + * @param a + * @param b + * @param c + * @param d + * @platform Web,Native + */ + public setTo(a: number = 0, b: number = 0, c: number = 0, d: number = 0) { + this.a = a; + this.b = b; + this.c = c; + this.d = d; + } + + /** + * @language en_US + * Fills this Plane3D with the coefficients from 3 points in 3d space. + * @param p0 Vector3 + * @param p1 Vector3 + * @param p2 Vector3 + */ + + /** + * @language zh_CN + * 由3个坐标来创建一个3d平面 + * @param p0 Vector3 + * @param p1 Vector3 + * @param p2 Vector3 + * @platform Web,Native + */ + public fromPoints(p0: Vector3, p1: Vector3, p2: Vector3) { + var d1x: number = p1.x - p0.x; + var d1y: number = p1.y - p0.y; + var d1z: number = p1.z - p0.z; + + var d2x: number = p2.x - p0.x; + var d2y: number = p2.y - p0.y; + var d2z: number = p2.z - p0.z; + + this.a = d1y * d2z - d1z * d2y; + this.b = d1z * d2x - d1x * d2z; + this.c = d1x * d2y - d1y * d2x; + this.d = -(this.a * p0.x + this.b * p0.y + this.c * p0.z); + } + + /** + * @language en_US + * Fills this Plane3D with the coefficients from the plane's normal and a point in 3d space. + * @param normal Vector3 + * @param point Vector3 + */ + /** + * @language zh_CN + * 由一条normal向量和一个坐标创建一个3d平面 + * @param normal Vector3 + * @param point Vector3 + * @platform Web,Native + */ + public fromNormalAndPoint(normal: Vector3, point: Vector3) { + this.a = normal.x; + this.b = normal.y; + this.c = normal.z; + this.d = -(this.a * point.x + this.b * point.y + this.c * point.z); + } + + /** + * @language en_US + * Normalize this Plane3D + * @returns Plane3D This Plane3D. + */ + /** + * @language zh_CN + * 单位化3d平面 + * @returns number 返回平面长度 + * @platform Web,Native + */ + public normalize(): number { + var len: number = Math.sqrt(this.a * this.a + this.b * this.b + this.c * this.c); + if (len > 0.0) { + var invLength: number = 1.0 / len; + this.a *= invLength; + this.b *= invLength; + this.c *= invLength; + this.d *= invLength; + } + + return len; + } + + /** + * @language en_US + * Returns the signed distance between this Plane3D and the point p. + * @param p Vector3 + * @returns Number + */ + /** + * @language zh_CN + * 计算3d平面到点p的距离 + * @param p Vector3 + * @returns number 返回计算后的距离 + * @platform Web,Native + */ + public distance(p: Vector3): number { + return this.a * p.x + this.b * p.y + this.c * p.z + this.d; + } + + /** + * @language en_US + * Classify a point against this Plane3D. (in front, back or intersecting) + * @param p Vector3 + * @param epsilon + * @returns PlaneClassification.FRONT在平面正面 + * PlaneClassification.BACK在平面背面面 + * PlaneClassification.INTERSECT在平面上 + */ + /** + * @language zh_CN + * 计算3d平面和点p的空间关系 + * @param p Vector3 + * @param epsilon 相对偏移值 + * @returns number int Plane3.FRONT or Plane3D.BACK or Plane3D.INTERSECT + * @platform Web,Native + */ + public classifyPoint(p: Vector3, epsilon: number = 0.01): number { + + var dis: number = this.distance(p); + + if (dis < -epsilon) { + return PlaneClassification.BACK; + } + else if (dis > epsilon) { + return PlaneClassification.FRONT; + } + + return PlaneClassification.INTERSECT; + } + + /** + * @language zh_CN + * 当前Plane3D以字符串形式返回 + * @returns string + * @platform Web,Native + */ + public toString(): string { + return "Plane3D [a:" + this.a + ", b:" + this.b + ", c:" + this.c + ", d:" + this.d + "]"; + } +} \ No newline at end of file diff --git a/src/math/PlaneClassification.ts b/src/math/PlaneClassification.ts new file mode 100644 index 00000000..9a8ec358 --- /dev/null +++ b/src/math/PlaneClassification.ts @@ -0,0 +1,36 @@ +export class PlaneClassification { + /** + * @language zh_CN + * 背面 + * @platform Web,Native + */ + public static BACK: number = 0; + + /** + * @language zh_CN + * 正面 + * @platform Web,Native + */ + public static FRONT: number = 1; + + /** + * @language zh_CN + * 在法线朝上的一面 + * @platform Web,Native + */ + public static IN: number = 0; + + /** + * @language zh_CN + * 在法线朝下的一面 + * @platform Web,Native + */ + public static OUT: number = 1; + + /** + * @language zh_CN + * 相交 + * @platform Web,Native + */ + public static INTERSECT: number = 2; +} \ No newline at end of file diff --git a/src/math/PolynomialCurve.ts b/src/math/PolynomialCurve.ts index 458373e3..c3c23d82 100644 --- a/src/math/PolynomialCurve.ts +++ b/src/math/PolynomialCurve.ts @@ -1,4 +1,5 @@ -import { AnimationCurve, FrameCache } from './AnimationCurve'; +import { FrameCache } from './enum/FrameCache'; +import { AnimationCurve } from './AnimationCurve'; import { cubicPolynomialRootsGeneric } from './Polynomials'; import { Vector2 } from './Vector2'; diff --git a/src/math/Quaternion.ts b/src/math/Quaternion.ts index e2a5e76c..1927259f 100644 --- a/src/math/Quaternion.ts +++ b/src/math/Quaternion.ts @@ -7,6 +7,7 @@ import { Vector3 } from './Vector3'; * @group Math */ export class Quaternion { + public static HELP_0: Quaternion = new Quaternion(0, 0, 0, 1); public static HELP_1: Quaternion = new Quaternion(0, 0, 0, 1); public static HELP_2: Quaternion = new Quaternion(0, 0, 0, 1); @@ -548,6 +549,11 @@ export class Quaternion { } return value < minInclusive ? minInclusive : value < maxInclusive ? value : maxInclusive; } + + static serialize(value: Quaternion): Quaternion { + let v = new Quaternion(value.x, value.y, value.z, value.w); + return v; + } } /** diff --git a/src/math/Vector3.ts b/src/math/Vector3.ts index 2c72253d..157e9e1c 100644 --- a/src/math/Vector3.ts +++ b/src/math/Vector3.ts @@ -1090,6 +1090,41 @@ export class Vector3 { return dotProduct / d; } } + + public static pointInsideTriangle(pt: Vector3, pt0: Vector3, pt1: Vector3, pt2: Vector3): boolean { + Vector3.HELP_0.setTo(pt.x, pt.z, 0); + Vector3.HELP_1.setTo(pt0.x, pt0.z, 0); + Vector3.HELP_2.setTo(pt1.x, pt1.z, 0); + Vector3.HELP_3.setTo(pt2.x, pt2.z, 0); + + return Vector3.pointInsideTriangle2d(); + } + + private static pointInsideTriangle2d(): boolean { + if (Vector3.productXY(Vector3.HELP_1, Vector3.HELP_2, Vector3.HELP_3) >= 0) { + return (Vector3.productXY(Vector3.HELP_1, Vector3.HELP_2, Vector3.HELP_0) >= 0) + && (Vector3.productXY(Vector3.HELP_2, Vector3.HELP_3, Vector3.HELP_0)) >= 0 + && (Vector3.productXY(Vector3.HELP_3, Vector3.HELP_1, Vector3.HELP_0) >= 0); + } + else { + return (Vector3.productXY(Vector3.HELP_1, Vector3.HELP_2, Vector3.HELP_0) <= 0) + && (Vector3.productXY(Vector3.HELP_2, Vector3.HELP_3, Vector3.HELP_0)) <= 0 + && (Vector3.productXY(Vector3.HELP_3, Vector3.HELP_1, Vector3.HELP_0) <= 0); + } + } + + private static productXY(p1: { x: number, y: number }, p2: { x: number, y: number }, p3: { x: number, y: number }): number { + var val: number = (p1.x - p3.x) * (p2.y - p3.y) - (p1.y - p3.y) * (p2.x - p3.x); + if (val > -0.00001 && val < 0.00001) + val = 0; + return val; + } + + static serialize(position: Vector3): Vector3 { + let v = new Vector3(position.x, position.y, position.z, position.w); + return v; + } + } diff --git a/src/math/enum/FrameCache.ts b/src/math/enum/FrameCache.ts new file mode 100644 index 00000000..da66614c --- /dev/null +++ b/src/math/enum/FrameCache.ts @@ -0,0 +1,10 @@ +/** + * @internal + * @group Math + */ +export class FrameCache { + public index: number; //= lhsIndex; + public time: number; // = lhs.time + timeOffset; + public timeEnd: number; // = rhs.time + timeOffset; + public coeff: number[] = []; //= lhsIndex; +} \ No newline at end of file diff --git a/src/math/enum/Keyframe.ts b/src/math/enum/Keyframe.ts new file mode 100644 index 00000000..23ef5012 --- /dev/null +++ b/src/math/enum/Keyframe.ts @@ -0,0 +1,41 @@ +import { BytesArray, ValueParser } from "../.."; + +/** + * @group Math + */ +export class Keyframe { + public serializedVersion: string = '2'; + public time: number; + public value: number; + public inSlope: number = 0; + public outSlope: number = 0; + public tangentMode: number = 0; + + public weightedMode: number = 0; + public inWeight: number; + public outWeight: number; + + constructor(time: number = 0, value: number = 0) { + this.time = time; + this.value = value; + } + + public unSerialized(data: any) { + this.serializedVersion = data['serializedVersion']; + this.time = data['time']; + this.value = data['value']; + this.tangentMode = data['tangentMode']; + this.inSlope = data['inSlope'] == 'Infinity' ? NaN : data['inSlope']; + this.outSlope = data['outSlope'] == 'Infinity' ? NaN : data['outSlope']; + } + + public unSerialized2(data: any) { + this.serializedVersion = data['serializedVersion']; + this.time = data['time']; + this.value = data['value']; + this.tangentMode = data['tangentMode']; + this.inSlope = data['inTangent'] == 'Infinity' ? NaN : data['inTangent']; + this.outSlope = data['outTangent'] == 'Infinity' ? NaN : data['outTangent']; + } + +} \ No newline at end of file diff --git a/src/math/enum/T/KeyframeT.ts b/src/math/enum/T/KeyframeT.ts new file mode 100644 index 00000000..4b358caf --- /dev/null +++ b/src/math/enum/T/KeyframeT.ts @@ -0,0 +1,136 @@ +import { CurveValueType, ValueParser } from "../../../loader/parser/prefab/prefabData/ValueParser"; +import { ValueEnumType } from "../../../loader/parser/prefab/prefabData/ValueType"; +import { BytesArray } from "../../../util/BytesArray"; +import { Quaternion } from "../../Quaternion"; +import { Vector2 } from "../../Vector2"; +import { Vector3 } from "../../Vector3"; +import { Vector4 } from "../../Vector4"; +import { Keyframe } from "../Keyframe"; + +/** + * @group Math + */ +export class KeyframeT { + public serializedVersion: string = '2'; + public time: number; + public tangentMode: number = 0; + public weightedMode: number = 0; + // public value: CurveValueType; + // public inSlope: CurveValueType; + // public outSlope: CurveValueType; + // public inWeight: CurveValueType + // public outWeight: CurveValueType + + public propertyKeyFrame: { [k: number]: Keyframe }; + + constructor(time: number = 0) { + this.time = time; + this.propertyKeyFrame = {}; + } + + public getK(k: number) { + return this.propertyKeyFrame[k]; + } + + private split(type: ValueEnumType, value: CurveValueType, property: string) { + switch (type) { + case ValueEnumType.single: + { + let keyFrame = this.getKeyFrame(0); + keyFrame[property] = value; + } + break; + case ValueEnumType.float: + { + let keyFrame = this.getKeyFrame(0); + keyFrame[property] = value; + } + break; + case ValueEnumType.vector2: + { + let v = value as Vector2; + let x_kf = this.getKeyFrame(0); + x_kf[property] = v.x; + let y_kf = this.getKeyFrame(1); + y_kf[property] = v.y; + } + break; + case ValueEnumType.vector3: + { + let v = value as Vector3; + let x_kf = this.getKeyFrame(0); + x_kf[property] = v.x; + let y_kf = this.getKeyFrame(1); + y_kf[property] = v.y; + let z_kf = this.getKeyFrame(2); + z_kf[property] = v.z; + } + break; + case ValueEnumType.vector4: + { + let v = value as Vector4; + let x_kf = this.getKeyFrame(0); + x_kf[property] = v.x; + let y_kf = this.getKeyFrame(1); + y_kf[property] = v.y; + let z_kf = this.getKeyFrame(2); + z_kf[property] = v.y; + let w_kf = this.getKeyFrame(3); + w_kf[property] = v.y; + } + break; + case ValueEnumType.quaternion: + { + let v = value as Quaternion; + let x_kf = this.getKeyFrame(0); + x_kf[property] = v.x; + let y_kf = this.getKeyFrame(1); + y_kf[property] = v.y; + let z_kf = this.getKeyFrame(2); + z_kf[property] = v.z; + let w_kf = this.getKeyFrame(3); + w_kf[property] = v.w; + } + break; + } + } + + private getKeyFrame(k: number): Keyframe { + let keyFrame = this.propertyKeyFrame[k]; + if (!keyFrame) { + keyFrame = new Keyframe(); + keyFrame.time = this.time; + keyFrame.tangentMode = this.tangentMode; + keyFrame.weightedMode = this.weightedMode; + this.propertyKeyFrame[k] = keyFrame; + } + + return keyFrame; + } + + public formBytes(bytes: BytesArray) { + this.time = bytes.readFloat32(); + { + let { t, v } = ValueParser.parser(bytes); + this.split(t, v, "value"); + } + { + let { t, v } = ValueParser.parser(bytes); + this.split(t, v, "inSlope"); + } + { + let { t, v } = ValueParser.parser(bytes); + this.split(t, v, "outSlope"); + } + this.tangentMode = bytes.readInt32(); + this.weightedMode = bytes.readInt32(); + { + let { t, v } = ValueParser.parser(bytes); + this.split(t, v, "inWeight"); + } + { + let { t, v } = ValueParser.parser(bytes); + this.split(t, v, "outWeight"); + } + } +} \ No newline at end of file diff --git a/src/math/enum/T/ValueOp.ts b/src/math/enum/T/ValueOp.ts new file mode 100644 index 00000000..aeeab6ae --- /dev/null +++ b/src/math/enum/T/ValueOp.ts @@ -0,0 +1,39 @@ +import { CurveValueType, Quaternion, ValueEnumType, Vector2, Vector3, Vector4 } from "../../.."; + +export class ValueOp { + public static sub(v1: T, v2: T) { + let t = v1.constructor.name; + switch (t) { + case `number`: + return (v1 as number) - (v2 as number); + case 'Vector2': + { + let vv1 = v1 as Vector2; + let vv2 = v2 as Vector2; + return new Vector2(vv1.x - vv2.x, vv1.y - vv2.y); + } + case 'Vector3': + { + let vv1 = v1 as Vector3; + let vv2 = v2 as Vector3; + return new Vector3(vv1.x - vv2.x, vv1.y - vv2.y, vv1.z - vv2.z) + } + case 'Vector4': + { + let vv1 = v1 as Vector4; + let vv2 = v2 as Vector4; + return new Vector4(vv1.x - vv2.x, vv1.y - vv2.y, vv1.z - vv2.z, vv1.w - vv2.w) + } + case 'Quaternion': + { + let vv1 = v1 as Quaternion; + let vv2 = v2 as Quaternion; + return new Quaternion(vv1.x - vv2.x, vv1.y - vv2.y, vv1.z - vv2.z, vv1.w - vv2.w) + } + default: + break; + } + + + } +} \ No newline at end of file diff --git a/src/math/enum/WrapTimeMode.ts b/src/math/enum/WrapTimeMode.ts new file mode 100644 index 00000000..b290d063 --- /dev/null +++ b/src/math/enum/WrapTimeMode.ts @@ -0,0 +1,11 @@ +/** + * Time Warp Mode + * @PingPong value min -> max -> min + * @Repeat value = value % repeatSpace + * @Clamp value = max(min( value , 1 ) , 0 ) + */ +export enum WrapTimeMode { + PingPong = 0, + Repeat = 1, + Clamp = 2, +} \ No newline at end of file diff --git a/src/math/navigation/DoubleArray.ts b/src/math/navigation/DoubleArray.ts new file mode 100644 index 00000000..25f0bb33 --- /dev/null +++ b/src/math/navigation/DoubleArray.ts @@ -0,0 +1,52 @@ +export class DoubleArray { + + private _keys: Array = new Array(); + + private _values: Array = new Array(); + + public getIndexByKey(key: any): number { + return this._keys.indexOf(key); + } + + public getValueByKey(key: any): any { + var index: number = this.getIndexByKey(key); + if (index > -1) { + return this._values[index]; + } + return null; + } + + public put(key: any, value: any): any { + if (key == null) + return null; + var old: any = this.remove(key); + this._keys.push(key); + this._values.push(value); + return old; + } + + public remove(key: any): any { + var index: number = this._keys.indexOf(key) + var item: any; + if (index > -1) { + item = this._values[index]; + this._keys.splice(index, 1); + this._values.splice(index, 1); + } + return item; + } + + public getValues(): Array { + return this._values; + } + + public getKeys(): Array { + return this._keys; + } + + public clear(): void { + this._values.length = 0; + this._keys.length = 0; + } + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DAstar.ts b/src/math/navigation/Navi3DAstar.ts new file mode 100644 index 00000000..41eeb91e --- /dev/null +++ b/src/math/navigation/Navi3DAstar.ts @@ -0,0 +1,108 @@ +import { Navi3DMaskType } from "./Navi3DMaskType"; +import { Navi3DMesh } from "./Navi3DMesh"; +import { Navi3DPoint } from "./Navi3DPoint"; +import { Navi3DTriangle } from "./Navi3DTriangle"; + +export class Navi3DAstar { + + private _openedList: Array; + private _closedList: Array; + private _endNode: Navi3DTriangle; + private _startNode: Navi3DTriangle; + private _triangleChannel: Array; + private _navMesh: Navi3DMesh; + private _findIndex: number = 0; + + constructor() { + this._openedList = new Array(); + this._closedList = new Array(); + } + + public findPath(navMesh: Navi3DMesh, startTriangle: Navi3DTriangle, endTriangle: Navi3DTriangle): boolean { + this._findIndex++; + this._navMesh = navMesh; + + this._startNode = startTriangle; + this._endNode = endTriangle; + + this._openedList.length = 0; + this._closedList.length = 0; + + if (this._startNode && this._endNode) { + this._startNode.gg = 0; + this._startNode.h = 0; + this._startNode.f = 0; + this._startNode.parent = null; + return this.search(); + } + return false; + } + + private search(): boolean { + var node: Navi3DTriangle = this._startNode; + var neibours: Array = []; + var test: Navi3DTriangle; + while (node != this._endNode) { + neibours = node.getNeibourTriangles(neibours, Navi3DMaskType.WalkAble, Navi3DMaskType.WalkAble); + for (test of neibours) { + if (test.closeId == this._findIndex) + continue; + if (test == node || !test.walkAble) { + continue; + } + var g: number = node.gg + Navi3DPoint.calcDistance(test, node) * test.costMultiplier; + var h: number = Navi3DPoint.calcDistance(test, this._endNode); + var f: number = g + h; + if (test.openId == this._findIndex) { + if (test.f > f) { + test.f = f; + test.gg = g; + test.h = h; + test.parent = node; + } + } + else { + test.f = f; + test.gg = g; + test.h = h; + test.parent = node; + test.openId = this._findIndex; + this._openedList.push(test); + } + } + node.closeId = this._findIndex; + this._closedList.push(node); + if (this._openedList.length == 0) { + return false; + } + this._openedList.sort(function (a: Navi3DTriangle, b: Navi3DTriangle) { + return a.f - b.f; + }); + node = (this._openedList.shift()); + } + this.buildPath(); + return true; + } + + private buildPath(): void { + this._triangleChannel = []; + var node: Navi3DTriangle = this._endNode; + this._triangleChannel.push(node); + while (node != this._startNode) { + node = node.parent; + this._triangleChannel.unshift(node); + } + } + + public get channel(): Array { + return this._triangleChannel; + } + +} + + + + + + + diff --git a/src/math/navigation/Navi3DConst.ts b/src/math/navigation/Navi3DConst.ts new file mode 100644 index 00000000..6483a107 --- /dev/null +++ b/src/math/navigation/Navi3DConst.ts @@ -0,0 +1,10 @@ +export class Navi3DConst { + public static SetConst(epsilon: number) { + this.EPSILON = epsilon; + this.POWER_EPSILON = epsilon * epsilon; + } + + public static EPSILON: number = 0.1; + + public static POWER_EPSILON: number = this.EPSILON * this.EPSILON; +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DEdge.ts b/src/math/navigation/Navi3DEdge.ts new file mode 100644 index 00000000..24cc45f9 --- /dev/null +++ b/src/math/navigation/Navi3DEdge.ts @@ -0,0 +1,147 @@ +import { Vector3 } from "../Vector3"; +import { Navi3DMaskType } from "./Navi3DMaskType"; +import { Navi3DPoint } from "./Navi3DPoint"; +import { Navi3DPointFat } from "./Navi3DPointFat"; +import { Navi3DTriangle } from "./Navi3DTriangle"; + +export class Navi3DEdge { + + private _edgeMask: number = 0; + private _edgeSize: number = 0; + private _pointA: Navi3DPoint; + private _pointB: Navi3DPoint; + private _triangleOwners: Array; + private _centerPoint: Vector3; + + private _edgeDirA2B: Vector3; + + public crossPoint: Vector3; + + public fatPointA: Navi3DPointFat; + + public fatPointB: Navi3DPointFat; + + private static CALC_FAT_VECTOR: Vector3 = new Vector3(); + + constructor(point0: Navi3DPoint, point1: Navi3DPoint) { + this._pointA = point0; + this._pointB = point1; + if (point0.id >= point1.id) { + throw new Error("edge point order error!!!"); + } + this._triangleOwners = new Array(); + this._centerPoint = new Vector3(); + this._edgeMask = Navi3DMaskType.WalkAble; + Navi3DPoint.CALC_VECTOR3D1.setTo(point0.x - point1.x, point0.y - point1.y, point0.z - point1.z); + this._edgeSize = Navi3DPoint.CALC_VECTOR3D1.length; + + this._centerPoint.setTo((point0.x + point1.x) / 2, (point0.y + point1.y) / 2, (point0.z + point1.z) / 2); + } + + public get size(): Number { + return this._edgeSize; + } + + public get triangleOwners(): Array { + return this._triangleOwners; + } + + public get centerPoint(): Vector3 { + return this._centerPoint; + } + + public initFatPoints(radius: number): void { + this._edgeDirA2B = this._pointB.subtract(this._pointA); + this._edgeDirA2B.normalize(); + + this.fatPointA = this.fatPointA || new Navi3DPointFat(this._pointA, this); + this.fatPointB = this.fatPointB || new Navi3DPointFat(this._pointB, this); + + if (this.fatPointA.radius != radius) { + Navi3DEdge.CALC_FAT_VECTOR.copyFrom(this._edgeDirA2B); + Navi3DEdge.CALC_FAT_VECTOR.scaleBy(radius); + Navi3DEdge.CALC_FAT_VECTOR.incrementBy(this._pointA); + this.fatPointA.copyFrom(Navi3DEdge.CALC_FAT_VECTOR); + this.fatPointA.radius = radius; + } + + if (this.fatPointB.radius != radius) { + Navi3DEdge.CALC_FAT_VECTOR.copyFrom(this._edgeDirA2B); + Navi3DEdge.CALC_FAT_VECTOR.scaleBy(-radius); + Navi3DEdge.CALC_FAT_VECTOR.incrementBy(this._pointB); + this.fatPointB.copyFrom(Navi3DEdge.CALC_FAT_VECTOR); + this.fatPointB.radius = radius; + } + + } + + public getFatPoint(pt: Navi3DPoint): Navi3DPointFat { + if (pt == this._pointA) + return this.fatPointA; + return this.fatPointB; + } + + public getAnotherFatPoint(pt: Navi3DPoint): Navi3DPointFat { + if (pt == this._pointA) + return this.fatPointB; + return this.fatPointA; + } + + public getAnotherPoint(pt: Navi3DPoint): Navi3DPoint { + if (pt == this._pointA) + return this._pointB; + return this._pointA; + } + + public containsPoint(pt: Vector3): Navi3DPoint { + if (Navi3DPoint.equalPoint(pt, this._pointA)) + return this._pointA; + if (Navi3DPoint.equalPoint(pt, this._pointB)) + return this._pointB; + return null; + } + + public addTriangleOwners(triangle: Navi3DTriangle): void { + if (triangle.edges.indexOf(this) == -1) { + throw new Error("the edge is not belong triangle!!!"); + } + if (this._triangleOwners.indexOf(triangle) == -1) { + this._triangleOwners.push(triangle); + } + } + + public getPublicPoint(edge: Navi3DEdge): Navi3DPoint { + if (this._pointA == edge._pointA || this._pointA == edge._pointB) { + return this._pointA; + } + else if (this._pointB == edge._pointA || this._pointB == edge._pointB) { + return this._pointB; + } + return null; + } + + public getEqualPoint(p: Vector3): Navi3DPoint { + if (Navi3DPoint.equalPoint(p, this._pointA)) + return this._pointA; + if (Navi3DPoint.equalPoint(p, this._pointB)) + return this._pointB; + return null; + } + + public get pointA(): Navi3DPoint { + return this._pointA; + } + + public get pointB(): Navi3DPoint { + return this._pointB; + } + + public get walkAble(): boolean { + return (this._edgeMask & Navi3DMaskType.WalkAble) == Navi3DMaskType.WalkAble; + } + + public testMask(value: number): boolean { + return (this._edgeMask & value) == value; + } + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DFunnel.ts b/src/math/navigation/Navi3DFunnel.ts new file mode 100644 index 00000000..0d8c5269 --- /dev/null +++ b/src/math/navigation/Navi3DFunnel.ts @@ -0,0 +1,312 @@ +import { Plane3D } from "../Plane3D"; +import { PlaneClassification } from "../PlaneClassification"; +import { Vector3 } from "../Vector3"; +import { Navi3DConst } from "./Navi3DConst"; +import { Navi3DEdge } from "./Navi3DEdge"; +import { Navi3DPoint } from "./Navi3DPoint"; +import { Navi3DPointFat } from "./Navi3DPointFat"; +import { Navi3DRouter } from "./Navi3DRouter"; +import { Navi3DTriangle } from "./Navi3DTriangle"; + +export class Navi3DFunnel { + + private _aiRadius: number = 0; + + private _router: Navi3DRouter; + + private _result: Array; + + private _tempPublicEdgeList: Array = new Array(); + + private _tempSamePlaneList: Array = new Array(); + + private static CROSS_TEST_DIRECTION: Vector3 = new Vector3(); + + constructor() { + this._router = new Navi3DRouter(); + } + + public searchPath(startPt: Vector3, endPt: Vector3, triangleList: Array, radius: number = 0): boolean { + if (radius <= 0) + radius = 1; + this._aiRadius = radius * 1.5; + // + //起点终点判断 + if (!this.searchEnable(startPt, endPt, triangleList)) + return false; + + this.search(startPt, endPt, triangleList); + return true; + } + + public get path(): Array { + return this._result; + } + + private searchEnable(startPt: Vector3, endPt: Vector3, triangleList: Array): boolean { + if (startPt == null || endPt == null || triangleList == null) + return false; + + if (triangleList[0].plane.classifyPoint(startPt, Navi3DConst.EPSILON) != PlaneClassification.INTERSECT) { + return false; + } + if (triangleList[triangleList.length - 1].plane.classifyPoint(endPt, Navi3DConst.EPSILON) != PlaneClassification.INTERSECT) { + return false; + } + return true; + } + + private search(startPt: Vector3, endPt: Vector3, triangleList: Array): void { + this._tempPublicEdgeList.length = 0; + this._tempSamePlaneList.length = 0; + var i: number = 0; + var crossedEdgeCount: number = triangleList.length - 1; + var tr: Navi3DTriangle; + var curEdge: Navi3DEdge; + var pt: Vector3; + var plane: Plane3D; + var crossPoint: Vector3; + + for (i = 0; i < crossedEdgeCount; i++) { + curEdge = triangleList[i].getPublicEdge(triangleList[i + 1]); + curEdge.crossPoint = null; + curEdge.initFatPoints(this._aiRadius); + this._tempPublicEdgeList.push(curEdge); + tr = triangleList[i]; + plane = tr.plane; + tr = triangleList[i + 1]; + pt = tr.getEdgeAgainstPoint(curEdge); + + this._tempSamePlaneList.push(plane.classifyPoint(pt, Navi3DConst.EPSILON) == PlaneClassification.INTERSECT); + } + + this._router.continuePass(startPt, endPt, this._tempPublicEdgeList[0]); + crossedEdgeCount = this._tempPublicEdgeList.length; + + + var cornerPoint: Vector3; + var cornerEdge: Navi3DEdge; + var continuePass: boolean; + var lastEdge: boolean; + + for (i = 0; i < crossedEdgeCount; i++) { + curEdge = this._tempPublicEdgeList[i]; + tr = triangleList[i + 1]; + lastEdge = i == crossedEdgeCount - 1; + if (lastEdge) { + pt = endPt; + } + else { + pt = tr.getEdgeAgainstPoint(curEdge); + } + + continuePass = this._router.passEdge(curEdge, this._tempPublicEdgeList[i + 1], pt, lastEdge); + if (!continuePass) { + cornerPoint = this._router.cornerPoint; + cornerEdge = this._router.cornerEdge; + i = this._tempPublicEdgeList.indexOf(cornerEdge); + this._router.continuePass(cornerPoint, endPt, this._tempPublicEdgeList[i + 1]); + } + } + + + this.pushAllPathPoint2(startPt, endPt); + if (this._result.length >= 3) { + this.optimusTerminusFat(); + this.optimusByRadius(); + } + + //copy result + let list: Vector3[] = []; + for (let point of this._result) { + list.push(new Vector3().copyFrom(point)); + } + this._result = list; + } + + private optimusTerminusFat(): void { + var startFat: Navi3DPointFat; + var endFat: Navi3DPointFat; + var pt: any; + + pt = this._result[1]; + if (pt instanceof Navi3DPointFat) { + startFat = pt; + } + + pt = this._result[this._result.length - 2]; + if (pt instanceof Navi3DPointFat) { + endFat = pt; + } + + if (startFat) { + this._result[1] = startFat.scalePoint(); + } + if (endFat && startFat != endFat) { + this._result[this._result.length - 2] = endFat.scalePoint(); + } + + } + + private pushAllPathPoint2(startPt: Vector3, endPt: Vector3): void { + var crossedEdgeCount: number = this._tempPublicEdgeList.length; + var curEdge: Navi3DEdge; + var curEdgeJ: Navi3DEdge; + + this._result = new Array(); + this._result.push(startPt); + + + var fromPoint: Vector3 = startPt; + var toPoint: Vector3; + var fatPoint: Navi3DPointFat; + var crossPoint: Vector3; + + + for (var i: number = 0; i < crossedEdgeCount; i++) { + curEdge = this._tempPublicEdgeList[i]; + fatPoint = null; + if (curEdge.crossPoint) { + fatPoint = this.getFatPoint(curEdge, curEdge.crossPoint); + if (fatPoint) { + this._result.push(fatPoint); + } + else { + this._result.push(curEdge.crossPoint); + } + fromPoint = curEdge.crossPoint; + } + else { + curEdgeJ = null; + toPoint = null; + //找到下一个点 + for (var j: number = i + 1; j < crossedEdgeCount; j++) { + curEdgeJ = this._tempPublicEdgeList[j]; + toPoint = curEdgeJ.crossPoint; + if (toPoint) { + break; + } + } + + if (toPoint == null) { + toPoint = endPt; + } + fatPoint = this.getFatPoint(curEdge, toPoint); + if (fatPoint) { + this._result.push(fatPoint); + } + else { + if (toPoint == fromPoint) { + crossPoint = toPoint.clone(); + } else { + Navi3DFunnel.CROSS_TEST_DIRECTION.setTo(toPoint.x - fromPoint.x, 0, toPoint.z - fromPoint.z); + crossPoint = this._router.calcCrossEdge(curEdge, fromPoint, Navi3DFunnel.CROSS_TEST_DIRECTION); + } + this._result.push(crossPoint); + } + } + } + this._result.push(endPt); + } + + private optimusByRadius(): void { + var optimusResult: Array = new Array(); + optimusResult.length = this._result.length; + + var count: number = this._result.length - 2; + var pt0: Vector3; + var pt1: Vector3; + var pt2: Vector3; + + var fatPt0: Navi3DPointFat; + var fatPt1: Navi3DPointFat; + var fatPt2: Navi3DPointFat; + + var edgePt0: Navi3DPoint; + var edgePt1: Navi3DPoint; + var edgePt2: Navi3DPoint; + + + var centerEdge: Navi3DEdge; + + var checkEnable: boolean; + var optimusPoint: Vector3; + var i: number; + + + for (i = 0; i < count; i++) { + edgePt0 = edgePt1 = edgePt2 = null; + fatPt0 = fatPt1 = fatPt2 = null; + checkEnable = false; + optimusPoint = null; + + pt0 = this._result[i]; + pt1 = this._result[i + 1]; + pt2 = this._result[i + 2]; + if (pt0 instanceof Navi3DPointFat) { + fatPt0 = pt0; + } + if (pt1 instanceof Navi3DPointFat) { + fatPt1 = pt1; + } + if (pt2 instanceof Navi3DPointFat) { + fatPt2 = pt2; + } + + if (fatPt0) { + edgePt0 = fatPt0.ownerPoint; + } + if (fatPt1) { + edgePt1 = fatPt1.ownerPoint; + } + if (fatPt2) { + edgePt2 = fatPt2.ownerPoint; + } + + if (edgePt0 && edgePt1 && edgePt0 == edgePt1 && edgePt1 != edgePt2) { + checkEnable = true; + } + + if (edgePt2 && edgePt1 && edgePt2 == edgePt1 && edgePt0 != edgePt1) { + checkEnable = true; + } + + if (checkEnable) { + Navi3DFunnel.CROSS_TEST_DIRECTION.copyFrom(pt0); + Navi3DFunnel.CROSS_TEST_DIRECTION.decrementBy(pt2); + centerEdge = fatPt1.ownerEdge; + + checkEnable = this._router.hasCrossPoint(centerEdge.pointA, centerEdge.pointB, pt2, Navi3DFunnel.CROSS_TEST_DIRECTION); + if (checkEnable) { + optimusPoint = this._router.calcCrossPointOut(edgePt1, pt1, pt2, Navi3DFunnel.CROSS_TEST_DIRECTION); + } + if (optimusPoint) { + optimusResult[i + 1] = optimusPoint; + } + } + } + } + + private getFatPoint(edge: Navi3DEdge, target: Vector3): Navi3DPointFat { + if (edge == null) + return null; + var fatPoint: Navi3DPointFat; + if (target instanceof Navi3DPointFat) { + fatPoint = target; + } + var edgePoint: Navi3DPoint; + if (fatPoint) { + edgePoint = fatPoint.ownerPoint; + } + else { + edgePoint = edge.getEqualPoint(target); + } + + if (edgePoint == null) + return null; + fatPoint = edge.getFatPoint(edgePoint); + return fatPoint; + } + + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DMaskType.ts b/src/math/navigation/Navi3DMaskType.ts new file mode 100644 index 00000000..ba980ba4 --- /dev/null +++ b/src/math/navigation/Navi3DMaskType.ts @@ -0,0 +1,3 @@ +export class Navi3DMaskType { + public static WalkAble: number = 1; +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DMergeVertex.ts b/src/math/navigation/Navi3DMergeVertex.ts new file mode 100644 index 00000000..3d2c00e9 --- /dev/null +++ b/src/math/navigation/Navi3DMergeVertex.ts @@ -0,0 +1,63 @@ +import { GeometryBase } from "../../core/geometry/GeometryBase"; +import { VertexAttributeName } from "../../core/geometry/VertexAttributeName"; +import { Vector3 } from "../Vector3"; + +export class Navi3DMergeVertex { + vertex: Vector3[]; + indices: number[]; + + merge(geometry: GeometryBase, threshould: number = 0.1): this { + let vertex = geometry.getAttribute(VertexAttributeName.position).data; + this.makeOriginVertex(vertex); + + let sameVertexIndex: Map = new Map(); + let redirectionIndex: number[] = []; + let mergePointCount: number = 0; + for (let i = 0, c = this.vertex.length; i < c; i++) { + let item = this.vertex[i]; + let samePointIndex = -1; + sameVertexIndex.forEach((v, i) => { + let distance = Vector3.distance(v, item); + if (distance < threshould) { + samePointIndex = i; + } + }) + if (samePointIndex > -1) { + redirectionIndex[i] = samePointIndex; + // console.log('points merged:', i, samePointIndex); + mergePointCount++; + } else { + sameVertexIndex.set(i, item); + redirectionIndex[i] = i; + } + } + console.log('mergePointCount:', mergePointCount); + + //force modify indices + this.indices = []; + let indices = geometry.getAttribute(VertexAttributeName.indices).data; + for (const i of indices) { + this.indices.push(redirectionIndex[i]); + } + return this; + } + + parse(geometry: GeometryBase): this { + let vertex = geometry.getAttribute(VertexAttributeName.position).data; + this.makeOriginVertex(vertex); + this.indices = []; + let indices = geometry.getAttribute(VertexAttributeName.indices).data; + for (const i of indices) { + this.indices.push(i); + } + return this; + } + + private makeOriginVertex(source) { + this.vertex = []; + for (let i = 0, c = source.length / 3; i < c; i++) { + let v = new Vector3(source[i * 3], source[i * 3 + 1], source[i * 3 + 2]); + this.vertex.push(v); + } + } +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DMesh.ts b/src/math/navigation/Navi3DMesh.ts new file mode 100644 index 00000000..dc8e37d2 --- /dev/null +++ b/src/math/navigation/Navi3DMesh.ts @@ -0,0 +1,167 @@ +import { IQuadNode } from "../../core/tree/quad/IQuadNode"; +import { QuadRoot } from "../../core/tree/quad/QuadRoot"; +import { Vector3 } from "../Vector3"; +import { DoubleArray } from "./DoubleArray"; +import { Navi3DAstar } from "./Navi3DAstar"; +import { Navi3DEdge } from "./Navi3DEdge"; +import { Navi3DFunnel } from "./Navi3DFunnel"; +import { Navi3DPoint } from "./Navi3DPoint"; +import { Navi3DTriangle } from "./Navi3DTriangle"; + +export class Navi3DMesh { + + private _nav3dPoints: Array; + private _nav3dEdges: Array; + private _nav3dTriangles: Array; + private _path: Array; + private _edgesDict: DoubleArray; + + private _nav3dAstar: Navi3DAstar; + + private _nav3dFunnel: Navi3DFunnel; + + private _terrainQuad: QuadRoot; + + private _triangleList: Array; + + public get edges(): Array { + return this._nav3dEdges; + } + + public get points(): Array { + return this._nav3dPoints; + } + + public get path(): Array { + return this._path; + } + + public get triangles(): Array { + return this._nav3dTriangles; + } + + constructor(pointList: Array, triangleIndexList: Array>) { + this._nav3dPoints = new Array(); + this._nav3dEdges = new Array(); + this._nav3dTriangles = new Array(); + this._edgesDict = new DoubleArray(); + + this.initPoints(pointList); + this.initEdgesAndTriangles(triangleIndexList); + + this.createConnections(); + + + this._nav3dAstar = new Navi3DAstar(); + this._nav3dFunnel = new Navi3DFunnel(); + + + this._terrainQuad = new QuadRoot(8, 128); + this._terrainQuad.createQuadTree(this._nav3dTriangles); + } + + public getTriangleAtPoint(point: Vector3, threshold: number = 5): IQuadNode { + return this._terrainQuad.getTriangleAtPoint(point, threshold); + } + + public findPath(startPt: Vector3, endPt: Vector3, aiRadius: number = 5): boolean { + this._path = null; + this._triangleList = null; + + var startNode: Navi3DTriangle = this.getTriangleAtPoint(startPt, 10) as any; + var endNode: Navi3DTriangle = this.getTriangleAtPoint(endPt, 10) as any; + + var success: boolean = this._nav3dAstar.findPath(this, startNode, endNode); + if (success) { + this._triangleList = this._nav3dAstar.channel; + success = this._nav3dFunnel.searchPath(startPt, endPt, this._triangleList, aiRadius); + this._path = this._nav3dFunnel.path; + return success; + } + return false; + } + + private initPoints(pointList: Array): void { + var point: Vector3; + var nevPoint: Navi3DPoint; + var count: number = pointList.length; + for (var i: number = 0; i < count; i++) { + point = pointList[i]; + nevPoint = new Navi3DPoint(i, point.x, point.y, point.z); + this._nav3dPoints.push(nevPoint); + } + } + + private initEdgesAndTriangles(triangleIndexList: Array>): void { + var indexOrderList: Array; + + var edge0: Navi3DEdge; + var edge1: Navi3DEdge; + var edge2: Navi3DEdge; + + var triangle: Navi3DTriangle; + + var count: number = triangleIndexList.length; + for (var i: number = 0; i < count; i++) { + indexOrderList = triangleIndexList[i]; + edge0 = this.tryCreateEdge(indexOrderList[0], indexOrderList[1]); + edge1 = this.tryCreateEdge(indexOrderList[1], indexOrderList[2]); + edge2 = this.tryCreateEdge(indexOrderList[2], indexOrderList[0]); + + if (edge0 == null || edge1 == null || edge2 == null) + continue; + triangle = new Navi3DTriangle(i, edge0, edge1, edge2); + this._nav3dTriangles.push(triangle); + } + } + + private tryCreateEdge(pointAId: number, pointBId: number): Navi3DEdge { + if (pointAId == pointBId) { + throw new Error("edge point index error!!!"); + } + if (pointAId > pointBId) { + var tempId: number = pointAId; + pointAId = pointBId; + pointBId = tempId; + } + var edge: Navi3DEdge = this._edgesDict.getValueByKey(pointAId + "_" + pointBId); + if (edge == null) { + edge = new Navi3DEdge(this._nav3dPoints[pointAId], this._nav3dPoints[pointBId]); + this._nav3dEdges.push(edge); + this._edgesDict.put(pointAId + "_" + pointBId, edge); + + } + return edge; + } + + private createConnections(): void { + var triangleACount: number = this._nav3dTriangles.length; + var triangleBCount: number = this._nav3dTriangles.length; + var triangleA: Navi3DTriangle; + var triangleB: Navi3DTriangle; + var edge: Navi3DEdge; + var publicEdge: Navi3DEdge; + + for (var i: number = 0; i < triangleACount; i++) { + //边上面记录拥有这条边的三角形 + triangleA = this._nav3dTriangles[i]; + for (edge of triangleA.edges) { + edge.addTriangleOwners(triangleA); + } + + for (var j: number = 0; j < triangleBCount; j++) { + //三角形相邻关系 + triangleB = this._nav3dTriangles[j]; + if (triangleA == triangleB) + continue; + publicEdge = triangleA.loopPublicEdge(triangleB); + if (publicEdge) { + triangleA.addNeibour(publicEdge, triangleB); + triangleB.addNeibour(publicEdge, triangleA); + } + } + } + + } + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DPoint.ts b/src/math/navigation/Navi3DPoint.ts new file mode 100644 index 00000000..ce54494e --- /dev/null +++ b/src/math/navigation/Navi3DPoint.ts @@ -0,0 +1,36 @@ +import { Vector3 } from "../Vector3"; +import { Navi3DConst } from "./Navi3DConst"; + +export class Navi3DPoint extends Vector3 { + + public static CALC_VECTOR3D1: Vector3 = new Vector3(); + + public static CALC_VECTOR3D2: Vector3 = new Vector3(); + + public static CALC_VECTOR3D3: Vector3 = new Vector3(); + + public static CALC_VECTOR3D4: Vector3 = new Vector3(); + + public static CALC_VECTOR3D5: Vector3 = new Vector3(); + + private _pointId: number = 0; + + constructor(id: number, X: number, Y: number, Z: number) { + super(X, Y, Z, 0); + this._pointId = id; + } + + public get id(): number { + return this._pointId; + } + + public static equalPoint(p1: Vector3, p2: Vector3): boolean { + return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z) < Navi3DConst.POWER_EPSILON; + } + + public static calcDistance(pt1: Vector3, pt2: Vector3): number { + Navi3DPoint.CALC_VECTOR3D3.setTo(pt1.x - pt2.x, pt1.y - pt2.y, pt1.z - pt2.z); + return Navi3DPoint.CALC_VECTOR3D3.length; + } + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DPoint2D.ts b/src/math/navigation/Navi3DPoint2D.ts new file mode 100644 index 00000000..ce9ac6cb --- /dev/null +++ b/src/math/navigation/Navi3DPoint2D.ts @@ -0,0 +1,36 @@ +export class Navi3DPoint2D { + public x: number; + + public y: number; + + public setTo(X: number, Y: number): void { + this.x = X; + this.y = Y; + } + + public equals(X: number, Y: number): boolean { + return X == this.x && Y == this.y; + } + + public equalPoint(pt: Navi3DPoint2D): boolean { + return this.equals(pt.x, pt.y); + } + + public get length(): number { + return Math.sqrt(this.x * this.x + this.y * this.y); + } + + public clone(): Navi3DPoint2D { + var point: Navi3DPoint2D = new Navi3DPoint2D(); + point.setTo(this.x, this.y); + return point; + } + + public normalize(): void { + var size: number = length; + if (size == 0) + return; + this.setTo(this.x / size, this.y / size); + } + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DPointFat.ts b/src/math/navigation/Navi3DPointFat.ts new file mode 100644 index 00000000..76725f6a --- /dev/null +++ b/src/math/navigation/Navi3DPointFat.ts @@ -0,0 +1,36 @@ +import { Navi3DEdge } from "./Navi3DEdge"; +import { Navi3DPoint } from "./Navi3DPoint"; + +export class Navi3DPointFat extends Navi3DPoint { + + private _ownerPoint: Navi3DPoint; + private _ownerEdge: Navi3DEdge; + + public radius: number = 0; + + constructor(_point: Navi3DPoint, _edge: Navi3DEdge) { + super(_point.id, 0, 0, 0); + this._ownerEdge = _edge; + this._ownerPoint = _point; + } + + public get ownerPoint(): Navi3DPoint { + return this._ownerPoint; + } + + public get ownerEdge(): Navi3DEdge { + return this._ownerEdge; + } + + public scalePoint(value: number = 0.7): Navi3DPointFat { + var point: Navi3DPointFat = new Navi3DPointFat(this._ownerPoint, this._ownerEdge); + point.copyFrom(this); + point.decrementBy(this._ownerPoint); + point.scaleBy(value); + point.radius = point.length; + point.incrementBy(this._ownerPoint); + return point; + + } + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DRouter.ts b/src/math/navigation/Navi3DRouter.ts new file mode 100644 index 00000000..91d5ba3b --- /dev/null +++ b/src/math/navigation/Navi3DRouter.ts @@ -0,0 +1,218 @@ +import { Vector3 } from "../Vector3"; +import { Navi3DEdge } from "./Navi3DEdge"; +import { Navi3DPoint } from "./Navi3DPoint"; + +export class Navi3DRouter { + + public endPoint: Vector3; + + public curPoint: Vector3; + + public rayA: Vector3; + + public rayB: Vector3; + + public rayAPoint: Navi3DPoint; + + public rayBPoint: Navi3DPoint; + + public static RAY_1: Vector3 = new Vector3(); + + public static RAY_2: Vector3 = new Vector3(); + + public static TEST_RAY: Vector3 = new Vector3(); + + public static TEST_RAY_1: Vector3 = new Vector3(); + + public static TEST_RAY_2: Vector3 = new Vector3(); + + private static CALC_CROSS_POINT: Vector3 = new Vector3(); + + private static CALC_CROSS_TEST: Vector3 = new Vector3(); + + public cornerPoint: Navi3DPoint; + + public cornerEdge: Navi3DEdge; + + public continuePass(fromPt: Vector3, endPt: Vector3, fromEdge: Navi3DEdge): void { + this.resetData(); + this.curPoint = fromPt; + this.endPoint = endPt; + this.cornerEdge = fromEdge; + } + + public passEdge(commonEdge: Navi3DEdge, nextCommonEdge: Navi3DEdge, targetPoint: Vector3, lastEdge: boolean): boolean { + if (this.rayA == null || this.rayB == null) { + this.rayA = Navi3DRouter.RAY_1; + this.rayB = Navi3DRouter.RAY_2; + this.rayAPoint = commonEdge.pointA; + this.rayBPoint = commonEdge.pointB; + + this.rayA.setTo(this.rayAPoint.x - this.curPoint.x, 0, this.rayAPoint.z - this.curPoint.z); + this.rayB.setTo(this.rayBPoint.x - this.curPoint.x, 0, this.rayBPoint.z - this.curPoint.z); + } + + if (lastEdge) { + return this.checkEndPoint(targetPoint); + } + + Navi3DRouter.TEST_RAY.setTo(targetPoint.x - this.curPoint.x, 0, targetPoint.z - this.curPoint.z); + + if (this.isPointAtCenter(Navi3DRouter.TEST_RAY, this.rayA, this.rayB)) { + if (!this.hasCrossPoint(nextCommonEdge.pointA, nextCommonEdge.pointB, this.rayAPoint, this.rayA)) { + this.rayA.copyFrom(Navi3DRouter.TEST_RAY); + if (targetPoint instanceof Navi3DPoint) { + this.rayAPoint = targetPoint; + } + else { + this.rayAPoint = null; + } + + } + else { + this.rayB.copyFrom(Navi3DRouter.TEST_RAY); + if (targetPoint instanceof Navi3DPoint) { + this.rayBPoint = targetPoint; + } + else { + this.rayBPoint = null; + } + } + + var anotherPoint: Navi3DPoint = nextCommonEdge.getAnotherPoint(targetPoint); + Navi3DRouter.TEST_RAY.setTo(anotherPoint.x - this.curPoint.x, 0, anotherPoint.z - this.curPoint.z); + if (anotherPoint == this.rayAPoint || anotherPoint == this.rayBPoint || this.isPointAtCenter(Navi3DRouter.TEST_RAY, this.rayA, this.rayB)) { + this.cornerEdge = nextCommonEdge; + } + } + else { + var needReturn: boolean; + Navi3DRouter.TEST_RAY_1.copyFrom(nextCommonEdge.pointA); + Navi3DRouter.TEST_RAY_1.decrementBy(this.curPoint); + Navi3DRouter.TEST_RAY_2.copyFrom(nextCommonEdge.pointB); + Navi3DRouter.TEST_RAY_2.decrementBy(this.curPoint); + Navi3DRouter.TEST_RAY_1.y = 0; + Navi3DRouter.TEST_RAY_2.y = 0; + if (this.isPointAtCenter(this.rayA, Navi3DRouter.TEST_RAY_1, Navi3DRouter.TEST_RAY_2) + || this.isPointAtCenter(this.rayB, Navi3DRouter.TEST_RAY_1, Navi3DRouter.TEST_RAY_2)) { + needReturn = false; + } + else { + needReturn = true; + } + + if (needReturn) { + if (this.isPointAtCenter(this.rayA, Navi3DRouter.TEST_RAY, this.rayB)) { + this.cornerPoint = this.rayAPoint; + } + else { + this.cornerPoint = this.rayBPoint; + } + + this.cornerEdge.crossPoint = this.cornerPoint; + return false; + } + } + return true; + } + + private checkEndPoint(targetPoint: Vector3): boolean { + + Navi3DRouter.TEST_RAY.setTo(targetPoint.x - this.curPoint.x, 0, targetPoint.z - this.curPoint.z); + if (this.isPointAtCenter(Navi3DRouter.TEST_RAY, this.rayA, this.rayB)) { + // + } + else { + if (this.isPointAtCenter(this.rayA, Navi3DRouter.TEST_RAY, this.rayB)) { + this.cornerPoint = this.rayAPoint; + } + else { + this.cornerPoint = this.rayBPoint; + } + this.cornerEdge.crossPoint = this.cornerPoint; + return false; + } + return true; + } + + public calcCrossEdge(_edge: Navi3DEdge, linePoint: Vector3, lineDirection: Vector3): Vector3 { + return this.calcCrossPoint(_edge.fatPointA, _edge.fatPointB, linePoint, lineDirection); + } + + public calcCrossPoint(segmentPt1: Vector3, segmentPt2: Vector3, linePoint: Vector3, lineDirection: Vector3): Vector3 { + Navi3DRouter.CALC_CROSS_POINT.copyFrom(segmentPt2); + Navi3DRouter.CALC_CROSS_POINT.decrementBy(segmentPt1); + + let distance = Navi3DRouter.CALC_CROSS_POINT.x * lineDirection.z - lineDirection.x * Navi3DRouter.CALC_CROSS_POINT.z; + var scale: number = 0; + if (distance != 0) { + scale = ((segmentPt1.z - linePoint.z) * lineDirection.x - (segmentPt1.x - linePoint.x) * lineDirection.z) / distance; + } + + if (scale > 1) { + scale = 1; + } + else if (scale < 0) { + scale = 0; + } + Navi3DRouter.CALC_CROSS_POINT.scaleBy(scale); + Navi3DRouter.CALC_CROSS_POINT.incrementBy(segmentPt1); + return Navi3DRouter.CALC_CROSS_POINT.clone(); + } + + public calcCrossPointOut(segmentPt1: Vector3, segmentPt2: Vector3, linePoint: Vector3, lineDirection: Vector3): Vector3 { + Navi3DRouter.CALC_CROSS_POINT.copyFrom(segmentPt2); + Navi3DRouter.CALC_CROSS_POINT.decrementBy(segmentPt1); + + var scale: number = ((segmentPt1.z - linePoint.z) * lineDirection.x - (segmentPt1.x - linePoint.x) * lineDirection.z) / + (Navi3DRouter.CALC_CROSS_POINT.x * lineDirection.z - lineDirection.x * Navi3DRouter.CALC_CROSS_POINT.z); + + if (scale <= 1 && scale >= 0) { + return null; + } + Navi3DRouter.CALC_CROSS_POINT.scaleBy(scale); + Navi3DRouter.CALC_CROSS_POINT.incrementBy(segmentPt1); + return Navi3DRouter.CALC_CROSS_POINT.clone(); + } + + public hasCrossPoint(segmentPt1: Vector3, segmentPt2: Vector3, linePoint: Vector3, lineDirection: Vector3): boolean { + Navi3DRouter.CALC_CROSS_TEST.copyFrom(segmentPt2); + Navi3DRouter.CALC_CROSS_TEST.decrementBy(segmentPt1); + + var scale: number = ((segmentPt1.z - linePoint.z) * lineDirection.x - (segmentPt1.x - linePoint.x) * lineDirection.z) / + (Navi3DRouter.CALC_CROSS_TEST.x * lineDirection.z - lineDirection.x * Navi3DRouter.CALC_CROSS_TEST.z); + return scale <= 1 && scale >= 0; + } + + private isPointAtCenter(point: Vector3, vectorA: Vector3, vectorB: Vector3): boolean { + var cp1: Vector3 = vectorA.crossProduct(point); + if (cp1.length == 0 && point.length < vectorA.length) { + return true; + } + + var cp2: Vector3 = vectorB.crossProduct(point); + if (cp2.length == 0 && point.length < vectorB.length) { + return true; + } + + cp1.normalize(); + cp2.normalize(); + cp1.incrementBy(cp2); + + return cp1.length < 0.01; + } + + public resetData(): void { + this.cornerEdge = null; + this.cornerPoint = null; + + this.curPoint = null; + this.rayA = this.rayB = null; + this.rayAPoint = this.rayBPoint = null; + + Navi3DRouter.RAY_1.setTo(0, 0, 0); + Navi3DRouter.RAY_2.setTo(0, 0, 0); + } + + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DTriangle.ts b/src/math/navigation/Navi3DTriangle.ts new file mode 100644 index 00000000..d2c8d783 --- /dev/null +++ b/src/math/navigation/Navi3DTriangle.ts @@ -0,0 +1,222 @@ +import { IQuadNode } from "../../core/tree/quad/IQuadNode"; +import { QuadAABB } from "../../core/tree/quad/QuadAABB"; +import { Plane3D } from "../Plane3D"; +import { Vector3 } from "../Vector3"; +import { DoubleArray } from "./DoubleArray"; +import { Navi3DEdge } from "./Navi3DEdge"; +import { Navi3DMaskType } from "./Navi3DMaskType"; +import { Navi3DPoint } from "./Navi3DPoint"; +import { Navi3DPoint2D } from "./Navi3DPoint2D"; + +export class Navi3DTriangle extends Vector3 implements IQuadNode { + + private _id: number = 0; + private _plane: Plane3D; + private _points: Array = new Array(); + + private _edges: Array = new Array(); + + private _neibourTriangles: DoubleArray = new DoubleArray(); + + private _pointAgainstEdge: DoubleArray = new DoubleArray(); + + private _edgeAgainstPoint: DoubleArray = new DoubleArray(); + + private _mask: number = 0; + + private _aabbBox: QuadAABB; + + public f: number = 0; + + public gg: number = 0; + + public h: number = 0; + + public parent: Navi3DTriangle; + + public costMultiplier: number = 1.0; + + public openId: number = 0; + + public closeId: number = 0; + + public get aabb(): QuadAABB { + return this._aabbBox; + } + + public initAABB(): void { + this._aabbBox = new QuadAABB(); + //添加节点 + this._aabbBox.addPoint(this._points[0]); + this._aabbBox.addPoint(this._points[1]); + this._aabbBox.addPoint(this._points[2]); + } + + public calcGlobalQuadAABB(): void { + } + + public get isTriangle(): boolean { + return true; + } + + constructor(Id: number, edgeA: Navi3DEdge, edgeB: Navi3DEdge, edgeC: Navi3DEdge) { + super(0, 0, 0, 0); + + this._id = Id; + this._mask = Navi3DMaskType.WalkAble; + this._edges.push(edgeA, edgeB, edgeC); + var edge: Navi3DEdge; + for (edge of this._edges) { + if (this._points.indexOf(edge.pointA) == -1) { + this._points.push(edge.pointA); + } + if (this._points.indexOf(edge.pointB) == -1) { + this._points.push(edge.pointB); + } + } + + this.x = (this._points[0].x + this._points[1].x + this._points[2].x) / 3; + this.y = (this._points[0].y + this._points[1].y + this._points[2].y) / 3; + this.z = (this._points[0].z + this._points[1].z + this._points[2].z) / 3; + + this._plane = new Plane3D(); + this._plane.fromPoints(this._points[0], this._points[1], this._points[2]); + this._plane.normalize(); + + this.genarateAgainstData(); + + this.initAABB(); + } + + private genarateAgainstData(): void { + var edge: Navi3DEdge; + var point: Navi3DPoint; + for (edge of this._edges) { + for (point of this._points) { + if (edge.pointA != point && edge.pointB != point) { + this._edgeAgainstPoint.put(edge, point); + this._pointAgainstEdge.put(point, edge); + } + } + } + } + + public get id(): number { + return this._id; + } + + public get plane(): Plane3D { + return this._plane; + } + + public get points(): Array { + return this._points; + } + + public addNeibour(edge: Navi3DEdge, triangle: Navi3DTriangle): void { + if (this._edges.indexOf(edge) >= 0) { + this._neibourTriangles.put(edge, triangle); + } + else { + throw new Error("the edge is not in triangle!!!"); + } + } + + public getNeibourTriangles(list: Array = null, edgeMask: number = 1, triangleMask: number = 1): Array { + list = list || new Array(); + list.length = 0; + var neibour: Navi3DTriangle; + var edge: Navi3DEdge; + var keys: Array = this._neibourTriangles.getKeys(); + var obj: any; + for (obj of keys) { + edge = obj; + if (edge.testMask(edgeMask)) { + neibour = this._neibourTriangles.getValueByKey(edge); + if (neibour.testMask(triangleMask)) { + list.push(neibour); + } + } + } + return list; + + } + + public getEdges(list: Array = null, edgeMask: number = 1): Array { + list = list || new Array(); + list.length = 0; + var edge: Navi3DEdge; + for (edge of this._edges) { + if (edge.testMask(edgeMask)) { + list.push(edge); + } + } + return list; + } + + public get walkAble(): boolean { + return this.testMask(Navi3DMaskType.WalkAble); + } + + public get edges(): Array { + return this._edges; + } + + public testMask(value: number): boolean { + return (this._mask & value) == value; + } + + public getEdgeAgainstPoint(edge: Navi3DEdge): Navi3DPoint { + return this._edgeAgainstPoint.getValueByKey(edge); + } + + public getPointAgainstEdge(point: Navi3DPoint): Navi3DEdge { + return this._pointAgainstEdge.getValueByKey(point); + } + + public getPublicEdge(triangle: Navi3DTriangle): Navi3DEdge { + if (triangle && triangle != this) { + var keys: Array = this._neibourTriangles.getKeys(); + var obj: any; + for (obj of keys) { + if (this._neibourTriangles.getValueByKey(obj) == triangle) + return obj; + } + } + return null; + } + + public loopPublicEdge(triangle: Navi3DTriangle): Navi3DEdge { + var edgeA: Navi3DEdge; + var edgeB: Navi3DEdge; + if (triangle && triangle != this) { + for (edgeA of this._edges) { + for (edgeB of triangle._edges) { + if (edgeA == edgeB) + return edgeA; + } + } + } + return null; + } + + public randomPoint(): Vector3 { + var pt0: Vector3 = this._points[2].subtract(this._points[0]); + // if(Math.random() > 0.5) + { + pt0.scaleBy(Math.random()); + } + pt0.incrementBy(this._points[0]); + + var pt1: Vector3 = this._points[1].subtract(pt0); + + // if(Math.random() > 0.5) + { + pt1.scaleBy(Math.random()); + } + pt1.incrementBy(pt0); + + return pt1; + } + +} \ No newline at end of file diff --git a/src/setting/EngineSetting.ts b/src/setting/EngineSetting.ts index 24a578bd..932afe8e 100644 --- a/src/setting/EngineSetting.ts +++ b/src/setting/EngineSetting.ts @@ -1,5 +1,6 @@ import { GlobalIlluminationSetting } from "./GlobalIlluminationSetting"; import { LightSetting } from "./LightSetting"; +import { LoaderSetting } from "./LoaderSetting"; import { MaterialSetting } from "./MaterialSetting"; import { OcclusionQuerySetting } from "./OcclusionQuerySetting"; import { PickSetting } from "./PickSetting"; @@ -48,4 +49,9 @@ export type EngineSetting = { * @internal */ material: MaterialSetting; + + /** + * loader setting + */ + loader: LoaderSetting; } \ No newline at end of file diff --git a/src/setting/LoaderSetting.ts b/src/setting/LoaderSetting.ts new file mode 100644 index 00000000..eb6489ea --- /dev/null +++ b/src/setting/LoaderSetting.ts @@ -0,0 +1,11 @@ + +/** + * Loader Setting + * @group Setting + */ +export type LoaderSetting = { + /** + * Number of concurrent loading + */ + numConcurrent: number; +}; diff --git a/src/setting/RenderSetting.ts b/src/setting/RenderSetting.ts index 2bfc6e8c..f050347a 100644 --- a/src/setting/RenderSetting.ts +++ b/src/setting/RenderSetting.ts @@ -1,10 +1,10 @@ -import { BloomSetting } from "./post/BloomSetting"; import { DepthOfViewSetting } from "./post/DepthOfViewSetting"; import { GlobalFogSetting } from "./post/GlobalFogSetting"; import { GTAOSetting } from "./post/GTAOSetting"; import { OutlineSetting } from "./post/OutlineSetting"; import { SSRSetting } from "./post/SSRSetting"; import { TAASetting } from "./post/TAASetting"; +import { BloomSetting } from "./post/BloomSetting"; export type RenderSetting = { debug: boolean; @@ -30,7 +30,7 @@ export type RenderSetting = { */ postProcessing: { enable?: boolean; - bloom?: BloomSetting; + bloom?: BloomSetting, ssao?: { debug: any; enable: boolean; diff --git a/src/setting/ShadowSetting.ts b/src/setting/ShadowSetting.ts index f287a342..c0d7e3cf 100644 --- a/src/setting/ShadowSetting.ts +++ b/src/setting/ShadowSetting.ts @@ -46,6 +46,10 @@ export type ShadowSetting = { * shadow mapping Size */ shadowSize: number; + /** + * shadow depth offset bias + */ + shadowBias: number; /** * Shadow softness */ diff --git a/src/setting/post/BloomSetting.ts b/src/setting/post/BloomSetting.ts index 2d480a56..11b75e6e 100644 --- a/src/setting/post/BloomSetting.ts +++ b/src/setting/post/BloomSetting.ts @@ -4,37 +4,12 @@ * @group Setting */ export type BloomSetting = { - /** - * enable - */ - enable: boolean; - /** - * Screen horizontal blur radius - */ - blurX: number; - /** - * Screen vertical blur radius - */ - blurY: number; - /** - * Strength setting - */ - strength: number; - - /** - * exposure setting - */ - exposure?: number; - /** - * Radius setting - */ - radius: number; - /** - * Luminosity threshold - */ - luminosityThreshold: number; - /** - * use debug or not - */ - debug: boolean; + enable?: boolean, + downSampleStep: number; + downSampleBlurSize: number; + downSampleBlurSigma: number; + upSampleBlurSize: number; + upSampleBlurSigma: number; + luminanceThreshole: number; + bloomIntensity: number; }; \ No newline at end of file diff --git a/src/shape/BoxGeometry.ts b/src/shape/BoxGeometry.ts index c68456b2..bce84985 100644 --- a/src/shape/BoxGeometry.ts +++ b/src/shape/BoxGeometry.ts @@ -196,7 +196,10 @@ export class BoxGeometry extends GeometryBase { indexStart: 0, indexCount: indices_arr.length, vertexStart: 0, + vertexCount: 0, + firstStart: 0, index: 0, + topology: 0, }); } diff --git a/src/shape/CylinderGeometry.ts b/src/shape/CylinderGeometry.ts index a03baad7..0a853237 100644 --- a/src/shape/CylinderGeometry.ts +++ b/src/shape/CylinderGeometry.ts @@ -79,7 +79,10 @@ export class CylinderGeometry extends GeometryBase { indexStart: start, indexCount: count, vertexStart: start, + vertexCount: 0, + firstStart: 0, index: index, + topology: 0, }); } diff --git a/src/shape/PlaneGeometry.ts b/src/shape/PlaneGeometry.ts index 3c4b78e2..e308dfa6 100644 --- a/src/shape/PlaneGeometry.ts +++ b/src/shape/PlaneGeometry.ts @@ -146,7 +146,10 @@ export class PlaneGeometry extends GeometryBase { indexStart: 0, indexCount: indices_arr.length, vertexStart: 0, + vertexCount: 0, + firstStart: 0, index: 0, + topology: 0 }); } diff --git a/src/shape/SphereGeometry.ts b/src/shape/SphereGeometry.ts index 645122d8..53913108 100644 --- a/src/shape/SphereGeometry.ts +++ b/src/shape/SphereGeometry.ts @@ -103,7 +103,7 @@ export class SphereGeometry extends GeometryBase { normal_arr[ni++] = z * normLen; uv_arr[ui++] = i / _segmentsW; - uv_arr[ui++] = j / _segmentsH; + uv_arr[ui++] = 1.0 - j / _segmentsH; if (i > 0 && j > 0) { var a: number = (_segmentsW + 1) * j + i; @@ -156,7 +156,10 @@ export class SphereGeometry extends GeometryBase { indexStart: 0, indexCount: indice_arr.length, vertexStart: 0, + vertexCount: 0, + firstStart: 0, index: 0, + topology: 0 }); this.bounds = new BoundingBox(Vector3.ZERO, new Vector3(this.radius * 2, this.radius * 2, this.radius * 2)) diff --git a/src/shape/StripeGeometry.ts b/src/shape/StripeGeometry.ts new file mode 100644 index 00000000..f7a4dc36 --- /dev/null +++ b/src/shape/StripeGeometry.ts @@ -0,0 +1,83 @@ +import { BoundingBox } from "../core/bound/BoundingBox"; +import { GeometryBase } from "../core/geometry/GeometryBase"; +import { VertexAttributeName } from "../core/geometry/VertexAttributeName"; +import { Vector3 } from "../math/Vector3"; + +/** + * Plane geometry + * @group Geometry + */ +export class StripeGeometry extends GeometryBase { + + segments: [Vector3, Vector3][]; + /** + * + * @constructor + * @param width Width of the plane + * @param height Height of the plane + * @param segmentW Number of width segments of a plane + * @param segmentH Number of height segments of a plane + * @param up Define the normal vector of a plane + */ + constructor(segments: [Vector3, Vector3][]) { + super(); + // this.geometrySource = new SerializeGeometrySource().setPrimitive('primitive-plane'); + this.segments = segments; + this.buildGeometry(); + } + + private buildGeometry(): void { + + this.bounds = new BoundingBox(); + let numIndices = (this.segments.length - 1) * 2 * 3; + + let vertexCount = this.segments.length * 2; + let position_arr = new Float32Array(vertexCount * 3); + let normal_arr = new Float32Array(vertexCount * 3); + let uv_arr = new Float32Array(vertexCount * 2); + let indices_arr = new Uint16Array(numIndices); + //210 123 + + let index = 0; + for (let item of this.segments) { + position_arr[index++] = item[0].x; + position_arr[index++] = item[0].y; + position_arr[index++] = item[0].z; + position_arr[index++] = item[1].x; + position_arr[index++] = item[1].y; + position_arr[index++] = item[1].z; + } + + index = 0; + let offset = 0; + while (index < numIndices) { + indices_arr[index++] = 2 + offset; + indices_arr[index++] = 1 + offset; + indices_arr[index++] = 0 + offset; + indices_arr[index++] = 1 + offset; + indices_arr[index++] = 2 + offset; + indices_arr[index++] = 3 + offset; + + offset += 2; + } + + this.setIndices(indices_arr); + this.setAttribute(VertexAttributeName.position, position_arr); + this.setAttribute(VertexAttributeName.normal, normal_arr); + this.setAttribute(VertexAttributeName.uv, uv_arr); + this.setAttribute(VertexAttributeName.TEXCOORD_1, uv_arr); + + this.addSubGeometry({ + indexStart: 0, + indexCount: indices_arr.length, + vertexStart: 0, + vertexCount: 0, + firstStart: 0, + index: 0, + topology: 0, + }); + + this.computeNormals(); + } + +} diff --git a/src/shape/TorusGeometry.ts b/src/shape/TorusGeometry.ts index 8e516f61..169cee0d 100644 --- a/src/shape/TorusGeometry.ts +++ b/src/shape/TorusGeometry.ts @@ -114,7 +114,10 @@ export class TorusGeometry extends GeometryBase { indexStart: 0, indexCount: indicesData.length, vertexStart: 0, + vertexCount: 0, + firstStart: 0, index: 0, + topology: 0, }); } diff --git a/src/textures/BitmapTexture2D.ts b/src/textures/BitmapTexture2D.ts index 15751ede..06f30a03 100644 --- a/src/textures/BitmapTexture2D.ts +++ b/src/textures/BitmapTexture2D.ts @@ -10,6 +10,7 @@ import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; */ export class BitmapTexture2D extends Texture { private _source: HTMLCanvasElement | ImageBitmap | OffscreenCanvas | HTMLImageElement; + public premultiplyAlpha: PremultiplyAlpha = 'none'; /** * @constructor @@ -18,6 +19,10 @@ export class BitmapTexture2D extends Texture { constructor(useMipmap: boolean = true) { super(); this.useMipmap = useMipmap; + + this.lodMinClamp = 0; + this.lodMaxClamp = 4; + // this.visibility = GPUShaderStage.COMPUTE | GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT; } @@ -37,7 +42,7 @@ export class BitmapTexture2D extends Texture { if (this._source instanceof HTMLImageElement) { this._source.decode().then(async () => { if (this._source instanceof HTMLImageElement) { - const imageBitmap = await createImageBitmap(this._source, { imageOrientation: this.flipY ? "flipY" : "from-image" }); + const imageBitmap = await createImageBitmap(this._source, { imageOrientation: this.flipY ? "flipY" : "from-image", premultiplyAlpha: 'none' }); this.generate(imageBitmap); } }); @@ -55,6 +60,7 @@ export class BitmapTexture2D extends Texture { * @param loaderFunctions callback function when load complete */ public async load(url: string, loaderFunctions?: LoaderFunctions) { + this.name = StringUtil.getURLName(url); if (url.indexOf(';base64') != -1) { const img = document.createElement('img'); let start = url.indexOf('data:image'); @@ -66,25 +72,32 @@ export class BitmapTexture2D extends Texture { const imageBitmap = await createImageBitmap(img, { resizeWidth: img.width, resizeHeight: img.height, - imageOrientation: this.flipY ? "flipY" : "from-image" + imageOrientation: this.flipY ? "flipY" : "from-image", + premultiplyAlpha: 'none' }); this.format = GPUTextureFormat.rgba8unorm; this.generate(imageBitmap); } else { - const r = await fetch(url, { - headers: Object.assign({ - 'Accept': 'image/avif,image/webp,*/*' - }, loaderFunctions?.headers) - }); - // const img = await r.blob(); - // await this.loadFromBlob(img); - let chunks = await LoaderBase.read(url, r, loaderFunctions); - let img = new Blob([chunks], { type: 'image/jpeg' }); - chunks = null; + return new Promise((succ, fial) => { + fetch(url, { + headers: Object.assign({ + 'Accept': 'image/avif,image/webp,*/*' + }, loaderFunctions?.headers) + }).then((r) => { + // const img = await r.blob(); + // await this.loadFromBlob(img); + LoaderBase.read(url, r, loaderFunctions).then((chunks) => { + let img = new Blob([chunks], { type: 'image/jpeg' }); + chunks = null; + this.loadFromBlob(img).then(() => { + succ(true); + }); + }); + + }) + }) - await this.loadFromBlob(img); } - this.name = StringUtil.getURLName(url); return true; } @@ -96,14 +109,15 @@ export class BitmapTexture2D extends Texture { */ public async loadFromBlob(imgData: Blob) { this.imageData = imgData; - let imageBitmap = await createImageBitmap(imgData, { imageOrientation: this.flipY ? 'flipY' : 'from-image' }); + let imageBitmap = await createImageBitmap(imgData, { imageOrientation: this.flipY ? 'flipY' : 'from-image', premultiplyAlpha: 'none' }); if (imageBitmap.width < 32 || imageBitmap.height < 32) { let width = Math.max(imageBitmap.width, 32); let height = Math.max(imageBitmap.height, 32); imageBitmap = await createImageBitmap(imageBitmap, { resizeWidth: width, resizeHeight: height, - imageOrientation: this.flipY ? "flipY" : "from-image" + imageOrientation: this.flipY ? "flipY" : "from-image", + premultiplyAlpha: 'none' }); } this.format = GPUTextureFormat.rgba8unorm; diff --git a/src/textures/BitmapTexture2DArray.ts b/src/textures/BitmapTexture2DArray.ts index 6a530a84..a07c316c 100644 --- a/src/textures/BitmapTexture2DArray.ts +++ b/src/textures/BitmapTexture2DArray.ts @@ -51,11 +51,11 @@ export class BitmapTexture2DArray extends Texture implements ITexture { if (bitmapTexture.width != this.width || bitmapTexture.height != this.height) { console.error("bitmap texture muse match bitmapTextureArray size!"); } - if (this._bitmapTextures.indexOf(bitmapTexture) == -1) { - bitmapTexture.pid = this._bitmapTextures.length; - this._bitmapTextures.push(bitmapTexture); - this.updateTexture(); - } + // if (this._bitmapTextures.indexOf(bitmapTexture) == -1) { + bitmapTexture.pid = this._bitmapTextures.length; + this._bitmapTextures.push(bitmapTexture); + this.updateTexture(); + // } } /** diff --git a/src/textures/ShadowTexture.ts b/src/textures/ShadowTexture.ts new file mode 100644 index 00000000..2c46720c --- /dev/null +++ b/src/textures/ShadowTexture.ts @@ -0,0 +1,186 @@ +import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; +import { GPUAddressMode, GPUTextureFormat } from '../gfx/graphics/webGpu/WebGPUConst'; +import { webGPUContext } from '../gfx/graphics/webGpu/Context3D'; +import { GPUContext } from '../gfx/renderJob/GPUContext'; +import { UUID } from '../util/Global'; +import { CResizeEvent } from '..'; +/** + * @internal + * Render target texture + * Render what we want to render onto a texture instead of rendering it onto the screen as we usually do + * @group Texture + */ +export class ShadowTexture extends Texture { + public resolveTarget: GPUTextureView; + sampleCount: number; + // storeOp: string = 'store'; + // loadOp: GPULoadOp = `load`; + // clearValue: GPUColor = [0, 0, 0, 0]; + + public clone() { + let texture = new ShadowTexture(this.width, this.height, this.format, this.useMipmap, this.usage, this.numberLayer, this.sampleCount); + texture.name = "clone_" + texture.name; + return texture; + } + + /** + * create virtual texture + * @param width width of texture + * @param height height of texture + * @param format GPUTextureFormat, default value is rgba8unorm + * @param useMipmap whether or not gen mipmap + * @returns + */ + constructor(width: number, height: number, format: GPUTextureFormat = GPUTextureFormat.rgba8unorm, useMipMap: boolean = false, usage?: GPUFlagsConstant, numberLayer: number = 1, sampleCount: number = 0, clear: boolean = true) { + super(width, height, numberLayer); + let device = webGPUContext.device; + this.name = UUID(); + + this.useMipmap = useMipMap; + this.sampleCount = sampleCount; + this.format = format; + this.numberLayer = numberLayer; + + if (usage != undefined) { + this.usage = usage; + } else { + this.usage = usage | GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST; + } + + // if (this.usage & GPUTextureUsage.RENDER_ATTACHMENT || this.format == GPUTextureFormat.depth24plus || this.format == GPUTextureFormat.depth32float) { + // webGPUContext.addEventListener(CResizeEvent.RESIZE, (e) => { + // let { width, height } = e.data; + // this.resize(width, height); + // }, this); + // } + this.resize(width, height); + } + + public resize(width, height) { + let device = webGPUContext.device; + if (this.gpuTexture) { + this.gpuTexture = null; + // Texture.delayDestroyTexture(this.gpuTexture); + this.view = null; + } + + this.width = width; + this.height = height; + + this.createTextureDescriptor(width, height, 1, this.format, this.usage, this.numberLayer, this.sampleCount); + // this.loadOp = clear ? `clear` : `load` + // this.loadOp = `clear` + + this.useMipmap = false; + + this.visibility = GPUShaderStage.COMPUTE | GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT; + + if (this.format == GPUTextureFormat.rgba32float) { + this.samplerBindingLayout.type = `non-filtering`; + this.textureBindingLayout.sampleType = `unfilterable-float`; + this.gpuSampler = device.createSampler({}); + } else if (this.format == GPUTextureFormat.depth32float) { + this.samplerBindingLayout.type = `filtering`; + this.sampler_comparisonBindingLayout.type = `comparison`; + this.textureBindingLayout.sampleType = `depth`; + this.gpuSampler = webGPUContext.device.createSampler({}); + this.gpuSampler_comparison = webGPUContext.device.createSampler({ + compare: 'less', + label: "sampler_comparison" + }); + } else if (this.format == GPUTextureFormat.depth24plus) { + this.samplerBindingLayout = { + type: `filtering`, + } + this.sampler_comparisonBindingLayout = { + type: 'comparison', + } + this.textureBindingLayout.sampleType = `depth`; + this.gpuSampler = webGPUContext.device.createSampler({}); + this.gpuSampler_comparison = webGPUContext.device.createSampler({ + compare: 'less', + label: "sampler_comparison" + }); + } else { + this.samplerBindingLayout.type = `filtering`; + this.textureBindingLayout.sampleType = `float`; + if (this.sampleCount > 0) { + this.textureBindingLayout.multisampled = true; + } + this.minFilter = 'linear'; + this.magFilter = 'linear'; + this.mipmapFilter = `linear`; + this.maxAnisotropy = 16; + + this.addressModeU = GPUAddressMode.clamp_to_edge; + this.addressModeV = GPUAddressMode.clamp_to_edge; + // this.visibility = GPUShaderStage.FRAGMENT; + this.gpuSampler = device.createSampler(this); + } + } + + /** + * create rt texture + * @param width texture width + * @param height texture height + * @param data texture pixel data + * @param useMipmap texture use mipmap switch + * @returns + */ + public create(width: number, height: number, useMiamp: boolean = true) { + let device = webGPUContext.device; + const bytesPerRow = width * 4; + let td = new Float32Array(width * height * 4); + + const textureDataBuffer = device.createBuffer({ + size: td.byteLength, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC, + }); + + device.queue.writeBuffer(textureDataBuffer, 0, td); + const commandEncoder = GPUContext.beginCommandEncoder(); + commandEncoder.copyBufferToTexture( + { + buffer: textureDataBuffer, + bytesPerRow: bytesPerRow, + }, + { + texture: this.getGPUTexture(), + }, + { + width: width, + height: height, + depthOrArrayLayers: 1, + }, + ); + + GPUContext.endCommandEncoder(commandEncoder); + } + + public readTextureToImage() { + let device = webGPUContext.device; + let w = webGPUContext.windowWidth; + let h = webGPUContext.windowHeight; + const bytesPerRow = w * 4; + let td = new Float32Array(w * h * 4); + + const textureBuffer = device.createBuffer({ + size: td.byteLength, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC, + }); + const commandEncoder = GPUContext.beginCommandEncoder(); + commandEncoder.copyTextureToBuffer( + { + texture: this.getGPUTexture() + }, + { + buffer: textureBuffer + }, + [w, h] + ); + + let arryBuffer = textureBuffer.getMappedRange(0, td.byteLength); + return arryBuffer; + } + +} diff --git a/src/textures/VirtualTexture.ts b/src/textures/VirtualTexture.ts index afbd24f3..43b28807 100644 --- a/src/textures/VirtualTexture.ts +++ b/src/textures/VirtualTexture.ts @@ -3,6 +3,7 @@ import { GPUAddressMode, GPUTextureFormat } from '../gfx/graphics/webGpu/WebGPUC import { webGPUContext } from '../gfx/graphics/webGpu/Context3D'; import { GPUContext } from '../gfx/renderJob/GPUContext'; import { UUID } from '../util/Global'; +import { CResizeEvent } from '..'; /** * @internal * Render target texture @@ -11,10 +12,17 @@ import { UUID } from '../util/Global'; */ export class VirtualTexture extends Texture { public resolveTarget: GPUTextureView; + sampleCount: number; // storeOp: string = 'store'; // loadOp: GPULoadOp = `load`; // clearValue: GPUColor = [0, 0, 0, 0]; + public clone() { + let texture = new VirtualTexture(this.width, this.height, this.format, this.useMipmap, this.usage, this.numberLayer, this.sampleCount); + texture.name = "clone_" + texture.name; + return texture; + } + /** * create virtual texture * @param width width of texture @@ -23,19 +31,43 @@ export class VirtualTexture extends Texture { * @param useMipmap whether or not gen mipmap * @returns */ - constructor(width: number, height: number, format: GPUTextureFormat = GPUTextureFormat.rgba8unorm, useMipMap: boolean = false, usage?: number, textureCount: number = 1, sampleCount: number = 0, clear: boolean = true) { - super(width, height, textureCount); + constructor(width: number, height: number, format: GPUTextureFormat = GPUTextureFormat.rgba8unorm, useMipMap: boolean = false, usage?: GPUFlagsConstant, numberLayer: number = 1, sampleCount: number = 0, clear: boolean = true) { + super(width, height, numberLayer); let device = webGPUContext.device; this.name = UUID(); + this.useMipmap = useMipMap; + this.sampleCount = sampleCount; + this.format = format; + this.numberLayer = numberLayer; + if (usage != undefined) { this.usage = usage; } else { - this.usage = GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST; + this.usage = usage | GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST; + } + + if (this.usage & GPUTextureUsage.RENDER_ATTACHMENT || this.format == GPUTextureFormat.depth24plus || this.format == GPUTextureFormat.depth32float) { + webGPUContext.addEventListener(CResizeEvent.RESIZE, (e) => { + let { width, height } = e.data; + this.resize(width, height); + }, this); + } + this.resize(width, height); + } + + public resize(width, height) { + let device = webGPUContext.device; + if (this.gpuTexture) { + Texture.delayDestroyTexture(this.gpuTexture); + this.gpuTexture = null; + this.view = null; } - this.createTextureDescriptor(width, height, 1, format, this.usage, textureCount, sampleCount); + this.width = width; + this.height = height; + this.createTextureDescriptor(width, height, 1, this.format, this.usage, this.numberLayer, this.sampleCount); // this.loadOp = clear ? `clear` : `load` // this.loadOp = `clear` @@ -43,11 +75,11 @@ export class VirtualTexture extends Texture { this.visibility = GPUShaderStage.COMPUTE | GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT; - if (format == GPUTextureFormat.rgba32float) { + if (this.format == GPUTextureFormat.rgba32float) { this.samplerBindingLayout.type = `non-filtering`; this.textureBindingLayout.sampleType = `unfilterable-float`; this.gpuSampler = device.createSampler({}); - } else if (format == GPUTextureFormat.depth32float) { + } else if (this.format == GPUTextureFormat.depth32float) { this.samplerBindingLayout.type = `filtering`; this.sampler_comparisonBindingLayout.type = `comparison`; this.textureBindingLayout.sampleType = `depth`; @@ -56,7 +88,7 @@ export class VirtualTexture extends Texture { compare: 'less', label: "sampler_comparison" }); - } else if (format == GPUTextureFormat.depth24plus) { + } else if (this.format == GPUTextureFormat.depth24plus) { this.samplerBindingLayout = { type: `filtering`, } @@ -72,7 +104,7 @@ export class VirtualTexture extends Texture { } else { this.samplerBindingLayout.type = `filtering`; this.textureBindingLayout.sampleType = `float`; - if (sampleCount > 0) { + if (this.sampleCount > 0) { this.textureBindingLayout.multisampled = true; } this.minFilter = 'linear'; diff --git a/src/util/BytesArray.ts b/src/util/BytesArray.ts new file mode 100644 index 00000000..a282f73c --- /dev/null +++ b/src/util/BytesArray.ts @@ -0,0 +1,290 @@ +import { Color, Matrix4, Quaternion, StringUtil, Vector2, Vector3, Vector4 } from ".."; + +/** + * @internal + * @group Util + */ +export class BytesArray extends DataView { + + public position: number = 0; + public littleEndian?: boolean = true; + constructor(buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number) { + super(buffer, byteOffset, byteLength); + this.position = 0; + this.position += this.byteOffset; + } + + //TODO Improve read/write byte + public readUTF() { + let len = this.readInt32(); + + let b = len % 4; + if (b > 0 && b < 4) { + b = 4 - b; + } + + let ret = ""; + // let count = Math.floor(len / 65535) + 1; + // for (let i = 0; i < count; i++) { + let strBuffer = new Int8Array(this.buffer, this.position, len); + this.position += len * Int8Array.BYTES_PER_ELEMENT; + ret += String.fromCharCode.apply(null, strBuffer); + // } + + this.position += b * Int8Array.BYTES_PER_ELEMENT; + return ret; + } + + public readStringArray() { + let ret: string[] = []; + let len = this.readInt32(); + for (let i = 0; i < len; i++) { + ret.push(this.readUTF()); + } + return ret; + } + + public readByte(): number { + let ret = this.buffer[this.position]; + this.position += 1; + return ret; + } + + public readBoolean(): boolean { + let ret = this.readInt32(); + this.position += 4; + return ret == 1 ? true : false; + } + + public readBytes(byteLen: number) { + let bufferView = new DataView(this.buffer, this.position, byteLen); + this.position += byteLen; + return bufferView.buffer; + } + + public readBytesArray() { + let byteLen = this.readInt32(); + let bufferView = new BytesArray(this.buffer.slice(this.position, this.position + byteLen)); + this.position += byteLen; + return bufferView; + } + + public readUnit8(): number { + let ret = this.getUint8(this.position); + this.position += Uint8Array.BYTES_PER_ELEMENT; + return ret; + } + + public readUnit16(): number { + let ret = this.getUint16(this.position); + this.position += Uint16Array.BYTES_PER_ELEMENT; + return ret; + } + + public readUnit32(): number { + let ret = this.getUint32(this.position); + this.position += Uint32Array.BYTES_PER_ELEMENT; + return ret; + } + + public readInt8(): number { + let ret = this.getInt8(this.position); + this.position += Int8Array.BYTES_PER_ELEMENT; + return ret; + } + + public readInt16(): number { + let ret = this.getInt16(this.position, this.littleEndian); + this.position += Int16Array.BYTES_PER_ELEMENT; + return ret; + } + + + public readInt32(): number { + let ret = this.getInt32(this.position, this.littleEndian); + this.position += Int32Array.BYTES_PER_ELEMENT; + return ret; + } + + public readFloat32(): number { + let ret = this.getFloat32(this.position, this.littleEndian); + this.position += Float32Array.BYTES_PER_ELEMENT; + return ret; + } + + public readFloat64(): number { + let ret = this.getFloat64(this.position, this.littleEndian); + this.position += Float64Array.BYTES_PER_ELEMENT; + return ret; + } + + public readInt32Array(): Int32Array { + let len = this.readInt32(); + let ret = new Int32Array(this.buffer, this.position, len); + ret = ret.slice(0, len); + this.position += ret.byteLength; + return ret; + } + + public readInt32List(): number[] { + let len = this.readInt32(); + let ret = []; + for (let i = 0; i < len; i++) { + ret.push(this.readInt32()); + } + return ret; + } + + public readFloatArray(): number[] { + let len = this.readInt32(); + let ret = []; + for (let i = 0; i < len; i++) { + let v = this.readFloat32(); + ret.push(v); + } + return ret; + } + + public readIntArray(): number[] { + let len = this.readInt32(); + let ret = []; + for (let i = 0; i < len; i++) { + let v = this.readInt32(); + ret.push(v); + } + return ret; + } + + public readVector2int() { + let v = new Vector2(); + v.x = this.readInt32(); + v.y = this.readInt32(); + return v; + } + + public readVector2() { + let v = new Vector2(); + v.x = this.readFloat32(); + v.y = this.readFloat32(); + return v; + } + + public readVector3() { + let v = new Vector3(); + v.x = this.readFloat32(); + v.y = this.readFloat32(); + v.z = this.readFloat32(); + return v; + } + + public readVector3Array() { + let list = []; + let len = this.readInt32(); + for (let i = 0; i < len; i++) { + list.push(this.readVector3()); + } + return list; + } + + public readVector4() { + let v = new Vector4(); + v.x = this.readFloat32(); + v.y = this.readFloat32(); + v.z = this.readFloat32(); + v.w = this.readFloat32(); + return v; + } + + public readVector4Array() { + let list = []; + let len = this.readInt32(); + for (let i = 0; i < len; i++) { + list.push(this.readVector4()); + } + return list; + } + + + public readColor() { + let v = new Color(); + v.r = this.readFloat32(); + v.g = this.readFloat32(); + v.b = this.readFloat32(); + v.a = this.readFloat32(); + return v; + } + + public readColorArray() { + let list = []; + let len = this.readInt32(); + for (let i = 0; i < len; i++) { + list.push(this.readColor()); + } + return list; + } + + public readQuaternion() { + let v = new Quaternion(); + v.x = this.readFloat32(); + v.y = this.readFloat32(); + v.z = this.readFloat32(); + v.w = this.readFloat32(); + return v; + } + + public readQuaternionArray() { + let list = []; + let len = this.readInt32(); + for (let i = 0; i < len; i++) { + list.push(this.readQuaternion()); + } + return list; + } + + public readMatrix44(): Matrix4 { + let m = new Matrix4(); + let rawData = m.rawData; + rawData[0] = this.readFloat32(); + rawData[1] = this.readFloat32(); + rawData[2] = this.readFloat32(); + rawData[3] = this.readFloat32(); + rawData[4] = this.readFloat32(); + rawData[5] = this.readFloat32(); + rawData[6] = this.readFloat32(); + rawData[7] = this.readFloat32(); + rawData[8] = this.readFloat32(); + rawData[9] = this.readFloat32(); + rawData[10] = this.readFloat32(); + rawData[11] = this.readFloat32(); + rawData[12] = this.readFloat32(); + rawData[13] = this.readFloat32(); + rawData[14] = this.readFloat32(); + rawData[15] = this.readFloat32(); + return m; + } + + public readMatrix44Array(): Matrix4[] { + let len = this.readInt32(); + let list = []; + for (let i = 0; i < len; i++) { + let m = this.readMatrix44(); + list.push(m); + } + return list; + } + + public readFloat32Array(len: number): Float32Array { + let ret = new Float32Array(this.buffer, this.position, len); + ret = ret.slice(0, this.byteLength); + this.position += len * Float32Array.BYTES_PER_ELEMENT; + return ret; + } + + public getFloat32Array(): Float32Array { + let ret = new Float32Array(this.buffer, this.byteOffset, this.byteLength / Float32Array.BYTES_PER_ELEMENT); + ret = ret.slice(0, this.byteLength); + return ret; + } + + +} diff --git a/src/util/BytesStream.ts b/src/util/BytesStream.ts deleted file mode 100644 index 8f608c6f..00000000 --- a/src/util/BytesStream.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @internal - * @group Util - */ -export class BytesStream extends DataView { - public position: number = 0; - constructor(buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number) { - super(buffer, byteOffset, byteLength); - } - - //TODO Improve read/write byte -} diff --git a/src/util/GeometryUtil.ts b/src/util/GeometryUtil.ts index 73323f94..a0830db1 100644 --- a/src/util/GeometryUtil.ts +++ b/src/util/GeometryUtil.ts @@ -1,4 +1,4 @@ -import { Matrix4 } from '..'; +import { Matrix4, VertexAttributeName } from '..'; import { GeometryBase } from '../core/geometry/GeometryBase'; import { ShaderReflection } from '../gfx/graphics/webGpu/shader/value/ShaderReflectionInfo'; /** @@ -9,6 +9,53 @@ export class GeometryUtil { } + public static mergeNumber(geometries: GeometryBase, num: number, target?: GeometryBase) { + let targetGeo = target || new GeometryBase(); + + let posLen = geometries.getAttribute(VertexAttributeName.position).data.length / 3; + let meshIndexList = new Float32Array(posLen * num); + for (const iterator of geometries.vertexAttributeMap) { + let attName = iterator[1].attribute; + if (attName == VertexAttributeName.indices) continue; + + let data = geometries.getAttribute(attName).data; + let len = data.length; + let attData = new Float32Array(len * num); + for (let i = 0; i < num; i++) { + attData.set(data, len * i); + for (let ii = 0; ii < posLen; ii++) { + meshIndexList[posLen * i + ii] = i; + } + } + targetGeo.setAttribute(attName, attData); + } + targetGeo.setAttribute(VertexAttributeName.vIndex, meshIndexList); + + let indexArray = geometries.getAttribute(VertexAttributeName.indices).data as Int16Array; + let indexLen = indexArray.length; + let newIndexArray = new Uint32Array(indexArray.length * num); + for (let i = 0; i < num; i++) { + for (let j = 0; j < indexLen; j++) { + let skipFace = i * posLen; + let index = i * indexLen; + const ii = indexArray[j] + skipFace; + newIndexArray[index + j] = ii; + } + } + + targetGeo.setIndices(newIndexArray); + targetGeo.addSubGeometry({ + indexStart: 0, + indexCount: newIndexArray.length, + vertexStart: 0, + index: 0, + vertexCount: 0, + firstStart: 0, + topology: 0 + }) + return targetGeo; + } + public static generateNormal() { } public static generateTangent() { } public static packUV() { } diff --git a/src/util/Global.ts b/src/util/Global.ts index 7fb9aff1..bd5506b6 100644 --- a/src/util/Global.ts +++ b/src/util/Global.ts @@ -1,3 +1,5 @@ +import { ParserFormat } from "../loader/parser/ParserFormat"; + /** * UUID * @param len @@ -66,8 +68,15 @@ export let ArrayItemIndex = function (array: any[], item: any) { return -1; } +export let mergeFunctions = (...funcs) => { + return function (...args) { + funcs.forEach(func => func.apply(this, args)); + }; +} + /** * Constructor */ export type Ctor = { new(any?): T, prototype: any }; +export type Parser = { new(any?): T, prototype: any, format: ParserFormat }; diff --git a/src/util/Object3DUtil.ts b/src/util/Object3DUtil.ts index de6d4fe7..66e1c663 100644 --- a/src/util/Object3DUtil.ts +++ b/src/util/Object3DUtil.ts @@ -46,6 +46,8 @@ export class Object3DUtil { this.initHeap(); let mat = new LitMaterial(); + mat.roughness = 0.5; + mat.metallic = 0.1; mat.baseColor = new Color(r, g, b, 1); let obj = new Object3D(); diff --git a/src/util/SerializeDecoration.ts b/src/util/SerializeDecoration.ts index d28a67ae..398b8b0d 100644 --- a/src/util/SerializeDecoration.ts +++ b/src/util/SerializeDecoration.ts @@ -85,4 +85,28 @@ export function RegisterComponent(cls, key, p1?, p2?, p3?): any { dic = window['__Component__'] = {}; } dic[cls.name] = cls; +} + +export function GetComponentClass(name: string) { + let coms = window['__Component__']; + if (coms[name]) { + return coms[name]; + } + return null; +} + +export function RegisterShader(cls, key, p1?, p2?, p3?): any { + let dic: { [name: string]: any } = window['__shader__']; + if (!dic) { + dic = window['__shader__'] = {}; + } + dic[cls.name] = cls; +} + +export function GetShader(name: string) { + let coms = window['__shader__']; + if (coms[name]) { + return coms[name]; + } + return null; } \ No newline at end of file diff --git a/src/util/StorageUtil.ts b/src/util/StorageUtil.ts new file mode 100644 index 00000000..bfbb15f6 --- /dev/null +++ b/src/util/StorageUtil.ts @@ -0,0 +1,19 @@ +export class StorageUtil { + + public static localData: any; + public static load(dataTable: string): T { + let jsonData = localStorage.getItem(dataTable); + if (jsonData) { + this.localData = JSON.parse(jsonData); + } else { + this.localData = {}; + StorageUtil.save(dataTable, this.localData); + } + return this.localData as T; + } + + public static save(table: string, data: T) { + let json = JSON.stringify(data) + localStorage.setItem(table, json); + } +} \ No newline at end of file diff --git a/test/components/PostEffects_HDRBloom.test.ts b/test/components/PostEffects_HDRBloom.test.ts index a1b37492..0aca8460 100644 --- a/test/components/PostEffects_HDRBloom.test.ts +++ b/test/components/PostEffects_HDRBloom.test.ts @@ -1,7 +1,7 @@ import { test, end, delay } from '../util' -import { Camera3D, CameraUtil, Engine3D, HDRBloomPost, Object3D, PostProcessingComponent, Scene3D, View3D } from '@orillusion/core'; +import { BloomPost, Camera3D, CameraUtil, Engine3D, Object3D, PostProcessingComponent, Scene3D, View3D } from '@orillusion/core'; -await test('Post HDRBloomPost test', async () => { +await test('Post BloomPost test', async () => { await Engine3D.init(); Engine3D.frameRate = 10; @@ -11,7 +11,7 @@ await test('Post HDRBloomPost test', async () => { Engine3D.startRenderView(view); let postProcessing = view.scene.addComponent(PostProcessingComponent); - postProcessing.addPost(HDRBloomPost); + postProcessing.addPost(BloomPost); await delay(100) Engine3D.pause() }) diff --git a/test/shader/RenderShader.test.ts b/test/shader/RenderShader.test.ts index 678833d6..4fd28811 100644 --- a/test/shader/RenderShader.test.ts +++ b/test/shader/RenderShader.test.ts @@ -1,5 +1,5 @@ import { test, expect, end, delay } from '../util' -import { Engine3D, RenderShader, ShaderLib } from '@orillusion/core'; +import { Engine3D, RenderShaderPass, ShaderLib } from '@orillusion/core'; const a = Engine3D; @@ -55,7 +55,7 @@ await test('RenderShader', async () => { expect(ShaderLib.getShader('TestShader')).toEqual(shaderCode); - let renderShader = new RenderShader('TestShader', 'TestShader'); + let renderShader = new RenderShaderPass('TestShader', 'TestShader'); renderShader.setShaderEntry('vsMain', 'fsMain'); expect(renderShader.vsEntryPoint).toEqual('vsMain'); diff --git a/vite.config.js b/vite.config.js index 1f2e31dd..403e39bc 100644 --- a/vite.config.js +++ b/vite.config.js @@ -2,12 +2,11 @@ import { defineConfig } from 'vite' import { readFile, writeFile, readdir, lstat } from 'fs/promises' import { resolve, parse } from 'path' -// import basicSsl from '@vitejs/plugin-basic-ssl' export default defineConfig(option => ({ server: { host: '0.0.0.0', port: 8000, - // hmr: false // open this line if no auto hot-reload required + hmr: false // open this line if no auto hot-reload required }, publicDir: option.command === 'build' ? false : 'public', resolve: { @@ -59,12 +58,11 @@ export default defineConfig(option => ({ }, { name: 'cors', configureServer: server => { - server.middlewares.use((_req, res, next) => { - res.setHeader("Cross-Origin-Resource-Policy", "cross-origin") - res.setHeader("Cross-Origin-Opener-Policy", "same-origin") - res.setHeader("Cross-Origin-Embedder-Policy", "require-corp") - next(); - }) + // server.middlewares.use((_req, res, next) => { + // res.setHeader("Cross-Origin-Resource-Policy", "cross-origin") + // res.setHeader("Cross-Origin-Opener-Policy", "same-origin") + // res.setHeader("Cross-Origin-Embedder-Policy", "require-corp") + // }) } }], build: {