diff --git a/package.json b/package.json index 319e923e..9e3f47af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orillusion/core", - "version": "0.7.3", + "version": "0.8.0", "author": "Orillusion", "description": "Orillusion WebGPU Engine", "type": "module", diff --git a/packages/debug/GUIHelp.ts b/packages/debug/GUIHelp.ts index 324b4320..841bd6ec 100644 --- a/packages/debug/GUIHelp.ts +++ b/packages/debug/GUIHelp.ts @@ -145,9 +145,16 @@ class _GUIHelp { } _addLabel(gui: GUI, label: string) { - GUIHelp._add(gui, { label: label }, 'label'); + return GUIHelp._add(gui, { label: label }, 'label'); } + _addLabelValue(gui: GUI, label: string, value: number) { + let obj = {}; + obj[label] = value; + return GUIHelp._add(gui, obj, label); + } + + _addButton(gui: GUI, label: string, fun: Function) { var controls = new (function () { this[label] = fun; diff --git a/packages/effect/grass/shader/GrassBaseShader.ts b/packages/effect/grass/shader/GrassBaseShader.ts index 7a6e39d6..820d7844 100644 --- a/packages/effect/grass/shader/GrassBaseShader.ts +++ b/packages/effect/grass/shader/GrassBaseShader.ts @@ -1,6 +1,6 @@ export let GrassBaseShader = /*wgsl*/ ` #include "GlobalUniform" - #include "ColorPassFragmentOutput" + #include "FragmentOutput" #include "ShadingInput" struct FragmentVarying { diff --git a/packages/effect/grass/shader/GrassCastShadowShader.ts b/packages/effect/grass/shader/GrassCastShadowShader.ts index 9446fa85..ebe89e51 100644 --- a/packages/effect/grass/shader/GrassCastShadowShader.ts +++ b/packages/effect/grass/shader/GrassCastShadowShader.ts @@ -54,7 +54,7 @@ export let GrassCastShadowShader = /* wgsl */` let grassPivot = localMatrix[3].xyz ; let bound = materialUniform.windBound ; - let time = TIME.y * 0.001 ; + let time = TIME_time() * 0.001 ; let cycleTime = sin(time) ; //sampler wind noise texture by vertex shader diff --git a/packages/effect/grass/shader/GrassShader.ts b/packages/effect/grass/shader/GrassShader.ts index 9b401019..dbffd135 100644 --- a/packages/effect/grass/shader/GrassShader.ts +++ b/packages/effect/grass/shader/GrassShader.ts @@ -10,6 +10,7 @@ export let GrassShader = /* wgsl */` #include "MatrixShader" #include "BrdfLut_frag" #include "LightingFunction_frag" + #include "ReflectionCG" struct MaterialUniform { baseColor: vec4, @@ -43,6 +44,7 @@ export let GrassShader = /* wgsl */` const DEGREES_TO_RADIANS : f32 = 3.1415926 / 180.0 ; const PI : f32 = 3.1415926 ; + const LUMEN = 10.764; @vertex fn VertMain( vertex:VertexAttributes ) -> VertexOutput { @@ -60,7 +62,7 @@ export let GrassShader = /* wgsl */` let grassPivot = localMatrix[3].xyz ; let bound = materialUniform.windBound ; - let time = TIME.y * 0.001 ; + let time = TIME_time() * 0.001 ; let cycleTime = sin(time) ; //sampler wind noise texture by vertex shader @@ -155,7 +157,7 @@ export let GrassShader = /* wgsl */` var irradiance = LinearToGammaSpace(globalUniform.skyExposure * textureSampleLevel(prefilterMap, prefilterMapSampler, fragData.N.xyz, 0.8 * (MAX_REFLECTION_LOD) ).rgb); let specular = vec3( pow(max(dot(viewDir, reflectDir), 0.0), (1.0 - roughness + 0.001) * 200.0 ) ) * mainLightColor * materialUniform.specular; - var diffuse = color.rgb / PI * grassColor.rgb * shadowStrut.directShadowVisibility[0] ; + var diffuse = color.rgb / PI * grassColor.rgb * directShadowVisibility[0] ; var finalColor = diffuse + specular + irradiance * grassColor.rgb * sunLight.quadratic;//+ backColor; ORI_ShadingInput.BaseColor = vec4(finalColor.rgb,1.0) ; diff --git a/packages/graphic/compute/grass/GrassAnimCompute_cs.ts b/packages/graphic/compute/grass/GrassAnimCompute_cs.ts new file mode 100644 index 00000000..de13330a --- /dev/null +++ b/packages/graphic/compute/grass/GrassAnimCompute_cs.ts @@ -0,0 +1,2 @@ +export let GrassAnimCompute_cs = /*wgsl*/` +` \ No newline at end of file diff --git a/packages/graphic/compute/grass/GrassGeometryCompute_cs.ts b/packages/graphic/compute/grass/GrassGeometryCompute_cs.ts new file mode 100644 index 00000000..167f8655 --- /dev/null +++ b/packages/graphic/compute/grass/GrassGeometryCompute_cs.ts @@ -0,0 +1,66 @@ +export let GrassGeometryCompute_cs = /*wgsl*/` + struct GrassNode { + grassCount: f32, + grassHSegment: f32, + grassWight: f32, + grassHeigh: f32, + grassX: f32, + grassY: f32, + grassZ: f32, + grassRotation: f32 + } + + @group(0) @binding(3) var nodeBuffer : array ; + + var zero_pos : vec3f = vec3f(0.0,0.0,0.0); + var zero_uv : vec2f = vec2f(0.0,0.0); + + + + fn compute(workgroup_id:vec3,local_invocation_id:vec3) { + // Grass geometry compute code goes here + var time = globalUniform.time * 0.005; + let globalIndex = workgroup_id.x * 256u + local_invocation_id.x ; + if(globalIndex < drawBuffer.skipFace2 * 12u){ + // if(globalIndex == 0u){ + // } + + let nodeInfo = nodeBuffer[globalIndex]; + let posWs = vec3f(nodeInfo.grassX, nodeInfo.grassY, nodeInfo.grassZ) ; + if(IsOutofFrustum(posWs.xyz,0.1)){ + // drawCube(globalIndex,posWs,nodeInfo.grassWight,nodeInfo.grassWight,nodeInfo.grassWight,0.0,time,0.0); + + let mat = buildYRotateXMat4(nodeInfo.grassRotation,posWs.x, posWs.y, posWs.z); + let vertexOffset = vec4f(sin(time + f32(local_invocation_id.x) / 16.0 ) ,0.0,0.0,0.0); + + let width = nodeInfo.grassWight * 0.5 ; + let height = nodeInfo.grassHeigh * 0.5 ; + + // var p0 = (mat * vec4f(-width, height, 0.0,1.0)) + vertexOffset; + // var p1 = (mat * vec4f(width, height, 0.0,1.0)) + vertexOffset; + // var p2 = mat * vec4f(width, 0.0, 0.0,1.0) ; + // var p3 = mat * vec4f(-width, 0.0, 0.0,1.0) ; + + // let u0 = vec2f(0.0, 0.0); + // let u1 = vec2f(1.0, 0.0); + // let u2 = vec2f(1.0, 1.0); + // let u3 = vec2f(0.0, 1.0); + + // drawFace(globalIndex,p0.xyz,p1.xyz,p2.xyz,u0,u1,u2); + // drawFace(globalIndex,p0.xyz,p2.xyz,p3.xyz,u0,u2,u3); + + var p0 = (mat * vec4f(width * 0.5, height, 0.0,1.0)) + vertexOffset; + var p1 = (mat * vec4f(-width, 0.0, 0.0,1.0)) ;// + vertexOffset; + var p2 = mat * vec4f(width, 0.0, 0.0,1.0) ; + let u0 = vec2f(0.5, 0.0); + let u1 = vec2f(1.0, 1.0); + let u2 = vec2f(0.0, 1.0); + drawFace(globalIndex,p0.xyz,p1.xyz,p2.xyz,u0,u1,u2); + + }else{ + // drawCube(globalIndex,zero_pos,0.0,0.0,0.0,0.0,0.0,0.0); + drawFace(globalIndex,zero_pos,zero_pos,zero_pos,zero_uv,zero_uv,zero_uv); + } + } + } +` \ No newline at end of file diff --git a/packages/graphic/compute/shape3d/Path2DShape3DCode_cs.ts b/packages/graphic/compute/shape3d/Path2DShape3DCode_cs.ts index f1dc6e6d..197b5039 100644 --- a/packages/graphic/compute/shape3d/Path2DShape3DCode_cs.ts +++ b/packages/graphic/compute/shape3d/Path2DShape3DCode_cs.ts @@ -442,10 +442,10 @@ fn drawPath2DCorner(shapeData:Path2DShape3D, currentPoint:Path3DKeyPoint){ var rotateFrom:vec3; if(isPositive){ rotateFrom = -prevPoint.right; - rotateMat = buildRotateYMat3(-cornerAngle * 2.0 / f32(cornerPointExt)); + rotateMat = buildRotateZ(-cornerAngle * 2.0 / f32(cornerPointExt)); }else{ rotateFrom = prevPoint.right; - rotateMat = buildRotateYMat3(cornerAngle * 2.0 / f32(cornerPointExt)); + rotateMat = buildRotateZ(cornerAngle * 2.0 / f32(cornerPointExt)); } tempV = currentPoint.overallLength - cornerUVLength * lastLengthUVRatio; diff --git a/packages/graphic/index.ts b/packages/graphic/index.ts index 71185dc3..689d3212 100644 --- a/packages/graphic/index.ts +++ b/packages/graphic/index.ts @@ -1,3 +1,6 @@ +export * from "./compute/grass/GrassAnimCompute_cs" +export * from "./compute/grass/GrassGeometryCompute_cs" +export * from "./renderer/GrassRenderer" export * from "./renderer/Shape3DRenderer" export * from "./renderer/Shape3DMaker" export * from "./renderer/shape3d/RoundRectShape3D" @@ -8,4 +11,4 @@ export * from "./renderer/shape3d/CurveShape3D" export * from "./renderer/shape3d/LineShape3D" export * from "./renderer/shape3d/Shape3D" export * from "./renderer/shape3d/Path3DShape3D" -export * from "./renderer/shape3d/Path2DShape3D" \ No newline at end of file +export * from "./renderer/shape3d/Path2DShape3D" diff --git a/packages/graphic/package.json b/packages/graphic/package.json index b92606ed..fe5bd929 100644 --- a/packages/graphic/package.json +++ b/packages/graphic/package.json @@ -14,7 +14,7 @@ "build:types": "tsc --emitDeclarationOnly -p tsconfig.json", "build:clean": "mv dist/packages/graphic/* dist && rm -rf dist/src && rm -rf dist/packages", "docs": "npm run docs:typedoc ../../docs/graphic index.ts", - "docs:typedoc": "npx typedoc --plugin typedoc-plugin-markdown --plugin ../../script/typedoc-plugin-not-exported.cjs --tsconfig tsconfig.json --gitRevision main --hideBreadcrumbs true --allReflectionsHaveOwnDocument true --readme none --excludeInternal --excludePrivate --excludeProtected --sort source-order --out" + "docs:typedoc": "npx typedoc --plugin typedoc-plugin-markdown --plugin ../../script/typedoc-plugin-not-exported.js --tsconfig tsconfig.json --gitRevision main --hideBreadcrumbs true --allReflectionsHaveOwnDocument true --readme none --excludeInternal --excludePrivate --excludeProtected --sort source-order --out" }, "license": "MIT", "repository": { diff --git a/packages/graphic/renderer/GrassRenderer.ts b/packages/graphic/renderer/GrassRenderer.ts new file mode 100644 index 00000000..2363a636 --- /dev/null +++ b/packages/graphic/renderer/GrassRenderer.ts @@ -0,0 +1,36 @@ + +import { ComputeShader, DynamicDrawStruct, DynamicFaceRenderer, Struct, graphicDynamicCompute } from "@orillusion/core"; +import { GrassGeometryCompute_cs } from "../compute/grass/GrassGeometryCompute_cs"; + +export class GrassNodeStruct extends DynamicDrawStruct { + grassCount: number = 1; + grassHSegment: number = 1; + grassWight: number = 2; + grassHeigh: number = 4; + grassX: number = 0; + grassY: number = 0; + grassZ: number = 0; + grassRotation: number = 0; +} + +export class GrassRenderer extends DynamicFaceRenderer { + grassGeometryCompute: ComputeShader; + + constructor() { + super(); + } + + public init(param?: any): void { + super.init(param); + } + + protected createComputeKernel(): void { + console.log("createComputeKernel"); + + + this.grassGeometryCompute = new ComputeShader(graphicDynamicCompute(GrassGeometryCompute_cs)); + this.grassGeometryCompute.workerSizeX = Math.floor(this.maxNodeCount / 256) + 1; + // this._onStartKernel.push(this.grassGeometryCompute); + this._onFrameKernelGroup.push(this.grassGeometryCompute); + } +} \ No newline at end of file diff --git a/packages/graphic/vite.config.js b/packages/graphic/vite.config.js index b274916b..979403e7 100644 --- a/packages/graphic/vite.config.js +++ b/packages/graphic/vite.config.js @@ -23,4 +23,4 @@ export default defineConfig({ } } } -}) \ No newline at end of file +}) diff --git a/packages/media-extention/package.json b/packages/media-extention/package.json index 3ea64355..5e90f42b 100644 --- a/packages/media-extention/package.json +++ b/packages/media-extention/package.json @@ -13,7 +13,7 @@ "build:types": "tsc --emitDeclarationOnly -p tsconfig.json", "build:clean": "mv dist/packages/media-extention/* dist && rm -rf dist/src && rm -rf dist/packages", "docs": "npm run docs:typedoc ../../docs/media-extention index.ts", - "docs:typedoc": "npx typedoc --plugin typedoc-plugin-markdown --plugin ../../script/typedoc-plugin-not-exported.cjs --tsconfig tsconfig.json --gitRevision main --hideBreadcrumbs true --allReflectionsHaveOwnDocument true --readme none --excludeInternal --excludePrivate --excludeProtected --sort source-order --out" + "docs:typedoc": "npx typedoc --plugin typedoc-plugin-markdown --plugin ../../script/typedoc-plugin-not-exported.js --tsconfig tsconfig.json --gitRevision main --hideBreadcrumbs true --allReflectionsHaveOwnDocument true --readme none --excludeInternal --excludePrivate --excludeProtected --sort source-order --out" }, "license": "MIT", "repository": { diff --git a/packages/particle/package.json b/packages/particle/package.json index 52c34652..ab16b5c7 100644 --- a/packages/particle/package.json +++ b/packages/particle/package.json @@ -13,7 +13,7 @@ "build:types": "tsc --emitDeclarationOnly -p tsconfig.json", "build:clean": "mv dist/packages/particle dist/types && rm -rf dist/src && rm -rf dist/packages", "docs": "npm run docs:typedoc ../../docs/particle index.ts", - "docs:typedoc": "npx typedoc --plugin typedoc-plugin-markdown --plugin ../../script/typedoc-plugin-not-exported.cjs --tsconfig tsconfig.json --gitRevision main --hideBreadcrumbs true --allReflectionsHaveOwnDocument true --readme none --excludeInternal --excludePrivate --excludeProtected --sort source-order --out" + "docs:typedoc": "npx typedoc --plugin typedoc-plugin-markdown --plugin ../../script/typedoc-plugin-not-exported.js --tsconfig tsconfig.json --gitRevision main --hideBreadcrumbs true --allReflectionsHaveOwnDocument true --readme none --excludeInternal --excludePrivate --excludeProtected --sort source-order --out" }, "license": "MIT", "repository": { diff --git a/packages/particle/shader/FastMath.ts b/packages/particle/shader/FastMath.ts index 38dd3c11..5466cf84 100644 --- a/packages/particle/shader/FastMath.ts +++ b/packages/particle/shader/FastMath.ts @@ -2,56 +2,56 @@ * @internal */ export let FastMath_shader = /* wgsl*/ ` -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 ) -{ - 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 ; - } -} +// 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 ) +// { +// 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/stats/package.json b/packages/stats/package.json index afb53f71..36ee8618 100644 --- a/packages/stats/package.json +++ b/packages/stats/package.json @@ -13,7 +13,7 @@ "build:types": "tsc --emitDeclarationOnly -p tsconfig.json", "build:clean": "mv dist/packages/stats/* dist && rm -rf dist/src && rm -rf dist/packages", "docs": "npm run docs:typedoc ../../docs/stats index.ts", - "docs:typedoc": "npx typedoc --plugin typedoc-plugin-markdown --plugin ../../script/typedoc-plugin-not-exported.cjs --tsconfig tsconfig.json --gitRevision main --hideBreadcrumbs true --allReflectionsHaveOwnDocument true --readme none --excludeInternal --excludePrivate --excludeProtected --sort source-order --out" + "docs:typedoc": "npx typedoc --plugin typedoc-plugin-markdown --plugin ../../script/typedoc-plugin-not-exported.js --tsconfig tsconfig.json --gitRevision main --hideBreadcrumbs true --allReflectionsHaveOwnDocument true --readme none --excludeInternal --excludePrivate --excludeProtected --sort source-order --out" }, "license": "MIT", "repository": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 26321fe9..b72acf31 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,7 +19,7 @@ devDependencies: typedoc: 0.25.7_typescript@5.3.3 typedoc-plugin-markdown: 3.17.1_typedoc@0.25.7 typescript: 5.3.3 - vite: 5.3.1 + vite: 5.3.3 xvfb-maybe: 0.2.1 packages: @@ -419,7 +419,7 @@ packages: dependencies: '@types/http-cache-semantics': 4.0.1 '@types/keyv': 3.1.4 - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/responselike': 1.0.0 dev: true @@ -434,15 +434,15 @@ packages: /@types/keyv/3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 dev: true /@types/minimist/1.2.2: resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} dev: true - /@types/node/20.14.9: - resolution: {integrity: sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==} + /@types/node/20.14.10: + resolution: {integrity: sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==} dependencies: undici-types: 5.26.5 dev: true @@ -454,14 +454,14 @@ packages: /@types/responselike/1.0.0: resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 dev: true /@types/yauzl/2.10.3: resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} requiresBuild: true dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 dev: true optional: true @@ -867,7 +867,7 @@ packages: requiresBuild: true dependencies: '@electron/get': 2.0.2 - '@types/node': 20.14.9 + '@types/node': 20.14.10 extract-zip: 2.0.1 transitivePeerDependencies: - supports-color @@ -1558,8 +1558,8 @@ packages: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} dev: true - /picocolors/1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + /picocolors/1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} dev: true /pify/2.3.0: @@ -1572,12 +1572,12 @@ packages: engines: {node: '>=4'} dev: true - /postcss/8.4.38: - resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + /postcss/8.4.39: + resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.7 - picocolors: 1.0.0 + picocolors: 1.0.1 source-map-js: 1.2.0 dev: true @@ -2022,8 +2022,8 @@ packages: spdx-expression-parse: 3.0.1 dev: true - /vite/5.3.1: - resolution: {integrity: sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==} + /vite/5.3.3: + resolution: {integrity: sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -2051,7 +2051,7 @@ packages: optional: true dependencies: esbuild: 0.21.5 - postcss: 8.4.38 + postcss: 8.4.39 rollup: 4.18.0 optionalDependencies: fsevents: 2.3.3 diff --git a/public b/public index 5a6f7231..1df88087 160000 --- a/public +++ b/public @@ -1 +1 @@ -Subproject commit 5a6f72318f7eac3cacde980adc3a3a108c2b0035 +Subproject commit 1df8808704217ad22f1baa6dfb21a0ce6cc5c0e3 diff --git a/samples/animation/Sample_CurveAnimation.ts b/samples/animation/Sample_CurveAnimation.ts index bd84a543..21e1374f 100644 --- a/samples/animation/Sample_CurveAnimation.ts +++ b/samples/animation/Sample_CurveAnimation.ts @@ -1,8 +1,8 @@ -import { Object3D, Scene3D, AnimationCurve, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, Keyframe, Object3DUtil, Time } from "@orillusion/core"; +import { Object3D, Scene3D, AnimationCurve, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, Keyframe, Object3DUtil, Time, PostProcessingComponent, FXAAPost, GBufferPost } from "@orillusion/core"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { GUIUtil } from "@samples/utils/GUIUtil"; -class Sample_AnimCurve { +export class Sample_AnimCurve { lightObj3D: Object3D; scene: Scene3D; Duck: Object3D; @@ -12,23 +12,24 @@ class Sample_AnimCurve { curve4: AnimationCurve; 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`; - Engine3D.setting.shadow.csmScatteringExp = 0.5; + Engine3D.setting.shadow.shadowBound = 150; + Engine3D.setting.shadow.shadowBias = 0.02; + GUIHelp.init(); + await Engine3D.init({ renderLoop: () => { this.renderUpdate() } }); this.scene = new Scene3D(); let sky = this.scene.addComponent(AtmosphericComponent); let camera = CameraUtil.createCamera3DObject(this.scene); - camera.enableCSM = true; camera.perspective(60, Engine3D.aspect, 0.01, 5000.0); - camera.object3D.addComponent(HoverCameraController).setCamera(-30, -45, 200); + let ctrl = camera.object3D.addComponent(HoverCameraController); + ctrl.setCamera(0, -45, 200); + ctrl.maxDistance = 1000; let view = new View3D(); view.scene = this.scene; @@ -36,10 +37,13 @@ class Sample_AnimCurve { Engine3D.startRenderView(view); + let postCom = this.scene.addComponent(PostProcessingComponent); + postCom.addPost(FXAAPost); + let post = postCom.addPost(GBufferPost); + GUIUtil.renderGBufferPost(post); + await this.initScene(); sky.relativeTransform = this.lightObj3D.transform; - - GUIUtil.renderDebug(); } async initScene() { @@ -52,7 +56,7 @@ class Sample_AnimCurve { let directLight = this.lightObj3D.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 30; + directLight.intensity = 3; this.scene.addChild(this.lightObj3D); GUIUtil.renderDirLight(directLight); @@ -89,7 +93,6 @@ class Sample_AnimCurve { } this.scene.addChild(Object3DUtil.GetSingleCube(300, 5, 300, 1, 1, 1)); - // load a gltf model this.Duck = (await Engine3D.res.loadGltf('PBR/Duck/Duck.gltf')) as Object3D; this.Duck.scaleX = this.Duck.scaleY = this.Duck.scaleZ = 0.3; @@ -108,5 +111,3 @@ class Sample_AnimCurve { } } } - -new Sample_AnimCurve().run(); \ No newline at end of file diff --git a/samples/animation/Sample_MorphTarget.ts b/samples/animation/Sample_MorphTarget.ts index bfab5393..cd234169 100644 --- a/samples/animation/Sample_MorphTarget.ts +++ b/samples/animation/Sample_MorphTarget.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Object3D, Scene3D, Engine3D, AtmosphericComponent, webGPUContext, HoverCameraController, View3D, DirectLight, KelvinUtil, Vector3, MorphTargetBlender, Entity, CameraUtil } from "@orillusion/core"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, webGPUContext, HoverCameraController, View3D, DirectLight, KelvinUtil, Vector3, MorphTargetBlender, Entity, CameraUtil, PostProcessingComponent, FXAAPost } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; // Sample of how to control the morphtarget animation @@ -10,8 +10,10 @@ export class Sample_MorphTarget { async run() { Engine3D.setting.shadow.shadowBound = 100; + Engine3D.setting.shadow.shadowBias = 0.05; await Engine3D.init(); + GUIHelp.init(); this.scene = new Scene3D(); let sky = this.scene.addComponent(AtmosphericComponent); @@ -20,15 +22,19 @@ export class Sample_MorphTarget { camera.perspective(60, webGPUContext.aspect, 1, 5000.0); camera.object3D.addComponent(HoverCameraController).setCamera(0, 0, 150); - this.initDirectLight(); - sky.relativeTransform = this.lightObj3D.transform; - await this.initMorphModel(); - let view = new View3D(); view.scene = this.scene; view.camera = camera; + this.initDirectLight(); + + sky.relativeTransform = this.lightObj3D.transform; + await this.initMorphModel(); + Engine3D.startRenderView(view); + + let postCom = this.scene.addComponent(PostProcessingComponent); + postCom.addPost(FXAAPost); } /******** light *******/ @@ -41,13 +47,12 @@ export class Sample_MorphTarget { let directLight = this.lightObj3D.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 25; - GUIUtil.renderDirLight(directLight, false); + directLight.intensity = 3; this.scene.addChild(this.lightObj3D); + GUIUtil.renderDirLight(directLight, true); } private async initMorphModel() { - GUIHelp.init(); // load lion model let model = await Engine3D.res.loadGltf('gltfs/glb/lion.glb'); diff --git a/samples/animation/Sample_PropertyAnimation.ts b/samples/animation/Sample_PropertyAnimation.ts index 9606cc89..f291c4d4 100644 --- a/samples/animation/Sample_PropertyAnimation.ts +++ b/samples/animation/Sample_PropertyAnimation.ts @@ -1,7 +1,7 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene"; import { GUIUtil } from "@samples/utils/GUIUtil"; -import { Scene3D, PropertyAnimation, Engine3D, Object3D, Object3DUtil, PropertyAnimClip, WrapMode } from "@orillusion/core"; +import { Scene3D, PropertyAnimation, Engine3D, Object3D, Object3DUtil, PropertyAnimClip, WrapMode, PostProcessingComponent, FXAAPost, GBufferPost } from "@orillusion/core"; class Sample_PropertyAnimation { scene: Scene3D; @@ -12,21 +12,28 @@ class Sample_PropertyAnimation { Engine3D.setting.shadow.updateFrameRate = 1; Engine3D.setting.shadow.shadowBound = 20; Engine3D.setting.shadow.shadowSize = 2048; + Engine3D.setting.shadow.shadowBias = 0.05; await Engine3D.init(); + GUIHelp.init(); let param = createSceneParam(); param.camera.distance = 16; let exampleScene = createExampleScene(param); - GUIHelp.init(); GUIUtil.renderDirLight(exampleScene.light, false); this.scene = exampleScene.scene; - exampleScene.camera.enableCSM = true; + // exampleScene.camera.enableCSM = true; await this.initScene(this.scene); Engine3D.startRenderView(exampleScene.view); + let postCom = this.scene.addComponent(PostProcessingComponent); + postCom.addPost(FXAAPost); + + let gBufferPost = postCom.addPost(GBufferPost); + GUIUtil.renderGBufferPost(gBufferPost); + this.displayGUI(); } diff --git a/samples/animation/Sample_Skeleton.ts b/samples/animation/Sample_Skeleton.ts index 45ad72be..55756662 100644 --- a/samples/animation/Sample_Skeleton.ts +++ b/samples/animation/Sample_Skeleton.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, webGPUContext, HoverCameraController, View3D, LitMaterial, MeshRenderer, BoxGeometry, DirectLight, KelvinUtil, Object3DUtil } from "@orillusion/core"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, webGPUContext, HoverCameraController, View3D, LitMaterial, MeshRenderer, BoxGeometry, DirectLight, KelvinUtil, Object3DUtil, PostProcessingComponent, FXAAPost } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; class Sample_Skeleton { @@ -29,6 +29,9 @@ class Sample_Skeleton { Engine3D.startRenderView(view); + let postCom = this.scene.addComponent(PostProcessingComponent); + postCom.addPost(FXAAPost); + await this.initScene(this.scene); sky.relativeTransform = this.lightObj3D.transform; } @@ -62,7 +65,7 @@ class Sample_Skeleton { let directLight = this.lightObj3D.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 25; + directLight.intensity = 3; GUIUtil.renderDirLight(directLight); scene.addChild(this.lightObj3D); } diff --git a/samples/animation/Sample_Skeleton2.ts b/samples/animation/Sample_Skeleton2.ts index 92dddc4f..91698926 100644 --- a/samples/animation/Sample_Skeleton2.ts +++ b/samples/animation/Sample_Skeleton2.ts @@ -52,7 +52,7 @@ class Sample_Skeleton2 { let directLight = this.lightObj3D.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 40; + directLight.intensity = 3; GUIHelp.init(); GUIUtil.renderDirLight(directLight); scene.addChild(this.lightObj3D); diff --git a/samples/animation/Sample_Skeleton3.ts b/samples/animation/Sample_Skeleton3.ts index 6646a5ec..38074eaf 100644 --- a/samples/animation/Sample_Skeleton3.ts +++ b/samples/animation/Sample_Skeleton3.ts @@ -108,7 +108,7 @@ class Sample_Skeleton3 { let directLight = this.lightObj3D.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 40; + directLight.intensity = 3; GUIUtil.renderDirLight(directLight); scene.addChild(this.lightObj3D); } diff --git a/samples/audio/Sample_DynamicAudio.ts b/samples/audio/Sample_DynamicAudio.ts index 73efc9ae..97616988 100644 --- a/samples/audio/Sample_DynamicAudio.ts +++ b/samples/audio/Sample_DynamicAudio.ts @@ -1,5 +1,5 @@ import { BoxGeometry, Camera3D, DirectLight, Engine3D, LitMaterial, KelvinUtil, MeshRenderer, Object3D, Scene3D, Vector3, Color, OrbitController, View3D, AtmosphericComponent } from '@orillusion/core'; -import { PositionAudio, AudioListener } from '@orillusion/media-extention' +import { PositionAudio, AudioListener } from '@orillusion/media-extention' import { GUIHelp } from '@orillusion/debug/GUIHelp'; export class Static_Audio { @@ -11,20 +11,22 @@ export class Static_Audio { private a = 40 private b = 80 private angle = 0 - constructor() {} + constructor() { } async run() { Engine3D.setting.shadow.autoUpdate = true; Engine3D.setting.shadow.updateFrameRate = 1; Engine3D.setting.shadow.type = 'HARD'; - Engine3D.setting.shadow.shadowBound = 100; + Engine3D.setting.shadow.shadowSize = 2048; + Engine3D.setting.shadow.shadowBound = 200; + Engine3D.setting.shadow.shadowBias = 0.002; await Engine3D.init({ renderLoop: this.loop.bind(this) }); this.scene = new Scene3D(); this.scene.addComponent(AtmosphericComponent); - + this.camera = new Object3D() this.camera.localPosition = new Vector3(0, 20, 50) let mainCamera = this.camera.addComponent(Camera3D) @@ -49,9 +51,9 @@ export class Static_Audio { let [speaker, man, music] = await Promise.all([ Engine3D.res.loadGltf('gltfs/speaker/scene.gltf'), Engine3D.res.loadGltf('gltfs/glb/CesiumMan.glb'), - fetch('https://cdn.orillusion.com/audio.ogg').then(res=>res.arrayBuffer()) + fetch('https://cdn.orillusion.com/audio.ogg').then(res => res.arrayBuffer()) ]) - speaker.localScale.set(4,4,4) + speaker.localScale.set(4, 4, 4) speaker.rotationX = -120 speaker.y = 0.5 let group = new Object3D() @@ -74,23 +76,23 @@ export class Static_Audio { await audio.loadBuffer(music) audio.refDistance = 10; audio.maxDistance = 100; - audio.setDirectionalCone( 180, 230, 0.1 ); + audio.setDirectionalCone(180, 230, 0.1); audio.showHelper() GUIHelp.init(); - GUIHelp.addButton('play', ()=>{ + GUIHelp.addButton('play', () => { audio.play() }) - GUIHelp.addButton('pause', ()=>{ + GUIHelp.addButton('pause', () => { audio.pause() }) - GUIHelp.addButton('stop', ()=>{ + GUIHelp.addButton('stop', () => { audio.stop() }) - GUIHelp.add({volume:1}, 'volume', 0, 1, 0.01).onChange( (v:number) =>{ + GUIHelp.add({ volume: 1 }, 'volume', 0, 1, 0.01).onChange((v: number) => { audio.setVolume(v) }) - GUIHelp.addButton('Toggle Helper', ()=>{ + GUIHelp.addButton('Toggle Helper', () => { audio.toggleHelper() }) GUIHelp.open() @@ -100,7 +102,7 @@ export class Static_Audio { let mr = wall.addComponent(MeshRenderer) mr.geometry = new BoxGeometry(40, 30, 1) let mat = new LitMaterial() - mat.baseColor = new Color(1,0,0) + mat.baseColor = new Color(1, 0, 0) mr.material = mat this.scene.addChild(wall) wall.z = -5 @@ -123,13 +125,13 @@ export class Static_Audio { let directLight = this.lightObj.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 30; + directLight.intensity = 3; this.scene.addChild(this.lightObj); } } - loop(){ + loop() { let man = this.scene.getChildByName('man') as Object3D - if(man){ + if (man) { this.angle += 0.005 man.x = this.a * Math.cos(this.angle) man.z = this.b * Math.sin(this.angle) + 30 diff --git a/samples/audio/Sample_StaticAudio.ts b/samples/audio/Sample_StaticAudio.ts index 9797c66d..76878cab 100644 --- a/samples/audio/Sample_StaticAudio.ts +++ b/samples/audio/Sample_StaticAudio.ts @@ -8,18 +8,20 @@ export class Static_Audio { camera: Object3D mats: any[]; audio: StaticAudio - constructor() {} + constructor() { } async run() { Engine3D.setting.shadow.autoUpdate = true; Engine3D.setting.shadow.updateFrameRate = 1; Engine3D.setting.shadow.type = 'HARD'; - Engine3D.setting.shadow.shadowBound = 100; + Engine3D.setting.shadow.shadowSize = 2048; + Engine3D.setting.shadow.shadowBound = 200; + Engine3D.setting.shadow.shadowBias = 0.002; await Engine3D.init(); this.scene = new Scene3D(); this.scene.addComponent(AtmosphericComponent); - + this.camera = new Object3D() this.camera.localPosition = new Vector3(0, 20, 50) let mainCamera = this.camera.addComponent(Camera3D) @@ -43,7 +45,7 @@ export class Static_Audio { { let group = new Object3D() let speaker = await Engine3D.res.loadGltf('gltfs/speaker/scene.gltf') - speaker.localScale.set(4,4,4) + speaker.localScale.set(4, 4, 4) speaker.rotationX = -120 //speaker.y = 1.5 group.addChild(speaker) @@ -56,16 +58,16 @@ export class Static_Audio { await audio.load('https://cdn.orillusion.com/audio.ogg') GUIHelp.init(); - GUIHelp.addButton('play', ()=>{ + GUIHelp.addButton('play', () => { audio.play() }) - GUIHelp.addButton('pause', ()=>{ + GUIHelp.addButton('pause', () => { audio.pause() }) - GUIHelp.addButton('stop', ()=>{ + GUIHelp.addButton('stop', () => { audio.stop() }) - GUIHelp.add({volume:1}, 'volume', 0, 1, 0.01).onChange( (v:number) =>{ + GUIHelp.add({ volume: 1 }, 'volume', 0, 1, 0.01).onChange((v: number) => { audio.setVolume(v) }) GUIHelp.open() @@ -75,7 +77,7 @@ export class Static_Audio { let mr = wall.addComponent(MeshRenderer) mr.geometry = new BoxGeometry(40, 30, 1) let mat = new LitMaterial() - mat.baseColor = new Color(1,0,0) + mat.baseColor = new Color(1, 0, 0) mr.material = mat this.scene.addChild(wall) wall.z = -5 @@ -98,7 +100,7 @@ export class Static_Audio { let directLight = this.lightObj.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 30; + directLight.intensity = 3; this.scene.addChild(this.lightObj); } } diff --git a/samples/base/Sample_AddRemove.ts b/samples/base/Sample_AddRemove.ts index e43835e1..9871129a 100644 --- a/samples/base/Sample_AddRemove.ts +++ b/samples/base/Sample_AddRemove.ts @@ -1,10 +1,23 @@ -import { Engine3D, Scene3D, CameraUtil, View3D, AtmosphericComponent, ComponentBase, Time, AxisObject, Object3DUtil, KelvinUtil, DirectLight, Object3D, HoverCameraController, MeshRenderer, LitMaterial, BoxGeometry, UnLit, UnLitMaterial, Interpolator } from "@orillusion/core"; +import { Engine3D, Scene3D, CameraUtil, View3D, AtmosphericComponent, ComponentBase, Time, AxisObject, Object3DUtil, KelvinUtil, DirectLight, Object3D, HoverCameraController, MeshRenderer, LitMaterial, BoxGeometry, UnLit, UnLitMaterial, Interpolator, FXAAPost, PostProcessingComponent } from "@orillusion/core"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; // sample use component class Sample_AddRemove { view: View3D; async run() { + Engine3D.setting.shadow.shadowSize = 2048 + Engine3D.setting.shadow.shadowBound = 175; + Engine3D.setting.shadow.shadowBias = 0.0061; + + Engine3D.setting.shadow.shadowBound = 550; + Engine3D.setting.shadow.shadowBias = 0.018; + Engine3D.setting.render.useCompressGBuffer = true; + + Engine3D.setting.reflectionSetting.reflectionProbeMaxCount = 8; + Engine3D.setting.reflectionSetting.reflectionProbeSize = 128; + Engine3D.setting.reflectionSetting.enable = true; + + Engine3D.setting.render.hdrExposure = 1.0; // init engine await Engine3D.init(); // create new Scene @@ -26,7 +39,7 @@ class Sample_AddRemove { lightObj.rotationZ = 150; let dirLight = lightObj.addComponent(DirectLight); dirLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); - dirLight.intensity = 10; + dirLight.intensity = 3; scene.addChild(lightObj); sky.relativeTransform = dirLight.transform; @@ -37,24 +50,21 @@ class Sample_AddRemove { // start render Engine3D.startRenderView(this.view); + + // let postProcessing = scene.addComponent(PostProcessingComponent); + // postProcessing.addPost(FXAAPost); + await this.test(); } private async test() { - let visibleList: Object3D[] = []; - let invisibleList: Object3D[] = []; + let list: Object3D[] = []; let player = await Engine3D.res.loadGltf('gltfs/anim/Minion_Lane_Super_Dawn/Minion_Lane_Super_Dawn.glb'); // gui GUIHelp.init(); GUIHelp.addButton("add", async () => { /******** player1 *******/ - let clone: Object3D - if (invisibleList.length > 0) { - clone = invisibleList[invisibleList.length-1]; - invisibleList.splice(invisibleList.length-1, 1); - } else { - clone = player.clone(); - } + let clone = player.clone() clone.transform.x = Math.random() * 100 - 50; clone.transform.y = Math.random() * 100 - 50; clone.transform.z = Math.random() * 100 - 50; @@ -63,17 +73,16 @@ class Sample_AddRemove { clone.transform.scaleZ = 20; this.view.scene.addChild(clone); - visibleList.push(clone); + list.push(clone); }); GUIHelp.addButton("remove", () => { - let index = Math.floor(visibleList.length * Math.random()); - let obj = visibleList[index]; + let index = Math.floor(list.length * Math.random()); + let obj = list[index]; if (obj) { - visibleList.splice(index, 1) + list.splice(index, 1) this.view.scene.removeChild(obj) - // obj.destroy(true); - invisibleList.push(obj) + obj.destroy(true); } }); diff --git a/samples/base/Sample_Destroy.ts b/samples/base/Sample_Destroy.ts index d7ab4d37..7acfbc16 100644 --- a/samples/base/Sample_Destroy.ts +++ b/samples/base/Sample_Destroy.ts @@ -35,7 +35,7 @@ class Sample_Destroy { // adjust lighting light.rotationX = 45 light.rotationY = 30 - component.intensity = 1 + component.intensity = 3 // add light object scene3D.addChild(light) { diff --git a/samples/base/Sample_Transform.ts b/samples/base/Sample_Transform.ts index c7d073d6..9c16aa87 100644 --- a/samples/base/Sample_Transform.ts +++ b/samples/base/Sample_Transform.ts @@ -34,7 +34,7 @@ light.rotationX = 45; light.rotationY = 30; // add direct light component let dirLight: DirectLight = light.addComponent(DirectLight); -dirLight.intensity = 1; +dirLight.intensity = 3; // add light object to scene scene3D.addChild(light); diff --git a/samples/base/Sample_UseComponent.ts b/samples/base/Sample_UseComponent.ts index ed7fac54..ba1f0cda 100644 --- a/samples/base/Sample_UseComponent.ts +++ b/samples/base/Sample_UseComponent.ts @@ -51,7 +51,7 @@ class Sample_UseComponent { let directLight = lightObj3D.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 40; + directLight.intensity = 3; GUIUtil.renderDirLight(directLight); scene.addChild(lightObj3D); } diff --git a/samples/base/Sample_InitEngine.ts b/samples/base/_Sample_InitEngine.ts similarity index 99% rename from samples/base/Sample_InitEngine.ts rename to samples/base/_Sample_InitEngine.ts index b06dd80c..1c77ec7f 100644 --- a/samples/base/Sample_InitEngine.ts +++ b/samples/base/_Sample_InitEngine.ts @@ -59,7 +59,7 @@ export class Sample_InitEngine { let directLight = lightObj3D.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 140; + directLight.intensity = 3; this.view.scene.addChild(lightObj3D); GUIUtil.renderDirLight(directLight, true); diff --git a/samples/benchmark/Sample_SphereDraw.ts b/samples/benchmark/Sample_SphereDraw.ts index 8415cb25..6742c58a 100644 --- a/samples/benchmark/Sample_SphereDraw.ts +++ b/samples/benchmark/Sample_SphereDraw.ts @@ -37,7 +37,7 @@ class Sample_SphereDraw { lightObj.rotationZ = 150; let dirLight = lightObj.addComponent(DirectLight); dirLight.lightColor = KelvinUtil.color_temperature_to_rgb(53355); - dirLight.intensity = 60; + dirLight.intensity = 3; this.scene.addChild(lightObj); sky.relativeTransform = dirLight.transform; diff --git a/samples/benchmark/Sample_drawCallInstance.ts b/samples/benchmark/Sample_drawCallInstance.ts index 92234a10..e2ecb9c3 100644 --- a/samples/benchmark/Sample_drawCallInstance.ts +++ b/samples/benchmark/Sample_drawCallInstance.ts @@ -7,6 +7,7 @@ import { GUIUtil } from '@samples/utils/GUIUtil'; class Sample_drawCallInstance { scene: Scene3D; public anim: boolean = false; + lightObj3D: Object3D; async run() { Engine3D.setting.pick.enable = false; @@ -39,7 +40,7 @@ class Sample_drawCallInstance { lightObj.rotationZ = 150; let dirLight = lightObj.addComponent(DirectLight); dirLight.lightColor = KelvinUtil.color_temperature_to_rgb(5500); - dirLight.intensity = 100; + dirLight.intensity = 3; dirLight.indirect = 1; this.scene.addChild(lightObj); @@ -65,6 +66,24 @@ class Sample_drawCallInstance { private _list: Object3D[] = []; private _rotList: number[] = []; initScene() { + { + this.lightObj3D = new Object3D(); + this.lightObj3D.x = 0; + this.lightObj3D.y = 30; + this.lightObj3D.z = -40; + this.lightObj3D.rotationX = 144; + this.lightObj3D.rotationY = 0; + this.lightObj3D.rotationZ = 0; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = true; + directLight.intensity = 30; + directLight.indirect = 1; + GUIHelp.init(); + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + let shareGeometry = new BoxGeometry(); let material = new LambertMaterial(); @@ -125,6 +144,7 @@ class Sample_drawCallInstance { this.scene.addChild(group); } + renderLoop() { if (this.anim) { let i = 0; diff --git a/samples/benchmark/Sample_drawCallShareGeometry.ts b/samples/benchmark/Sample_drawCallShareGeometry.ts index 49bbe1eb..d3bc674b 100644 --- a/samples/benchmark/Sample_drawCallShareGeometry.ts +++ b/samples/benchmark/Sample_drawCallShareGeometry.ts @@ -39,7 +39,7 @@ export class Sample_drawCallShareGeometry { lightObj.rotationZ = 150; let dirLight = lightObj.addComponent(DirectLight); dirLight.lightColor = KelvinUtil.color_temperature_to_rgb(5500); - dirLight.intensity = 100; + dirLight.intensity = 40; dirLight.indirect = 1; this.scene.addChild(lightObj); diff --git a/samples/compute/Sample_Cloth.ts b/samples/compute/Sample_Cloth.ts index c043c10d..766275a5 100644 --- a/samples/compute/Sample_Cloth.ts +++ b/samples/compute/Sample_Cloth.ts @@ -10,9 +10,9 @@ export class Demo_Cloth { Engine3D.setting.shadow.autoUpdate = true; Engine3D.setting.shadow.updateFrameRate = 1; - Engine3D.setting.shadow.shadowBound = 8; - Engine3D.setting.shadow.shadowSize = 1024; - Engine3D.setting.shadow.shadowBias = 0.00001; + Engine3D.setting.shadow.shadowBound = 10; + Engine3D.setting.shadow.shadowSize = 2048; + Engine3D.setting.shadow.shadowBias = 0.001; await Engine3D.init({}); @@ -23,7 +23,7 @@ export class Demo_Cloth { await this.initScene(scene); let camera = CameraUtil.createCamera3DObject(scene); - + camera.perspective(60, webGPUContext.aspect, 0.01, 10000.0); let ctl = camera.object3D.addComponent(HoverCameraController); ctl.setCamera(30, -28, 2); @@ -77,7 +77,7 @@ export class Demo_Cloth { lightObj.rotationY = 0; lightObj.rotationZ = 0; let lc = lightObj.addComponent(DirectLight); - lc.intensity = 20; + lc.intensity = 3; lc.castShadow = true; scene.addChild(lightObj); } diff --git a/samples/compute/Sample_Softbody.ts b/samples/compute/Sample_Softbody.ts index 7d40231f..a238fb08 100644 --- a/samples/compute/Sample_Softbody.ts +++ b/samples/compute/Sample_Softbody.ts @@ -3,7 +3,7 @@ import { AtmosphericComponent, BoxGeometry, CameraUtil, DirectLight, Engine3D, F import { BunnySimulator } from "./softbody/BunnySimulator"; export class Demo_Softbody { - constructor() {} + constructor() { } async run() { @@ -21,8 +21,8 @@ export class Demo_Softbody { await this.initScene(scene); let camera = CameraUtil.createCamera3DObject(scene); - - camera.perspective(60, webGPUContext.aspect, 1 , 5000.0); + + camera.perspective(60, webGPUContext.aspect, 1, 5000.0); let ctl = camera.object3D.addComponent(HoverCameraController); ctl.setCamera(30, -28, 15); @@ -61,7 +61,7 @@ export class Demo_Softbody { simulator.castShadow = true; simulator.SetInteractionBox(box); scene.addChild(bunny); - + // { // let mat = new HDRLitMaterial(); // mat.baseMap = defaultTexture.createTexture(32, 32, 72, 126, 2, 255); @@ -85,7 +85,7 @@ export class Demo_Softbody { lightObj.rotationZ = 0; let lc = lightObj.addComponent(DirectLight); lc.castShadow = true; - lc.intensity = 20; + lc.intensity = 3; scene.addChild(lightObj); } diff --git a/samples/ext/Sample_Grass.ts b/samples/ext/Sample_Grass.ts index a2a2e594..bb02a82a 100644 --- a/samples/ext/Sample_Grass.ts +++ b/samples/ext/Sample_Grass.ts @@ -56,7 +56,7 @@ export class Sample_Grass { let sunLight = sunObj.addComponent(DirectLight); sunLight.lightColor = KelvinUtil.color_temperature_to_rgb(6553); sunLight.castShadow = true; - sunLight.intensity = 49; + sunLight.intensity = 40; sunObj.transform.rotationX = 50; sunObj.transform.rotationY = 50; GUIUtil.renderDirLight(sunLight); diff --git a/samples/ext/Sample_Terrain.ts b/samples/ext/Sample_Terrain.ts index eb21cceb..031266ed 100644 --- a/samples/ext/Sample_Terrain.ts +++ b/samples/ext/Sample_Terrain.ts @@ -55,7 +55,7 @@ class Sample_Terrain { let sunLight = sunObj.addComponent(DirectLight); sunLight.lightColor = KelvinUtil.color_temperature_to_rgb(6553); sunLight.castShadow = true; - sunLight.intensity = 49; + sunLight.intensity = 3; sunObj.transform.rotationX = 50; sunObj.transform.rotationY = 50; GUIUtil.renderDirLight(sunLight); diff --git a/samples/ext/Sample_Boxes.ts b/samples/ext/_Sample_Boxes.ts similarity index 99% rename from samples/ext/Sample_Boxes.ts rename to samples/ext/_Sample_Boxes.ts index 8907a5c7..2336ff6e 100644 --- a/samples/ext/Sample_Boxes.ts +++ b/samples/ext/_Sample_Boxes.ts @@ -59,7 +59,7 @@ class Sample_Boxes { let sunLight = sunObj.addComponent(DirectLight); sunLight.lightColor = KelvinUtil.color_temperature_to_rgb(6553); sunLight.castShadow = true; - sunLight.intensity = 45; + sunLight.intensity = 3; sunObj.transform.rotationX = 50; sunObj.transform.rotationY = 50; GUIUtil.renderDirLight(sunLight); diff --git a/samples/geometry/Sample_ConduitGeometry2.ts b/samples/geometry/Sample_ConduitGeometry2.ts index 9bed6d7f..fead2d3c 100644 --- a/samples/geometry/Sample_ConduitGeometry2.ts +++ b/samples/geometry/Sample_ConduitGeometry2.ts @@ -18,15 +18,15 @@ class Sample_ConduitGeometry2 { async run() { GUIHelp.init(); Engine3D.setting.shadow.shadowBound = 50; - Engine3D.setting.shadow.shadowSize = 1024; + Engine3D.setting.shadow.shadowBias = 0.01; let param = createSceneParam(); param.camera.distance = 60; await Engine3D.init(); let exampleScene = createExampleScene(param); - exampleScene.camera.enableCSM = true; + // exampleScene.camera.enableCSM = true; this.scene = exampleScene.scene; let job = Engine3D.startRenderView(exampleScene.view); - job.addPost(new BloomPost()); + // job.addPost(new BloomPost()); await this.createMaterial(); await this.loadCurveData(); @@ -78,8 +78,8 @@ 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'); + await texture.load('textures/grid.jpg'); + // await texture.load('textures/cell.png'); this.material.baseMap = texture; } diff --git a/samples/geometry/Sample_ConduitGeometry3.ts b/samples/geometry/Sample_ConduitGeometry3.ts index 04fd2e8c..80ffb678 100644 --- a/samples/geometry/Sample_ConduitGeometry3.ts +++ b/samples/geometry/Sample_ConduitGeometry3.ts @@ -14,6 +14,7 @@ class Sample_ConduitGeometry3 { async run() { GUIHelp.init(); Engine3D.setting.shadow.shadowBound = 50; + Engine3D.setting.shadow.shadowBias = 0.02; let param = createSceneParam(); param.camera.distance = 50; await Engine3D.init(); diff --git a/samples/geometry/Sample_InternalGeometry.ts b/samples/geometry/Sample_InternalGeometry.ts index 56ddbc42..38b20d84 100644 --- a/samples/geometry/Sample_InternalGeometry.ts +++ b/samples/geometry/Sample_InternalGeometry.ts @@ -8,6 +8,7 @@ class Sample_InternalGeometry { async run() { Engine3D.setting.shadow.autoUpdate = true; Engine3D.setting.shadow.shadowBound = 200; + Engine3D.setting.shadow.shadowSize = 2048; GUIHelp.init(); await Engine3D.init(); @@ -30,7 +31,7 @@ class Sample_InternalGeometry { // add a direction light let lightObj3D = this.lightObj = new Object3D(); let sunLight = lightObj3D.addComponent(DirectLight); - sunLight.intensity = 15; + sunLight.intensity = 3; sunLight.lightColor = KelvinUtil.color_temperature_to_rgb(6553); sunLight.castShadow = true; lightObj3D.rotationX = 53.2; diff --git a/samples/geometry/Sample_VertexAnimation.ts b/samples/geometry/Sample_VertexAnimation.ts index 7063adc5..a38063a8 100644 --- a/samples/geometry/Sample_VertexAnimation.ts +++ b/samples/geometry/Sample_VertexAnimation.ts @@ -36,7 +36,7 @@ class Smaple_VertexAnimation { // add light let lightObj3D = this.lightObj = new Object3D(); let directLight = lightObj3D.addComponent(DirectLight); - directLight.intensity = 25; + directLight.intensity = 3; directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; lightObj3D.rotationX = 53.2; @@ -53,6 +53,7 @@ class Smaple_VertexAnimation { let renderer = floor.addComponent(MeshRenderer); renderer.geometry = this.floorGeometry; renderer.material = new LitMaterial(); + renderer.material.doubleSide = true; renderer.castShadow = true; renderer.receiveShadow = true; this.scene.addChild(floor); diff --git a/samples/gi/Sample_GI.ts b/samples/gi/Sample_GI.ts index c5959152..4571d7b8 100644 --- a/samples/gi/Sample_GI.ts +++ b/samples/gi/Sample_GI.ts @@ -1,9 +1,9 @@ -import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene"; -import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Object3DUtil, GTAOPost, PostProcessingComponent, TAAPost, BloomPost, FXAAPost } from "@orillusion/core"; +import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Object3DUtil, PostProcessingComponent, TAAPost, BloomPost, FXAAPost, CameraUtil, HoverCameraController, AtmosphericComponent, DirectLight, KelvinUtil, View3D, GTAOPost } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; class Sample_GI { + lightObj3D: Object3D; scene: Scene3D; async run() { @@ -28,7 +28,9 @@ class Sample_GI { Engine3D.setting.gi.ddgiGamma = 1; Engine3D.setting.gi.autoRenderProbe = true; - Engine3D.setting.shadow.shadowBound = 200; + Engine3D.setting.shadow.shadowBound = 400; + Engine3D.setting.shadow.shadowSize = 2048; + Engine3D.setting.shadow.shadowBias = 0.05; Engine3D.setting.shadow.debug = true; Engine3D.setting.shadow.autoUpdate = true; @@ -43,39 +45,60 @@ class Sample_GI { } }); GUIHelp.init(); - let param = createSceneParam(); - param.camera.distance = 200; - let exampleScene = createExampleScene(param); - exampleScene.atmosphericSky.exposure = 0.5; - this.scene = exampleScene.scene; - 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); + this.scene = new Scene3D(); + let sky = this.scene.addComponent(AtmosphericComponent); + + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 0.01, 5000.0); + + let ctrl = camera.object3D.addComponent(HoverCameraController); + ctrl.setCamera(0, -45, 200); + ctrl.maxDistance = 1000; + + let view = new View3D(); + view.scene = this.scene; + view.camera = camera; + await this.initScene(); - this.addGIProbes(); - // GUIUtil.renderAtomosphericSky(exampleScene.atmosphericSky); - GUIUtil.renderDirLight(exampleScene.light, false); + + this.addGIProbes(view); + + Engine3D.startRenderView(view); + + let postCom = this.scene.addComponent(PostProcessingComponent); + postCom.addPost(FXAAPost); GUIUtil.renderDebug(); - GUIUtil.renderAtmosphericSky(exampleScene.atmosphericSky); + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 35; + this.lightObj3D.rotationY = 110; + this.lightObj3D.rotationZ = 0; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = true; + directLight.intensity = 3; + this.scene.addChild(this.lightObj3D); + + GUIUtil.renderDirLight(directLight); + } + sky.relativeTransform = this.lightObj3D.transform; + + GUIUtil.renderAtmosphericSky(sky); } private giComponent: GlobalIlluminationComponent; - private addGIProbes() { + private addGIProbes(view: View3D) { let probeObj = new Object3D(); - this.giComponent = probeObj.addComponent(GlobalIlluminationComponent); + this.giComponent = probeObj.addComponent(GlobalIlluminationComponent, view.scene); this.scene.addChild(probeObj); } async initScene() { + { let floorHeight = 20; let floor = Object3DUtil.GetSingleCube(1000, floorHeight, 1000, 0.5, 0.5, 0.5); diff --git a/samples/gi/Sample_GICornellBox.ts b/samples/gi/Sample_GICornellBox.ts index 05e16610..10ef5814 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, BloomPost } from "@orillusion/core"; +import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Vector3, GTAOPost, PostProcessingComponent, BloomPost, View3D } from "@orillusion/core"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { GUIUtil } from "@samples/utils/GUIUtil"; @@ -31,7 +31,9 @@ class Sample_GICornellBox { Engine3D.setting.gi.autoRenderProbe = true; Engine3D.setting.shadow.debug = true; - Engine3D.setting.shadow.shadowSize = 1024; + Engine3D.setting.shadow.shadowBound = 80; + Engine3D.setting.shadow.shadowSize = 2048; + Engine3D.setting.shadow.shadowBias = 0.02; Engine3D.setting.shadow.autoUpdate = true; Engine3D.setting.shadow.updateFrameRate = 1; @@ -50,25 +52,22 @@ class Sample_GICornellBox { let exampleScene = createExampleScene(param); exampleScene.hoverCtrl.setCamera(0, 0, 50, new Vector3(0, 10, 0)); - exampleScene.camera.enableCSM = true; + // exampleScene.camera.enableCSM = true; this.scene = exampleScene.scene; - this.addGIProbes(); + this.addGIProbes(this.scene.view); Engine3D.startRenderViews([exampleScene.view]); let postProcessing = this.scene.addComponent(PostProcessingComponent); - postProcessing.addPost(GTAOPost); postProcessing.addPost(BloomPost); - Engine3D.setting.shadow.csmScatteringExp = 0.8; - GUIHelp.add(Engine3D.setting.shadow, 'csmScatteringExp', 0.5, 1, 0.001); await this.initScene(); } private giComponent: GlobalIlluminationComponent; - private addGIProbes() { + private addGIProbes(view: View3D) { let probeObj = new Object3D(); GUIHelp.init(); - this.giComponent = probeObj.addComponent(GlobalIlluminationComponent); + this.giComponent = probeObj.addComponent(GlobalIlluminationComponent, view.scene); this.scene.addChild(probeObj); } diff --git a/samples/graphic/Sample_GraphicGrass.ts b/samples/graphic/Sample_GraphicGrass.ts new file mode 100644 index 00000000..a70acc96 --- /dev/null +++ b/samples/graphic/Sample_GraphicGrass.ts @@ -0,0 +1,143 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, Graphic3DMesh, Matrix4, BlendMode, Color, Vector4, GeoJsonStruct, GeoJsonUtil, ShapeInfo, DynamicDrawStruct, Object3DUtil, PostProcessingComponent, GTAOPost } from "@orillusion/core"; +import { Stats } from "@orillusion/stats"; +import { GrassNodeStruct, GrassRenderer } from "@orillusion/graphic"; + + + +export class Sample_GraphicGrass { + lightObj3D: Object3D; + scene: Scene3D; + view: View3D; + colors: Color[]; + constructor() { } + + async run() { + + Matrix4.maxCount = 10000; + Matrix4.allocCount = 10000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + this.colors = []; + + 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, -60, 25); + + this.view = new View3D(); + this.view.scene = this.scene; + this.view.camera = camera; + + Engine3D.startRenderView(this.view); + + // GUIUtil.renderDebug(); + + // let post = this.scene.addComponent(PostProcessingComponent); + // let bloom = post.addPost(GTAOPost); + // bloom.bloomIntensity = 1.0 + // GUIUtil.renderBloom(bloom); + + 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 = 3; + // GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + // let floor = Object3DUtil.GetSingleCube(3000, 1, 3000, 0.5, 0.5, 0.5); + // floor.y = -1; + // this.scene.addChild(floor); + + // let c1 = Object3DUtil.GetSingleCube(20, 20, 20, 0.85, 0.85, 0.85); + // this.scene.addChild(c1); + + await this.addGrass(0); + // await this.addGrass(1); + // await this.addGrass(2); + // await this.addGrass(3); + // await this.addGrass(4); + } + + private async addGrass(grassGroup: number) { + let texts = []; + // texts.push(await Engine3D.res.loadTexture("terrain/grass/GrassRealistic.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture('terrain/test01/bitmap.png') as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/line3.png") as BitmapTexture2D); + + // texts.push(await Engine3D.res.loadTexture("terrain/grass/single.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("terrain/grass/single2.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("terrain/grass/single3.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("terrain/grass/GrassThick.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("terrain/grass/GrassRealistic.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/line4.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/grid.jpg") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/frame64.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/line_001064.png") as BitmapTexture2D); + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + { + // Unable to fix error related to missing GrassRenderer + // Leaving code as-is + + let mr = Graphic3DMesh.drawNode( + `path_geojson` + grassGroup, + GrassRenderer, + GrassNodeStruct, + this.scene, + bitmapTexture2DArray, + 10000, + 10000 * 2 + ); + let mat = mr.material as UnLitTexArrayMaterial; + // mat.baseColor = new Color(0.2, 10.7, 0.56, 1.0); + for (let i = 0; i < 1; i++) { + mr.setTextureID(i, Math.floor(Math.random() * texts.length)); + } + + let space = 50; + for (const nodeInfo of mr.nodes) { + let node = nodeInfo as GrassNodeStruct; + node.grassWight = Math.random() * 1.0 + 1.0; + node.grassHeigh = Math.random() * 15.0 + 2.5; + node.grassRotation = Math.random() * 360; + + let radiu = Math.random() * space + Math.random() * space + Math.random() * space; + let angle = Math.random() * 360; + node.grassX = Math.sin(angle) * radiu; + node.grassZ = Math.cos(angle) * radiu; + } + mr.updateShape(); + // Engine3D.views[0].graphic3D.drawFillCircle(`zero`, Vector3.ZERO, 0.5); + } + } + + update() { + Engine3D.views[0].graphic3D.drawCameraFrustum(Engine3D.views[0].camera); + } +} diff --git a/samples/graphic/Sample_GraphicMeshWave.ts b/samples/graphic/Sample_GraphicMeshWave.ts index 7ddc167c..32e67d24 100644 --- a/samples/graphic/Sample_GraphicMeshWave.ts +++ b/samples/graphic/Sample_GraphicMeshWave.ts @@ -59,7 +59,7 @@ export class Sample_GraphicMeshWave { let directLight = this.lightObj3D.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = false; - directLight.intensity = 10; + directLight.intensity = 3; GUIUtil.renderDirLight(directLight); this.scene.addChild(this.lightObj3D); } diff --git a/samples/graphic/Sample_GraphicMesh_0.ts b/samples/graphic/Sample_GraphicMesh_0.ts index f3de297f..18ca0b2d 100644 --- a/samples/graphic/Sample_GraphicMesh_0.ts +++ b/samples/graphic/Sample_GraphicMesh_0.ts @@ -60,7 +60,7 @@ export class Sample_GraphicMesh_0 { let directLight = this.lightObj3D.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = false; - directLight.intensity = 10; + directLight.intensity = 3; GUIUtil.renderDirLight(directLight); this.scene.addChild(this.lightObj3D); } diff --git a/samples/graphic/_Sample_GraphicShape.ts b/samples/graphic/_Sample_GraphicShape.ts new file mode 100644 index 00000000..ba5b3e50 --- /dev/null +++ b/samples/graphic/_Sample_GraphicShape.ts @@ -0,0 +1,155 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, Graphic3DMesh, Matrix4, BlendMode, Color, Vector4, LineJoin, GeoJsonStruct, GeoJsonUtil, ShapeInfo } from "@orillusion/core"; +import { Stats } from "@orillusion/stats"; + +export class _Sample_GraphicShape { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + view: View3D; + + colors: Color[]; + trail3ds: Object3D[][]; + + constructor() { } + + async run() { + + Matrix4.maxCount = 10000; + Matrix4.allocCount = 10000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + this.colors = []; + + 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, -60, 25); + + this.view = new View3D(); + this.view.scene = this.scene; + this.view.camera = camera; + + Engine3D.startRenderView(this.view); + + // GUIUtil.renderDebug(); + + // let post = this.scene.addComponent(PostProcessingComponent); + // let bloom = post.addPost(BloomPost); + // bloom.bloomIntensity = 1.0 + // GUIUtil.renderBloom(bloom); + + 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 geoJsonData = await Engine3D.res.loadJSON("gis/geojson/pudong.geoJson") as GeoJsonStruct; + let geoJsonData = await Engine3D.res.loadJSON("gis/geojson/100000.geoJson") as GeoJsonStruct; + + let texts = []; + // texts.push(await Engine3D.res.loadTexture("textures/line.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/line2.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/line3.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/line4.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/grid.jpg") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/frame64.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/line_001064.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"; + mat.blendMode = BlendMode.SOFT_ADD; + + let mat4 = new Matrix4(); + mat4.rawData.set([]); + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 1; + this.height = 1; + + let neg = true; + + let lineArray = GeoJsonUtil.getPath(geoJsonData); + let mr = Graphic3DMesh.drawShape(`path_geojson`, this.scene, bitmapTexture2DArray); + for (let i = 0; i < this.width * this.height; i++) { + mr.setTextureID(i, Math.floor(Math.random() * texts.length)); + } + + // for (let ii = 0; ii < 1; ii++) { + for (let ii = 0; ii < lineArray.length; ii++) { + this.parts = mr.object3Ds; + + let shapeInfo = new ShapeInfo(); + shapeInfo.shapeType = 3; + shapeInfo.lineJoin = LineJoin.bevel; + shapeInfo.width = 0.25; + shapeInfo.uScale = 1; + shapeInfo.vScale = 10; + shapeInfo.uSpeed = 0; + shapeInfo.vSpeed = 6; + mr.setShape(ii, shapeInfo); + let tmp = []; + for (let i = 0; i < lineArray[ii].length; i++) { + let p = lineArray[ii][i]; + let newPos = new Vector4(); + newPos.set(p.x - 121, p.y, p.z - 31, 0.0); + tmp.push(newPos); + newPos.multiplyScalar(25); + mr.shapes[ii].paths.push(newPos); + } + + // mr.shapes[ii].paths.push(new Vector4(0.0, 0.0, 0.0)); + // mr.shapes[ii].paths.push(new Vector4(1.0, 0.0, 0.0)); + // mr.shapes[ii].paths.push(new Vector4(2.0, 0.0, 5.0)); + // mr.shapes[ii].paths.push(new Vector4(4.0, 0.0, 2.0)); + // mr.shapes[ii].paths.push(new Vector4(8.0, 0.0, 2.0)); + // mr.shapes[ii].paths.push(new Vector4(10.0, 0.0, 5.0)); + console.log(`path${ii}`, tmp.length); + // Engine3D.views[0].graphic3D.drawLines(`path${ii}`, tmp); + } + mr.updateShape(); + // Engine3D.views[0].graphic3D.drawFillCircle(`zero`, Vector3.ZERO, 0.5); + + } + } + + update() { + } +} diff --git a/samples/graphic/_Sample_GraphicTrailing.ts b/samples/graphic/_Sample_GraphicTrailing.ts new file mode 100644 index 00000000..488fa6ca --- /dev/null +++ b/samples/graphic/_Sample_GraphicTrailing.ts @@ -0,0 +1,173 @@ +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, Color, PostProcessingComponent, BloomPost, TrailGeometry, AnimationCurve, Keyframe, AnimationCurveT, KeyframeT, DepthOfFieldPost } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_Trailing { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + view: View3D; + + colors: Color[]; + trail3ds: Object3D[]; + + 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; + + this.colors = []; + + 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); + + this.view = new View3D(); + this.view.scene = this.scene; + this.view.camera = camera; + + Engine3D.startRenderView(this.view); + + GUIUtil.renderDebug(); + + let post = this.scene.addComponent(PostProcessingComponent); + // let DOFPost = post.addPost(DepthOfFieldPost) + // DOFPost.near = 0 + // DOFPost.far = 150 + // DOFPost.pixelOffset = 2 + // GUIUtil.renderDepthOfField(DOFPost); + + let bloom = post.addPost(BloomPost); + bloom.bloomIntensity = 10.0 + GUIUtil.renderBloom(bloom); + + 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("particle/fx_a_fragment_003.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/grid.jpg") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/frame.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/128/line_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/line_0001.PNG") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/line_0013.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/line_0017.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 = 20; + this.height = 20; + let mr = Graphic3DMesh.drawRibbon("trail", this.scene, bitmapTexture2DArray, 50, this.width * this.height); + this.parts = mr.object3Ds; + this.trail3ds = mr.object3Ds; + + mr.material.blendMode = BlendMode.ADD; + // mr.material.transparent = true; + mr.material.doubleSide = true; + mr.material.depthWriteEnabled = false; + // mr.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + mr.setTextureID(i, Math.floor(Math.random() * texts.length)); + // mr.setTextureID(i, 0); + } + + let c1 = new Color(0.65, 0.1, 0.2, 0.15); + let c2 = new Color(1.0, 1.1, 0.2, 0.65); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + } + + this.updateOnce(1000); + } + + private tmpArray: any[] = []; + update() { + } + + updateOnce(engineFrame: number) { + if (this.trail3ds && this.trail3ds.length > 0) { + let curveX = new AnimationCurve(); + let lenX = Math.floor(Math.random() * 10) + 1; + for (let pi = 0; pi < lenX; pi++) { + curveX.addKeyFrame(new Keyframe(pi / (lenX - 1), Math.random() * 2 - 1)); + } + + let curveY = new AnimationCurve(); + let lenY = Math.floor(Math.random() * 10) + 1; + for (let pi = 0; pi < lenY; pi++) { + curveY.addKeyFrame(new Keyframe(pi / (lenY - 1), Math.random() * 2 - 1)); + } + + let curveZ = new AnimationCurve(); + let lenZ = Math.floor(Math.random() * 10) + 1; + for (let pi = 0; pi < lenZ; pi++) { + curveZ.addKeyFrame(new Keyframe(pi / (lenZ - 1), Math.random() * 2 - 1)); + } + + for (let i = 0; i < this.trail3ds.length; i++) { + const trail3d = this.trail3ds[i]; + let dir = new Vector3(Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1); + // for (let j = 0; j < trail3d.length; j++) { + // let p = j / (trail3d.length - 1); + // let vx = curveX.getValue(p); + // let vy = curveY.getValue(p); + // let vz = curveZ.getValue(p); + // trail3d[j].x = vx * dir.x * 100; + // trail3d[j].y = vy * dir.y * 100; + // trail3d[j].z = vz * dir.z * 100; + // } + } + } + } + +} diff --git a/samples/graphic/_Sample_GraphicTrailing2.ts b/samples/graphic/_Sample_GraphicTrailing2.ts new file mode 100644 index 00000000..602a614a --- /dev/null +++ b/samples/graphic/_Sample_GraphicTrailing2.ts @@ -0,0 +1,161 @@ +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, Color, PostProcessingComponent, BloomPost, TrailGeometry, AnimationCurve, Keyframe, AnimationCurveT, KeyframeT, DepthOfFieldPost, Quaternion } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_Trailing2 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + view: View3D; + + colors: Color[]; + trail3ds: Object3D[]; + + 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; + + this.colors = []; + + 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); + + this.view = new View3D(); + this.view.scene = this.scene; + this.view.camera = camera; + + Engine3D.startRenderView(this.view); + + GUIUtil.renderDebug(); + + let post = this.scene.addComponent(PostProcessingComponent); + // let DOFPost = post.addPost(DepthOfFieldPost) + // DOFPost.near = 0 + // DOFPost.far = 150 + // DOFPost.pixelOffset = 2 + // GUIUtil.renderDepthOfField(DOFPost); + + let bloom = post.addPost(BloomPost); + bloom.bloomIntensity = 10.0 + GUIUtil.renderBloom(bloom); + + 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("particle/fx_a_fragment_003.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/grid.jpg") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/frame.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/128/line_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/line_0001.PNG") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/line_0013.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/line_0017.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 = 10; + this.height = 10; + let mr = Graphic3DMesh.drawRibbon("trail", this.scene, bitmapTexture2DArray, 127, this.width * this.height); + this.parts = mr.object3Ds; + this.trail3ds = mr.object3Ds; + + mr.material.blendMode = BlendMode.ADD; + // mr.material.transparent = true; + mr.material.doubleSide = true; + mr.material.depthWriteEnabled = false; + // mr.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + mr.setTextureID(i, Math.floor(Math.random() * texts.length)); + // mr.setTextureID(i, 0); + } + + let c1 = new Color(0.65, 0.1, 0.2, 0.15); + let c2 = new Color(1.0, 1.1, 0.2, 0.65); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + } + + this.updateOnce(1000); + } + + private tmpArray: any[] = []; + update() { + } + + updateOnce(engineFrame: number) { + if (this.trail3ds && this.trail3ds.length > 0) { + for (let i = 0; i < this.trail3ds.length; i++) { + const trail3d = this.trail3ds[i]; + let dir = new Vector3(0, 1, 0); + let lx = 10 * Math.random() + 10; + let ly = 0.1 * Math.random() + 0.1; + let lz = 10 * Math.random() + 10; + let oy = 1 * Math.random() + 1; + // for (let j = 0; j < trail3d.length; j++) { + // let p = j / (trail3d.length - 1); + + // let q = Quaternion.HELP_0; + // q.fromEulerAngles(0, p * 360 * 4, 0); + // q.transformVector(Vector3.RIGHT, dir); + + // trail3d[j].x = dir.x * lx * p; + // trail3d[j].y = j * ly + oy; + // trail3d[j].z = dir.z * lz * p; + // } + } + } + } + +} diff --git a/samples/graphic/_Sample_GraphicTrailing3.ts b/samples/graphic/_Sample_GraphicTrailing3.ts new file mode 100644 index 00000000..0ea0c634 --- /dev/null +++ b/samples/graphic/_Sample_GraphicTrailing3.ts @@ -0,0 +1,161 @@ +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, Color, PostProcessingComponent, BloomPost, TrailGeometry, AnimationCurve, Keyframe, AnimationCurveT, KeyframeT, DepthOfFieldPost, Quaternion } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicTrailing3 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + view: View3D; + + colors: Color[]; + trail3ds: Object3D[]; + + 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; + + this.colors = []; + + 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); + + this.view = new View3D(); + this.view.scene = this.scene; + this.view.camera = camera; + + Engine3D.startRenderView(this.view); + + GUIUtil.renderDebug(); + + let post = this.scene.addComponent(PostProcessingComponent); + // let DOFPost = post.addPost(DepthOfFieldPost) + // DOFPost.near = 0 + // DOFPost.far = 150 + // DOFPost.pixelOffset = 2 + // GUIUtil.renderDepthOfField(DOFPost); + + let bloom = post.addPost(BloomPost); + bloom.bloomIntensity = 10.0 + GUIUtil.renderBloom(bloom); + + 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("particle/fx_a_fragment_003.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/grid.jpg") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/frame.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/128/line_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/line_0001.PNG") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/line_0013.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/line_0017.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 = 10; + this.height = 10; + let mr = Graphic3DMesh.drawRibbon("trail", this.scene, bitmapTexture2DArray, 127, this.width * this.height); + this.parts = mr.object3Ds; + this.trail3ds = mr.object3Ds; + + mr.material.blendMode = BlendMode.ADD; + // mr.material.transparent = true; + mr.material.doubleSide = true; + mr.material.depthWriteEnabled = false; + // mr.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + mr.setTextureID(i, Math.floor(Math.random() * texts.length)); + // mr.setTextureID(i, 0); + } + + let c1 = new Color(0.65, 0.1, 0.2, 0.15); + let c2 = new Color(1.0, 1.1, 0.2, 0.65); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + } + + this.updateOnce(1000); + } + + private tmpArray: any[] = []; + update() { + } + + updateOnce(engineFrame: number) { + if (this.trail3ds && this.trail3ds.length > 0) { + for (let i = 0; i < this.trail3ds.length; i++) { + const trail3d = this.trail3ds[i]; + let dir = new Vector3(0, 1, 0); + let lx = 10 * Math.random() + 10; + let ly = 0.1 * Math.random() + 0.1; + let lz = 10 * Math.random() + 10; + let oy = 1 * Math.random() + 1; + // for (let j = 0; j < trail3d.length; j++) { + // let p = j / (trail3d.length - 1); + + // let q = Quaternion.HELP_0; + // q.fromEulerAngles(0, p * 360 * 4, 0); + // q.transformVector(Vector3.RIGHT, dir); + + // trail3d[j].x = dir.x * lx * p; + // trail3d[j].y = j * ly + oy; + // trail3d[j].z = dir.z * lz * p; + // } + } + } + } + +} diff --git a/samples/gui/Sample_POI.ts b/samples/gui/Sample_POI.ts index 7526ffe3..9ab45392 100644 --- a/samples/gui/Sample_POI.ts +++ b/samples/gui/Sample_POI.ts @@ -11,18 +11,20 @@ class Sample_POI { async run() { Engine3D.setting.shadow.autoUpdate = true; Engine3D.setting.shadow.updateFrameRate = 1; + Engine3D.setting.shadow.shadowSize = 2048; Engine3D.setting.shadow.shadowBound = 20; + Engine3D.setting.shadow.shadowBias = 0.005; Engine3D.setting.shadow.csmScatteringExp = 1; await Engine3D.init({ renderLoop: () => { this.loop(); } }); let param = createSceneParam(); - param.camera.distance = 16; + param.camera.distance = 30; let exampleScene = createExampleScene(param); GUIHelp.init(); this.scene = exampleScene.scene; - exampleScene.camera.enableCSM = true; + // exampleScene.camera.enableCSM = true; Engine3D.startRenderView(exampleScene.view); diff --git a/samples/gui/Sample_UIPanelScissor.ts b/samples/gui/Sample_UIPanelScissor.ts index 5ba143ec..bf49853a 100644 --- a/samples/gui/Sample_UIPanelScissor.ts +++ b/samples/gui/Sample_UIPanelScissor.ts @@ -6,6 +6,7 @@ import { VideoTexture } from "@orillusion/media-extention"; class Sample_UIPanelScissor { + videoTexture: VideoTexture; async run() { Engine3D.setting.shadow.autoUpdate = true; @@ -28,12 +29,15 @@ class Sample_UIPanelScissor { //create UI root let panelRoot: Object3D = new Object3D(); panelRoot.scaleX = panelRoot.scaleY = panelRoot.scaleZ = 0.1; + this.videoTexture = new VideoTexture(); + await this.videoTexture.load('/video/dt.mp4'); + await Engine3D.res.loadFont('fnt/0.fnt'); this.createPanel(panelRoot, canvas, new Color(1, 1, 1, 1)); } - private async createPanel(panelRoot: Object3D, canvas: GUICanvas, color: Color) { + private createPanel(panelRoot: Object3D, canvas: GUICanvas, color: Color) { let panel = panelRoot.addComponent(WorldPanel); panel.cullMode = "none"; canvas.addChild(panel.object3D); @@ -61,9 +65,7 @@ class Sample_UIPanelScissor { { // make video - let videoTexture = new VideoTexture(); - await videoTexture.load('/video/dt.mp4'); - image.sprite = makeAloneSprite('dt.mp4', videoTexture); + image.sprite = makeAloneSprite('dt.mp4', this.videoTexture); image.uiTransform.resize(350, 250); } diff --git a/samples/gui/panel/GUIPanelPOI.ts b/samples/gui/panel/GUIPanelPOI.ts index b943b2bd..31fa3524 100644 --- a/samples/gui/panel/GUIPanelPOI.ts +++ b/samples/gui/panel/GUIPanelPOI.ts @@ -107,7 +107,7 @@ export class GUIPanelPOI { text.uiTransform.x = 110; text.uiTransform.y = -48; text.alignment = TextAnchor.UpperLeft; - text.text = 'Orilussion'; + text.text = 'Orillusion'; text.fontSize = 22; text.color = new Color(0.9, 0.9, 0.9, 1.0); } diff --git a/samples/index.ts b/samples/index.ts index a65bfb48..a66a72eb 100644 --- a/samples/index.ts +++ b/samples/index.ts @@ -1,3 +1,16 @@ +import { Sample_AnimCurve } from "./animation/Sample_CurveAnimation"; +import { Sample_PointLight } from "./lights/Sample_PointLight"; +import { Sample_PointLightShadow } from "./lights/Sample_PointLightShadow"; +import { Sample_CarPaint } from "./material/Sample_CarPaint"; +import { Sample_SSGI } from "./post/Sample_SSGI"; + +// new Sample_CarPaint().run(); +// new Sample_SSGI().run(); + +// new Sample_AnimCurve().run(); + +// new Sample_PointLightShadow().run(); + /******** Load all samples in /src/sample/ ********/ { // find all demos in /sample diff --git a/samples/lights/PointLightsScript.ts b/samples/lights/PointLightsScript.ts index 3928621c..4e7bc5bf 100644 --- a/samples/lights/PointLightsScript.ts +++ b/samples/lights/PointLightsScript.ts @@ -79,9 +79,11 @@ export class PointLightsScript extends ComponentBase { poi.r = Math.random() + 0.1; poi.g = Math.random() + 0.1; poi.b = Math.random() + 0.1; - poi.intensity = Math.random() * 1.5 + 10; - poi.range *= Math.random() * 0.5 + 0.5; - + poi.intensity = 0.6 * Math.random() + 0.3; + poi.range = 10 * Math.random() + 20; + poi.castShadow = true; + poi.radius = 0.01; + poi.at = 8; this.object3D.addChild(obj); this._points.push(poi); diff --git a/samples/lights/Sample_AddRemovePointLight.ts b/samples/lights/Sample_AddRemovePointLight.ts index 4ab4b4c8..fea75d9f 100644 --- a/samples/lights/Sample_AddRemovePointLight.ts +++ b/samples/lights/Sample_AddRemovePointLight.ts @@ -69,7 +69,7 @@ class Sample_AddRemovePointLight { let script = pointLight.addComponent(PointLight); script.lightColor = Color.random(); script.intensity = 6 * Math.random() + 3; - script.range = 25 * Math.random() + 15; + script.range = 45 * Math.random() + 80; script.castShadow = true; pointLight.x = Math.random() * 200 - 100; pointLight.y = 5; diff --git a/samples/lights/Sample_CSM.ts b/samples/lights/Sample_CSM.ts index 9bb51299..ea95f85f 100644 --- a/samples/lights/Sample_CSM.ts +++ b/samples/lights/Sample_CSM.ts @@ -11,7 +11,8 @@ class Sample_CSM { viewCamera: Camera3D; async run() { Engine3D.setting.shadow.autoUpdate = true; - Engine3D.setting.shadow.shadowSize = 1024; + Engine3D.setting.shadow.shadowSize = 2048; + Engine3D.setting.shadow.shadowBound = 512; await Engine3D.init({ renderLoop: () => { this.loop(); } }); GUIHelp.init(); @@ -26,8 +27,8 @@ class Sample_CSM { mainCamera.object3D.z = -15; mainCamera.object3D.addComponent(HoverCameraController).setCamera(-15, -35, 200); - sky.relativeTransform = this.initLight('mainLight', 30, 45); - this.initLight('subLight', 10, 10); + sky.relativeTransform = this.initLight('mainLight', 3, 45); + this.initLight('subLight', 2, 10); this.initScene(); let view = new View3D(); diff --git a/samples/lights/Sample_DirectLightShadow.ts b/samples/lights/Sample_DirectLightShadow.ts index 0d001eaf..3f989d37 100644 --- a/samples/lights/Sample_DirectLightShadow.ts +++ b/samples/lights/Sample_DirectLightShadow.ts @@ -6,12 +6,16 @@ import { GUIUtil } from "@samples/utils/GUIUtil"; class Sample_DirectLightShadow { 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.shadow.enable = true; + Engine3D.setting.shadow.autoUpdate = true; + Engine3D.setting.shadow.updateFrameRate = 1; + Engine3D.setting.shadow.shadowBound = 400; + Engine3D.setting.shadow.shadowSize = 2048; + Engine3D.setting.shadow.shadowBias = 0.02; + Engine3D.setting.occlusionQuery.octree = { width: 1000, height: 1000, depth: 1000, x: 0, y: 0, z: 0 } await Engine3D.init({}); @@ -47,7 +51,7 @@ class Sample_DirectLightShadow { lightObj3D.rotationY = 62; lightObj3D.rotationZ = 0; let sunLight = lightObj3D.addComponent(DirectLight); - sunLight.intensity = 15; + sunLight.intensity = 3; sunLight.lightColor = KelvinUtil.color_temperature_to_rgb(6553); sunLight.castShadow = true; diff --git a/samples/lights/Sample_MovebleLight.ts b/samples/lights/Sample_MovebleLight.ts index f79f334c..32bb046d 100644 --- a/samples/lights/Sample_MovebleLight.ts +++ b/samples/lights/Sample_MovebleLight.ts @@ -27,8 +27,9 @@ class Sample_MovebleLight { //create PointLight let lightObj = new Object3D(); this.light = lightObj.addComponent(PointLight); - this.light.intensity = 10; + this.light.intensity = 4; this.light.range = 20; + this.light.radius = 0.1; lightObj.z = 5; this.light.lightColor = KelvinUtil.color_temperature_to_rgb(2345); this.light.castShadow = true; @@ -41,8 +42,8 @@ class Sample_MovebleLight { const gui = new dat.GUI(); let light = gui.addFolder("light"); light.add(this.light, "intensity", 5, 30, 1); - light.add(this.light, "range", 10, 30, 1); - light.add(this.light, "radius", 0.1, 2, 0.1); + light.add(this.light, "range", 1, 30, 1); + light.add(this.light, "radius", 0.01, 2, 0.01); light.addColor(lightColor, "color").onChange((v) => { this.light.lightColor = new Color(v[0] / 255, v[1] / 255, v[2] / 255); }); diff --git a/samples/lights/Sample_PointLight.ts b/samples/lights/Sample_PointLight.ts index a63a3425..5236958f 100644 --- a/samples/lights/Sample_PointLight.ts +++ b/samples/lights/Sample_PointLight.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { AtmosphericComponent, BoxGeometry, CameraUtil, Engine3D, HoverCameraController, LitMaterial, MeshRenderer, Object3D, PointLight, Scene3D, SphereGeometry, View3D, } from "@orillusion/core"; +import { AtmosphericComponent, BoxGeometry, CameraUtil, Engine3D, FXAAPost, HoverCameraController, LitMaterial, MeshRenderer, Object3D, PointLight, PostProcessingComponent, Scene3D, SphereGeometry, View3D, } from "@orillusion/core"; import { PointLightsScript } from "./PointLightsScript"; import { Object3DUtil } from "../../src/util/Object3DUtil"; import { GUIUtil } from "@samples/utils/GUIUtil"; @@ -33,6 +33,9 @@ export class Sample_PointLight { Engine3D.startRenderViews([view]); + let postProcessing = this.scene.addComponent(PostProcessingComponent); + postProcessing.addPost(FXAAPost); + GUIUtil.renderDebug(); } @@ -53,7 +56,7 @@ export class Sample_PointLight { let mat = new LitMaterial(); // make 20 box - for (let i = 0; i < 20; i++) { + for (let i = 0; i < 10; i++) { for (let j = 0; j < 10; j++) { let box = new Object3D(); let mr2 = box.addComponent(MeshRenderer); diff --git a/samples/lights/Sample_PointLightShadow.ts b/samples/lights/Sample_PointLightShadow.ts index d4f3dd0c..9343d6a1 100644 --- a/samples/lights/Sample_PointLightShadow.ts +++ b/samples/lights/Sample_PointLightShadow.ts @@ -3,7 +3,7 @@ import { Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraControl import { GUIUtil } from "@samples/utils/GUIUtil"; // sample of point light shadow -class Sample_PointLightShadow { +export class Sample_PointLightShadow { scene: Scene3D; lightObj: Object3D; async run() { @@ -48,7 +48,7 @@ class Sample_PointLightShadow { //make point light let pointLight = lightObj3D.addComponent(PointLight); - pointLight.range = 100; + pointLight.range = 200; pointLight.intensity = 5; pointLight.castShadow = true; scene.addChild(lightObj3D); @@ -80,6 +80,4 @@ class Sample_PointLightShadow { let floor = Object3DUtil.GetSingleCube(2000, 1, 2000, 0.5, 0.5, 0.5); this.scene.addChild(floor); } -} - -new Sample_PointLightShadow().run(); \ No newline at end of file +} \ No newline at end of file diff --git a/samples/lights/Sample_ShadowToggle.ts b/samples/lights/Sample_ShadowToggle.ts index 26da74f8..06b4df88 100644 --- a/samples/lights/Sample_ShadowToggle.ts +++ b/samples/lights/Sample_ShadowToggle.ts @@ -8,7 +8,9 @@ class Sample_ShadowToggle { async run() { Engine3D.setting.shadow.enable = true; Engine3D.setting.shadow.autoUpdate = true; - Engine3D.setting.shadow.shadowSize = 1024; + Engine3D.setting.shadow.shadowSize = 2048; + Engine3D.setting.shadow.shadowBound = 200; + Engine3D.setting.shadow.shadowBias = 0.02; await Engine3D.init({}); GUIHelp.init(); @@ -41,7 +43,7 @@ class Sample_ShadowToggle { lightObj3D.rotationY = 62; lightObj3D.rotationZ = 0; let sunLight = lightObj3D.addComponent(DirectLight); - sunLight.intensity = 15; + sunLight.intensity = 4; sunLight.lightColor = KelvinUtil.color_temperature_to_rgb(6553); sunLight.castShadow = true; @@ -53,7 +55,7 @@ class Sample_ShadowToggle { initScene() { // add sphere { - let geometry = new SphereGeometry(20, 20, 20); + let geometry = new SphereGeometry(20, 64, 64); let material = new LitMaterial(); material.name = 'Sphere Material'; let obj = new Object3D(); diff --git a/samples/lights/Sample_SpotLight.ts b/samples/lights/Sample_SpotLight.ts index 5be5566b..81617447 100644 --- a/samples/lights/Sample_SpotLight.ts +++ b/samples/lights/Sample_SpotLight.ts @@ -52,12 +52,13 @@ class Sample_SpotLight { lightObj3D.transform.rotationX = 342; lightObj3D.transform.rotationY = 360; lightObj3D.transform.rotationZ = 199; - spotLight.lightColor.r = 255 / 255; - spotLight.lightColor.g = 157 / 255; - spotLight.lightColor.b = 5 / 255; - spotLight.intensity = 80; + spotLight.lightColor.r = 160 / 255; + spotLight.lightColor.g = 160 / 255; + spotLight.lightColor.b = 100 / 255; + spotLight.intensity = 4; spotLight.radius = 1; spotLight.range = 787; + spotLight.at = 25; spotLight.outerAngle = 96; spotLight.innerAngle = 0; spotLight.castShadow = true; diff --git a/samples/lights/Sample_DirectLight.ts b/samples/lights/_Sample_DirectLight.ts similarity index 100% rename from samples/lights/Sample_DirectLight.ts rename to samples/lights/_Sample_DirectLight.ts diff --git a/samples/loader/Sample_FlightHelmet.ts b/samples/loader/Sample_FlightHelmet.ts index 10473a05..1f13cac0 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, AtmosphericComponent, DirectLight, KelvinUtil, Time } from "@orillusion/core"; +import { Object3D, Scene3D, HoverCameraController, Engine3D, CameraUtil, View3D, SSRPost, AtmosphericComponent, DirectLight, KelvinUtil, Time, PostProcessingComponent, FXAAPost, SphereReflection } from "@orillusion/core"; import { GUIUtil as GUIUtil } from "@samples/utils/GUIUtil"; class Sample_FlightHelmet { @@ -19,7 +19,8 @@ class Sample_FlightHelmet { }); Engine3D.setting.shadow.autoUpdate = true; - Engine3D.setting.shadow.shadowBound = 10; + Engine3D.setting.shadow.shadowBound = 20; + Engine3D.setting.shadow.shadowBias = 0.001; Engine3D.setting.render.postProcessing.ssao.radius = 0.018; Engine3D.setting.render.postProcessing.ssao.aoPower = 1; @@ -35,7 +36,11 @@ class Sample_FlightHelmet { Engine3D.startRenderView(view); + let postCom = this.scene.addComponent(PostProcessingComponent); + postCom.addPost(FXAAPost); await this.initScene(); + + GUIUtil.renderShadowSetting(); } async initScene() { @@ -62,7 +67,7 @@ class Sample_FlightHelmet { let directLight = this.lightObj3D.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 44; + directLight.intensity = 5; this.scene.addChild(this.lightObj3D); GUIUtil.renderDirLight(directLight); } diff --git a/samples/loader/Sample_LoadGLB.ts b/samples/loader/Sample_LoadGLB.ts index e68ee1c8..77b96fe2 100644 --- a/samples/loader/Sample_LoadGLB.ts +++ b/samples/loader/Sample_LoadGLB.ts @@ -12,6 +12,8 @@ export class Sample_LoadGLB { GUIHelp.init(); await Engine3D.init(); Engine3D.setting.shadow.autoUpdate = true; + Engine3D.setting.shadow.shadowBound = 150; + Engine3D.setting.shadow.shadowBias = 0.1; let ex = createExampleScene(); this.scene = ex.scene; @@ -26,8 +28,6 @@ export class Sample_LoadGLB { await this.initScene(); let post = this.scene.addComponent(PostProcessingComponent); - let gtao = post.addPost(GTAOPost); - // let taa = post.addPost(TAAPost); let hdr = post.addPost(BloomPost); GUIUtil.renderBloom(hdr); @@ -90,7 +90,7 @@ export class Sample_LoadGLB { } }; - + GUIHelp.add({ Model: `HIE-Hand-Armor` }, 'Model', Object.keys(list)).onChange(async (v) => { let { url, scale, offset, rotation } = list[v]; this.loadGLB(url, offset, scale, rotation); diff --git a/samples/loader/Sample_LoadGLB2.ts b/samples/loader/Sample_LoadGLB2.ts index f6701594..663dbe40 100644 --- a/samples/loader/Sample_LoadGLB2.ts +++ b/samples/loader/Sample_LoadGLB2.ts @@ -11,21 +11,22 @@ export class Sample_LoadGLB2 { async run() { Engine3D.setting.render.debug = true; Engine3D.setting.shadow.autoUpdate = true; - + Engine3D.setting.shadow.shadowBound = 10; + Engine3D.setting.shadow.shadowBias = 0.005; await Engine3D.init(); let exampleScene = createExampleScene(); exampleScene.atmosphericSky.displaySun = false; exampleScene.atmosphericSky.sunRadiance = 1; this.scene = exampleScene.scene; - exampleScene.hoverCtrl.setCamera(-45, -45, 10); - exampleScene.light.intensity = 10; + exampleScene.hoverCtrl.setCamera(-45, -20, 16); + exampleScene.light.intensity = 5; Engine3D.startRenderView(exampleScene.view); await this.initScene(); GUIHelp.init(); GUIUtil.renderAtmosphericSky(exampleScene.atmosphericSky); - GUIUtil.renderDebug(); + // GUIUtil.renderDebug(); } async initScene() { diff --git a/samples/loader/Sample_LoadGLB3.ts b/samples/loader/Sample_LoadGLB3.ts index de8c9783..e714dca9 100644 --- a/samples/loader/Sample_LoadGLB3.ts +++ b/samples/loader/Sample_LoadGLB3.ts @@ -8,11 +8,14 @@ export class Sample_LoadGLB3 { async run() { await Engine3D.init(); Engine3D.setting.shadow.autoUpdate = true; + Engine3D.setting.shadow.shadowBound = 5; + Engine3D.setting.shadow.shadowBias = 0.002; + let exampleScene = createExampleScene(); this.scene = exampleScene.scene; - exampleScene.hoverCtrl.setCamera(-45, -45, 10); - exampleScene.light.intensity = 10; + exampleScene.hoverCtrl.setCamera(-45, -20, 8); + exampleScene.light.intensity = 5; Engine3D.startRenderView(exampleScene.view); await this.initScene(); } diff --git a/samples/loader/Sample_LoadGLTF.ts b/samples/loader/Sample_LoadGLTF.ts index a8b96b4b..307da6ac 100644 --- a/samples/loader/Sample_LoadGLTF.ts +++ b/samples/loader/Sample_LoadGLTF.ts @@ -51,7 +51,7 @@ class Sample_LoadGLTF { let directLight = this.lightObj3D.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 18; + directLight.intensity = 5; GUIHelp.init(); GUIUtil.renderDirLight(directLight); this.scene.addChild(this.lightObj3D); diff --git a/samples/material/Sample_ChangeMaterial.ts b/samples/material/Sample_ChangeMaterial.ts index 020acd3f..5ca15358 100644 --- a/samples/material/Sample_ChangeMaterial.ts +++ b/samples/material/Sample_ChangeMaterial.ts @@ -46,7 +46,7 @@ class Sample_ChangeMaterial { let directLight = lightObj.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 6; + directLight.intensity = 5; this.scene.addChild(lightObj); } diff --git a/samples/material/Sample_ClearCoat.ts b/samples/material/Sample_ClearCoat.ts index 3b7b013a..de889f41 100644 --- a/samples/material/Sample_ClearCoat.ts +++ b/samples/material/Sample_ClearCoat.ts @@ -8,7 +8,7 @@ class Sample_ClearCoat { async run() { Engine3D.setting.pick.enable = true; - Engine3D.setting.pick.mode = `pixel`; + // Engine3D.setting.pick.mode = `pixel`; Engine3D.setting.render.debug = true; GUIHelp.init(); @@ -53,7 +53,7 @@ class Sample_ClearCoat { let directLight = this.lightObj3D.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 43; + directLight.intensity = 1; GUIUtil.renderDirLight(directLight); this.scene.addChild(this.lightObj3D); } @@ -82,19 +82,23 @@ class Sample_ClearCoat { let mr = obj.addComponent(MeshRenderer); mr.geometry = geo; let mat = new LitMaterial(); - mat.baseColor = new Color(1.0, 0.0, 0.0); - mat.metallic = 0; - mat.roughness = 1; - mat.clearCoatRoughnessMap = clearCoatRoughnessTex; + mat.baseColor = Color.randomRGB(); + mat.metallic = 1; + mat.roughness = 0.85; + // mat.clearCoatRoughnessMap = clearCoatRoughnessTex; // mat.clearcoatFactor = i / 10; - mat.clearcoatColor = new Color(0.0, 0.0, 0.0); - mat.clearcoatWeight = 0.65; - mat.clearcoatFactor = 1; - mat.clearcoatRoughnessFactor = i / 10; + mat.clearcoatColor = new Color(1.0, 1.0, 1.0); + mat.clearcoatWeight = 1; + mat.clearcoatFactor = 0.5; + mat.ior = 1.5; + mat.clearcoatRoughnessFactor = 0.03; mr.material = mat; this.scene.addChild(obj); obj.x = space * i - space * 10 * 0.5; + + mat.name = `clearCoat_${i}` + GUIUtil.renderLitMaterial(mat); } } } diff --git a/samples/material/Sample_PBR.ts b/samples/material/Sample_PBR.ts index 4259ffbc..c6983109 100644 --- a/samples/material/Sample_PBR.ts +++ b/samples/material/Sample_PBR.ts @@ -45,7 +45,7 @@ class Sample_PBR { let directLight = this.lightObj3D.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = false; - directLight.intensity = 10; + directLight.intensity = 3; GUIUtil.renderDirLight(directLight); this.scene.addChild(this.lightObj3D); } diff --git a/samples/material/Sample_PBRMaterial.ts b/samples/material/Sample_PBRMaterial.ts index 40eeba35..f0f92189 100644 --- a/samples/material/Sample_PBRMaterial.ts +++ b/samples/material/Sample_PBRMaterial.ts @@ -11,7 +11,7 @@ class Sample_PBRMaterial { //config settings Engine3D.setting.render.debug = true; Engine3D.setting.shadow.shadowBound = 50; - + Engine3D.setting.shadow.shadowBias = 0.02; await Engine3D.init({ canvasConfig: { alpha: true, zIndex: 11, backgroundImage: '/logo/bg.webp' } }); GUIHelp.init(999); @@ -48,7 +48,7 @@ class Sample_PBRMaterial { let directLight = this.lightObj3D.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 72; + directLight.intensity = 5; GUIUtil.renderDirLight(directLight); this.scene.addChild(this.lightObj3D); diff --git a/samples/material/Sample_UVMove.ts b/samples/material/Sample_UVMove.ts index 77b36736..1153ddcc 100644 --- a/samples/material/Sample_UVMove.ts +++ b/samples/material/Sample_UVMove.ts @@ -47,7 +47,7 @@ class Sample_UVMove { let directLight = lightObj.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 6; + directLight.intensity = 2; this.scene.addChild(lightObj); } @@ -73,7 +73,7 @@ class Sample_UVMove { let material = new LitMaterial(); material.baseMap = await Engine3D.res.loadTexture("particle/T_Fx_Object_229.png");; renderer.material = material; - material.blendMode = BlendMode.ADD; + material.blendMode = BlendMode.NORMAL; renderer.geometry = new PlaneGeometry(100, 100, 1, 1); this.scene.addChild(plane); diff --git a/samples/material/_Sample_CarPaint.ts b/samples/material/_Sample_CarPaint.ts new file mode 100644 index 00000000..e2393819 --- /dev/null +++ b/samples/material/_Sample_CarPaint.ts @@ -0,0 +1,173 @@ +import { + View3D, DirectLight, Engine3D, + PostProcessingComponent, LitMaterial, HoverCameraController, + KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, + CameraUtil, webGPUContext, BoxGeometry, TAAPost, AtmosphericComponent, GTAOPost, Color, BloomPost, SSRPost, SSGIPost, GBufferPost, FXAAPost, SkyRenderer, Reflection, SphereReflection, GBufferFrame, ProfilerUtil, Time, SpotLight, Object3DUtil, Object3DTransformTools, PointLight, DepthOfFieldPost, OutlinePost, Material, Vector3 +} from '@orillusion/core'; +import { GUIHelp } from '@orillusion/debug/GUIHelp'; +import { GUIUtil } from '@samples/utils/GUIUtil'; + +export class Sample_CarPaint { + lightObj: Object3D; + scene: Scene3D; + view: View3D; + + async run() { + Engine3D.setting.shadow.shadowSize = 2048 + Engine3D.setting.shadow.shadowBound = 175; + Engine3D.setting.shadow.shadowBias = 0.0061; + + Engine3D.setting.shadow.shadowBound = 550; + Engine3D.setting.shadow.shadowBias = 0.018; + Engine3D.setting.render.useCompressGBuffer = true; + + Engine3D.setting.reflectionSetting.reflectionProbeMaxCount = 8; + Engine3D.setting.reflectionSetting.reflectionProbeSize = 128; + Engine3D.setting.reflectionSetting.enable = true; + + Engine3D.setting.render.hdrExposure = 1.0; + + GUIHelp.init(); + await Engine3D.init(); + + this.scene = new Scene3D(); + let sky = this.scene.getOrAddComponent(SkyRenderer); + sky.map = await Engine3D.res.loadTextureCubeStd('sky/LDR_sky.jpg'); + sky.exposure = 1.0; + sky.useSkyReflection(); + // sky.enable = false; + + let mainCamera = CameraUtil.createCamera3DObject(this.scene, 'camera'); + mainCamera.perspective(60, webGPUContext.aspect, 1, 8000.0); + let ctrl = mainCamera.object3D.addComponent(HoverCameraController); + ctrl.setCamera(-90, -25, 1200); + this.view = new View3D(); + this.view.scene = this.scene; + this.view.camera = mainCamera; + + Object3DTransformTools.instance.active(this.scene); + + await this.initScene(); + + Engine3D.startRenderView(this.view); + + let ssgi: SSGIPost; + let postProcessing = this.scene.addComponent(PostProcessingComponent); + postProcessing.addPost(FXAAPost); + + // ** test pass + // let TAA = postProcessing.addPost(TAAPost); + // let gtao = postProcessing.addPost(GTAOPost); + // GUIUtil.renderGTAO(gtao); + // let gBufferPost = postProcessing.addPost(GBufferPost); + // GUIUtil.renderGBufferPost(gBufferPost); + // let bloom = postProcessing.addPost(BloomPost); + // GUIUtil.renderBloom(bloom); + + // let taa = postProcessing.addPost(TAAPost); + // GUIUtil.renderTAA(taa); + // let depth = postProcessing.addPost(DepthOfFieldPost); + // GUIUtil.renderDepthOfField(depth); + // ** test pass + // let post = postProcessing.addPost(OutlinePost); + // GUIUtil.renderOutlinePost(post); + + // ** test pass + // let ssrt = postProcessing.addPost(SSRPost); + // ssgi = postProcessing.addPost(SSGIPost); + // GUIUtil.renderDirLight(this.lightObj.getComponent(DirectLight)); + GUIUtil.renderProfiler(ProfilerUtil.viewCount(this.view)); + GUIUtil.renderShadowSetting(); + let f = GUIHelp.addFolder("SSGI"); + f.open(); + GUIHelp.add(Engine3D.setting.sky, 'skyExposure', 0.0, 5.0, 0.0001); + GUIHelp.add(Engine3D.setting.render, 'hdrExposure', 0.0, 5.0, 0.0001); + GUIHelp.endFolder(); + } + + async initScene() { + { + // this.lightObj = new Object3D(); + // this.lightObj.rotationX = 45; + // this.lightObj.rotationY = 110; + // this.lightObj.rotationZ = 0; + + // this.lightObj.rotationX = 44.56; + // this.lightObj.rotationY = 112.8; + // this.lightObj.rotationZ = 0; + // let lc = this.lightObj.addComponent(DirectLight); + // lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + // lc.castShadow = true; + // lc.intensity = 15; + // lc.indirect = 0.1; + // this.scene.addChild(this.lightObj); + // GUIUtil.renderDirLight(lc); + } + + { + // let reflection = new Object3D(); + // let ref = reflection.addComponent(SphereReflection); + // ref.autoUpdate = true; + // // ref.debug(0, 5); + // reflection.x = 0; + // reflection.y = 300; + // reflection.z = 0; + // this.scene.addChild(reflection); + // GUIUtil.renderTransform(reflection.transform); + } + + { + let pl = Object3DUtil.GetPointLight( + new Vector3(0, 300, 0), + new Vector3(0, 0, 0), + 2590, + 1, + 1, + 1, + 1500, + true + ); + this.scene.addChild(pl.object3D); + GUIUtil.showPointLightGUI(pl); + } + + // let giScene = await Engine3D.res.loadGltf("gltfs/pbrCar/car.gltf"); + let giScene = await Engine3D.res.loadGltf("gltfs/scene/ue5_006.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/测试汽车1.gltf"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/测试汽车.glb"); + + let i = 0; + let cacheMat = new Map(); + giScene.forChild((child: Object3D) => { + let mr = child.getComponent(MeshRenderer); + if (mr) { + let mat = mr.material; + mat.doubleSide = true; + + if (mat instanceof LitMaterial) { + let has = mat.shader.hasDefine('USE_CLEARCOAT'); + // if (has && !cacheMat.has(mat.name) && mat.name.includes("白色")) { + // GUIUtil.renderLitMaterial(mat); + // cacheMat.set(mat.name, mat); + // } + + if (has && !cacheMat.has(mat.name)) { + GUIUtil.renderLitMaterial(mat); + cacheMat.set(mat.name, mat); + } else { + // if (i < 1) + // mr.enable = false; + // this.view.graphic3D.drawMeshWireframe(child.name + i++, mr.geometry, mr.transform); + } + } + } + }); + + //Demonstration + giScene.scaleX = 100; + giScene.scaleY = 100; + giScene.scaleZ = 100; + this.scene.addChild(giScene); + } +} + diff --git a/samples/material/script/UVMoveComponent.ts b/samples/material/script/UVMoveComponent.ts index f083e222..fe583423 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.getUniformV4(`transformUV1`); + let value = this._material.getUniformV4(`baseMapOffsetSize`); 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.setUniformVector4(`transformUV1`, value); + this._material.setUniformVector4(`baseMapOffsetSize`, value); } } } \ No newline at end of file diff --git a/samples/matrix/Sample_Matrix.ts b/samples/matrix/Sample_Matrix.ts deleted file mode 100644 index 630a6adc..00000000 --- a/samples/matrix/Sample_Matrix.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { GUIHelp } from '@orillusion/debug/GUIHelp'; -import { Stats } from '@orillusion/stats' -import { Engine3D, Scene3D, AtmosphericComponent, CameraUtil, HoverCameraController, Object3D, MeshRenderer, BoxGeometry, LitMaterial, DirectLight, KelvinUtil, View3D, PropertyAnimClip, PropertyAnimation, WrapMode } from '@orillusion/core'; -import { GUIUtil } from '@samples/utils/GUIUtil'; - -// simple base demo -class Sample_Matrix { - async run() { - // init engine - await Engine3D.init(); - // create new Scene - let scene = new Scene3D(); - - // add performance stats - scene.addComponent(Stats); - - // add an Atmospheric sky enviroment - let sky = scene.addComponent(AtmosphericComponent); - sky.sunY = 0.6; - - // init camera3D - let mainCamera = CameraUtil.createCamera3D(null, scene); - mainCamera.perspective(60, Engine3D.aspect, 1, 2000.0); - - // add a basic camera controller - let hoverCameraController = mainCamera.object3D.addComponent(HoverCameraController); - hoverCameraController.setCamera(15, -15, 10); - - - // add a basic direct light - let lightObj = new Object3D(); - lightObj.rotationX = 45; - lightObj.rotationY = 60; - lightObj.rotationZ = 150; - let dirLight = lightObj.addComponent(DirectLight); - dirLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); - dirLight.intensity = 10; - scene.addChild(lightObj); - - sky.relativeTransform = dirLight.transform; - - // create a view with target scene and camera - let view = new View3D(); - view.scene = scene; - view.camera = mainCamera; - - // start render - Engine3D.startRenderView(view); - - - // create a basic cube - let cubeObj = new Object3D(); - let mr = cubeObj.addComponent(MeshRenderer); - mr.geometry = new BoxGeometry(); - let mat = new LitMaterial(); - mr.material = mat; - scene.addChild(cubeObj); - this.initPropertyAnim(cubeObj); - - let transform = cubeObj.transform; - // debug GUI - GUIHelp.init(); - GUIUtil.renderTransform(transform); - } - - private async initPropertyAnim(owner: Object3D) { - // add PropertyAnimation - let animation = owner.addComponent(PropertyAnimation); - - //load a animation clip - let json: any = await Engine3D.res.loadJSON('json/anim_0.json'); - let animClip = new PropertyAnimClip(); - animClip.parse(json); - animClip.wrapMode = WrapMode.Loop; - animation.defaultClip = animClip.name; - animation.autoPlay = true; - - // register clip to animation - animation.appendClip(animClip); - return animation; - } -} - -new Sample_Matrix().run() \ No newline at end of file diff --git a/samples/particle/Sample_CandleFlame.ts b/samples/particle/Sample_CandleFlame.ts index 32a61312..5622661d 100644 --- a/samples/particle/Sample_CandleFlame.ts +++ b/samples/particle/Sample_CandleFlame.ts @@ -46,8 +46,8 @@ export class Sample_CandleFlame { let lightObj = this.lightObj = new Object3D(); let pl = lightObj.addComponent(PointLight); pl.range = 56; - pl.radius = 1; - pl.intensity = 15; + pl.radius = 0.01; + pl.intensity = 5; pl.castShadow = true; pl.realTimeShadow = true; pl.lightColor = new Color(67 / 255, 195 / 255, 232 / 255); diff --git a/samples/physics/Sample_Physics01.ts b/samples/physics/Sample_Physics01.ts index c8d23945..c59b8419 100644 --- a/samples/physics/Sample_Physics01.ts +++ b/samples/physics/Sample_Physics01.ts @@ -86,7 +86,7 @@ class SamplePhysics01 { floorMat.baseMap = Engine3D.res.grayTexture; floorMat.roughness = 0.85; floorMat.metallic = 0.01; - floorMat.envIntensity = 0.01; + // floorMat.envIntensity = 0.01; let floor = new Object3D(); let renderer = floor.addComponent(MeshRenderer); diff --git a/samples/physics/Sample_PhysicsBox.ts b/samples/physics/Sample_PhysicsBox.ts index 247016cb..8befd643 100644 --- a/samples/physics/Sample_PhysicsBox.ts +++ b/samples/physics/Sample_PhysicsBox.ts @@ -86,7 +86,7 @@ class Sample_PhysicsBox { floorMat.baseMap = Engine3D.res.grayTexture; floorMat.roughness = 0.85; floorMat.metallic = 0.01; - floorMat.envIntensity = 0.01; + // floorMat.envIntensity = 0.01; let floor = new Object3D(); let meshRenderer = floor.addComponent(MeshRenderer); diff --git a/samples/pick/Sample_OutlineEffectPick.ts b/samples/pick/Sample_OutlineEffectPick.ts index 4264e65c..14a1d962 100644 --- a/samples/pick/Sample_OutlineEffectPick.ts +++ b/samples/pick/Sample_OutlineEffectPick.ts @@ -3,7 +3,7 @@ import { GUIUtil } from "@samples/utils/GUIUtil"; import { createExampleScene } from "@samples/utils/ExampleScene"; import { Object3D, Scene3D, Color, Engine3D, OutlinePost, SphereGeometry, LitMaterial, MeshRenderer, ColliderComponent, PointerEvent3D, outlinePostManager, FXAAPost } from "@orillusion/core"; -class Sample_OutlineEffectPick { +export class Sample_OutlineEffectPick { lightObj: Object3D; scene: Scene3D; selectColor: Color; @@ -15,7 +15,11 @@ class Sample_OutlineEffectPick { } async run() { - Engine3D.setting.pick.enable = true; + Engine3D.setting.shadow.enable = true; + Engine3D.setting.shadow.shadowSize = 2048 + Engine3D.setting.shadow.shadowBound = 50; + Engine3D.setting.shadow.shadowBias = 0.05; + Engine3D.setting.pick.mode = `pixel`; Engine3D.setting.render.postProcessing.outline.outlinePixel = 3; @@ -32,7 +36,6 @@ 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); @@ -107,4 +110,4 @@ class Sample_OutlineEffectPick { } -new Sample_OutlineEffectPick().run(); \ No newline at end of file +// new Sample_OutlineEffectPick().run(); \ No newline at end of file diff --git a/samples/post/Sample_Bloom.ts b/samples/post/Sample_Bloom.ts index e52ca91f..386f8bf7 100644 --- a/samples/post/Sample_Bloom.ts +++ b/samples/post/Sample_Bloom.ts @@ -50,7 +50,7 @@ class Sample_Bloom { let lc = this.lightObj.addComponent(DirectLight); lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355); lc.castShadow = true; - lc.intensity = 10; + lc.intensity = 3; this.scene.addChild(this.lightObj); } @@ -96,7 +96,7 @@ class Sample_Bloom { { let litMat = new LitMaterial(); litMat.emissiveColor = new Color(0.0, 0.0, 1.0); - litMat.emissiveIntensity = 1.8; + litMat.emissiveIntensity = 0.6; let sp = new Object3D(); let mr = sp.addComponent(MeshRenderer); mr.geometry = new SphereGeometry(15, 30, 30); @@ -110,7 +110,7 @@ class Sample_Bloom { { let litMat = new LitMaterial(); litMat.emissiveColor = new Color(1.0, 1.0, 0.0); - litMat.emissiveIntensity = 1.2; + litMat.emissiveIntensity = 0.8; let sp = new Object3D(); let mr = sp.addComponent(MeshRenderer); mr.geometry = new SphereGeometry(15, 30, 30); diff --git a/samples/post/Sample_DepthOfView.ts b/samples/post/Sample_DepthOfView.ts index d68e072c..eb4766be 100644 --- a/samples/post/Sample_DepthOfView.ts +++ b/samples/post/Sample_DepthOfView.ts @@ -32,14 +32,14 @@ class Sample_DepthOfView { let postProcessing = this.scene.addComponent(PostProcessingComponent) let DOFPost = postProcessing.addPost(DepthOfFieldPost) - DOFPost.near = 0 - DOFPost.far = 150 + DOFPost.near = 160 + DOFPost.far = 550 DOFPost.pixelOffset = 2 let GUIHelp = new dat.GUI() GUIHelp.addFolder('Depth of Field') - GUIHelp.add(DOFPost, 'near', 0, 100, 1) - GUIHelp.add(DOFPost, 'far', 150, 300, 1) + GUIHelp.add(DOFPost, 'near', 0, 400, 1) + GUIHelp.add(DOFPost, 'far', 150, 1000, 1) console.log("run"); @@ -55,7 +55,7 @@ class Sample_DepthOfView { let lc = this.lightObj.addComponent(DirectLight) lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355) lc.castShadow = true - lc.intensity = 10 + lc.intensity = 5 scene.addChild(this.lightObj) } diff --git a/samples/post/Sample_FXAA.ts b/samples/post/Sample_FXAA.ts index 70043ed1..9c20eea4 100644 --- a/samples/post/Sample_FXAA.ts +++ b/samples/post/Sample_FXAA.ts @@ -47,7 +47,7 @@ class Sample_Bloom { let lc = this.lightObj.addComponent(DirectLight); lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355); lc.castShadow = true; - lc.intensity = 10; + lc.intensity = 5; this.scene.addChild(this.lightObj); } diff --git a/samples/post/Sample_Fog.ts b/samples/post/Sample_Fog.ts index 144bc509..286c017d 100644 --- a/samples/post/Sample_Fog.ts +++ b/samples/post/Sample_Fog.ts @@ -44,7 +44,7 @@ class Sample_Fog { let lc = this.lightObj.addComponent(DirectLight); lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355); lc.castShadow = true; - lc.intensity = 30; + lc.intensity = 5; this.scene.addChild(this.lightObj); } diff --git a/samples/post/Sample_GTAO.ts b/samples/post/Sample_GTAO.ts index adcfe035..5ac70ee3 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 + CameraUtil, webGPUContext, BoxGeometry, AtmosphericComponent, GTAOPost, Color, FXAAPost, GBufferPost } from '@orillusion/core'; import { GUIHelp } from '@orillusion/debug/GUIHelp'; import { GUIUtil } from '@samples/utils/GUIUtil'; @@ -14,6 +14,7 @@ export class Sample_GTAO { async run() { Engine3D.setting.shadow.shadowSize = 2048 Engine3D.setting.shadow.shadowBound = 500; + Engine3D.setting.shadow.shadowBias = 0.05; Engine3D.setting.render.debug = true; await Engine3D.init(); @@ -42,7 +43,7 @@ export class Sample_GTAO { let lc = this.lightObj.addComponent(DirectLight); lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355); lc.castShadow = true; - lc.intensity = 45; + lc.intensity = 5; lc.indirect = 0.3; this.scene.addChild(this.lightObj); GUIUtil.renderDirLight(lc); @@ -50,86 +51,68 @@ export class Sample_GTAO { let postProcessing = this.scene.addComponent(PostProcessingComponent); let post = postProcessing.addPost(GTAOPost); - post.maxDistance = 60; - this.gui(); + post.maxDistance = 6; + post.maxPixel = 15; + GUIUtil.renderGTAO(post); - GUIUtil.renderDebug(); + GUIUtil.renderShadowSetting(); } async initScene() { + let mat = new LitMaterial(); + mat.roughness = 1.0; + mat.metallic = 0.0; + + let floor = new Object3D(); + let mr = floor.addComponent(MeshRenderer); + mr.geometry = new PlaneGeometry(400, 400); + mr.material = mat; + this.scene.addChild(floor); + + { + let wall = new Object3D(); + let mr = wall.addComponent(MeshRenderer); + mr.geometry = new BoxGeometry(5, 260, 320); + mr.material = mat; + wall.x = -320 * 0.5; + this.scene.addChild(wall); + } + + { + let wall = new Object3D(); + let mr = wall.addComponent(MeshRenderer); + mr.geometry = new BoxGeometry(5, 260, 320); + mr.material = mat; + wall.x = 320 * 0.5; + this.scene.addChild(wall); + } + + { + let wall = new Object3D(); + let mr = wall.addComponent(MeshRenderer); + mr.geometry = new BoxGeometry(320, 260, 5); + mr.material = mat; + wall.z = -320 * 0.5; + this.scene.addChild(wall); + } + { let mat = new LitMaterial(); + mat.baseMap = Engine3D.res.whiteTexture; + mat.baseColor = new Color(1.0, 0.464, 0.0); + mat.normalMap = Engine3D.res.normalTexture; + mat.aoMap = Engine3D.res.whiteTexture; mat.roughness = 1.0; mat.metallic = 0.0; - let floor = new Object3D(); - let mr = floor.addComponent(MeshRenderer); - mr.geometry = new PlaneGeometry(400, 400); + let sp = new Object3D(); + let mr = sp.addComponent(MeshRenderer); + mr.geometry = new SphereGeometry(50, 30, 30); mr.material = mat; - this.scene.addChild(floor); - - { - let wall = new Object3D(); - let mr = wall.addComponent(MeshRenderer); - mr.geometry = new BoxGeometry(5, 260, 320); - mr.material = mat; - wall.x = -320 * 0.5; - this.scene.addChild(wall); - } - - { - let wall = new Object3D(); - let mr = wall.addComponent(MeshRenderer); - mr.geometry = new BoxGeometry(5, 260, 320); - mr.material = mat; - wall.x = 320 * 0.5; - this.scene.addChild(wall); - } - - { - let wall = new Object3D(); - let mr = wall.addComponent(MeshRenderer); - mr.geometry = new BoxGeometry(320, 260, 5); - mr.material = mat; - wall.z = -320 * 0.5; - this.scene.addChild(wall); - } - - { - { - let mat = new LitMaterial(); - mat.baseMap = Engine3D.res.whiteTexture; - mat.baseColor = new Color(1.0, 0.464, 0.0); - mat.normalMap = Engine3D.res.normalTexture; - mat.aoMap = Engine3D.res.whiteTexture; - mat.roughness = 1.0; - mat.metallic = 0.0; - - let sp = new Object3D(); - let mr = sp.addComponent(MeshRenderer); - mr.geometry = new SphereGeometry(50, 30, 30); - mr.material = mat; - this.scene.addChild(sp); - } - } + this.scene.addChild(sp); } } - private gui() { - GUIHelp.init(); - let postProcessing = this.scene.getComponent(PostProcessingComponent); - let post = postProcessing.getPost(GTAOPost); - - GUIHelp.addFolder("GTAO"); - GUIHelp.add(post, "maxDistance", 0.0, 50, 1); - GUIHelp.add(post, "maxPixel", 0.0, 50, 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(); - } } -// new Sample_GTAO().run(); diff --git a/samples/post/Sample_GodRay.ts b/samples/post/Sample_GodRay.ts index bb254d52..f84af12d 100644 --- a/samples/post/Sample_GodRay.ts +++ b/samples/post/Sample_GodRay.ts @@ -2,7 +2,7 @@ import { View3D, DirectLight, Engine3D, PostProcessingComponent, LitMaterial, HoverCameraController, KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, - CameraUtil, webGPUContext, BoxGeometry, AtmosphericComponent, Time, GodRayPost, BloomPost + CameraUtil, webGPUContext, BoxGeometry, AtmosphericComponent, GTAOPost, Color, FXAAPost, GBufferPost, GodRayPost, Time, BloomPost } from '@orillusion/core'; import { GUIHelp } from '@orillusion/debug/GUIHelp'; import { GUIUtil } from '@samples/utils/GUIUtil'; @@ -12,14 +12,17 @@ export class Sample_GodRay { scene: Scene3D; async run() { - Engine3D.setting.shadow.shadowSize = 1024; - Engine3D.setting.shadow.shadowBound = 400; + Engine3D.setting.shadow.shadowSize = 2048 + Engine3D.setting.shadow.shadowBound = 500; + Engine3D.setting.shadow.shadowBias = 0.05; + Engine3D.setting.render.debug = true; await Engine3D.init({ renderLoop: () => { this.loop() } }); + GUIHelp.init(); this.scene = new Scene3D(); let sky = this.scene.addComponent(AtmosphericComponent); - GUIHelp.init(); + sky.sunY = 0.6; let mainCamera = CameraUtil.createCamera3DObject(this.scene, 'camera'); mainCamera.perspective(60, webGPUContext.aspect, 1, 5000.0); @@ -27,21 +30,33 @@ export class Sample_GodRay { ctrl.setCamera(110, -10, 300); await this.initScene(); - sky.relativeTransform = this.lightObj.transform; let view = new View3D(); view.scene = this.scene; view.camera = mainCamera; - mainCamera.enableCSM = true; Engine3D.startRenderView(view); + this.lightObj = new Object3D(); + this.lightObj.rotationX = 15; + this.lightObj.rotationY = 134; + this.lightObj.rotationZ = 0; + let lc = this.lightObj.addComponent(DirectLight); + lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + lc.castShadow = true; + lc.intensity = 45; + lc.indirect = 0.3; + this.scene.addChild(this.lightObj); + GUIUtil.renderDirLight(lc); + sky.relativeTransform = this.lightObj.transform; + let postProcessing = this.scene.addComponent(PostProcessingComponent); let godRay = postProcessing.addPost(GodRayPost); - postProcessing.addPost(BloomPost); + // postProcessing.addPost(BloomPost); GUIUtil.renderAtmosphericSky(sky, false); GUIUtil.renderGodRay(godRay); } + async initScene() { { this.lightObj = new Object3D(); @@ -51,7 +66,7 @@ export class Sample_GodRay { let lc = this.lightObj.addComponent(DirectLight); lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355); lc.castShadow = true; - lc.intensity = 20; + lc.intensity = 5; this.scene.addChild(this.lightObj); GUIUtil.renderDirLight(lc, false); } @@ -69,7 +84,6 @@ export class Sample_GodRay { this.createPlane(this.scene); } - private ball: Object3D; private createPlane(scene: Scene3D) { let mat = new LitMaterial(); @@ -115,7 +129,4 @@ export class Sample_GodRay { this.ball.localPosition = position; } } - } - -// new Sample_GodRay().run(); diff --git a/samples/post/Sample_Outline.ts b/samples/post/Sample_Outline.ts index 78917c56..245fc2f2 100644 --- a/samples/post/Sample_Outline.ts +++ b/samples/post/Sample_Outline.ts @@ -1,18 +1,25 @@ import { DirectLight, Engine3D, View3D, LitMaterial, HoverCameraController, KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, PostProcessingComponent, CameraUtil, webGPUContext, OutlinePost, outlinePostManager, AtmosphericComponent, Color, FXAAPost } from '@orillusion/core' +import { GUIHelp } from '@orillusion/debug/GUIHelp'; import * as dat from '@orillusion/debug/dat.gui.module' +import { GUIUtil } from '@samples/utils/GUIUtil'; -class Sample_Outline { +export class Sample_Outline { lightObj: Object3D scene: Scene3D constructor() { } async run() { - Engine3D.setting.shadow.enable = false + Engine3D.setting.shadow.enable = true; + Engine3D.setting.shadow.shadowSize = 2048 + Engine3D.setting.shadow.shadowBound = 50; + Engine3D.setting.shadow.shadowBias = 0.05; + await Engine3D.init({ canvasConfig: { devicePixelRatio: 1 - } + }, + renderLoop: () => this.loop() }) this.scene = new Scene3D() @@ -21,8 +28,7 @@ class Sample_Outline { let mainCamera = CameraUtil.createCamera3DObject(this.scene, 'camera') mainCamera.perspective(60, webGPUContext.aspect, 1, 2000.0) let ctrl = mainCamera.object3D.addComponent(HoverCameraController) - ctrl.setCamera(180, -45, 15) - + ctrl.setCamera(-75, -30, 20) await this.initScene(this.scene) let view = new View3D() @@ -31,7 +37,7 @@ class Sample_Outline { Engine3D.startRenderView(view) let postProcessing = this.scene.addComponent(PostProcessingComponent) - // let outlinePost = postProcessing.addPost(FXAAPost) + postProcessing.addPost(FXAAPost) let outlinePost = postProcessing.addPost(OutlinePost) const GUIHelp = new dat.GUI() @@ -57,16 +63,15 @@ class Sample_Outline { /******** light *******/ { this.lightObj = new Object3D() - this.lightObj.x = 0 - this.lightObj.y = 30 - this.lightObj.z = -40 - this.lightObj.rotationX = 45 - this.lightObj.rotationY = 0 - this.lightObj.rotationZ = 45 + this.lightObj.rotationX = 15 + this.lightObj.rotationY = 110 + this.lightObj.rotationZ = 0 let lc = this.lightObj.addComponent(DirectLight) lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355) - lc.intensity = 10 + lc.castShadow = true + lc.intensity = 5 scene.addChild(this.lightObj) + GUIUtil.renderDirLight(lc); } this.createPlane(scene) @@ -114,6 +119,9 @@ class Sample_Outline { this.sphereList.push(obj) } } + + loop() { + } } -new Sample_Outline().run() +// new Sample_Outline().run() diff --git a/samples/post/Sample_SSR.ts b/samples/post/Sample_SSR.ts index 0d08b9e7..4527b3d6 100644 --- a/samples/post/Sample_SSR.ts +++ b/samples/post/Sample_SSR.ts @@ -1,15 +1,18 @@ import { DirectLight, Engine3D, View3D, LitMaterial, HoverCameraController, KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, SSRPost, Time, CameraUtil, webGPUContext, PostProcessingComponent, BloomPost, AtmosphericComponent } from '@orillusion/core' -import * as dat from '@orillusion/debug/dat.gui.module' +import { GUIHelp } from '@orillusion/debug/GUIHelp' +import { GUIUtil } from '@samples/utils/GUIUtil'; -class Sample_SSR { +export class Sample_SSR { lightObj: Object3D scene: Scene3D - mats: any[] - - constructor() { } async run() { - Engine3D.setting.shadow.enable = true + Engine3D.setting.shadow.enable = true; + Engine3D.setting.shadow.shadowSize = 2048 + Engine3D.setting.shadow.shadowBound = 200; + Engine3D.setting.shadow.shadowBias = 0.05; + GUIHelp.init(); + await Engine3D.init({ canvasConfig: { devicePixelRatio: 1 @@ -23,7 +26,7 @@ class Sample_SSR { let mainCamera = CameraUtil.createCamera3DObject(this.scene, 'camera') mainCamera.perspective(60, webGPUContext.aspect, 1, 2000.0) let ctrl = mainCamera.object3D.addComponent(HoverCameraController) - ctrl.setCamera(180, -5, 60) + ctrl.setCamera(-75, -20, 40) await this.initScene(this.scene) let view = new View3D() @@ -46,19 +49,31 @@ class Sample_SSR { let lc = this.lightObj.addComponent(DirectLight) lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355) lc.castShadow = true - lc.intensity = 27 + lc.intensity = 10 scene.addChild(this.lightObj) + GUIUtil.renderDirLight(lc); } // load test model let minimalObj = await Engine3D.res.loadGltf('/PBR/ToyCar/ToyCar.gltf') - minimalObj.scaleX = minimalObj.scaleY = minimalObj.scaleZ = 1000 + minimalObj.scaleX = minimalObj.scaleY = minimalObj.scaleZ = 1000; + minimalObj.y = -1.1; scene.addChild(minimalObj) + minimalObj.forChild((obj: Object3D) => { + let mr = obj.getComponent(MeshRenderer) + if (mr && mr.material) { + if (mr.material.name == 'ToyCar') { + let mat = mr.material as LitMaterial; + mat.metallic = 0.5; + mat.clearcoatFactor = 0.25; + } + } + } + ); await this.createPlane(scene) return true } - private sphere: Object3D private async createPlane(scene: Scene3D) { @@ -68,7 +83,7 @@ class Sample_SSR { { let floorMaterial = new LitMaterial() - floorMaterial.roughness = 0.5 + floorMaterial.roughness = 0.12 floorMaterial.metallic = 0.5 let planeGeometry = new PlaneGeometry(200, 200) @@ -78,8 +93,7 @@ class Sample_SSR { mr.geometry = planeGeometry scene.addChild(floor) - const GUIHelp = new dat.GUI() - GUIHelp.add(floorMaterial, 'roughness', 0, 1, 0.01) + GUIHelp.add(floorMaterial, 'roughness', 0.01, 1, 0.01) GUIHelp.add(floorMaterial, 'metallic', 0, 1, 0.01) } @@ -125,4 +139,3 @@ class Sample_SSR { } } -new Sample_SSR().run() diff --git a/samples/post/Sample_TAA.ts b/samples/post/Sample_TAA.ts index 08a4abb1..1be9fba5 100644 --- a/samples/post/Sample_TAA.ts +++ b/samples/post/Sample_TAA.ts @@ -4,16 +4,18 @@ import { KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, CameraUtil, webGPUContext, BoxGeometry, TAAPost, AtmosphericComponent } from '@orillusion/core'; +import { GUIHelp } from '@orillusion/debug/GUIHelp'; +import { GUIUtil } from '@samples/utils/GUIUtil'; -class Sample_TAA { +export class Sample_TAA { lightObj: Object3D; scene: Scene3D; async run() { - // Engine3D.setting.shadow.enable = false; - // Engine3D.setting.shadow.debug = true; - Engine3D.setting.shadow.shadowSize = 2048 - Engine3D.setting.shadow.shadowBound = 50; + Engine3D.setting.shadow.enable = true; + Engine3D.setting.shadow.shadowSize = 2048; + Engine3D.setting.shadow.shadowBound = 40; + Engine3D.setting.shadow.shadowBias = 0.005; await Engine3D.init(); @@ -35,7 +37,10 @@ class Sample_TAA { Engine3D.startRenderView(view); let postProcessing = this.scene.addComponent(PostProcessingComponent); - postProcessing.addPost(TAAPost); + let taa = postProcessing.addPost(TAAPost); + GUIHelp.init(); + GUIUtil.renderTAA(taa); + } async initScene() { @@ -47,7 +52,7 @@ class Sample_TAA { let lc = this.lightObj.addComponent(DirectLight); lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355); lc.castShadow = true; - lc.intensity = 10; + lc.intensity = 4; this.scene.addChild(this.lightObj); } @@ -103,4 +108,3 @@ class Sample_TAA { } } -new Sample_TAA().run(); diff --git a/samples/post/_Sample_SSGI.ts b/samples/post/_Sample_SSGI.ts new file mode 100644 index 00000000..a06f8abb --- /dev/null +++ b/samples/post/_Sample_SSGI.ts @@ -0,0 +1,244 @@ +import { + View3D, DirectLight, Engine3D, + PostProcessingComponent, LitMaterial, HoverCameraController, + KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, + CameraUtil, webGPUContext, BoxGeometry, TAAPost, AtmosphericComponent, GTAOPost, Color, BloomPost, SSRPost, SSGIPost, GBufferPost, FXAAPost, SkyRenderer, Reflection, SphereReflection, GBufferFrame, ProfilerUtil, Time, SpotLight, Object3DUtil, Object3DTransformTools, PointLight, DepthOfFieldPost, OutlinePost +} from '@orillusion/core'; +import { GUIHelp } from '@orillusion/debug/GUIHelp'; +import { Stats } from '@orillusion/stats'; +import { PhysicTransformController } from '@samples/physics/helps/components/PhysicTransformController'; +import { GUIUtil } from '@samples/utils/GUIUtil'; + +export class Sample_SSGI { + lightObj: Object3D; + scene: Scene3D; + view: View3D; + + async run() { + Engine3D.setting.shadow.shadowSize = 2048 + Engine3D.setting.shadow.shadowBound = 175; + Engine3D.setting.shadow.shadowBias = 0.0061; + + Engine3D.setting.shadow.shadowBound = 250; + Engine3D.setting.shadow.shadowBias = 0.018; + Engine3D.setting.render.useCompressGBuffer = true; + + Engine3D.setting.reflectionSetting.reflectionProbeMaxCount = 8; + Engine3D.setting.reflectionSetting.reflectionProbeSize = 128; + Engine3D.setting.reflectionSetting.enable = true; + + Engine3D.setting.render.hdrExposure = 1.0; + + GUIHelp.init(); + await Engine3D.init(); + + this.scene = new Scene3D(); + // this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + // let sky = this.scene.getOrAddComponent(SkyRenderer); + // sky.map = await Engine3D.res.loadHDRTextureCube('/hdri/daytime2.hdr'); + // this.scene.envMap = sky.map; + sky.exposure = 1.0; + + let mainCamera = CameraUtil.createCamera3DObject(this.scene, 'camera'); + // mainCamera.enableCSM = true; + mainCamera.perspective(60, webGPUContext.aspect, 1, 5000.0); + let ctrl = mainCamera.object3D.addComponent(HoverCameraController); + ctrl.setCamera(-90, -25, 200); + this.view = new View3D(); + this.view.scene = this.scene; + this.view.camera = mainCamera; + + Object3DTransformTools.instance.active(this.scene); + + await this.initScene(); + sky.relativeTransform = this.lightObj.transform; + + Engine3D.startRenderView(this.view); + + let ssgi: SSGIPost; + let postProcessing = this.scene.addComponent(PostProcessingComponent); + postProcessing.addPost(FXAAPost); + + // ** test pass + // let TAA = postProcessing.addPost(TAAPost); + let gtao = postProcessing.addPost(GTAOPost); + GUIUtil.renderGTAO(gtao); + let gBufferPost = postProcessing.addPost(GBufferPost); + GUIUtil.renderGBufferPost(gBufferPost); + // let bloom = postProcessing.addPost(BloomPost); + // GUIUtil.renderBloom(bloom); + + // let taa = postProcessing.addPost(TAAPost); + // GUIUtil.renderTAA(taa); + // let depth = postProcessing.addPost(DepthOfFieldPost); + // GUIUtil.renderDepthOfField(depth); + // ** test pass + // let post = postProcessing.addPost(OutlinePost); + // GUIUtil.renderOutlinePost(post); + + // ** test pass + // let ssrt = postProcessing.addPost(SSRPost); + // ssgi = postProcessing.addPost(SSGIPost); + // GUIUtil.renderDirLight(this.lightObj.getComponent(DirectLight)); + + GUIUtil.renderShadowSetting(); + let f = GUIHelp.addFolder("SSGI"); + f.open(); + GUIHelp.add(Engine3D.setting.sky, 'skyExposure', 0.0, 5.0, 0.0001); + GUIHelp.add(Engine3D.setting.render, 'hdrExposure', 0.0, 5.0, 0.0001); + GUIHelp.endFolder(); + } + + async initScene() { + { + this.lightObj = new Object3D(); + this.lightObj.rotationX = 45; + this.lightObj.rotationY = 110; + this.lightObj.rotationZ = 0; + + this.lightObj.rotationX = 44.56; + this.lightObj.rotationY = 112.8; + this.lightObj.rotationZ = 0; + let lc = this.lightObj.addComponent(DirectLight); + lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + lc.castShadow = true; + lc.intensity = 4 + lc.indirect = 0.1; + this.scene.addChild(this.lightObj); + GUIUtil.renderDirLight(lc); + + // let spotObj = new Object3D(); + // spotObj.addChild(Object3DUtil.GetCube()); + // let l = spotObj.addComponent(SpotLight); + // l.castShadow = true; + // this.scene.addChild(spotObj); + // GUIUtil.showSpotLightGUI(l); + + // spotObj.x = -652.02; + // spotObj.y = 291.67; + // spotObj.z = -225.11; + + // spotObj.rotationX = -8.24; + // spotObj.rotationY = 48.38; + // spotObj.rotationZ = 0; + + // l.lightColor = new Color().copyFromArray([147, 101, 101, 255]); + + // l.intensity = 3; + // l.range = 1000; + // l.outerAngle = 114; + + // let pointObj = new Object3D(); + // pointObj.addChild(Object3DUtil.GetCube()); + // let pl = pointObj.addComponent(PointLight); + // pl.castShadow = true; + // this.scene.addChild(pointObj); + + // pointObj.x = -652.02; + // pointObj.y = 291.67; + // pointObj.z = -225.11; + + // pl.lightColor = new Color().copyFromArray([147, 101, 101, 255]); + + // pl.intensity = 3; + // pl.range = 1000; + // GUIUtil.showPointLightGUI(pl); + } + + // let giScene = await Engine3D.res.loadGltf("live/Archive/pxd.gltf"); + // let giScene = await Engine3D.res.loadGltf("live/Archive/live.glb"); + // let giScene = await Engine3D.res.loadGltf("live/Archive/live2.glb"); + // let giScene = await Engine3D.res.loadGltf("gi/GITest.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/wukong/wukong.gltf"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/ue5_001.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/ue5_002.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/ue5_003.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/ue5_004.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/ue5_005.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/SM_Ground_Grass_01.glb"); + + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/frazer-nash.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/Example_Streets.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/Corridor_Gardens_Pergola01.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/SM_Statue_09.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/SM_Statue_08.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/SM_Female_Bust_Statuette_01a.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/SM_Old_Wooden_Figurine_01a.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/SM_Art_01c.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/SM_Art_01b.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/SM_Geode_01a.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/SM_F_Display_Stand_01a.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/ue5_006.glb"); + let giScene = await Engine3D.res.loadGltf("gltfs/dt/DingLeiChangFang.gltf"); + + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/ue5_007.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/Corridor_Gardens_FountainPool01.gltf"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/cim.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/pbrCar/car.gltf"); + giScene.forChild((child: Object3D) => { + let mr = child.getComponent(MeshRenderer); + if (mr) { + let mat = mr.material; + if (mat instanceof LitMaterial) { + GUIUtil.renderLitMaterial(mat); + } + } + }); + + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/SM_Platform_01d.glb"); + // let giScene = await Engine3D.res.loadGltf("gltfs/scene/SM_Outfit_01d.glb"); + + // let ab = giScene.getChildByName("SM_Outfit_01d1") as Object3D; + // let abMR = ab.getComponent(MeshRenderer); + // let mat = abMR.material; + // GUIUtil.renderLitMaterial(mat as LitMaterial); + + // let ab = giScene.getChildByName("SM_Water_Pot_01a1") as Object3D; + // let abMR = (ab.entityChildren[0] as Object3D).getComponent(MeshRenderer); + // let mat = abMR.material; + // GUIUtil.renderLitMaterial(mat as LitMaterial); + + //Demonstration + giScene.scaleX = 10; + giScene.scaleY = 10; + giScene.scaleZ = 10; + this.scene.addChild(giScene); + + let ab = giScene.getChildByName("BP_Car_Circle_01a") as Object3D; + if (ab) { + setInterval(() => { + ab.rotationY += Time.delta * 0.001 * 1; + }, 16); + } + + + let space = 100; + let ii = 0; + for (let i = 0; i < 2; i++) { + for (let j = 0; j < 2; j++) { + let reflection = new Object3D(); + let ref = reflection.addComponent(SphereReflection); + reflection.x = i * space - space * 0.5; + reflection.y = 10; + reflection.z = j * space - space * 0.5; + ref.debug(ii++, 0.1); + this.scene.addChild(reflection); + } + } + + { + let emiss = Object3DUtil.GetCube(); + let mr = emiss.getComponent(MeshRenderer); + let mat = mr.material as LitMaterial; + // mat.emissiveColor = new Color(0.2, 0.2, 0.8); + // mat.emissiveIntensity = 1.5; + + emiss.scaleX = 10; + emiss.scaleY = 10; + emiss.scaleZ = 10; + this.scene.addChild(emiss); + } + } +} + diff --git a/samples/render/Sample_BlendMode.ts b/samples/render/Sample_BlendMode.ts index 2b856efd..66ad0a8e 100644 --- a/samples/render/Sample_BlendMode.ts +++ b/samples/render/Sample_BlendMode.ts @@ -45,7 +45,7 @@ class Sample_BlendMode2 { let directLight = lightObj.addComponent(DirectLight); directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); directLight.castShadow = true; - directLight.intensity = 6; + directLight.intensity = 2; directLight.debug(); this.scene.addChild(lightObj); } @@ -55,20 +55,19 @@ class Sample_BlendMode2 { let plane = new Object3D(); let renderer = plane.addComponent(MeshRenderer); let material = new UnLitMaterial(); - material.baseMap = await Engine3D.res.loadTexture("particle/T_Fx_Object_229.png");; + material.baseMap = await Engine3D.res.loadTexture("particle/T_Fx_Object_229.png"); + material.blendMode = BlendMode.NORMAL; renderer.material = material; renderer.geometry = new PlaneGeometry(100, 100, 1, 1); - material.blendMode = BlendMode.NORMAL; this.scene.addChild(plane); GUIHelp.init(); // blend mode - let blendMode = { - NONE: BlendMode.NONE, - NORMAL: BlendMode.NORMAL, - ADD: BlendMode.ADD, - ALPHA: BlendMode.ALPHA, + let blendMode = {} + for(let i in BlendMode){ + if(!i.match(/\d/)) + blendMode[i] = BlendMode[i]; } // change blend mode by click dropdown box GUIHelp.add({ blendMode: material.blendMode }, 'blendMode', blendMode).onChange((v) => { diff --git a/samples/render/Sample_HighPrecision.ts b/samples/render/Sample_LogDepth.ts similarity index 52% rename from samples/render/Sample_HighPrecision.ts rename to samples/render/Sample_LogDepth.ts index 713108c8..4634ff95 100644 --- a/samples/render/Sample_HighPrecision.ts +++ b/samples/render/Sample_LogDepth.ts @@ -1,24 +1,16 @@ -import { Engine3D, Scene3D, AtmosphericComponent, View3D, CameraUtil, HoverCameraController, Object3D, MeshRenderer, SphereGeometry, UnLitMaterial, BoxGeometry, SkyRenderer, Color } from "@orillusion/core"; -import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { GUIUtil } from "@samples/utils/GUIUtil"; - -export class Sample_HighPrecision { +import { Engine3D, Scene3D, AtmosphericComponent, View3D, CameraUtil, HoverCameraController, Object3D, MeshRenderer, SphereGeometry, UnLitMaterial, BoxGeometry, SkyRenderer, Color, Vector3 } from "@orillusion/core"; +export class Sample_LogDepth { async run() { Engine3D.setting.render.useLogDepth = true; - await Engine3D.init(); let scene = new Scene3D(); - - GUIHelp.init(); - let camera = CameraUtil.createCamera3DObject(scene); camera.perspective(60, Engine3D.aspect, 1.0, 6000 * 10000.0); - camera.object3D.z = 3; let cameraController = camera.object3D.addComponent(HoverCameraController); - cameraController.setCamera(20, -45, 1500 * 10000.0); + cameraController.setCamera(20, -45, 2000 * 10000.0); cameraController.minDistance = 601 * 10000.0; cameraController.maxDistance = 6000 * 10000.0; @@ -42,37 +34,23 @@ export class Sample_HighPrecision { scene.addChild(obj); } + let boxGeo = new BoxGeometry(10000.0, 10000.0, 10000.0) + for(let i = 0; i < 100; i++) { + let parant = new Object3D(); let obj = new Object3D(); obj.x = 600 * 10000.0; + obj.localScale = new Vector3(50 + Math.random() * 300, 10 + Math.random() * 10, 10 + Math.random()); let mr = obj.addComponent(MeshRenderer); - mr.geometry = new BoxGeometry(600 * 10000.0, 100 * 10000.0, 100 * 10000.0); + mr.geometry = boxGeo; let mat = new UnLitMaterial(); - mat.baseColor = new Color(1, 0, 0) + mat.baseColor = new Color(Math.random(), Math.random(), Math.random()) mr.material = mat; - scene.addChild(obj); - } - - { - let obj = new Object3D(); - obj.y = 600 * 10000.0; - let mr = obj.addComponent(MeshRenderer); - mr.geometry = new BoxGeometry(100 * 10000.0, 600 * 10000.0, 100 * 10000.0); - let mat = new UnLitMaterial(); - mat.baseColor = new Color(0, 1, 0) - mr.material = mat; - scene.addChild(obj); - } - - { - let obj = new Object3D(); - obj.z = 600 * 10000.0; - let mr = obj.addComponent(MeshRenderer); - mr.geometry = new BoxGeometry(100 * 10000.0, 100 * 10000.0, 600 * 10000.0); - let mat = new UnLitMaterial(); - mat.baseColor = new Color(0, 0, 1) - mr.material = mat; - scene.addChild(obj); + parant.addChild(obj); + parant.rotationX = Math.random() * 360; + parant.rotationY = Math.random() * 360; + parant.rotationZ = Math.random() * 360; + scene.addChild(parant); } } } diff --git a/samples/render/Sample_TextureSample.ts b/samples/render/Sample_TextureSample.ts index 4db6a3db..77980f52 100644 --- a/samples/render/Sample_TextureSample.ts +++ b/samples/render/Sample_TextureSample.ts @@ -9,6 +9,7 @@ class Sample_TextureSample { async run() { await Engine3D.init(); + Engine3D.setting.shadow.shadowBias = 0.01; this.scene = new Scene3D(); let sky = this.scene.addComponent(AtmosphericComponent); @@ -62,7 +63,9 @@ class Sample_TextureSample { let component = plane.addComponent(UVMoveComponent); GUIUtil.renderUVMove(component); - this.scene.addChild(Object3DUtil.GetSingleCube(10, 10, 10, 1, 0.5, 0.5)); + // let box = Object3DUtil.GetSingleCube(10, 10, 10, 1, 0.5, 0.5); + // box.y = 5; + // this.scene.addChild(box); // enum GPUAddressMode let address = {} diff --git a/samples/utils/ExampleScene.ts b/samples/utils/ExampleScene.ts index 76f17251..67a5335d 100644 --- a/samples/utils/ExampleScene.ts +++ b/samples/utils/ExampleScene.ts @@ -74,7 +74,7 @@ export function createSceneParam(): ExampleSceneParam { }, kelvin: 5355, - intensity: 30, + intensity: 2, castShadow: true } } diff --git a/samples/utils/GUIUtil.ts b/samples/utils/GUIUtil.ts index f069acbb..3493d803 100644 --- a/samples/utils/GUIUtil.ts +++ b/samples/utils/GUIUtil.ts @@ -1,11 +1,56 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { AnimatorComponent, AtmosphericComponent, BillboardType, BlendMode, BloomPost, Color, DepthOfFieldPost, DirectLight, Engine3D, GPUCullMode, GTAOPost, GlobalFog, GlobalIlluminationComponent, GodRayPost, LitMaterial, Material, MorphTargetBlender, Object3D, PointLight, SkinnedMeshRenderer2, SpotLight, Transform, UIImage, UIPanel, UIShadow, Vector2, Vector4, View3D } from "@orillusion/core"; import { UVMoveComponent } from "@samples/material/script/UVMoveComponent"; +import { ProfilerDraw, PassType, OutlinePost, GBufferPost, Engine3D, AtmosphericComponent, GlobalFog, Transform, BloomPost, GodRayPost, Object3D, DirectLight, PointLight, SpotLight, GlobalIlluminationComponent, View3D, UIShadow, Color, UIPanel, GPUCullMode, BillboardType, LitMaterial, BlendMode, MorphTargetBlender, SkinnedMeshRenderer2, AnimatorComponent, GTAOPost, TAAPost, DepthOfFieldPost, Vector4, Vector2 } from "@orillusion/core"; export class GUIUtil { + static renderProfiler(arg0: ProfilerDraw) { + let gui = GUIHelp._creatPanel(); + let cache = {}; + for (const key in PassType) { + let i = parseInt(key); + if (i >= 0) { + } else { + let fg = GUIHelp._addFolder(gui, key); + fg.open(); + cache[key] = [ + GUIHelp._addLabelValue(fg, `indicesCount`, arg0[key].indicesCount), + GUIHelp._addLabelValue(fg, `vertexCount`, arg0[key].vertexCount), + GUIHelp._addLabelValue(fg, `triCount`, arg0[key].triCount), + GUIHelp._addLabelValue(fg, `instanceCount`, arg0[key].instanceCount), + GUIHelp._addLabelValue(fg, `drawCount`, arg0[key].drawCount), + GUIHelp._addLabelValue(fg, `pipelineCount`, arg0[key].pipelineCount), + ] + } + } + gui.open(); + + setInterval(() => { + for (const key in PassType) { + let i = parseInt(key); + if (i >= 0) { + } else { + cache[key][0].setValue(arg0[key].indicesCount); + cache[key][1].setValue(arg0[key].vertexCount); + cache[key][2].setValue(arg0[key].triCount); + cache[key][3].setValue(arg0[key].instanceCount); + cache[key][4].setValue(arg0[key].drawCount); + cache[key][5].setValue(arg0[key].pipelineCount); + } + } + }, 2000); + } + static renderOutlinePost(post: OutlinePost) { + GUIHelp.addFolder('OutlinePost'); + GUIHelp.add(post, 'outlinePixel', 0, 2048, 1); + GUIHelp.add(post, 'fadeOutlinePixel', 0.0001, 0.2, 0.00001); + GUIHelp.add(post, 'strength', 0.0001, 0.2, 0.00001); + GUIHelp.add(post, 'useAddMode'); + open && GUIHelp.open(); + GUIHelp.endFolder(); + } public static renderShadowSetting(open: boolean = true) { GUIHelp.addFolder('ShadowSetting'); @@ -17,6 +62,27 @@ export class GUIUtil { GUIHelp.endFolder(); } + + static renderGBufferPost(post: GBufferPost, open: boolean = true) { + GUIHelp.addFolder('GBufferPost&Reflection'); + let bufferState = { + current: 0, + abldeo: 1, + viewNormal: 2, + worldNormal: 3, + roughness: 4, + metallic: 5, + alpha: 6, + modelID: 7, + } + GUIHelp.add(post, 'state', bufferState); + GUIHelp.add(post, 'size1', 64.0, 1024, 1.0); + GUIHelp.add(post, 'size2', 64.0, 1024, 1.0); + open && GUIHelp.open(); + GUIHelp.endFolder(); + } + + //render AtmosphericComponent public static renderAtmosphericSky(component: AtmosphericComponent, open: boolean = true, name?: string) { name ||= 'AtmosphericSky'; @@ -61,12 +127,12 @@ export class GUIUtil { } //render transform - public static renderTransform(transform: Transform, open: boolean = true, name?: string) { + public static renderTransform(transform: Transform, open: boolean = true, name?: string, scale?: number) { name ||= 'Transform'; GUIHelp.addFolder(name); - GUIHelp.add(transform, 'x', -100.0, 100.0, 0.01); - GUIHelp.add(transform, 'y', -100.0, 100.0, 0.01); - GUIHelp.add(transform, 'z', -100.0, 100.0, 0.01); + GUIHelp.add(transform, 'x', -scale, scale, 0.01); + GUIHelp.add(transform, 'y', -scale, scale, 0.01); + GUIHelp.add(transform, 'z', -scale, scale, 0.01); 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); @@ -82,11 +148,12 @@ export class GUIUtil { name ||= 'Bloom'; GUIHelp.addFolder(name); GUIHelp.add(bloom, 'downSampleBlurSize', 3, 15, 1); - GUIHelp.add(bloom, 'downSampleBlurSigma', 0.01, 1, 0.001); + GUIHelp.add(bloom, 'downSampleBlurSigma', 0.01, 500, 0.001); GUIHelp.add(bloom, 'upSampleBlurSize', 3, 15, 1); - GUIHelp.add(bloom, 'upSampleBlurSigma', 0.01, 1, 0.001); + GUIHelp.add(bloom, 'upSampleBlurSigma', 0.01, 500, 0.001); GUIHelp.add(bloom, 'luminanceThreshole', 0.001, 10.0, 0.001); GUIHelp.add(bloom, 'bloomIntensity', 0.001, 10.0, 0.001); + GUIHelp.add(bloom, 'hdr', 0.001, 10.0, 0.001); open && GUIHelp.open(); GUIHelp.endFolder(); } @@ -125,7 +192,7 @@ export class GUIUtil { GUIHelp.add(light.transform, 'rotationY', 0.0, 360.0, 0.01); GUIHelp.add(light.transform, 'rotationZ', 0.0, 360.0, 0.01); GUIHelp.addColor(light, 'lightColor'); - GUIHelp.add(light, 'intensity', 0.0, 300.0, 0.01); + GUIHelp.add(light, 'intensity', 0.0, 50.0, 0.01); GUIHelp.add(light, 'indirect', 0.0, 1.0, 0.01); GUIHelp.add(light, 'castShadow'); @@ -145,9 +212,9 @@ export class GUIUtil { GUIHelp.add(light, 'r', 0.0, 1.0, 0.001); GUIHelp.add(light, 'g', 0.0, 1.0, 0.001); GUIHelp.add(light, 'b', 0.0, 1.0, 0.001); - GUIHelp.add(light, 'intensity', 0.0, 1500.0, 0.001); - GUIHelp.add(light, 'at', 0.0, 1600.0, 0.001); - GUIHelp.add(light, 'radius', 0.0, 1000.0, 0.001); + GUIHelp.add(light, 'intensity', 0.0, 100.0, 0.001); + GUIHelp.add(light, 'at', 0.0, 100.0, 0.001); + GUIHelp.add(light, 'radius', 0.0, 1.0, 0.001); GUIHelp.add(light, 'range', 0.0, 1000.0, 0.001); GUIHelp.add(light, 'quadratic', 0.0, 2.0, 0.001); GUIHelp.add(light, 'castShadow'); @@ -168,9 +235,9 @@ export class GUIUtil { GUIHelp.add(light.transform, 'rotationZ', -360, 360.0, 0.01); GUIHelp.addColor(light, 'lightColor'); - GUIHelp.add(light, 'intensity', 0.0, 1600.0, 0.001); - GUIHelp.add(light, 'at', 0.0, 1600.0, 0.001); - GUIHelp.add(light, 'radius', 0.0, 1000.0, 0.001); + GUIHelp.add(light, 'intensity', 0.0, 100.0, 0.001); + GUIHelp.add(light, 'at', 0.0, 100.0, 0.001); + GUIHelp.add(light, 'radius', 0.0, 10.0, 0.001); GUIHelp.add(light, 'range', 0.0, 1000.0, 0.001); GUIHelp.add(light, 'outerAngle', 0.0, 180.0, 0.001); GUIHelp.add(light, 'innerAngle', 0.0, 100.0, 0.001); @@ -436,6 +503,12 @@ export class GUIUtil { mat.baseColor = color; }); + GUIHelp.add(mat.baseColor, 'a').onChange((v) => { + let color = mat.baseColor; + color.a = v; + mat.baseColor = color; + }); + let blendMode = { NONE: BlendMode.NONE, NORMAL: BlendMode.NORMAL, @@ -463,8 +536,25 @@ export class GUIUtil { mat.metallic = v; }); + GUIHelp.addColor(mat, 'clearcoatColor').onChange((v) => { + let color = mat.clearcoatColor; + color.copyFromArray(v); + mat.clearcoatColor = color; + }); + + GUIHelp.add(mat, 'clearcoatFactor', 0.0, 1.0, 0.0001).onChange((v) => { + mat.clearcoatFactor = v; + }); + + GUIHelp.add(mat, 'clearcoatRoughnessFactor', 0.0, 1.0, 0.0001).onChange((v) => { + mat.clearcoatRoughnessFactor = v; + }); + + GUIHelp.add(mat, 'ior', 1.0, 4.0, 0.0001).onChange((v) => { + mat.ior = v; + }); + GUIHelp.add(mat, 'castShadow'); - GUIHelp.add(mat, 'acceptShadow'); open && GUIHelp.open(); @@ -555,6 +645,17 @@ export class GUIUtil { GUIHelp.endFolder(); } + public static renderTAA(post: TAAPost, open: boolean = true) { + GUIHelp.addFolder("TAA"); + GUIHelp.add(post, "jitterSeedCount", 2, 8, 1); + GUIHelp.add(post, "blendFactor", 0.0, 1.0, 0.01); + GUIHelp.add(post, "sharpFactor", 0.1, 0.9, 0.01); + GUIHelp.add(post, "sharpPreBlurFactor", 0.1, 0.9, 0.01); + GUIHelp.add(post, "temporalJitterScale", 0.0, 1.0, 0.01); + open && GUIHelp.open(); + GUIHelp.endFolder(); + } + static renderDepthOfField(post: DepthOfFieldPost) { GUIHelp.addFolder("DOFPost"); GUIHelp.add(post, 'near', 0, 100, 1) diff --git a/src/Engine3D.ts b/src/Engine3D.ts index 5778ec85..18fc299d 100644 --- a/src/Engine3D.ts +++ b/src/Engine3D.ts @@ -25,6 +25,7 @@ import { WasmMatrix } from '@orillusion/wasm-matrix/WasmMatrix'; import { Matrix4 } from './math/Matrix4'; import { FXAAPost } from './gfx/renderJob/post/FXAAPost'; import { PostProcessingComponent } from './components/post/PostProcessingComponent'; +import { GBufferFrame } from './gfx/renderJob/frame/GBufferFrame'; /** * Orillusion 3D Engine @@ -46,6 +47,11 @@ export class Engine3D { */ public static inputSystem: InputSystem; + /** + * input system in engine3d + */ + public static divB: HTMLDivElement; + /** * more view in engine3d */ @@ -59,8 +65,6 @@ export class Engine3D { private static _renderLoop: Function; private static _lateRender: Function; private static _requestAnimationFrameID: number = 0; - static Engine3D: any; - static divB: HTMLDivElement; /** * set engine render frameRate 24/30/60/114/120/144/240/360 fps or other @@ -139,16 +143,18 @@ export class Engine3D { drawTrMax: Number.MAX_SAFE_INTEGER, zPrePass: false, useLogDepth: false, + useCompressGBuffer: false, gi: false, postProcessing: { bloom: { - downSampleStep: 5, - downSampleBlurSize: 5, + downSampleStep: 3, + downSampleBlurSize: 9, downSampleBlurSigma: 1.0, - upSampleBlurSize: 5, + upSampleBlurSize: 9, upSampleBlurSigma: 1.0, luminanceThreshole: 1.0, bloomIntensity: 1.0, + hdr: 1.0 }, globalFog: { debug: false, @@ -187,7 +193,7 @@ export class Engine3D { groupCount: 4, outlinePixel: 2, fadeOutlinePixel: 4, - textureScale: 0.7, + textureScale: 1, useAddMode: false, debug: true, }, @@ -238,11 +244,12 @@ export class Engine3D { shadow: { enable: true, type: 'HARD', - pointShadowBias: 0.002, - shadowSize: 1024, + pointShadowBias: 0.0005, + shadowSize: 2048, pointShadowSize: 1024, shadowSoft: 0.005, - shadowBias: 0.0001, + shadowBound: 100, + shadowBias: 0.05, needUpdate: true, autoUpdate: true, updateFrameRate: 2, @@ -296,6 +303,13 @@ export class Engine3D { }, loader: { numConcurrent: 20, + }, + reflectionSetting: { + reflectionProbeMaxCount: 8, + reflectionProbeSize: 256, + width: 256 * 6, + height: 8 * 256, + enable: true } }; @@ -329,6 +343,17 @@ export class Engine3D { await webGPUContext.init(descriptor.canvasConfig); + //****pre compute setting****/ + this.setting.reflectionSetting.width = this.setting.reflectionSetting.reflectionProbeSize * 6; + this.setting.reflectionSetting.height = this.setting.reflectionSetting.reflectionProbeSize * this.setting.reflectionSetting.reflectionProbeMaxCount; + GBufferFrame.getGBufferFrame( + GBufferFrame.reflections_GBuffer, + this.setting.reflectionSetting.width, + this.setting.reflectionSetting.height, + false + ); + //****pre compute setting****/ + ShaderLib.init(); ShaderUtil.init(); @@ -466,6 +491,8 @@ export class Engine3D { for (i = 0; i < views.length; i++) { const view = views[i]; view.scene.waitUpdate(); + let [w, h] = webGPUContext.presentationSize; + view.camera.viewPort.setTo(0, 0, w, h); view.camera.resetPerspective(webGPUContext.aspect); } diff --git a/src/assets/Res.ts b/src/assets/Res.ts index 3ef00b0b..8e2b768c 100644 --- a/src/assets/Res.ts +++ b/src/assets/Res.ts @@ -179,15 +179,13 @@ export class Res { if (this._prefabPool.has(url)) { return this._prefabPool.get(url) as Object3D; } - if (loaderFunctions?.onUrl) { - url = await loaderFunctions.onUrl(url); - } let parser; let ext = url.substring(url.lastIndexOf('.')).toLowerCase(); let loader = new FileLoader(); if (ext == '.gltf') { parser = await loader.load(url, GLTFParser, loaderFunctions); + } else { parser = await loader.load(url, GLBParser, loaderFunctions); } @@ -208,9 +206,6 @@ export class Res { if (this._prefabPool.has(url)) { return this._prefabPool.get(url) as Object3D; } - if (loaderFunctions?.onUrl) { - url = await loaderFunctions.onUrl(url); - } let parser; let ext = url.substring(url.lastIndexOf('.')).toLowerCase(); @@ -234,9 +229,6 @@ export class Res { if (this._prefabPool.has(url)) { return this._prefabPool.get(url) as Object3D; } - if (loaderFunctions?.onUrl) { - url = await loaderFunctions.onUrl(url); - } let loader = new FileLoader(); let parser = await loader.load(url, B3DMParser, loaderFunctions, userData); let obj = parser.data; @@ -254,9 +246,6 @@ export class Res { if (this._prefabPool.has(url)) { return this._prefabPool.get(url) as Object3D; } - if (loaderFunctions?.onUrl) { - url = await loaderFunctions.onUrl(url); - } let loader = new FileLoader(); let parser = await loader.load(url, I3DMParser, loaderFunctions, userData); let obj = parser.data; @@ -275,9 +264,6 @@ export class Res { if (this._texturePool.has(url)) { return this._texturePool.get(url); } - if (loaderFunctions?.onUrl) { - url = await loaderFunctions.onUrl(url); - } let texture = new BitmapTexture2D(); texture.flipY = flipY; await texture.load(url, loaderFunctions); @@ -328,9 +314,7 @@ export class Res { if (this._texturePool.has(url)) { return this._texturePool.get(url); } - if (loaderFunctions?.onUrl) { - url = await loaderFunctions.onUrl(url); - } + let hdrTexture = new HDRTexture(); hdrTexture = await hdrTexture.load(url, loaderFunctions); this._texturePool.set(url, hdrTexture); @@ -348,9 +332,6 @@ export class Res { if (this._texturePool.has(url)) { return this._texturePool.get(url); } - if (loaderFunctions?.onUrl) { - url = await loaderFunctions.onUrl(url); - } let hdrTexture = new HDRTextureCube(); hdrTexture = await hdrTexture.load(url, loaderFunctions); this._texturePool.set(url, hdrTexture); @@ -367,9 +348,6 @@ export class Res { if (this._texturePool.has(url)) { return this._texturePool.get(url); } - if (loaderFunctions?.onUrl) { - url = await loaderFunctions.onUrl(url); - } let ldrTextureCube = new LDRTextureCube(); ldrTextureCube = await ldrTextureCube.load(url, loaderFunctions); this._texturePool.set(url, ldrTextureCube); @@ -403,9 +381,6 @@ export class Res { if (this._texturePool.has(url)) { return this._texturePool.get(url); } - if (loaderFunctions?.onUrl) { - url = await loaderFunctions.onUrl(url); - } let cubeMap = new BitmapTextureCube(); await cubeMap.loadStd(url); @@ -417,9 +392,6 @@ export class Res { * @param url the path of image */ public async loadJSON(url: string, loaderFunctions?: LoaderFunctions) { - if (loaderFunctions?.onUrl) { - url = await loaderFunctions.onUrl(url); - } return await new FileLoader() .loadJson(url, loaderFunctions) .then(async (ret) => { diff --git a/src/assets/shader/ShaderLib.ts b/src/assets/shader/ShaderLib.ts index 612dfc6d..34f5b218 100644 --- a/src/assets/shader/ShaderLib.ts +++ b/src/assets/shader/ShaderLib.ts @@ -5,7 +5,7 @@ import { MathShader } from './math/MathShader'; import { PhysicMaterialUniform_frag } from './materials/uniforms/PhysicMaterialUniform_frag'; import { UnLitMaterialUniform_frag } from './materials/uniforms/UnLitMaterialUniform_frag'; import { UnLit_frag } from './lighting/UnLit_frag'; -import { VertexAttributes } from './core/struct/VertexAttributes'; +import { VertexAttributes_vert } from './core/struct/VertexAttributes'; import { VideoUniform_frag } from './materials/uniforms/VideoUniform_frag'; import { IrradianceVolumeData_frag } from "./lighting/IrradianceVolumeData_frag"; import { Inline_vert } from './core/inline/Inline_vert'; @@ -19,7 +19,7 @@ import { WorldMatrixUniform } from './core/common/WorldMatrixUniform'; import { FastMathShader } from './math/FastMathShader'; import { NormalMap_frag } from './materials/program/NormalMap_frag'; import { FragmentVarying } from './core/struct/FragmentVarying'; -import { ColorPassFragmentOutput } from './core/struct/ColorPassFragmentOutput'; +import { FragmentOutput } from './core/struct/FragmentOutput'; import { ShadingInput } from './core/struct/ShadingInput'; import { IESProfiles_frag } from './lighting/IESProfiles_frag'; import { ShadowMapping_frag } from './materials/program/ShadowMapping_frag'; @@ -45,6 +45,11 @@ 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'; +import { BitUtil } from './utils/BitUtil'; +import { GBufferStand } from './core/common/GBufferStand'; +import { ReflectionShader_shader } from './materials/ReflectionShader_shader'; +import { ReflectionCG } from './env/ReflectionCG'; +import { SHCommon_frag } from './core/common/SHCommon_frag'; /** * @internal @@ -54,6 +59,9 @@ export class ShaderLib { public static init() { ShaderLib.register('MathShader', MathShader); ShaderLib.register('FastMathShader', FastMathShader); + ShaderLib.register("BitUtil", BitUtil); + ShaderLib.register("GBufferStand", GBufferStand); + ShaderLib.register("SHCommon_frag", SHCommon_frag); ShaderLib.register('MatrixShader', MatrixShader); @@ -68,12 +76,12 @@ export class ShaderLib { ShaderLib.register('InstanceUniform', InstanceUniform); ShaderLib.register('Inline_vert', Inline_vert); - ShaderLib.register('VertexAttributes_vert', VertexAttributes); + ShaderLib.register('VertexAttributes_vert', VertexAttributes_vert); ShaderLib.register('Common_vert', Common_vert); ShaderLib.register('Common_frag', Common_frag); ShaderLib.register('FragmentVarying', FragmentVarying); - ShaderLib.register('ColorPassFragmentOutput', ColorPassFragmentOutput); + ShaderLib.register('FragmentOutput', FragmentOutput); ShaderLib.register('ClusterLight', ClusterLight); ShaderLib.register('ShadingInput', ShadingInput); @@ -87,13 +95,15 @@ export class ShaderLib { ShaderLib.register('EnvMap_frag', EnvMap_frag); 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('ReflectionCG', ReflectionCG); + ShaderLib.register('ReflectionShader_shader', ReflectionShader_shader); ShaderLib.register('Clearcoat_frag', Clearcoat_frag); ShaderLib.register('LitShader', Lit_shader); ShaderLib.register('PBRLItShader', PBRLItShader); diff --git a/src/assets/shader/cluster/ClusterBoundsSource_cs.ts b/src/assets/shader/cluster/ClusterBoundsSource_cs.ts index 994b2e71..da7e0cca 100644 --- a/src/assets/shader/cluster/ClusterBoundsSource_cs.ts +++ b/src/assets/shader/cluster/ClusterBoundsSource_cs.ts @@ -34,15 +34,15 @@ export let ClusterBoundsSource_cs: string = /* wgsl */` return v ; } - fn gridToIndex(i:vec3) -> u32{ - return i.z * u32(clusterTileX) * u32(clusterTileY) + i.y * u32(clusterTileX) + i.x ; - } - fn ScreenToView(screen : vec4) -> vec4 { let texCoord = screen.xy / vec2(clustersUniform.screenWidth, clustersUniform.screenHeight); let clip = vec4(vec2(texCoord.x, 1.0 - texCoord.y) * 2.0 - vec2(1.0, 1.0), screen.z, screen.w); return convertNDCToView(clip); - } + } + + fn gridToIndex(i:vec3) -> u32{ + return i.z * u32(clusterTileX) * u32(clusterTileY) + i.y * u32(clusterTileX) + i.x ; + } fn LineIntersectionToZPlane( eye:vec3 , ndcPoint :vec3 , z:f32) -> vec3 { diff --git a/src/assets/shader/compute/BloomEffect_cs.ts b/src/assets/shader/compute/BloomEffect_cs.ts index e5029fa0..f42aa013 100644 --- a/src/assets/shader/compute/BloomEffect_cs.ts +++ b/src/assets/shader/compute/BloomEffect_cs.ts @@ -1,3 +1,4 @@ +import { ColorUtil } from "../utils/ColorUtil"; let BloomCfg = /*wgsl*/ ` struct BloomCfg{ @@ -52,8 +53,7 @@ let GaussBlur = function (GaussNxN: string, inTex: string, inTexSampler: string) 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; + var coord:vec2 = uv + vec2(f32(i), f32(j)) * stride ; color += textureSampleLevel(${inTex}, ${inTexSampler}, coord, 0.0).xyz * w; weight += w; } @@ -71,6 +71,7 @@ let GaussBlur = function (GaussNxN: string, inTex: string, inTexSampler: string) //________________________pixel filter export let threshold: string = /*wgsl*/ ` +${ColorUtil} ${BloomCfg} @group(0) @binding(1) var inTex : texture_2d; @@ -88,18 +89,18 @@ fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_inv 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 linerColor = gammaToLiner(color.rgb); + var lum = dot(vec3(0.2126, 0.7152, 0.0722), linerColor.rgb) ; + + var ret = linerColor.xyz; + var contribution = max(0, lum - bloomCfg.luminanceThreshole) ; + // if(contribution > 0.0){ + // ret = linerColor * contribution; + ret = ACESToneMapping(linerColor,contribution); + // }else{ + // ret = vec3f(0.0,0.0,0.0); // } - 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)); + textureStore(outTex, fragCoord, vec4(vec3f(ret), color.w)); } ` @@ -170,9 +171,9 @@ fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_inv 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_1(uv, i32(bloomCfg.upSampleBlurSize), prev_stride, bloomCfg.upSampleBlurSigma); - let rgb2 = GaussNxN_0(uv, i32(bloomCfg.upSampleBlurSize), curr_stride, bloomCfg.upSampleBlurSigma); - color = vec4(rgb1 + rgb2, color.w); + 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); } ` @@ -180,6 +181,7 @@ fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_inv //__________________________blend export let post = /*wgsl*/ ` +${ColorUtil} ${BloomCfg} ${CalcUV_01} @@ -191,19 +193,6 @@ ${CalcUV_01} 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) { @@ -213,7 +202,9 @@ fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_inv return; } var color = textureLoad(_MainTex, fragCoord, 0); - var uv = CalcUV_01(fragCoord, texSize); + 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 diff --git a/src/assets/shader/compute/DDGILighting_CSShader.ts b/src/assets/shader/compute/DDGILighting_CSShader.ts index b7805526..06864683 100644 --- a/src/assets/shader/compute/DDGILighting_CSShader.ts +++ b/src/assets/shader/compute/DDGILighting_CSShader.ts @@ -6,7 +6,7 @@ var PI: f32 = 3.14159265359; #include "GlobalUniform" #include "MathShader" #include "FastMathShader" -#include "ColorUtil" +#include "ColorUtil_frag" struct ConstUniform{ screenWidth:f32, diff --git a/src/assets/shader/compute/DepthOfView_cs.ts b/src/assets/shader/compute/DepthOfView_cs.ts index f3b9c499..e663bb31 100644 --- a/src/assets/shader/compute/DepthOfView_cs.ts +++ b/src/assets/shader/compute/DepthOfView_cs.ts @@ -1,5 +1,6 @@ export let DepthOfView_cs: string = /*wgsl*/ ` #include "GlobalUniform" +#include "GBufferStand" struct BlurSetting{ near: f32, @@ -7,35 +8,42 @@ export let DepthOfView_cs: string = /*wgsl*/ ` pixelOffset: f32, } - @group(0) @binding(1) var blurSetting: BlurSetting; - @group(0) @binding(2) var positionBufferTex : texture_2d; - @group(0) @binding(3) var normalBufferTex : texture_2d; - @group(0) @binding(4) var inTexSampler : sampler; - @group(0) @binding(5) var inTex : texture_2d; - @group(0) @binding(6) var outTex : texture_storage_2d; + @group(0) @binding(2) var blurSetting: BlurSetting; + @group(0) @binding(3) var inTexSampler : sampler; + @group(0) @binding(4) var inTex : texture_2d; + @group(0) @binding(5) var outTex : texture_storage_2d; var cameraPosition: vec3; var texSize: vec2; var fragCoord: vec2; + var fragUV: vec2; var texelSize: vec2; + const PI = 3.1415926 ; + @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; - texelSize = 1.0 / vec2(texSize - 1); + if(fragCoord.x >= i32(texSize.x) || fragCoord.y >= i32(texSize.y)){ - return; + return; } + fragUV = vec2(fragCoord) / vec2(texSize); + texelSize = 1.0 / vec2(texSize - 1); + var gBuffer = getGBuffer( fragCoord ) ; + useNormalMatrixInv(); + cameraPosition = globalUniform.CameraPos.xyz ; - let wPosition:vec3 = textureLoad(positionBufferTex, fragCoord , 0).xyz; + var wPosition = getWorldPositionFromGBuffer(gBuffer,fragUV); var distance = length(wPosition - cameraPosition); var oc:vec4 = textureLoad(inTex, fragCoord, 0); if(distance > blurSetting.near){ - let normal = textureLoad(normalBufferTex, fragCoord, 0); + var normal = getWorldNormalFromGBuffer(gBuffer); var pixelScale = 0.5; - if(normal.w > 0.5){ + if(gBuffer.x > 9999.0){ distance = min(distance, blurSetting.far); pixelScale = (distance - blurSetting.near) / (blurSetting.far - blurSetting.near); } diff --git a/src/assets/shader/compute/GTAO_cs.ts b/src/assets/shader/compute/GTAO_cs.ts index 683d2f9d..a3b7f883 100644 --- a/src/assets/shader/compute/GTAO_cs.ts +++ b/src/assets/shader/compute/GTAO_cs.ts @@ -1,5 +1,6 @@ export let GTAO_cs: string = /*wgsl*/ ` #include "GlobalUniform" + #include "GBufferStand" struct GTAO{ maxDistance: f32, @@ -12,38 +13,47 @@ export let GTAO_cs: string = /*wgsl*/ ` blendColor: f32, } - @group(0) @binding(1) var gtaoData: GTAO; - @group(0) @binding(2) var directions : array>; - @group(0) @binding(3) var aoBuffer : array; - - @group(0) @binding(4) var posTex : texture_2d; - @group(0) @binding(5) var normalTex : texture_2d; - @group(0) @binding(6) var inTex : texture_2d; - @group(0) @binding(7) var outTex : texture_storage_2d; + @group(0) @binding(2) var gtaoData: GTAO; + @group(0) @binding(3) var directions : array>; + @group(0) @binding(4) var aoBuffer : array; + + @group(0) @binding(5) var inTex : texture_2d; + @group(0) @binding(6) var outTex : texture_storage_2d; var texSize: vec2; var fragCoord: vec2; + var fragUV: vec2; var wPosition: vec3; var wNormal: vec4; var maxPixelScaled: f32; + + var gBuffer: GBuffer; + + const PI = 3.1415926 ; @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; + return; } - wNormal = textureLoad(normalTex, fragCoord, 0); + + fragUV = vec2(fragCoord) / vec2(texSize - 1); + useNormalMatrixInv(); + + gBuffer = getGBuffer( fragCoord ) ; + wNormal = vec4f(getWorldNormalFromGBuffer(gBuffer),1.0); + var visible = getRoughnessFromGBuffer(gBuffer); + var oc = textureLoad(inTex, fragCoord, 0); let index = fragCoord.x + fragCoord.y * i32(texSize.x); let lastFactor = aoBuffer[index]; var newFactor = 0.0; - if(wNormal.w < 0.5){//sky - - }else{ - wPosition = textureLoad(posTex, fragCoord, 0).xyz; + if(visible > 0.0){//sky + wPosition = getWorldPositionFromGBuffer(gBuffer,fragUV); let ndc = globalUniform.projMat * globalUniform.viewMat * vec4(wPosition, 1.0); let ndcZ = ndc.z / ndc.w; maxPixelScaled = calcPixelByNDC(ndcZ); @@ -103,10 +113,10 @@ export let GTAO_cs: string = /*wgsl*/ ` } fn rayMarch() -> f32{ - let originNormal = normalize(vec3(wNormal.xyz) * 2.0 - 1.0); + let originNormal = normalize(vec3(wNormal.xyz)); let stepPixel = maxPixelScaled / gtaoData.rayMarchSegment; var weight:f32 = 0.0; - var totalWeight:f32 = 0.1; + var totalWeight:f32 = 0.00001; for(var i:i32 = 0; i < 8; i += 1){ let dirVec2 = directions[i]; for(var j:f32 = 1.1; j < maxPixelScaled; j += stepPixel){ @@ -116,8 +126,11 @@ export let GTAO_cs: string = /*wgsl*/ ` && sampleCoord.y < i32(texSize.y) ) { totalWeight += 1.0; - let samplePosition = textureLoad(posTex, sampleCoord, 0).xyzw; - if(samplePosition.w>0.0){ + + let subGBuffer = getGBuffer( sampleCoord ) ; + let samplePosition = getWorldPositionFromGBuffer(subGBuffer,vec2f(sampleCoord)/vec2f(texSize)); + var visible = getRoughnessFromGBuffer(subGBuffer); + if(visible>0.0){ let distanceVec2 = samplePosition.xyz - wPosition; let distance = length(distanceVec2); if(distance < gtaoData.maxDistance ){ diff --git a/src/assets/shader/compute/GodRay_cs.ts b/src/assets/shader/compute/GodRay_cs.ts index 487fc66b..68b8ef8f 100644 --- a/src/assets/shader/compute/GodRay_cs.ts +++ b/src/assets/shader/compute/GodRay_cs.ts @@ -3,6 +3,8 @@ import { CSM } from "../../../core/csm/CSM"; export let GodRay_cs: string = /*wgsl*/ ` #include "GlobalUniform" + #include "GBufferStand" + struct LightData { index:f32, lightType:i32, @@ -46,13 +48,11 @@ export let GodRay_cs: string = /*wgsl*/ ` scatteringExponent: f32, } - @group(0) @binding(1) var godRayUniform: GodRayUniform; - @group(0) @binding(2) var posTex : texture_2d; - @group(0) @binding(3) var normalTex : texture_2d; - @group(0) @binding(4) var inTex : texture_2d; - @group(0) @binding(5) var outTex : texture_storage_2d; - @group(0) @binding(6) var shadowMapSampler : sampler_comparison; - @group(0) @binding(7) var shadowMap : texture_depth_2d_array; + @group(0) @binding(2) var godRayUniform: GodRayUniform; + @group(0) @binding(3) var inTex : texture_2d; + @group(0) @binding(4) var outTex : texture_storage_2d; + @group(0) @binding(5) var shadowMapSampler : sampler_comparison; + @group(0) @binding(6) var shadowMap : texture_depth_2d_array; @group(1) @binding(0) var lightBuffer: array; @@ -68,12 +68,17 @@ export let GodRay_cs: string = /*wgsl*/ ` var viewDirection: vec3 ; var texSize: vec2; + var fragUV: vec2; var fragCoord: vec2; var wPosition: vec3; var wNormal: vec4; var directLight: LightData; var shadowStrut: ShadowStruct ; + var gBuffer: GBuffer; + + const PI = 3.1415926 ; + const csmCount:i32 = ${CSM.Cascades} ; fn directShadowMaping(P:vec3, N:vec3, shadowBias: f32) { let enableCSM:bool = globalUniform.enableCSM > 0.5; @@ -133,7 +138,13 @@ export let GodRay_cs: string = /*wgsl*/ ` if(fragCoord.x >= i32(texSize.x) || fragCoord.y >= i32(texSize.y)){ return; } - wNormal = textureLoad(normalTex, fragCoord, 0); + fragUV = vec2(fragCoord) / vec2(texSize - 1); + useNormalMatrixInv(); + + gBuffer = getGBuffer( fragCoord ) ; + wNormal = vec4f(getWorldNormalFromGBuffer(gBuffer),1.0); + var visible = getRoughnessFromGBuffer(gBuffer); + var oc = textureLoad(inTex, fragCoord, 0); var outColor = oc.xyz; directLight = lightBuffer[0] ; @@ -143,10 +154,10 @@ export let GodRay_cs: string = /*wgsl*/ ` let lightColor = directLight.lightColor; var godRayFactor = 0.0; - if(wNormal.w > 0.5){ + if(visible > 0.0 ){ //not sky let lightPos = models.matrix[u32(directLight.lightMatrixIndex)][3].xyz; - wPosition = textureLoad(posTex, fragCoord, 0).xyz; + wPosition = getWorldPositionFromGBuffer(gBuffer,fragUV); viewDirection = normalize(globalUniform.CameraPos - wPosition) ; godRayFactor = rayMarch(); godRayFactor = updateGodRay(historyData, godRayFactor); diff --git a/src/assets/shader/compute/IBLEnvMapCreator_cs.ts b/src/assets/shader/compute/IBLEnvMapCreator_cs.ts index 1727f4fd..d8618870 100644 --- a/src/assets/shader/compute/IBLEnvMapCreator_cs.ts +++ b/src/assets/shader/compute/IBLEnvMapCreator_cs.ts @@ -117,9 +117,9 @@ export let IBLEnvMapCreator_cs: string = /*wgsl*/ ` return normalize(sampleVec); } - fn multiSample(localPos:vec3, roughness:f32) -> vec4 + fn multiSample(normal:vec3, roughness:f32) -> vec4 { - var N: vec3 = normalize(localPos); + var N: vec3 = normalize(normal); var R: vec3 = N; var V: vec3 = R; diff --git a/src/assets/shader/compute/OutlineCalcOutline_cs.ts b/src/assets/shader/compute/OutlineCalcOutline_cs.ts index 099ee088..74979c42 100644 --- a/src/assets/shader/compute/OutlineCalcOutline_cs.ts +++ b/src/assets/shader/compute/OutlineCalcOutline_cs.ts @@ -1,5 +1,8 @@ export let OutlineCalcOutline_cs: string = /*wgsl*/ ` +#include "GlobalUniform" +#include "GBufferStand" + struct OutlineSettingData{ strength: f32, useAddMode: f32, @@ -27,25 +30,29 @@ export let OutlineCalcOutline_cs: string = /*wgsl*/ ` list: array, } - @group(0) @binding(0) var outlineSetting: OutlineSettingData; - @group(0) @binding(1) var slotsBuffer : array; - @group(0) @binding(2) var weightBuffer : array; - @group(0) @binding(3) var entitiesBuffer : array; - @group(0) @binding(4) var indexTexture : texture_2d; + @group(0) @binding(2) var outlineSetting: OutlineSettingData; + @group(0) @binding(3) var slotsBuffer : array; + @group(0) @binding(4) var weightBuffer : array; + @group(0) @binding(5) var entitiesBuffer : array; var texSize: vec2; var lowSize: vec2; var fragCoord: vec2; + var fragUV: vec2; var fragCoordLow: vec2; var coordIndex: i32; var fragOutline: OutlineWeightData; + const PI = 3.1415926 ; @compute @workgroup_size( 8 , 8 , 1 ) fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) { + useNormalMatrixInv(); fragCoordLow = vec2( globalInvocation_id.xy ); - texSize = textureDimensions(indexTexture).xy; + texSize = textureDimensions(gBufferTexture).xy; + fragUV = vec2(fragCoordLow) / vec2(texSize); + lowSize = vec2(i32(outlineSetting.lowTexWidth), i32(outlineSetting.lowTexHeight)); let scaleValue = f32(texSize.x) / f32(lowSize.x); fragCoord.x = i32(f32(fragCoordLow.x) * scaleValue); @@ -60,9 +67,9 @@ export let OutlineCalcOutline_cs: string = /*wgsl*/ ` coordIndex = fragCoordLow.x + fragCoordLow.y * lowSize.x; fragOutline = weightBuffer[coordIndex]; - var wPos = textureLoad(indexTexture, fragCoord, 0 ) ; - - fragOutline.entityIndex = round(wPos.w); + + var gBuffer = getGBuffer( fragCoord ) ; + fragOutline.entityIndex = f32(getIDFromGBuffer_i32(gBuffer)); fragOutline.slotIndex = -1.0; fragOutline.outerSlotIndex = -1.0; fragOutline.weight = 0.0; diff --git a/src/assets/shader/compute/Picker_cs.ts b/src/assets/shader/compute/Picker_cs.ts index c731fe32..f746fe1d 100644 --- a/src/assets/shader/compute/Picker_cs.ts +++ b/src/assets/shader/compute/Picker_cs.ts @@ -2,6 +2,7 @@ export let Picker_cs: string = /*wgsl*/ ` #include "GlobalUniform" + #include "GBufferStand" struct PickResult{ pick_meshID:f32, @@ -18,28 +19,27 @@ export let Picker_cs: string = /*wgsl*/ ` v7:vec4 } - //@group(0) @binding(0) var globalUniform: GlobalUniform; - @group(0) @binding(1) var outBuffer: PickResult; - @group(0) @binding(2) var positionMap : texture_2d; - @group(0) @binding(3) var normalMap : texture_2d; + @group(0) @binding(2) var outBuffer: PickResult; + const PI = 3.1415926 ; @compute @workgroup_size( 1 ) fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) { var result:PickResult ; - // result.pick_meshID - let texSize = textureDimensions(positionMap).xy; + let texSize = textureDimensions(gBufferTexture).xy; let screenPoint = vec2(globalUniform.mouseX/globalUniform.windowWidth,globalUniform.mouseY/globalUniform.windowHeight); - let mouseUV = screenPoint * vec2(texSize.xy); - let pos = textureLoad(positionMap, vec2(mouseUV) , 0); - let normal = textureLoad(normalMap, vec2(mouseUV) , 0); - - outBuffer.pick_meshID = f32(pos.w) ; - outBuffer.pick_meshID2 = f32(pos.w) ; + let mouseUV = screenPoint * vec2(texSize.xy); + let fragCoord = vec2(i32(mouseUV.x), i32(mouseUV.y)); + var gBuffer = getGBuffer( fragCoord ) ; + let pick_meshID = getIDFromGBuffer_i32(gBuffer); + outBuffer.pick_meshID = f32(pick_meshID) ; + outBuffer.pick_meshID2 = f32(pick_meshID) ; outBuffer.pick_Tangent = vec4(2.0,2.0,2.0,2.0) ; outBuffer.pick_UV = vec2(globalUniform.mouseX,globalUniform.mouseY) ; - outBuffer.pick_Position = pos; - outBuffer.pick_Normal = normal; + let wPosition = getWorldPositionFromGBuffer(gBuffer,screenPoint); + let wNormal = getWorldNormalFromGBuffer(gBuffer); + outBuffer.pick_Position = vec4(wPosition, 1.0) ; + outBuffer.pick_Normal = vec4(wNormal, 1.0) ; } ` diff --git a/src/assets/shader/compute/PreFilteredEnvironment_cs copy.ts b/src/assets/shader/compute/PreFilteredEnvironment_cs copy.ts new file mode 100644 index 00000000..f311bf50 --- /dev/null +++ b/src/assets/shader/compute/PreFilteredEnvironment_cs copy.ts @@ -0,0 +1,200 @@ +export let PreFilteredEnvironment_cs2: string = /*wgsl*/ ` + // input reflection buffer texture + // sample prefiltered cube uv texture + // storge info to oct map + #include "GenerayRandomDir" + #include "BitUtil" + #include "MathShader" + + struct UniformData{ + roughness : f32 , + roughness1 : f32 , + roughness2 : f32 , + roughness3 : f32 , + } + + @group(0) @binding(0) var inputTex : texture_2d; + @group(0) @binding(1) var outputTexture : texture_storage_2d;//rgba32float + @group(1) @binding(0) var uniformData:UniformData;//rgba32float + + var reflectionSize : vec2f ; + var PROBE_SOURCESIZE : vec2f ; + var PROBEMAP_SOURCESIZE : vec2f ; + var aspect : vec2f ; + var spaceV : f32 ; + + var i32InputFragCoord : vec2i; + var PI_2 : f32 = 3.1415926 * 2.0 ; + var PI : f32 = 3.1415926 ; + var RAYS_PER_PROBE : f32 = 32.0 ; + + var screenSize : vec2f ; + + fn useSphereReflection(){ + reflectionSize = vec2f(textureDimensions(inputTex).xy); + PROBE_SOURCESIZE = reflectionSize / vec2f(6.0,8.0); + PROBEMAP_SOURCESIZE = reflectionSize ; + aspect = PROBE_SOURCESIZE / PROBEMAP_SOURCESIZE; + spaceV = 1.0 / 8.0; + } + + @compute @workgroup_size( 16 , 16 , 1 ) + fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) + { + var color : vec4f ; + useSphereReflection(); + screenSize = vec2f(textureDimensions(outputTexture).xy); + + i32InputFragCoord = vec2( globalInvocation_id.xy ) ; + let i = globalInvocation_id.z ; + let roughness = uniformData.roughness ; + + let suv = vec2f(i32InputFragCoord) ; + let subUV = vec2f((suv.x+0.5) % (256.0*6.0),(suv.y+0.5) % 256.0) / vec2f( (256.0*6.0), 256.0 ) ; + let faceID = i32((suv.x / 256.0)); + let probeID = i32(floor(suv.y / 256.0)); + + var sphereUV = subUV ;//(suv / screenSize) ; + var dir: vec3 = UvToDir(sphereUV) ;//* 0.5 + 0.5 ; + + var preColor = PreFilterEnvMap(roughness,dir,0.0); + + // var cc = vec4f(getReflectionsMap(dir,0.0),1.0) ; + color.y = vec3fToFloat(preColor.xyz); + color.z = vec3fToFloat(dir); + + textureStore(outputTexture,i32InputFragCoord,color); + } + + fn getReflectionsMap(n:vec3,gid:f32) -> vec3f { + var uv = getSampleProbeUV(n,gid); + let color = textureLoad(inputTex, vec2i(uv*screenSize) , 0); + return floatToVec3f(color.y) ; + } + + fn getSampleProbeUV(dir:vec3,gid:f32) -> vec2 { + let faceId = dir_to_faceId(dir); + var targetUV:vec2 = convert_xyz_to_cube_uv(dir.x, dir.y, dir.z); + targetUV.x = 1.0 - targetUV.x; + // targetUV.y = 1.0 - targetUV.y; + let threshould = 0.5 / PROBE_SOURCESIZE; + targetUV = clamp(targetUV, vec2(threshould), vec2(1.0 - threshould)); + + targetUV.x = f32(faceId) + targetUV.x; + + let aspect:vec2f = PROBE_SOURCESIZE / PROBEMAP_SOURCESIZE; + targetUV = targetUV * aspect ; + + targetUV.y = targetUV.y + (spaceV*gid); + + return targetUV ; + } + + + +fn radicalInverse_VdC( bits2:u32) -> f32 +{ + var bits = bits2; + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return f32(bits) * 2.3283064365386963e-10f; // / 0x100000000 +} + + +fn hammersley( i:u32, N:u32) -> vec2f +{ + return vec2f(f32(i) / f32(N), radicalInverse_VdC(i)); +} + +fn ImportanceSampleGGX( xi:vec2f, roughness:f32, N:vec3f) -> vec3f +{ + var alpha2 = roughness * roughness * roughness * roughness; + + var phi = 2.0f * 3.1415926 * xi.x ; + var cosTheta = sqrt( (1.0f - xi.y) / (1.0f + (alpha2 - 1.0f) * xi.y )); + var sinTheta = sqrt( 1.0f - cosTheta*cosTheta ); + + var h : vec3f ; + h.x = sinTheta * cos( phi ); + h.y = sinTheta * sin( phi ); + h.z = cosTheta; + + var up = vec3f(1,0,0) ; + if(abs(N.z) < 0.9999){ + up = vec3f(0,0,1) ; + } + var tangentX = normalize( cross( up, N ) ); + var tangentY = cross( N, tangentX ); + + return (tangentX * h.x + tangentY * h.y + N * h.z); +} + +const NUM_SAMPLES = 512u; +fn PreFilterEnvMap( roughness2:f32, R:vec3f , gid:f32 ) -> vec3f +{ + var res = vec3f(0.0f); + var totalWeight = 0.0f; + + var normal = normalize(R); + var toEye = normal; + + var roughness = roughness2; + //roughness = max(0.02f,roughness); + + for(var i=1u;i<=NUM_SAMPLES;i+=1u) + { + var xi:vec2f = hammersley(i, NUM_SAMPLES) ; + + var halfway = ImportanceSampleGGX(xi,roughness,normal); + var lightVec = 2.0f * dot( toEye,halfway ) * halfway - toEye; + + var NdotL = dot( normal, lightVec ) ; + var NdotH = max(0.0,dot( normal, halfway )) ; + var HdotV = max(0.0,dot( halfway, toEye )) ; + + if( NdotL > 0.0 ) + { + var D = specularD(roughness,NdotH); + var pdf = (D * NdotH / (4.0 * HdotV)) + 0.0001f ; + + var saSample = 1.0f / (f32(NUM_SAMPLES) * pdf + 0.00001f); + lightVec = normalize(lightVec); + // res += sampleBuffer(lightVec,gid).rgb *NdotL; + res += vec3f(getReflectionsMap(lightVec,0.0)) * NdotL;; + totalWeight += NdotL; + + + // var uv = convert_xyz_to_cube_uv(lightVec.x,lightVec.y,lightVec.z) ; + + // // let uv_f32:vec2 = subUV * vec2f(256.0*6.0,256.0*8.0); + // var bc = textureLoad(inputTex, vec2i(uv) , 0); + + // res += floatToVec3f(bc.y) ; + // totalWeight += 1.0; + } + } + + return res / max(totalWeight,0.001f); +} + +fn specularD( roughness:f32, NoH:f32) -> f32 +{ + var NoH2 = NoH * NoH; + var r2 = roughness * roughness; + return r2 / pow(NoH2 * (r2 - 1.0) + 1.0, 2.0); +} + +` + +// var sphereUV = (suv / screenSize) ; +// var dir: vec3 = UvToDir(sphereUV) ;//* 0.5 + 0.5 ; +// var negUV: vec2 = DirTOUV(dir) ;//* 0.5 + 0.5 ; + +// var cc = vec4f(getReflectionsMap(dir,0.0),1.0) ; +// color.y = vec3fToFloat(cc.xyz); +// color.z = vec3fToFloat(dir); + +// textureStore(outputTexture,i32InputFragCoord,color); \ No newline at end of file diff --git a/src/assets/shader/compute/PreFilteredEnvironment_cs.ts b/src/assets/shader/compute/PreFilteredEnvironment_cs.ts new file mode 100644 index 00000000..dcae65a8 --- /dev/null +++ b/src/assets/shader/compute/PreFilteredEnvironment_cs.ts @@ -0,0 +1,212 @@ +export let PreFilteredEnvironment_cs: string = /*wgsl*/ ` + // input reflection buffer texture + // sample prefiltered cube uv texture + // storge info to oct map + #include "GenerayRandomDir" + #include "BitUtil" + #include "MathShader" + #include "ColorUtil_frag" + + struct UniformData{ + probeSize : f32 , + probeCount : f32 , + width : f32 , + height : f32 , + } + + @group(0) @binding(0) var inputTex : texture_2d; + @group(0) @binding(1) var outputTexture : texture_storage_2d;//rgba32float rgba16float + @group(1) @binding(0) var uniformData:UniformData;//rgba32float + + var reflectionSize : vec2f ; + var PROBE_SOURCESIZE : vec2f ; + var PROBEMAP_SOURCESIZE : vec2f ; + var aspect : vec2f ; + var spaceV : f32 ; + + var i32InputFragCoord : vec2i; + var PI_2 : f32 = 3.1415926 * 2.0 ; + var PI : f32 = 3.1415926 ; + + var probeSize : f32 = 256.0 ; + var probeCount : f32 = 8.0 ; + var faceCount : f32 = 6.0 ; + var mipCount : f32 = 8.0 ; + + const NUM_SAMPLES = 256u; + var inputSize : vec2f ; + var outSize : vec2f ; + + fn useSphereReflection(){ + probeSize = uniformData.probeSize ; + probeCount = uniformData.probeCount; + reflectionSize = vec2f(textureDimensions(inputTex).xy); + PROBE_SOURCESIZE = reflectionSize / vec2f(faceCount,probeCount); + PROBEMAP_SOURCESIZE = reflectionSize ; + aspect = PROBE_SOURCESIZE / PROBEMAP_SOURCESIZE; + spaceV = 1.0 / probeCount ; + } + + @compute @workgroup_size( 16 , 16 , 1 ) + fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) + { + var color : vec4f ; + useSphereReflection(); + inputSize = vec2f(textureDimensions(inputTex).xy); + outSize = vec2f(textureDimensions(outputTexture).xy); + + i32InputFragCoord = vec2( globalInvocation_id.xy ) ; + + let i = f32(globalInvocation_id.z) ; + let count = floor(i / mipCount) ; + preOneMip(count,floor(i % mipCount)); + } + + fn preOneMip( gid:f32,mip:f32 ){ + let isuv = vec2f(i32InputFragCoord) ; + let suv = isuv * (inputSize/outSize); + let probeID = i32(floor(suv.y / probeSize)); + let mipID = i32((isuv.x / probeSize)); + if(probeID == i32(gid) && mipID == i32(mip)){ + + let sphereUV = vec2f((isuv.x+0.5) % (probeSize),(isuv.y+0.5) % probeSize) / vec2f( (probeSize), probeSize ) ; + var dir: vec3 = octDecode(sphereUV * 2.0 - 1.0) ; + var preColor = PreFilterEnvMap(mip/mipCount + 0.05,dir,gid); + textureStore(outputTexture,vec2i(i32InputFragCoord),preColor); + } + } + + fn PreFilterEnvMap( roughness2:f32, R:vec3f , gid:f32 ) -> vec4f + { + var resColor = vec3f(0.0f); + var resDepth = 0.0; + + var totalColorWeight = 0.0f; + var totalDepthWeight = 0.0f; + + var normal = normalize(R); + var toEye = normal; + + var roughness = roughness2; + + for(var i=1u;i<=NUM_SAMPLES;i+=1u) + { + var xi:vec2f = hammersley(i, NUM_SAMPLES) ; + + var halfway = ImportanceSampleGGX(xi,roughness,normal); + var lightVec = 2.0f * dot( toEye,halfway ) * halfway - toEye; + + var NdotL = dot( normal, lightVec ) ; + var NdotH = max(0.0,dot( normal, halfway )) ; + var HdotV = max(0.0,dot( halfway, toEye )) ; + + if( NdotL > 0.0 ) + { + var D = specularD(roughness,NdotH); + var pdf = (D * NdotH / (4.0 * HdotV)) + 0.0001f ; + + var saSample = 1.0f / (f32(NUM_SAMPLES) * pdf + 0.00001f); + lightVec = normalize(lightVec); + + var buffer = getReflectionsMap(lightVec,gid); + var rgb = unpack4x8unorm(u32(buffer.z)).rgb; + var m = unpack4x8unorm(u32(buffer.w)).z; + var rgbmColor = DecodeRGBM(vec4f(rgb,m)); + resDepth += buffer.x ; + resColor += rgbmColor * NdotL; + + totalColorWeight += NdotL; + totalDepthWeight += 1.0; + } + } + + resDepth = resDepth / max(totalDepthWeight,0.001f); + resColor = resColor / max(totalColorWeight,0.001f); + + let rgbm = EncodeRGBM(resColor) ; + let gBuffer = vec4f( + resDepth, + 0.0, + f32(pack4x8unorm(vec4f(rgbm.rgb,0.0))), + f32(pack4x8unorm(vec4f(0.0,0.0,rgbm.w,0.0))), + ) ; + // return gBuffer ; + return vec4f(resColor,1.0) ; + } + + fn getReflectionsMap(n:vec3,gid:f32) -> vec4f { + var uv = getSampleProbeUV(n,gid); + let color = textureLoad(inputTex, vec2i(uv*inputSize) , 0); + return color ; + } + + fn getSampleProbeUV(dir:vec3,gid:f32) -> vec2 { + let faceId = dir_to_faceId(dir); + var targetUV:vec2 = convert_xyz_to_cube_uv(dir.x, dir.y, dir.z); + targetUV.x = 1.0 - targetUV.x; + let threshould = 0.5 / PROBE_SOURCESIZE; + targetUV = clamp(targetUV, vec2(threshould), vec2(1.0 - threshould)); + targetUV.x = f32(faceId) + targetUV.x; + let aspect:vec2f = PROBE_SOURCESIZE / PROBEMAP_SOURCESIZE; + targetUV = targetUV * aspect ; + targetUV.y = targetUV.y + (spaceV * gid); + return targetUV ; + } + + fn radicalInverse_VdC( bits2:u32) -> f32 + { + var bits = bits2; + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return f32(bits) * 2.3283064365386963e-10f; // / 0x100000000 + } + + fn hammersley( i:u32, N:u32) -> vec2f + { + return vec2f(f32(i) / f32(N), radicalInverse_VdC(i)); + } + + fn ImportanceSampleGGX( xi:vec2f, roughness:f32, N:vec3f) -> vec3f + { + var alpha2 = roughness * roughness * roughness * roughness; + + var phi = 2.0f * 3.1415926 * xi.x ; + var cosTheta = sqrt( (1.0f - xi.y) / (1.0f + (alpha2 - 1.0f) * xi.y )); + var sinTheta = sqrt( 1.0f - cosTheta*cosTheta ); + + var h : vec3f ; + h.x = sinTheta * cos( phi ); + h.y = sinTheta * sin( phi ); + h.z = cosTheta; + + var up = vec3f(1,0,0) ; + if(abs(N.z) < 0.9999){ + up = vec3f(0,0,1) ; + } + + var tangentX = normalize( cross( up, N ) ); + var tangentY = cross( N, tangentX ); + return (tangentX * h.x + tangentY * h.y + N * h.z); + } + + fn specularD( roughness:f32, NoH:f32) -> f32 + { + var NoH2 = NoH * NoH; + var r2 = roughness * roughness; + return r2 / pow(NoH2 * (r2 - 1.0) + 1.0, 2.0); + } + +` + +// var sphereUV = (suv / inputSize) ; +// var dir: vec3 = UvToDir(sphereUV) ;//* 0.5 + 0.5 ; +// var negUV: vec2 = DirTOUV(dir) ;//* 0.5 + 0.5 ; + +// var cc = vec4f(getReflectionsMap(dir,0.0),1.0) ; +// color.y = vec3fToFloat(cc.xyz); +// color.z = vec3fToFloat(dir); + +// textureStore(outputTexture,i32InputFragCoord,color); \ No newline at end of file diff --git a/src/assets/shader/compute/SSGI2_cs.ts b/src/assets/shader/compute/SSGI2_cs.ts new file mode 100644 index 00000000..13d1fe46 --- /dev/null +++ b/src/assets/shader/compute/SSGI2_cs.ts @@ -0,0 +1,186 @@ +export let SSGI2_cs: string = /*wgsl*/ ` + #include "GlobalUniform" + #include "MathShader" + #include "FastMathShader" + #include "BitUtil" + #include "ColorUtil_frag" + #include "GBufferStand" + + struct FrameBuffer{ + frameCount : f32 , + indirectIns : f32 , + delay : f32 , + frameCount4 : f32 , + d1 : f32 , + d2 : f32 , + d3 : f32 , + d4 : f32 , + } + + @group(0) @binding(3) var combineTexture : texture_2d; + @group(0) @binding(5) var newTexture : texture_storage_2d; + + @group(0) @binding(6) var updateBuffer: FrameBuffer ; + + var i32InputSize: vec2 ; + var i32GbufferSize: vec2 ; + + var f32InputSize: vec2 ; + var f32GBufferSize: vec2 ; + + var i32InputFragCoord: vec2 ; + var i32GbufferFragCoord: vec2 ; + + var f32InputFragCoord: vec2 ; + var f32GbufferFragCoord: vec2 ; + + var f32InputUV: vec2 ; + var f32GbufferUV: vec2 ; + + var inputToGBuffer: vec2 ; + + var gBuffer: GBuffer ; + var wColor: vec3; + + var halfPi: f32 ; + + const PI: f32 = 3.141592653; + const I64: f32 = 1.0/64.0; + // const halfPi = 20.371832715762602978417121711682 ; + const offsetCount = 20u ; + + @compute @workgroup_size( 16 , 16 , 1 ) + fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) + { + i32InputFragCoord = vec2( globalInvocation_id.xy ) ; + f32InputFragCoord = vec2( globalInvocation_id.xy ) ; + + i32InputSize = vec2i(textureDimensions(newTexture).xy); + i32GbufferSize = vec2i(textureDimensions(gBufferTexture).xy); + + f32InputSize = vec2f(i32InputSize); + f32GBufferSize = vec2f(i32GbufferSize); + + inputToGBuffer = 1.0/(f32InputSize / f32GBufferSize) ; + + f32InputUV = f32InputFragCoord / f32InputSize ; + + f32GbufferUV = f32InputUV ; + + f32GbufferFragCoord = f32GbufferUV * f32GBufferSize; + i32GbufferFragCoord = vec2i(f32GbufferFragCoord) ; + + gBuffer = getGBuffer(i32GbufferFragCoord) ; + wColor = getRGBMColorFromGBuffer(gBuffer); + var n = getViewNormalFromGBuffer(gBuffer); + var p = getWorldPositionFromGBuffer(gBuffer,f32GbufferUV); + + let f = -globalUniform.far; + if(gBuffer.x <= f ){ + textureStore(newTexture, i32InputFragCoord , vec4f(0.0) ); + return ; + } + + halfPi = 1.0 / (PI*0.5) * f32(offsetCount); + + var trackColor:vec4f = vec4f(0.0); + + trackColor = ray(i32InputFragCoord,f32InputFragCoord); + // trackColor = vec4f(n.xyz,1.0); + + textureStore(newTexture, i32InputFragCoord , trackColor ); + } + + fn ray(i32InputFragCoord:vec2,f32InputFragCoord:vec2) -> vec4f { + var Output = vec4f(0.0); + let i64pi = I64*PI ; + let iFrame = updateBuffer.frameCount; + var lastColor2 = textureLoad(combineTexture, i32InputFragCoord , 0) ; + if (iFrame > 1.0 ) { + var CurrentFrame = f32(iFrame); + var SSOffset = vec2f(0.0); + + gBuffer = getGBuffer(i32GbufferFragCoord) ; + var VColor = getRGBMColorFromGBuffer(gBuffer); + var VNormal = getViewNormalFromGBuffer(gBuffer) ; + var VPPos = getViewPositionFromGBuffer(gBuffer,f32GbufferUV) ; + var ModFC = f32InputFragCoord % 4.; + var RandPhiOffset = ARand21(vec2f(1.234)+ (CurrentFrame*3.26346) % 7.2634 ); + var RandPhi2 = (((floor(ModFC.x)+floor(ModFC.y)*4.0+CurrentFrame*5.0) % 16.0)+RandPhiOffset)*2.0*PI*I64 ; + + var stepScale = ceil( 128.0 / f32(offsetCount) ) ; + var skyColor = vec4f(0.0,0.0,0.0,1.0); + var ii = 0.0; + var i=0u; + for (; i < 4u; i+=1u) { + let RandPhi = f32(i+1u) * (RandPhi2 + PI * 0.5); + let SSDir = (vec2f(cos(RandPhi),sin(RandPhi))); + + var StepDist = stepScale ; + let StepCoeff = 0.15+0.15*ARand21(f32InputUV*(1.4+f32(iFrame)*3.26346%6.2634)); + + var BitMask = 0u; + var s = 1u ; + for (; s<= offsetCount ; s+=1u) + { + let SUV : vec2f = f32InputFragCoord + SSDir * StepDist; + + //round 2d offset + let CurrentStep = max( 1.0 , (StepDist * StepCoeff) ); + StepDist += CurrentStep; + + //fullsize + let offsetUV = (SUV / f32InputSize) ; + let i32InputUV = vec2i( offsetUV * f32GBufferSize ); + let stepGBuffer = getGBuffer(vec2i(i32InputUV)); + var SSVC = getRGBMColorFromGBuffer(stepGBuffer); + + var uuv = (SUV * inputToGBuffer); + uuv = uuv / f32GBufferSize ; + var SVPPos = getViewPositionFromGBuffer(stepGBuffer,uuv) ; + var SWPos = getWorldPositionFromGBuffer(stepGBuffer,uuv) ; + var SNormal = getViewNormalFromGBuffer(stepGBuffer) ; + + let f = (globalUniform.far - globalUniform.near) - 1000.0; + if(stepGBuffer.x <= f ){ + let svvd = SVPPos.xyz-VPPos ; + var NorDot = dot(VNormal,(svvd))-0.001; + + if(stepGBuffer.x < -1.1 || NorDot < 1.570796 ) + { + continue ; + } + + var TanDist = (length(svvd-NorDot*VNormal)); + + if(TanDist <= 0.00001 ) + { + continue ; + } + + var Angle1f = atan2(NorDot,TanDist); + var Angle2f = atan2((NorDot-0.03*max(1.0,StepDist*0.07)),TanDist); + + var Angle1 = max(0.0,ceil(Angle1f*halfPi)); + var Angle2 = max(0.0,floor(Angle2f*halfPi)); + + var SBitMask = (u32(pow(2.0,Angle1-Angle2))-1u) << u32(Angle2); + + let b1 = f32(countOneBits(SBitMask & (~BitMask)))/max(1.0,Angle1-Angle2) ; + let b2 = pow(cos(Angle2*i64pi),2.0)-pow(cos(Angle1*i64pi),2.0); + let b3 = sqrt(max(0.0,dot(SNormal,-svvd))) ; + let fb = b1 * b2 * b3 ; + + var lastColor2 = textureLoad(combineTexture, vec2i(SUV) , 0) ; + Output = vec4f(Output.xyz + vec3f(fb * (SSVC.xyz + lastColor2.xyz * 0.15) ) , 1.0); + BitMask = BitMask | SBitMask; + } + } + } + }else{ + Output = vec4f( wColor.xyz , 1.0 ); + } + + return Output ; + } + ` \ No newline at end of file diff --git a/src/assets/shader/compute/SSR_BlendColor_cs.ts b/src/assets/shader/compute/SSR_BlendColor_cs.ts index cd1b6340..c10d8117 100644 --- a/src/assets/shader/compute/SSR_BlendColor_cs.ts +++ b/src/assets/shader/compute/SSR_BlendColor_cs.ts @@ -1,9 +1,11 @@ export let SSR_BlendColor_cs: string = /*wgsl*/ ` -@group(0) @binding(0) var rayTraceBuffer : array; - @group(0) @binding(1) var colorMap : texture_2d; - @group(0) @binding(2) var ssrMapSampler : sampler; - @group(0) @binding(3) var ssrMap : texture_2d; - @group(0) @binding(4) var outTex : texture_storage_2d; + #include 'GlobalUniform' + + @group(0) @binding(2) var rayTraceBuffer : array; + @group(0) @binding(3) var colorMap : texture_2d; + @group(0) @binding(4) var ssrMapSampler : sampler; + @group(0) @binding(5) var ssrMap : texture_2d; + @group(0) @binding(6) var outTex : texture_storage_2d; var colorTexSize: vec2; var ssrTexSize: vec2; @@ -26,7 +28,7 @@ export let SSR_BlendColor_cs: string = /*wgsl*/ ` return vec2(u, v); } - + const PI = 3.1415926; @compute @workgroup_size( 8 , 8 , 1 ) fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) { @@ -40,13 +42,13 @@ export let SSR_BlendColor_cs: string = /*wgsl*/ ` ssrCoord = vec2(vec2(fragCoord.xy) * scale); let index = ssrCoord.x + ssrCoord.y * i32(ssrTexSize.x); let hitData = rayTraceBuffer[index]; - var color = textureLoad(colorMap, fragCoord , 0); + var lastColor = textureLoad(colorMap, fragCoord , 0); + let time = globalUniform.time; + var uv01 = CalcUV_01(fragCoord, colorTexSize); var ssrColor = textureSampleLevel(ssrMap, ssrMapSampler, uv01, 0.0); - var tc = mix(color, ssrColor, hitData.fresnel) ; - var outColor = tc ; - outColor.a = color.a ; + var outColor = mix(lastColor, ssrColor, hitData.fresnel) ; textureStore(outTex, fragCoord , outColor ); } diff --git a/src/assets/shader/compute/SSR_IS_cs.ts b/src/assets/shader/compute/SSR_IS_cs.ts index 24c30728..10422eb5 100644 --- a/src/assets/shader/compute/SSR_IS_cs.ts +++ b/src/assets/shader/compute/SSR_IS_cs.ts @@ -1,4 +1,6 @@ export let SSR_IS_cs: string = /*wgsl*/ ` +#include 'BitUtil' + struct SSRUniformData { ssrBufferSizeX: f32, ssrBufferSizeY: f32, @@ -62,7 +64,6 @@ export let SSR_IS_cs: string = /*wgsl*/ ` var mixFactor = historyPosition[coordIndex].w; if(bufferData.alpha >= 0.0 && bufferData.roughness < ssrUniform.roughnessThreshold){ - let roughness = clamp(bufferData.roughness, 0.0, 1.0); let prefilterColor = bufferData.skyColor; var ssrColor = textureLoad(colorMap, vec2(bufferData.hitCoord), 0); ssrColor.w = bufferData.alpha; diff --git a/src/assets/shader/compute/SSR_RayTrace_cs.ts b/src/assets/shader/compute/SSR_RayTrace_cs.ts index 9456b838..742e865e 100644 --- a/src/assets/shader/compute/SSR_RayTrace_cs.ts +++ b/src/assets/shader/compute/SSR_RayTrace_cs.ts @@ -1,5 +1,8 @@ export let SSR_RayTrace_cs: string = /*wgsl*/ ` #include "GlobalUniform" + #include "MathShader" + #include "BitUtil" + #include "GBufferStand" struct SSRUniformData { ssrBufferSizeX: f32, @@ -41,16 +44,12 @@ export let SSR_RayTrace_cs: string = /*wgsl*/ ` fresnel:f32, } - @group(0) @binding(0) var standUniform: GlobalUniform; - @group(0) @binding(1) var ssrUniform: SSRUniformData; - @group(0) @binding(2) var rayTraceBuffer : array; + @group(0) @binding(2) var ssrUniform: SSRUniformData; + @group(0) @binding(3) var rayTraceBuffer : array; @group(0) @binding(4) var historyPosition : array>; - @group(0) @binding(5) var zBufferTexture : texture_2d; - @group(0) @binding(6) var normalBufferTex : texture_2d; - @group(0) @binding(7) var materialBufferTex : texture_2d; - @group(0) @binding(8) var prefilterMapSampler: sampler; - @group(0) @binding(9) var prefilterMap: texture_cube; + @group(0) @binding(5) var prefilterMap: texture_cube; + @group(0) @binding(6) var prefilterMapSampler: sampler; var rayOrigin: vec3; var rayDirection: vec3; @@ -70,6 +69,7 @@ export let SSR_RayTrace_cs: string = /*wgsl*/ ` var historyPos: vec3; var coordIndex: i32; + var sampleUV: vec2; var PI: f32 = 3.14159; @compute @workgroup_size( 8 , 8 , 1 ) @@ -78,8 +78,9 @@ export let SSR_RayTrace_cs: string = /*wgsl*/ ` ssrBufferCoord = vec2( globalInvocation_id.xy); ssrBufferSize = vec2(i32(ssrUniform.ssrBufferSizeX), i32(ssrUniform.ssrBufferSizeY)); if(ssrBufferCoord.x >= ssrBufferSize.x || ssrBufferCoord.y >= ssrBufferSize.y){ - return; + return; } + useNormalMatrixInv(); coordIndex = ssrBufferCoord.x + ssrBufferCoord.y * ssrBufferSize.x; colorTexSize = vec2(i32(ssrUniform.colorMapSizeX), i32(ssrUniform.colorMapSizeY)); @@ -91,7 +92,10 @@ export let SSR_RayTrace_cs: string = /*wgsl*/ ` hitData.hitNormal = vec3(0.0, 1.0, 0.0); hitData.hitSky = 1; - worldPosition = textureLoad(zBufferTexture, fragCoordColor , 0).xyz; + sampleUV = vec2f(fragCoordColor) / vec2f(colorTexSize) ; + //gBufferTexture + let gBuffer : GBuffer = getGBuffer( vec2i(fragCoordColor) ); + worldPosition = getWorldPositionFromGBuffer(gBuffer,sampleUV) ; historyPos = historyPosition[coordIndex].xyz; var mixFactor = 0.2; @@ -100,13 +104,12 @@ export let SSR_RayTrace_cs: string = /*wgsl*/ ` } historyPosition[coordIndex] = vec4(worldPosition, mixFactor); - let normal_v4 = textureLoad(normalBufferTex, fragCoordColor , 0); - worldNormal = normalize(vec3(normal_v4.xyz) * 2.0 - 1.0); - let materialData = textureLoad(materialBufferTex, fragCoordColor , 0 ); - let roughness = materialData.g * (1.0 - materialData.b); - fresnel = (1.0 - roughness) * ssrUniform.reflectionRatio; + worldNormal = getWorldNormalFromGBuffer(gBuffer) ; - cameraPosition = vec3(standUniform.cameraWorldMatrix[3].xyz); + let roughness = getRoughnessFromGBuffer(gBuffer); + fresnel = (1.0 - roughness) * ssrUniform.reflectionRatio; + fresnel *= fresnel; + cameraPosition = vec3(globalUniform.cameraWorldMatrix[3].xyz); rayOrigin = vec3(worldPosition.xyz); rayDirection = normalize(vec3(worldPosition.xyz - cameraPosition)); @@ -120,13 +123,13 @@ export let SSR_RayTrace_cs: string = /*wgsl*/ ` reflectionDir = normalize(reflect(rayDirection, normalRandom)); - if(normal_v4.w > 0.5 && roughness < ssrUniform.roughnessThreshold){ + if(roughness > 0.0 && roughness < ssrUniform.roughnessThreshold){ let uvOrigin = vec2(f32(fragCoordColor.x), f32(fragCoordColor.y)); let rayMarchPosition = rayOrigin + reflectionDir * 100.0; - var uvRayMarch = standUniform.projMat * (standUniform.viewMat * vec4(rayMarchPosition, 1.0)); + var uvRayMarch = globalUniform.projMat * (globalUniform.viewMat * vec4(rayMarchPosition, 1.0)); var uvOffset = (vec2(uvRayMarch.xy / uvRayMarch.w) + 1.0) * 0.5; uvOffset.y = 1.0 - uvOffset.y; - uvOffset = uvOffset * vec2(colorTexSize - 1) - uvOrigin; + uvOffset = uvOffset * vec2(colorTexSize) - uvOrigin; uvOffset = normalize(uvOffset); rayTrace(uvOffset); @@ -213,13 +216,7 @@ export let SSR_RayTrace_cs: string = /*wgsl*/ ` let calcRoughness = clamp(roughness, 0.0, 1.0); let MAX_REFLECTION_LOD = f32(textureNumLevels(prefilterMap)) ; var prefilterColor = textureSampleLevel(prefilterMap, prefilterMapSampler, reflectionDir, calcRoughness * MAX_REFLECTION_LOD); - return LinearToGammaSpace(vec3(prefilterColor.xyz)) * standUniform.skyExposure; - } - - fn LinearToGammaSpace(linRGB: vec3) -> vec3 { - var linRGB1 = max(linRGB, vec3(0.0)); - linRGB1 = pow(linRGB1, vec3(0.4166666567325592)); - return max(((1.0549999475479126 * linRGB1) - vec3(0.054999999701976776)), vec3(0.0)); + return LinearToGammaSpace(vec3(prefilterColor.xyz)) * globalUniform.skyExposure; } fn convertColorCoordFromSSRCoord(coord:vec2) -> vec2{ @@ -280,12 +277,13 @@ export let SSR_RayTrace_cs: string = /*wgsl*/ ` var uv = fromUV + vec2(i32(offsetFloat32.x), i32(offsetFloat32.y)); let hitRet = rayInterestScene(uv); if(hitRet == 1){ - let WN = textureLoad(normalBufferTex, hitData.hitCoord , 0 ); - if(WN.w > 0.5){ - hitData.hitSky = 0; + let gBuffer = getGBuffer(hitData.hitCoord); + if(getRoughnessFromGBuffer(gBuffer) >= 0.0){ + hitData.hitSky = 0; } - let normal = vec3(WN.xyz) * 2.0 - 1.0; - hitData.hitNormal = normalize(vec3(normal.xyz)); + + let WN = getWorldNormalFromGBuffer(gBuffer); + hitData.hitNormal = normalize(WN); break; } } @@ -296,7 +294,8 @@ export let SSR_RayTrace_cs: string = /*wgsl*/ ` if(uv.x < 0 || uv.y < 0 || uv.x >= colorTexSize.x || uv.y >= colorTexSize.y){ return 2; }else{ - let hitPos = textureLoad(zBufferTexture, uv , 0 ); + let gBuffer = getGBuffer(uv); + let hitPos = getWorldPositionFromGBuffer(gBuffer , vec2f(uv) / vec2f(colorTexSize) ); let testDir = normalize(vec3(hitPos.xyz - rayOrigin)); let cosValue = dot(reflectionDir, testDir); diff --git a/src/assets/shader/compute/TAA_cs.ts b/src/assets/shader/compute/TAA_cs.ts index 510088fc..19dd04e3 100644 --- a/src/assets/shader/compute/TAA_cs.ts +++ b/src/assets/shader/compute/TAA_cs.ts @@ -1,5 +1,6 @@ export let TAA_cs: string = /*wgsl*/ ` #include "GlobalUniform" +#include "GBufferStand" struct TAAData{ preProjMatrix: mat4x4, @@ -14,25 +15,25 @@ struct TAAData{ slot1: f32, } -@group(0) @binding(0) var standUniform: GlobalUniform; -@group(0) @binding(1) var taaData: TAAData; -@group(0) @binding(2) var preColorBuffer : array>; - -@group(0) @binding(3) var preColorTexSampler : sampler; -@group(0) @binding(4) var preColorTex : texture_2d; -@group(0) @binding(5) var posTex : texture_2d; +@group(0) @binding(2) var taaData: TAAData; +@group(0) @binding(3) var preColorBuffer : array>; +@group(0) @binding(4) var preColorTexSampler : sampler; +@group(0) @binding(5) var preColorTex : texture_2d; @group(0) @binding(6) var inTexSampler : sampler; @group(0) @binding(7) var inTex : texture_2d; @group(0) @binding(8) var outTex : texture_storage_2d; +const PI = 3.1415926 ; +const FLT_EPS = 5.960464478e-8; // 2^-24, machine epsilon: 1 + EPS = 1 (half of the ULP for 1.0f) + var texSize: vec2; var fragCoord: vec2; +var fragUV: vec2; var coordIndex: i32; var color_min: vec4; var color_max: vec4; var color_avg: vec4; var re_proj_uv01: vec2; -var FLT_EPS:f32 = 5.960464478e-8; // 2^-24, machine epsilon: 1 + EPS = 1 (half of the ULP for 1.0f) @compute @workgroup_size( 8 , 8 , 1 ) fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) @@ -42,7 +43,9 @@ fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_inv if(fragCoord.x >= i32(texSize.x) || fragCoord.y >= i32(texSize.y)){ return; } - let frame = standUniform.frame; + useNormalMatrixInv(); + fragUV = vec2(fragCoord) / vec2(texSize - 1); + let frame = globalUniform.frame; coordIndex = fragCoord.x + fragCoord.y * i32(texSize.x); let oc = blendColor(); @@ -58,12 +61,14 @@ fn blendColor() -> vec4 var reProjectionCoord:vec2 = vec2(fragCoord); //var jitterUVOffset = 0.5 * vec2(taaData.jitterX, -taaData.jitterY); if(taaData.jitterFrameIndex > 0.5){ - var wPos = textureLoad(posTex, fragCoord, 0); + let gBuffer : GBuffer = getGBuffer(fragCoord); + var wPos = getWorldPositionFromGBuffer(gBuffer,fragUV) ; + let roughness = getRoughnessFromGBuffer(gBuffer); let ndc = taaData.preProjMatrix * (taaData.preViewMatrix * vec4(wPos.xyz, 1.0)); re_proj_uv01 = vec2(ndc.x, -ndc.y) / ndc.w; re_proj_uv01 = (re_proj_uv01 + 1.0) * 0.5; - if(re_proj_uv01.x >= 0.0 && re_proj_uv01.x <= 1.0 && re_proj_uv01.y >= 0.0 && re_proj_uv01.y <= 1.0){ + if(roughness > 0.0 && re_proj_uv01.x >= 0.0 && re_proj_uv01.x <= 1.0 && re_proj_uv01.y >= 0.0 && re_proj_uv01.y <= 1.0){ mixWeight = taaData.blendFactor; //reProjectionCoord = re_proj_uv01 + jitterUVOffset; reProjectionCoord.x = re_proj_uv01.x * f32(texSize.x - 1); @@ -75,7 +80,7 @@ fn blendColor() -> vec4 } } - var curUV01 = vec2(fragCoord) / vec2(texSize - 1); + var curUV01 = fragUV; //curUV01 += jitterUVOffset; let curColor = textureSampleLevel(inTex, inTexSampler, curUV01, 0.0); @@ -88,7 +93,6 @@ fn blendColor() -> vec4 preColor = clip_aabb(color_min.xyz, color_max.xyz, color_avg, preColor); var outColor = mix(preColor, curColor, mixWeight); - return outColor; } diff --git a/src/assets/shader/compute/utils/Combine_cs.ts b/src/assets/shader/compute/utils/Combine_cs.ts new file mode 100644 index 00000000..2fc71ac8 --- /dev/null +++ b/src/assets/shader/compute/utils/Combine_cs.ts @@ -0,0 +1,61 @@ +export let Combine_cs = /* wgsl */` + #include "GlobalUniform" + #include "BitUtil" + #include 'ColorUtil_frag' + #include 'GBufferStand' + + struct FrameBuffer{ + frameCount : f32 , + indirectIns : f32 , + delay : f32 , + colorIns : f32 , + d1 : f32 , + d2 : f32 , + d3 : f32 , + d4 : f32 , + } + + + // @group(0) @binding(0) var inputATexture : texture_2d; + // @group(0) @binding(1) var inputATextureSampler : sampler; + @group(0) @binding(2) var inputBTexture : texture_2d; + @group(0) @binding(3) var inputBTextureSampler : sampler; + + @group(0) @binding(4) var outTexture : texture_storage_2d; + @group(0) @binding(5) var updateBuffer: FrameBuffer ; + + var fragCoord:vec2; + + const PI = 3.1415926 ; + + @compute @workgroup_size( 16 , 16 , 1 ) + fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) + { + fragCoord = globalInvocation_id.xy; + let textsize = vec2f(textureDimensions(inputBTexture).xy); + let size = vec2f(textureDimensions(outTexture).xy); + let inputUV = vec2f(fragCoord) / size ; + let inputUV2 = vec2(inputUV * textsize) ; + + let time = globalUniform.time ; + + let gBuffer = getGBuffer(vec2i(fragCoord)); + let b = textureSampleLevel( inputBTexture, inputBTextureSampler, inputUV , 0.0 ); + + let albedoColor = getAbldeoFromGBuffer(gBuffer) / PI ; + let bufferColor = getRGBMColorFromGBuffer(gBuffer) ; + var colorA = bufferColor.xyz * updateBuffer.colorIns ; + var color = b.xyz * updateBuffer.indirectIns * albedoColor ; + + + // color = LinearToGammaSpace(color); + // var currentPixel:vec4f = vec4f((colorA.xyz + color.xyz ) , 1.0) ; + var currentPixel:vec4f = vec4f(colorA.xyz + color , 1.0) ; + // var currentPixel:vec4f = vec4f(bufferColor , 1.0) ; + // var currentPixel:vec4f = vec4f(1.0,0.0,0.0, 1.0) ; + textureStore(outTexture, fragCoord , currentPixel ); + } + + + +` \ No newline at end of file diff --git a/src/assets/shader/compute/utils/Denoising_cs.ts b/src/assets/shader/compute/utils/Denoising_cs.ts new file mode 100644 index 00000000..d43d49ed --- /dev/null +++ b/src/assets/shader/compute/utils/Denoising_cs.ts @@ -0,0 +1,34 @@ +export let Denoising_cs = /* wgsl */` + // #include "GlobalUniform" + + struct FrameBuffer{ + frameCount : f32 , + indirectIns : f32 , + delay : f32 , + frameCount4 : i32 , + } + + @group(0) @binding(1) var updateBuffer: FrameBuffer ; + @group(0) @binding(2) var newTexture : texture_2d; + @group(0) @binding(3) var oldTexture : texture_2d; + @group(0) @binding(4) var combineTexture : texture_storage_2d; + var fragCoord:vec2; + + @compute @workgroup_size( 16 , 16 , 1 ) + fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) + { + fragCoord = globalInvocation_id.xy; + + // if(updateBuffer.frameCount < 256){ + let newPixel = textureLoad( newTexture, fragCoord, 0 ); + let oldPixel = textureLoad( oldTexture, fragCoord, 0 ); + + let weight = updateBuffer.delay ; + var currentPixel:vec4f; + currentPixel = vec4f(newPixel.xyz * weight + (1.0-weight) * oldPixel.xyz , 1.0 ); + textureStore(combineTexture, fragCoord , currentPixel ); + } + + + +` \ No newline at end of file diff --git a/src/assets/shader/compute/utils/TestComputeLoadBuffer.ts b/src/assets/shader/compute/utils/TestComputeLoadBuffer.ts new file mode 100644 index 00000000..84a2a323 --- /dev/null +++ b/src/assets/shader/compute/utils/TestComputeLoadBuffer.ts @@ -0,0 +1,140 @@ +export let TestComputeLoadBuffer = /* wgsl */` + #include "GlobalUniform" + #include "MathShader" + #include "FastMathShader" + #include "BitUtil" + #include "ColorUtil_frag" + #include "GBufferStand" + + struct Uniform{ + state:i32, + state1:i32, + state2:i32, + state3:i32, + } + + @group(0) @binding(auto) var outputTexture : texture_storage_2d; + @group(0) @binding(auto) var reflectionsGBufferTexture : texture_2d; + @group(0) @binding(auto) var currentRenderTexture : texture_2d; + @group(0) @binding(auto) var envMap : texture_2d; + @group(0) @binding(auto) var uniformData : Uniform; + + var fragCoord:vec2; + var screenSize:vec2; + var fragColor:vec4f; + const PI = 3.1415926 ; + + var colorSet : array, 9> = array, 9>( + vec3(1.0, 0.0, 0.0), + vec3(1.0, 0.5, 0.0), + vec3(0.5, 1.0, 0.0), + vec3(0.0, 1.0, 0.0), + vec3(0.0, 1.0, 0.5), + vec3(0.0, 0.5, 1.0), + vec3(0.0, 0.0, 1.0), + vec3(0.5, 0.0, 1.0), + vec3(1.0, 0.0, 0.5) + ); + + @compute @workgroup_size( 16 , 16 , 1 ) + fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) + { + + fragCoord = globalInvocation_id.xy; + screenSize = vec2u(textureDimensions(outputTexture)); + + useNormalMatrixInv(); + + let color = textureLoad(currentRenderTexture, fragCoord , 0); + fragColor = color ; + + var outPixel:vec3f ; + var a = globalUniform.time ; + + var state = uniformData.state ; + //render normal color + let gBuffer : GBuffer = getGBuffer( vec2i(fragCoord) ); + switch (state) { + case 0:{ + break; + } + case 1:{ + fragColor = vec4f(getAbldeoFromGBuffer(gBuffer).rgb,1.0) ; + break; + } + case 2:{ + fragColor = vec4f(getViewNormalFromGBuffer(gBuffer),1.0) ; + break; + } + case 3:{ + fragColor = vec4f(getWorldNormalFromGBuffer(gBuffer),1.0) ; + break; + } + case 4:{ + fragColor = vec4f(vec3f(getRoughnessFromGBuffer(gBuffer)),1.0) ; + break; + } + case 5:{ + fragColor = vec4f(vec3f(getMetaillicFromGBuffer(gBuffer)),1.0) ; + break; + } + case 6:{ + fragColor = vec4f(vec3f(getAlphaFromGBuffer(gBuffer)),1.0) ; + break; + } + case 7:{ + let id = (f32(getIDFromGBuffer_i32(gBuffer)) * f_r22g8.r) % 9.0; + fragColor = vec4f(colorSet[u32(id)],1.0) ; + break; + } + + default:{ + break; + } + } + + let size = f32(uniformData.state1) ; + let renderRec1 = vec4f(0.0,0.0,size,size); + renderBufferToViewPort(reflectionsGBufferTexture,renderRec1); + + let size2 = f32(uniformData.state2) ; + let renderRec2 = vec4f(0.0,size,size2,size2); + renderColorBufferToViewPort(envMap,renderRec2); + + //not chage final color out put + textureStore(outputTexture, fragCoord , fragColor ); + } + + fn renderBufferToViewPort( texture:texture_2d , viewRectangle:vec4f) { + let size = vec2f(textureDimensions(texture)); + let f32FragCoord = vec2f(fragCoord); + if(insideRectangle(f32FragCoord,viewRectangle)){ + let uv = clipViewUV(viewRectangle,size,f32FragCoord); + let gBuffer = textureGBuffer(texture,uv); + let color = getRGBMColorFromGBuffer(gBuffer); + fragColor = vec4f(color,1.0); + } + } + + fn renderColorBufferToViewPort( texture:texture_2d , viewRectangle:vec4f) { + let size = vec2f(textureDimensions(texture)); + let f32FragCoord = vec2f(fragCoord); + if(insideRectangle(f32FragCoord,viewRectangle)){ + let uv = clipViewUV(viewRectangle,size,f32FragCoord); + let color = textureLoad(texture, uv , 0).rgb; + fragColor = vec4f(color,1.0); + } + } + + fn textureGBuffer( texture:texture_2d , fragCoord:vec2u ) -> GBuffer { + let bufferTex = textureLoad(texture, fragCoord , 0) ; + var gBuffer:GBuffer ; + gBuffer.x = bufferTex.x ; + gBuffer.y = bufferTex.y ; + gBuffer.z = bufferTex.z ; + gBuffer.w = bufferTex.w ; + return gBuffer ; + } + + +` \ No newline at end of file diff --git a/src/assets/shader/compute/utils/TextureCompress.ts b/src/assets/shader/compute/utils/TextureCompress.ts new file mode 100644 index 00000000..8d52d579 --- /dev/null +++ b/src/assets/shader/compute/utils/TextureCompress.ts @@ -0,0 +1,163 @@ +import { Texture } from "../../../../gfx/graphics/webGpu/core/texture/Texture" + +export let textureCompress = (colorMap:Texture,sourceTexture: Texture[], destTexture: Texture[], workX: number, workY: number, workZ: number = 1) => { + let begin = 0; + let bindInputTexture = ''; + let preG = ''; + + preG += /* wgsl */` + fn acesFilm( x:vec3f) -> vec3f { + return clamp((x*(2.51*x+vec3f(0.03)))/(x*(2.43*x+vec3f(0.59))+vec3f(0.14)),vec3f(0.0),vec3f(1.0)); + } + `; + + for (let i = 0; i < sourceTexture.length; i++) { + const inputTexture = sourceTexture[i]; + let inTextureName = `source${i}Map`; + let inTextureSamplerName = `source${i}MapSampler`; + + bindInputTexture += /* wgsl */` + @group(0) @binding(${(begin+i) * 2 + 0}) var ${inTextureName} : texture_2d;\n + @group(0) @binding(${(begin+i) * 2 + 1}) var ${inTextureSamplerName} : sampler; + `; + + + + preG += GaussBlur(`GaussBlur_${inTextureName}_1`,inTextureName,inTextureSamplerName); + preG += GaussBlur(`GaussBlur_${inTextureName}_0`,inTextureName,inTextureSamplerName); + } + + begin += sourceTexture.length ; + let bindOutputTexture = ''; + for (let i = 0; i < destTexture.length; i++) { + bindOutputTexture += /* wgsl */`@group(0) @binding(${(begin+i) * 2 + 0}) var dest${i}Map : texture_storage_2d;\n`; + } + + let loadMainColor = ""; + if(colorMap){ + begin += destTexture.length ; + bindInputTexture += /* wgsl */`@group(0) @binding(${(begin) * 2 + 0}) var colorMap : texture_2d;\n + + ` + loadMainColor += /* wgsl */` + mainColor = textureLoad( colorMap ,fragCoord, 0) ; + ` ; + } + + let compute_workgroup_size = /* wgsl */`@compute @workgroup_size(${workX}, ${workY},${workZ})`; + + let copyTexture = copyToTexture(sourceTexture.length,colorMap?true:false); + + let compute_shader = /* wgsl */` + ${GaussWeight2D} + ${CalcUV_01} + ${bindInputTexture} + ${bindOutputTexture} + ${preG} + + var fragCoord: vec2; + var texSize: vec2; + + var mainColor: vec4f; + + ${compute_workgroup_size} + fn CsMain(@builtin(global_invocation_id) globalInvocation_id : vec3){ + fragCoord = vec2( globalInvocation_id.xy ); + texSize = textureDimensions(dest0Map).xy; + if(fragCoord.x >= i32(texSize.x) || fragCoord.y >= i32(texSize.y)){ + return; + } + + ${loadMainColor} + + ${copyTexture} + } + ` + return compute_shader +} + +let copyToTexture = (len:number,combineMainColor:boolean)=>{ + let code = `` + for (let i = 0; i < len ; i++) { + code += upSample(`GaussBlur_source${i}Map`,`dest${i}Map`,combineMainColor); + } + return code ; +} + +let upSample = (funName:string,outeTextureName:string,combineMainColor:boolean)=>{ + let code = /* wgsl */` + var color = vec4(0.0, 0.0, 0.0, 1.0); + var uv = CalcUV_01(fragCoord, texSize); + + // 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 = ${funName}_1(uv, i32(1), prev_stride, 1.0); + let rgb2 = ${funName}_0(uv, i32(1), curr_stride, 1.0); + color = vec4((rgb1 + rgb2) * 0.5 , color.w) ; + // color *= 3.1415926 ; + color = vec4f(pow(acesFilm(max(vec3f(0.),color.xyz)),vec3f(0.45)),1.) * 0.5 ; + ${combineMainColor ? "color = (color + mainColor) ;": "" } + // color = color / (1.0+color) * 2.0 ; + textureStore(${outeTextureName}, fragCoord, color ); + ` + return code; +} + +let CalcUV_01 = /*wgsl*/ ` + fn CalcUV_01(coord:vec2, texSize:vec2) -> vec2 + { + let u = (f32(coord.x) + 0.5) / f32(texSize.x); + let v = (f32(coord.y) + 0.5) / f32(texSize.y); + return vec2(u, v); + } +` + +//_______________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; + +} +// let merge = (a: string, b: string) => { +// let code = /* wgsl */ ` + +// ` +// return a + b; +// } diff --git a/src/assets/shader/compute/utils/tw.ts b/src/assets/shader/compute/utils/tw.ts new file mode 100644 index 00000000..9981b845 --- /dev/null +++ b/src/assets/shader/compute/utils/tw.ts @@ -0,0 +1,62 @@ +export let tw = /* wgsl */` + + @group(0) @binding(1) var inputTexture : texture_2d; + @group(0) @binding(2) var outputTexture : texture_storage_2d; + + // @group(0) @binding(3) var posTexture : texture_2d; + // @group(0) @binding(4) var normalTexture : texture_2d; + // @group(0) @binding(5) var colorTexture : texture_2d; + + var fragCoord:vec2; + // var wPosition: vec4; + // var wNormal: vec4; + // var wColor: vec4; + + // var finalMatrix: mat4x4; + // var ORI_NORMALMATRIX: mat3x3; + + + @compute @workgroup_size( 16 , 16 , 1 ) + fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) + { + fragCoord = globalInvocation_id.xy; + + wColor = textureLoad(colorTexture, fragCoord , 0); + + + finalMatrix = globalUniform.projMat * globalUniform.viewMat ; + let nMat = mat3x3(finalMatrix[0].xyz,finalMatrix[1].xyz,finalMatrix[2].xyz) ; + ORI_NORMALMATRIX = transpose(inverse( nMat )); + + wPosition = textureLoad(posTexture, fragCoord, 0); + wNormal = textureLoad(normalTexture, fragCoord, 0); + var VPPos = (finalMatrix * vec4f(wPosition.xyz,1.0)).xyz ; + var VPNormal = normalize(ORI_NORMALMATRIX * wNormal.xyz) ; + + var LastPixel = textureLoad(inputTexture,fragCoord,0); + + var NewPixel:vec4f = wColor ; + var NewRadius = max(1.,ceil(1.99-LastPixel.w*0.25)); + var RadiusCoeff = max(1.,2.25-LastPixel.w*0.25); + if (NewRadius>0.5) { + var NewWeight = 1.; + for (var x=-NewRadius; x(SUV), 0); + var SVNormal:vec3f = textureLoad(posTexture, vec2(SUV), 0).xyz * 2.0 - 1.0; + var SWeight = max(0.0001,float(dot(Normal,SVPos-VPPos)<0.01))* + max(0.01,float(dot(Normal,normalize(SVNormal))>0.9)); + NewPixel += texture(iChannel1,SUV*IRES) * SWeight; + NewWeight += SWeight; + } + } + NewPixel /= NewWeight; + } + } + +` \ No newline at end of file diff --git a/src/assets/shader/core/base/Common_frag.ts b/src/assets/shader/core/base/Common_frag.ts index 87949689..8b7c5e87 100644 --- a/src/assets/shader/core/base/Common_frag.ts +++ b/src/assets/shader/core/base/Common_frag.ts @@ -1,35 +1,49 @@ export let Common_frag: string = /*wgsl*/ ` #include "GlobalUniform" #include "FragmentVarying" - #include "ColorPassFragmentOutput" + #include "FragmentOutput" #include "ShadingInput" + #include "ColorUtil_frag" + #include "BitUtil" var ORI_FragmentOutput: FragmentOutput; 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_VertexVarying.vWorldNormal = normalize(vertex_varying.vWorldNormal); ORI_FragmentOutput.color = vec4(1.0, 0.0, 0.0, 1.0); viewDir = normalize(globalUniform.CameraPos.xyz - ORI_VertexVarying.vWorldPos.xyz) ; - #if USE_WORLDPOS - ORI_FragmentOutput.worldPos = ORI_VertexVarying.vWorldPos; - #endif - #if USEGBUFFER - ORI_FragmentOutput.worldNormal = vec4(ORI_ShadingInput.Normal.rgb ,1.0); - ORI_FragmentOutput.material = vec4(0.0,1.0,0.0,0.0); - #endif + frag(); #if USE_DEBUG debugFragmentOut(); #endif + #if USE_DEFAULTFRAGOUT + // let finalMatrix = globalUniform.projMat * globalUniform.viewMat ; + // let nMat = mat3x3(finalMatrix[0].xyz,finalMatrix[1].xyz,finalMatrix[2].xyz) ; + // let ORI_NORMALMATRIX = transpose(inverse( nMat )); + // var vNormal = normalize(ORI_NORMALMATRIX * (ORI_VertexVarying.vWorldNormal)); + + // let gBuffer = packNHMDGBuffer( + // ORI_VertexVarying.fragCoord.z, + // ORI_ShadingInput.BaseColor.rgb, + // ORI_ShadingInput.BaseColor.rgb, + // vec3f(ORI_ShadingInput.Roughness,ORI_ShadingInput.Metallic,ORI_ShadingInput.AmbientOcclusion), + // ORI_ShadingInput.Normal, + // ORI_ShadingInput.Opacity + // ) ; + #endif + #if USE_OUTDEPTH #if USE_LOGDEPTH ORI_FragmentOutput.out_depth = log2DepthFixPersp(ORI_VertexVarying.fragPosition.w, globalUniform.near, globalUniform.far); @@ -42,5 +56,29 @@ export let Common_frag: string = /*wgsl*/ ` } + fn packNHMDGBuffer(depth:f32, albedo:vec3f,hdrLighting:vec3f,rmao:vec3f,normal:vec3f,alpha:f32) -> vec4f { + var gBuffer : vec4f ; + var octUVNormal = (octEncode(normalize( (normal) )) + 1.0) * 0.5 ; + var yc = f32(r11g11b9_to_float(vec3f(octUVNormal,rmao.r))) ; + #if USE_CASTREFLECTION + var rgbm = EncodeRGBM(hdrLighting); + var zc = f32(pack4x8unorm(vec4f(rgbm.rgb,0.0))) ; + var wc = f32(pack4x8unorm(vec4f(rmao.rg,rgbm.a,0.0))); + #else + var zc = f32(vec4fToFloat_7bits(vec4f(albedo.rgb,alpha))); + var wc = f32(r22g8_to_float(vec2f(f32(modelIndex)/f_r22g8.r,rmao.g))); + #endif + + gBuffer.x = depth ; + gBuffer.y = yc ; + gBuffer.z = zc ; + gBuffer.w = wc ; + return gBuffer ; + } + + fn transformUV( uv:vec2f , offsetScale:vec4f ) -> vec2f{ + return uv * offsetScale.zw + offsetScale.xy ; + } + ` diff --git a/src/assets/shader/core/common/GBufferStand.ts b/src/assets/shader/core/common/GBufferStand.ts new file mode 100644 index 00000000..df1e83a2 --- /dev/null +++ b/src/assets/shader/core/common/GBufferStand.ts @@ -0,0 +1,186 @@ +export let GBufferStand = /* wgsl */ ` + #include "MathShader" + #include "FastMathShader" + #include "BitUtil" + #include "ColorUtil_frag" + + @group(0) @binding(1) var gBufferTexture : texture_2d; + + struct GBuffer{ + x : f32 , + y : f32 , + z : f32 , + w : f32 , + } + + struct ViewSpaceGBuffer{ + depth:f32, + color:vec3f , + abldeoColor:vec3f , + viewPosition:vec3f, + viewNormal:vec3f, + roughness:f32, + metallic:f32, + } + + struct WorldSpaceGBuffer{ + depth:f32, + color:vec3f , + abldeoColor:vec3f , + worldPosition:vec3f, + worldNormal:vec3f, + roughness:f32, + metallic:f32, + } + + fn getViewSpaceGBuffer(fragCoord:vec2i , uv:vec2f ) -> ViewSpaceGBuffer { + var sampleUV = uv ; + sampleUV.y = 1.0 - sampleUV.y ; + let gBufferTexture = textureLoad(gBufferTexture, fragCoord , 0) ; + + var gBuffer : ViewSpaceGBuffer ; + //x channel view space depth + gBuffer.depth = gBufferTexture.x ; + let viewPos = getViewPosition(gBufferTexture.x,sampleUV); + gBuffer.viewPosition = viewPos; + + //y channel last final color texture + gBuffer.color = floatToVec3f(gBufferTexture.y) ; + + //z channel view space normal + let zChannel = floatToVec3f(gBufferTexture.z) ; + let octUV = zChannel.xy * 2.0 - 1.0 ; + gBuffer.viewNormal = octDecode(octUV.xy) ; + + //w channel view space normal + let wChannel = floatToVec3f(gBufferTexture.w) ; + gBuffer.abldeoColor = wChannel.xyz ; + + gBuffer.roughness = zChannel.z ; + gBuffer.metallic = 0.0 ;//wChannel.w ; + + return gBuffer ; + } + + fn getWorldSpaceGBuffer(fragCoord:vec2i , uv:vec2f ) -> WorldSpaceGBuffer { + var sampleUV = uv ; + sampleUV.y = 1.0 - sampleUV.y ; + let gBufferTexture = textureLoad(gBufferTexture, fragCoord , 0) ; + + var gBuffer : WorldSpaceGBuffer ; + //x channel view space depth + gBuffer.depth = gBufferTexture.x ; + let worldPos = getWorldPosition(gBufferTexture.x,sampleUV); + gBuffer.worldPosition = worldPos; + + //y channel last final color texture + gBuffer.color = floatToVec3f(gBufferTexture.y) ; + + //z channel world space normal and roughness + let zChannel = floatToVec3f(gBufferTexture.z) ; + let octUV = zChannel.xy * 2.0 - 1.0 ; + gBuffer.worldNormal = getWorldNormal(octDecode(octUV.xy)) ; + + //w channel abldeoColor and metallic + let wChannel = floatToVec3f(gBufferTexture.w) ; + gBuffer.abldeoColor = wChannel.xyz ; + + gBuffer.roughness = zChannel.z ; + gBuffer.metallic = 0.0 ;//wChannel.w ; + + return gBuffer ; + } + + fn getGBuffer(fragCoord:vec2i) -> GBuffer { + let gBufferTexture = textureLoad(gBufferTexture, fragCoord , 0) ; + var gBuffer:GBuffer ; + gBuffer.x = gBufferTexture.x ; + gBuffer.y = gBufferTexture.y ; + gBuffer.z = gBufferTexture.z ; + gBuffer.w = gBufferTexture.w ; + return gBuffer ; + } + + fn getDepthFromGBuffer(gBuffer:GBuffer) -> f32 { + return gBuffer.x ; + } + + fn getViewPositionFromGBuffer(gBuffer:GBuffer,screenUV:vec2f) -> vec3f { + var sampleUV = screenUV ; + sampleUV.x = 1.0 - sampleUV.x ; + sampleUV.y = 1.0 - sampleUV.y ; + let viewPos = getViewPosition(gBuffer.x,sampleUV); + return viewPos; + } + + fn getViewNormalFromGBuffer(gBuffer:GBuffer) -> vec3f { + let worldNormal = getWorldNormalFromGBuffer(gBuffer) ; + return getViewNormal(worldNormal); + } + + fn getWorldPositionFromGBuffer(gBuffer:GBuffer,uv:vec2f) -> vec3f { + var sampleUV = uv ; + sampleUV.y = 1.0 - sampleUV.y ; + let worldPos = getWorldPosition(gBuffer.x,sampleUV); + return worldPos; + } + + fn getSkyPositionFromGBuffer(uv:vec2f) -> vec3f { + var sampleUV = uv ; + sampleUV.y = 1.0 - sampleUV.y ; + let worldPos = getWorldPosition(0.9999999, sampleUV); + return worldPos; + } + + fn getRGBMColorFromGBuffer(gBuffer:GBuffer) -> vec3f { + let rgb = unpack4x8unorm(u32(gBuffer.z)).rgb ; + let m = unpack4x8unorm(u32(gBuffer.w)).z ; + return DecodeRGBM(vec4f(rgb,m)) ; + } + + + fn getWorldNormalFromGBuffer(gBuffer:GBuffer) -> vec3f { + // let viewNormal = getViewNormalFromGBuffer(gBuffer) ; + // let worldNormal = getWorldNormal(viewNormal) ; + // return worldNormal; + let zChannel = float_to_r11g11b9(gBuffer.y) ; + let octUV = zChannel.xy * 2.0 - 1.0 ; + let viewNormal = octDecode(octUV.xy); + return viewNormal; + } + + + + fn getAbldeoFromGBuffer(gBuffer:GBuffer) -> vec4f { + let rgba = floatToVec4f_7bits(gBuffer.z).rgba ; + return rgba ; + } + + fn getAlphaFromGBuffer(gBuffer:GBuffer) -> f32 { + let rgba = floatToVec4f_7bits(gBuffer.z).rgba ; + return rgba.a; + } + + fn getMetaillicFromGBuffer(gBuffer:GBuffer) -> f32 { + let channel = float_to_r22g8(gBuffer.w) ; + return channel.y; + } + + fn getRoughnessFromGBuffer(gBuffer:GBuffer) -> f32 { + let channel = float_to_r11g11b9(gBuffer.y) ; + return channel.z; + } + + fn getIDFromGBuffer_f32_01(gBuffer:GBuffer) -> f32 { + let channel = float_to_r22g8(gBuffer.w) ; + return channel.x; + } + + fn getIDFromGBuffer_i32(gBuffer:GBuffer) -> i32 { + let id_f32_01 = getIDFromGBuffer_f32_01(gBuffer) ; + let id = i32(round(id_f32_01 * f_r22g8.r)); + return id; + } + + +` \ No newline at end of file diff --git a/src/assets/shader/core/common/GlobalUniform.ts b/src/assets/shader/core/common/GlobalUniform.ts index 79f5a55b..59cd7748 100644 --- a/src/assets/shader/core/common/GlobalUniform.ts +++ b/src/assets/shader/core/common/GlobalUniform.ts @@ -2,19 +2,36 @@ import { CSM } from "../../../../core/csm/CSM"; export let GlobalUniform: string = /*wgsl*/ ` + #include "MathShader" + struct GlobalUniform { + projMat: mat4x4, viewMat: mat4x4, cameraWorldMatrix: mat4x4, pvMatrixInv : mat4x4, + viewToWorld : mat4x4, shadowMatrix: array, 8u>, + csmShadowBias: vec4, + csmMatrix: array,${CSM.Cascades}>, shadowLights:mat4x4, + reflectionProbeSize:f32, + reflectionProbeMaxCount:f32, + reflectionMapWidth:f32, + reflectionMapHeight:f32, + + reflectionCount:f32, + test2:f32, + test3:f32, + test4:f32, + CameraPos: vec3, frame: f32, + SH: array , time: f32, delta: f32, @@ -41,20 +58,59 @@ export let GlobalUniform: string = /*wgsl*/ ` shadowSoft: f32, enableCSM:f32, + csmMargin:f32, nDirShadowStart: i32, nDirShadowEnd: i32, nPointShadowStart: i32, nPointShadowEnd: i32, - empty1: i32, - empty2: i32, - empty3: i32, + cameraForward:vec3f, frustumPlanes: array, + }; @group(0) @binding(0) var globalUniform: GlobalUniform; + + fn getViewPosition(z:f32,uv:vec2f) -> vec3f { + let pvMatrixInv = globalUniform.pvMatrixInv ; + let clip = vec4((uv * 2.0 - 1.0) , z , 1.0); + var viewPos = pvMatrixInv * clip ; + return viewPos.xyz / viewPos.w ; + } + + fn getWorldPosition(z:f32,uv:vec2f) -> vec3f { + let viewToWorld = globalUniform.viewToWorld ; + let clip = vec4((uv * 2.0 - 1.0) , z , 1.0); + var worldPos = viewToWorld * clip ; + worldPos = worldPos / worldPos.w ; + return worldPos.xyz ; + } + + var NORMALMATRIX_INV : mat3x3 ; + var NORMALMATRIX : mat3x3 ; + fn useNormalMatrix() { + let finalMatrix = globalUniform.projMat * globalUniform.viewMat ; + let nMat = mat3x3(finalMatrix[0].xyz,finalMatrix[1].xyz,finalMatrix[2].xyz) ; + NORMALMATRIX = transpose(inverse( nMat )); + } + + fn useNormalMatrixInv() { + let finalMatrix = globalUniform.projMat * globalUniform.viewMat ; + let nMat = mat3x3(finalMatrix[0].xyz,finalMatrix[1].xyz,finalMatrix[2].xyz) ; + NORMALMATRIX_INV = transpose(( nMat )); + } + + fn getWorldNormal(viewNormal:vec3f) -> vec3f { + var worldNormal = NORMALMATRIX_INV * viewNormal ; + return normalize(worldNormal.xyz); + } + + fn getViewNormal(worldNormal:vec3f) -> vec3f { + var viewNormal = globalUniform.viewMat * vec4f(worldNormal,0.0) ; + return normalize(viewNormal.xyz); + } ` diff --git a/src/assets/shader/core/common/SHCommon_frag.ts b/src/assets/shader/core/common/SHCommon_frag.ts new file mode 100644 index 00000000..4062e68e --- /dev/null +++ b/src/assets/shader/core/common/SHCommon_frag.ts @@ -0,0 +1,86 @@ + +export let SHCommon_frag: string = /*wgsl*/ ` + +fn Y0(v : vec3f ) -> f32 { + return ((1.0 / 2.0) * sqrt(1.0 / PI)); +} + +fn Y1(v: vec3f ) -> f32 { + return ( sqrt(3.0 / (4.0 * PI)) * v.z ) ; +} + +fn Y2(v: vec3f ) -> f32 { + return (sqrt(3.0 / (4.0 * PI)) * v.y) ; +} + +fn Y3(v: vec3f ) -> f32 { + return (sqrt(3.0 / (4.0 * PI)) * v.x) ; +} + +fn Y4(v: vec3f ) -> f32 { + return (1.0 / 2.0 * sqrt(15.0 / PI) * v.x * v.z) ; +} + +fn Y5(v: vec3f ) -> f32 { + return (1.0 / 2.0 * sqrt(15.0 / PI) * v.z * v.y) ; +} + +fn Y6(v: vec3f ) -> f32 { + return (1.0 / 4.0 * sqrt(5.0 / PI) * (-v.x * v.x - v.z * v.z + 2.0 * v.y * v.y)) ; +} + +fn Y7(v: vec3f ) -> f32 { + return (1.0 / 2.0 * -sqrt(15.0 / PI) * v.y * v.x) ; +} + +fn Y8(v: vec3f ) -> f32 { + return (1.0 / 4.0 * sqrt(15.0 / PI) * (v.x * v.x - v.z * v.z)) ; +} + +fn Y9(v: vec3f ) -> f32 { + return (1.0 / 4.0 * sqrt(35.0 / (2.0 * PI)) * (3.0 * v.x * v.x - v.z * v.z) * v.z) ; +} + +fn Y10(v: vec3f ) -> f32 { + return ( 1.0 / 2.0 * sqrt(105.0 / PI) * v.x * v.z * v.y ); +} + +fn Y11(v: vec3f ) -> f32 { + return ( 1.0 / 4.0 * sqrt(21.0 / (2.0 * PI)) * v.z * (4.0 * v.y * v.y - v.x * v.x - v.z * v.z) ); +} + +fn Y12(v: vec3f ) -> f32 { + return ( 1.0 / 4.0 * sqrt(7.0 / PI) * v.y * (2 * v.y * v.y - 3.0 * v.x * v.x - 3.0 * v.z * v.z) ); +} + +fn Y13(v: vec3f ) -> f32 { + return ( 1.0 / 4.0 * sqrt(21.0 / (2.0 * PI)) * v.x * (4.0 * v.y * v.y - v.x * v.x - v.z * v.z) ); +} + +fn Y14(v: vec3f ) -> f32 { + return ( 1.0 / 4.0 * sqrt(105.0 / PI) * (v.x * v.x - v.z * v.z) * v.y ); +} + +fn Y15(v: vec3f ) -> f32 { + return ( 1.0 / 4.0 * sqrt(35.0 / (2.0 * PI)) * (v.x * v.x - 3.0 * v.z * v.z) * v.x ); +} + +fn SH9(dir: vec3, coefficients: array) -> vec4 { + let N: vec3 = vec3(dir.z, dir.y, dir.x); + let v: vec3 = normalize(N); + + let color = coefficients[0] * Y0(v) + + coefficients[1] * Y1(v) + + coefficients[2] * Y2(v) + + coefficients[3] * Y3(v) + + coefficients[4] * Y4(v) + + coefficients[5] * Y5(v) + + coefficients[6] * Y6(v) + + coefficients[7] * Y7(v) + + coefficients[8] * Y8(v) + ; + + return vec4(color.rgb,1.0) ; +} +` + diff --git a/src/assets/shader/core/inline/Inline_vert.ts b/src/assets/shader/core/inline/Inline_vert.ts index 3a2f3ac9..9ccf7d91 100644 --- a/src/assets/shader/core/inline/Inline_vert.ts +++ b/src/assets/shader/core/inline/Inline_vert.ts @@ -14,27 +14,35 @@ export let Inline_vert: string = /*wgsl*/ ` var ORI_CameraWorldDir: vec3; var ORI_ViewDir: vec3; - var TIME: vec4; - var MOUSE: vec4; - var SCREEN: vec4; + fn TIME() -> vec3f { + return vec3f(globalUniform.frame, globalUniform.time , globalUniform.delta); + } - var ProjectionParams: vec4; + fn TIME_frame() -> f32 { + return globalUniform.frame ; + } - fn vertex_inline(vertex:VertexAttributes){ - TIME.x = globalUniform.frame; - TIME.y = globalUniform.time; - TIME.z = globalUniform.delta; + fn TIME_time() -> f32 { + return globalUniform.time ; + } + + fn TIME_delta() -> f32 { + return globalUniform.delta ; + } - MOUSE.x = globalUniform.mouseX; - MOUSE.y = globalUniform.mouseY; + fn MOUSE() -> vec2f { + return vec2f( globalUniform.mouseX, globalUniform.mouseY) ; + } - SCREEN.x = globalUniform.windowWidth; - SCREEN.y = globalUniform.windowHeight; + fn SCREEN() -> vec2f { + return vec2f( globalUniform.windowWidth, globalUniform.windowHeight) ; + } - ProjectionParams.x = globalUniform.near; - ProjectionParams.y = globalUniform.far; - ProjectionParams.z = 1.0 + 1.0 / globalUniform.far; + fn ProjectionParams() -> vec3f { + return vec3f( globalUniform.near, globalUniform.far,1.0 + 1.0 / globalUniform.far) ; + } + fn vertex_inline(vertex:VertexAttributes){ ORI_MATRIX_P = globalUniform.projMat ; ORI_MATRIX_V = globalUniform.viewMat ; ORI_MATRIX_PV = ORI_MATRIX_P * ORI_MATRIX_V ; diff --git a/src/assets/shader/core/pass/SkyGBuffer_pass.ts b/src/assets/shader/core/pass/SkyGBuffer_pass.ts index 6dfb63a9..01031709 100644 --- a/src/assets/shader/core/pass/SkyGBuffer_pass.ts +++ b/src/assets/shader/core/pass/SkyGBuffer_pass.ts @@ -1,5 +1,6 @@ export let SkyGBuffer_pass: string = /*wgsl*/ ` #include "GlobalUniform" +#include "ColorUtil_frag" struct uniformData { eyesPos: vec3, @@ -21,14 +22,8 @@ var baseMap: texture_cube; @group(2) @binding(0) var global: uniformData; -fn LinearToGammaSpace(linRGB: vec3) -> vec3 { - 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(auto) fragUV: vec2, @location(auto) vWorldPos: vec4, @location(auto) vWorldNormal: vec3) -> FragmentOutput { +fn main(@location(auto) fragUV: vec2,@location(auto) vClipPos: vec4, @location(auto) vWorldPos: vec4, @location(auto) vWorldNormal: vec3 , @builtin(position) fragCoord : vec4 ) -> FragmentOutput { let maxLevel: u32 = textureNumLevels(baseMap); let textureColor:vec3 = textureSampleLevel(baseMap, baseMapSampler, normalize(vWorldPos.xyz), global.roughness * f32(maxLevel) ).xyz; let o_Color = 0.618 * vec4(LinearToGammaSpace(textureColor) * globalUniform.skyExposure , 1.0); diff --git a/src/assets/shader/core/struct/FragmentOutput.ts b/src/assets/shader/core/struct/FragmentOutput.ts new file mode 100644 index 00000000..137683e8 --- /dev/null +++ b/src/assets/shader/core/struct/FragmentOutput.ts @@ -0,0 +1,20 @@ + + +export let FragmentOutput: string = /*wgsl*/ ` + #if USE_CASTREFLECTION + struct FragmentOutput { + @location(auto) gBuffer: vec4, + #if USE_OUTDEPTH + @builtin(frag_depth) out_depth: f32 + #endif + }; + #else + struct FragmentOutput { + @location(auto) color: vec4, + @location(auto) gBuffer: vec4, + #if USE_OUTDEPTH + @builtin(frag_depth) out_depth: f32 + #endif + }; + #endif +` diff --git a/src/assets/shader/core/struct/ShadingInput.ts b/src/assets/shader/core/struct/ShadingInput.ts index 77f76427..764cfd8a 100644 --- a/src/assets/shader/core/struct/ShadingInput.ts +++ b/src/assets/shader/core/struct/ShadingInput.ts @@ -25,5 +25,22 @@ export let ShadingInput: string = /*wgsl*/ ` FragDepth:f32, SSS:vec3f, + + // color:vec4f , + // normal:vec3f, + // alpha:f32, + // roughness:f32, + // metallic:f32, + // occlusion:f32, + // specularColor:vec4f , + // specularIntensity:vec4f , + // emissiveColor:vec4f, + // emissiveIntensity:f32, + // shadow:f32, + // ior:f32, + // alphaClip:f32, + + // position:vec4f, + // depth:f32 } ` diff --git a/src/assets/shader/core/struct/VertexAttributeIndexShader.ts b/src/assets/shader/core/struct/VertexAttributeIndexShader.ts index a6d3d54b..98bfaf2f 100644 --- a/src/assets/shader/core/struct/VertexAttributeIndexShader.ts +++ b/src/assets/shader/core/struct/VertexAttributeIndexShader.ts @@ -93,7 +93,7 @@ export let VertexAttributeIndexShader: string = /*wgsl*/ ` 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_ViewPos = viewPosition ; ORI_VertexOut.varying_Clip = clipPosition; ORI_VertexOut.varying_WPos = worldPos; ORI_VertexOut.varying_WNormal = normalize( vertexNormal.xyz); diff --git a/src/assets/shader/core/struct/VertexAttributes.ts b/src/assets/shader/core/struct/VertexAttributes.ts index f85560bd..eb251d39 100644 --- a/src/assets/shader/core/struct/VertexAttributes.ts +++ b/src/assets/shader/core/struct/VertexAttributes.ts @@ -1,7 +1,7 @@ import { SkeletonAnimation_shader } from "../../anim/SkeletonAnimation_shader"; import { MorphTarget_shader } from "../../../../components/anim/morphAnim/MorphTarget_shader"; -export let VertexAttributes: string = /*wgsl*/ ` +export let VertexAttributes_vert: string = /*wgsl*/ ` var PI: f32 = 3.14159265359; #if USE_METAHUMAN ${MorphTarget_shader.getMorphTargetShaderBinding(3, 0)} diff --git a/src/assets/shader/env/ReflectionCG.ts b/src/assets/shader/env/ReflectionCG.ts new file mode 100644 index 00000000..ee9dfb01 --- /dev/null +++ b/src/assets/shader/env/ReflectionCG.ts @@ -0,0 +1,134 @@ +export let ReflectionCG: string = /* wgsl */ ` + #include 'MathShader' + #include 'BitUtil' + #include 'GlobalUniform' + + struct ReflectionInfo{ + gid:f32, + worldPosition:vec3f, + radius:f32, + worldPosition2:vec3f, + } + + @group(1) @binding(auto) + var reflectionMap: texture_2d; + @group(1) @binding(auto) + var reflectionMapSampler: sampler; + + @group(2) @binding(8) + var reflectionBuffer : array; + + var reflectionSize : vec2f ; + var PROBE_SOURCESIZE : vec2f ; + var PROBEMAP_SOURCESIZE : vec2f ; + var aspect : vec2f ; + var spaceV : f32 ; + + fn useSphereReflection(){ + reflectionSize = vec2f(textureDimensions(reflectionMap).xy); + PROBE_SOURCESIZE = vec2f(globalUniform.reflectionProbeSize); + PROBEMAP_SOURCESIZE = vec2f(globalUniform.reflectionMapWidth,globalUniform.reflectionMapHeight) ; + aspect = PROBE_SOURCESIZE / PROBEMAP_SOURCESIZE; + spaceV = 1.0 / globalUniform.reflectionProbeMaxCount; + } + + fn getSampleProbeUV(dir:vec3,gid:f32) -> vec2 { + let faceId = dir_to_faceId(dir); + var targetUV:vec2 = convert_xyz_to_cube_uv(dir.x, dir.y, dir.z); + targetUV.x = 1.0 - targetUV.x; + // targetUV.y = 1.0 - targetUV.y; + let threshould = 0.5 / PROBE_SOURCESIZE; + targetUV = clamp(targetUV, vec2(threshould), vec2(1.0 - threshould)); + + targetUV.x = f32(faceId) + targetUV.x; + targetUV = targetUV * aspect ; + targetUV.y = targetUV.y + (spaceV*gid); + return targetUV ; + } + + // fn getReflectionsMap(n:vec3,gid:f32) -> vec3f { + // var uv = getSampleProbeUV(-n,gid); + // let color = textureSample(reflectionMap,reflectionMapSampler,uv) ; + // return floatToVec3f(color.y) ; + // } + + const magic = vec4f(0.9852,0.99214,0.00754,0.0); + fn getReflectionsBuffer(n:vec3,gid:f32,mip:f32) -> vec4f { + let scaleA = vec2f(1.0/8.0,1.0/globalUniform.reflectionProbeMaxCount) ; + let mipSource = clamp((mip * 8.0),0.0,8.0) ; + let mip1 = floor(mipSource) ; + let mip2 = mip1 + 1.0 ; + let mipPect = mipSource - mip1 ; + var uv = (octEncode(-n) + 1.0) * 0.5 * magic.xy + magic.zw ; + var uv1 = (uv * scaleA + vec2f((mip1 * (scaleA.x)) ,0.0 )); + var uv2 = (uv * scaleA + vec2f((mip2 * (scaleA.x)) ,0.0 )); + let b1 = textureSampleLevel(reflectionMap,reflectionMapSampler,uv1,0.0); + let b2 = textureSampleLevel(reflectionMap,reflectionMapSampler,uv2,0.0); + let b1Color = b1.rgb ; + let b2Color = b2.rgb ; + + // let rgb1 = unpack4x8unorm(u32(b1.z)).rgb ; + // let rgb2 = unpack4x8unorm(u32(b2.z)).rgb ; + + // let m1 = unpack4x8unorm(u32(b1.w)).z ; + // let m2 = unpack4x8unorm(u32(b2.w)).z ; + + // let b1Color = DecodeRGBM(vec4f(rgb1,m1)); + // let b2Color = DecodeRGBM(vec4f(rgb2,m2)); + + // let b1D = b1.x; + // let b2D = b2.x; + + let color = mix(b1Color,b2Color,vec3f(mipPect)); ; + // let depth = mix(b1D,b2D,(mipPect)); + // return vec4f(color,depth) ; + return vec4f(color,0.0) ; + } + + fn getReflectionsEnv(reflectDir:vec3,worldPos:vec3f,mip:f32) -> vec3f{ + let maxCount = u32(globalUniform.reflectionProbeMaxCount) ; + var nearColor = vec3f(0.0); + if(globalUniform.reflectionCount > 0.0){ + var nearDistance = 99999.0 ; + var nearReflectionIndex = 0u ; + for(var i = 0u ; i < maxCount; i+=1u){ + var reflectionInfo = reflectionBuffer[i]; + let dis = length(reflectionInfo.worldPosition - worldPos) ; + if(dis < nearDistance){ + nearDistance = dis; + nearReflectionIndex = i; + } + } + nearColor = getReflectionsBuffer(reflectDir,f32(nearReflectionIndex),mip).xyz; + }else{ + nearColor = textureSampleLevel(envMap, envMapSampler, reflectDir , mip * 12.0 ).rgb ; + } + return nearColor ; + } + + // fn getReflectionsEnv(n:vec3,worldPos:vec3f,mip:f32) -> vec3f{ + // let count = 1.0 ;//globalUniform.reflectionProbeMaxCount ; + // var nearColor = vec3f(0.0); + // var nearDistance = 99999.0 ; + // for(var i = 0.0 ; i < count; i+=1.0){ + // var reflectionInfo = reflectionBuffer[i32(i)]; + // let dis = length(reflectionInfo.worldPosition - worldPos) ; + // if(dis > reflectionInfo.radius){ + // var buffer = getReflectionsBuffer(n,i,mip); + // var d = buffer.w; + // if(d <= -globalUniform.far){ + // d = 99999.0 - 1.0 ; + // } + // if(nearDistance > d){ + // nearColor = buffer.xyz; + // nearDistance = d; + // } + // }else{ + // nearColor = vec3f(1.0,0.0,0.0); + // } + // } + // return nearColor ; + // } + + +` \ No newline at end of file diff --git a/src/assets/shader/graphic/GraphicDecCompute.ts b/src/assets/shader/graphic/GraphicDecCompute.ts new file mode 100644 index 00000000..d06940d3 --- /dev/null +++ b/src/assets/shader/graphic/GraphicDecCompute.ts @@ -0,0 +1,165 @@ +export let graphicDecCompute = (segmentCode: number) => { + let code = /*wgsl*/` + #include "GlobalUniform" + struct VertexInfo{ + position:vec3f, + // px:f32, + // py:f32, + // pz:f32, + nx:f32, + ny:f32, + nz:f32, + uv_x:f32, + uv_y:f32, + uv2_x:f32, + uv2_y:f32, + index:f32, + index2:f32 + } + + struct TrailInfo{ + index : f32 , + segment : f32 , + visible : f32 , + width: f32, + + uv: vec4f, + + uvSpeed: vec2f, + smoothLine: f32, + faceMode: f32, + up: vec4f, + ids:array + } + + @group(0) @binding(1) var vertexBuffer : array; + @group(0) @binding(2) var trailBuffer : array; + @group(0) @binding(3) var models : array>; + + var time:f32; + var viewDir:vec3f; + + @compute @workgroup_size(256) + fn CsMain(@builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) global_invocation_id : vec3){ + let rID = workgroup_id.x ; + let trailInfo = trailBuffer[rID]; + let vLen = u32(trailInfo.segment+1.0) ; + let vID = global_invocation_id.x ; + + // if(vID < vLen ){ + time = globalUniform.time * 0.001; + var right:vec3f ; + + switch (u32(trailInfo.faceMode)) { + case 0u:{ + right = getRightByMode(vID,vLen,viewDir,trailInfo) ; + break; + } + case 1u:{ + right = vec3f(0.0,0.0,1.0) ; + break; + } + case 2u:{ + right = getRightByMode(vID,vLen,trailInfo.up.xyz,trailInfo) ; + break; + } + default:{ + break; + } + } + writeTOBuffer(rID,vID,vLen,right,trailInfo); + // } + } + + + + fn writeTOBuffer(rID:u32, vID:u32 , vLen:u32, right:vec3f , trailInfo:TrailInfo ){ + let i0 = (vID + (vLen * rID)) * 2u ; + let li = i0 + 0u ; + let ri = i0 + 1u ; + + let worldPos = models[i32(trailInfo.ids[vID])][3].xyz ; + let leftPos = worldPos - right.xyz * trailInfo.width ; + let rightPos = worldPos + right.xyz * trailInfo.width ; + + vertexBuffer[li].position = leftPos ; + vertexBuffer[ri].position = rightPos ; + + let uvS = time * trailInfo.uvSpeed ; + + vertexBuffer[li].uv_x = (trailInfo.uv.x) + uvS.x ; + vertexBuffer[ri].uv_x = (trailInfo.uv.z + trailInfo.uv.x) + uvS.x ; + + // var ld = 0.0 ; + // var rd = 0.0 ; + // if(vID>0u){ + // let vid0 = getVID(vID,vLen,rID); + // let vid1 = getVID(vID-1u,vLen,rID); + + // ld = distance( vertexBuffer[li].position , vertexBuffer[vid1.x].position ) ; + // rd = distance( vertexBuffer[ri].position , vertexBuffer[vid1.y].position ) ; + + // vertexBuffer[li].uv_y = vertexBuffer[vid1.x].uv_y + 1.0 / ld * 100.0 ;//+ uvS.y ; + // vertexBuffer[ri].uv_y = vertexBuffer[vid1.y].uv_y + 1.0 / rd * 100.0 ;//+ uvS.y ; + // }else{ + let v = (1.0 - f32(vID) / trailInfo.segment) * trailInfo.uv.w + trailInfo.uv.y; + vertexBuffer[li].uv_y = v + uvS.y ; + vertexBuffer[ri].uv_y = v + uvS.y ; + // } + } + + fn getRight(p0:vec3f,p1:vec3f,p2:vec3f,up:vec3f) -> vec3f { + let d0 = normalize(p1 - p0) ; + let d1 = normalize(p2 - p1) ; + // var a = dot(d0,d1) ; + // var ep = 0.0 ; + // if(a<0.0){ + // a = -a ; + // ep = 1.0/sin(a*0.25) ; + // }else if(a == 0.0){ + // ep = 1.414 ; + // }else{ + // ep = 1.0 ; + // } + let forward = normalize((d0 + d1)+ vec3f(0.000001,0.000001,0.000001)) ; + return normalize(cross(forward,up)) ;//* ep ; + } + + fn getVID(vID:u32,vLen:u32,rID:u32) -> vec2 { + let i0 = (vID + (vLen * rID)) * 2u ; + let li = i0 + 0u ; + let ri = i0 + 1u ; + return vec2(li,ri); + } + + fn getRightByMode( vID:u32 , vLen:u32, up:vec3f, trailInfo:TrailInfo ) -> vec3f{ + var right:vec3f; + if(vID==0u){ + // first + let sp0 = models[i32(trailInfo.ids[ 0 ])][3].xyz ; + let sp1 = models[i32(trailInfo.ids[ 1 ])][3].xyz ; + let firstFront = normalize(sp1 - sp0) ; + viewDir = -normalize(globalUniform.CameraPos.xyz - sp0) ; + right = normalize(cross(firstFront,viewDir)); + }else if( vID < (vLen-1) ){ + // body + let bp0 = models[i32(trailInfo.ids[vID-1])][3].xyz ; + let bp1 = models[i32(trailInfo.ids[vID])][3].xyz ; + let bp2 = models[i32(trailInfo.ids[vID+1])][3].xyz ; + viewDir = -normalize(globalUniform.CameraPos.xyz - bp1) ; + right = getRight(bp0,bp1,bp2,viewDir) ; + }else{ + // last + let ep0 = models[i32(trailInfo.ids[u32(trailInfo.segment)-1u])][3].xyz ; + let ep1 = models[i32(trailInfo.ids[u32(trailInfo.segment)])][3].xyz ; + let endFront = normalize(ep1 - ep0) ; + viewDir = -normalize(globalUniform.CameraPos.xyz - ep1) ; + right = normalize(cross(endFront,viewDir)); + } + return normalize(right) ; + } + ` + return code; +} + + diff --git a/src/assets/shader/graphic/GraphicTrailCompute2.ts b/src/assets/shader/graphic/GraphicTrailCompute2.ts new file mode 100644 index 00000000..51b0e321 --- /dev/null +++ b/src/assets/shader/graphic/GraphicTrailCompute2.ts @@ -0,0 +1,165 @@ +export let GraphicTrailCompute2 = (segmentCode: number) => { + let code = /*wgsl*/` + #include "GlobalUniform" + struct VertexInfo{ + position:vec3f, + // px:f32, + // py:f32, + // pz:f32, + nx:f32, + ny:f32, + nz:f32, + uv_x:f32, + uv_y:f32, + uv2_x:f32, + uv2_y:f32, + index:f32, + index2:f32 + } + + struct TrailInfo{ + index : f32 , + segment : f32 , + visible : f32 , + width: f32, + + uv: vec4f, + + uvSpeed: vec2f, + smoothLine: f32, + faceMode: f32, + up: vec4f, + ids:array + } + + @group(0) @binding(1) var vertexBuffer : array; + @group(0) @binding(2) var trailBuffer : array; + @group(0) @binding(3) var models : array>; + + var time:f32; + var viewDir:vec3f; + + @compute @workgroup_size(256) + fn CsMain(@builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) global_invocation_id : vec3){ + let rID = workgroup_id.x ; + let trailInfo = trailBuffer[rID]; + let vLen = u32(trailInfo.segment+1.0) ; + let vID = global_invocation_id.x ; + + // if(vID < vLen ){ + time = globalUniform.time * 0.001; + var right:vec3f ; + + switch (u32(trailInfo.faceMode)) { + case 0u:{ + right = getRightByMode(vID,vLen,viewDir,trailInfo) ; + break; + } + case 1u:{ + right = vec3f(0.0,0.0,1.0) ; + break; + } + case 2u:{ + right = getRightByMode(vID,vLen,trailInfo.up.xyz,trailInfo) ; + break; + } + default:{ + break; + } + } + writeTOBuffer(rID,vID,vLen,right,trailInfo); + // } + } + + + + fn writeTOBuffer(rID:u32, vID:u32 , vLen:u32, right:vec3f , trailInfo:TrailInfo ){ + let i0 = (vID + (vLen * rID)) * 2u ; + let li = i0 + 0u ; + let ri = i0 + 1u ; + + let worldPos = models[i32(trailInfo.ids[vID])][3].xyz ; + let leftPos = worldPos - right.xyz * trailInfo.width ; + let rightPos = worldPos + right.xyz * trailInfo.width ; + + vertexBuffer[li].position = leftPos ; + vertexBuffer[ri].position = rightPos ; + + let uvS = time * trailInfo.uvSpeed ; + + vertexBuffer[li].uv_x = (trailInfo.uv.x) + uvS.x ; + vertexBuffer[ri].uv_x = (trailInfo.uv.z + trailInfo.uv.x) + uvS.x ; + + // var ld = 0.0 ; + // var rd = 0.0 ; + // if(vID>0u){ + // let vid0 = getVID(vID,vLen,rID); + // let vid1 = getVID(vID-1u,vLen,rID); + + // ld = distance( vertexBuffer[li].position , vertexBuffer[vid1.x].position ) ; + // rd = distance( vertexBuffer[ri].position , vertexBuffer[vid1.y].position ) ; + + // vertexBuffer[li].uv_y = vertexBuffer[vid1.x].uv_y + 1.0 / ld * 100.0 ;//+ uvS.y ; + // vertexBuffer[ri].uv_y = vertexBuffer[vid1.y].uv_y + 1.0 / rd * 100.0 ;//+ uvS.y ; + // }else{ + let v = (1.0 - f32(vID) / trailInfo.segment) * trailInfo.uv.w + trailInfo.uv.y; + vertexBuffer[li].uv_y = v + uvS.y ; + vertexBuffer[ri].uv_y = v + uvS.y ; + // } + } + + fn getRight(p0:vec3f,p1:vec3f,p2:vec3f,up:vec3f) -> vec3f { + let d0 = normalize(p1 - p0) ; + let d1 = normalize(p2 - p1) ; + // var a = dot(d0,d1) ; + // var ep = 0.0 ; + // if(a<0.0){ + // a = -a ; + // ep = 1.0/sin(a*0.25) ; + // }else if(a == 0.0){ + // ep = 1.414 ; + // }else{ + // ep = 1.0 ; + // } + let forward = normalize((d0 + d1)+ vec3f(0.000001,0.000001,0.000001)) ; + return normalize(cross(forward,up)) ;//* ep ; + } + + fn getVID(vID:u32,vLen:u32,rID:u32) -> vec2 { + let i0 = (vID + (vLen * rID)) * 2u ; + let li = i0 + 0u ; + let ri = i0 + 1u ; + return vec2(li,ri); + } + + fn getRightByMode( vID:u32 , vLen:u32, up:vec3f, trailInfo:TrailInfo ) -> vec3f{ + var right:vec3f; + if(vID==0u){ + // first + let sp0 = models[i32(trailInfo.ids[ 0 ])][3].xyz ; + let sp1 = models[i32(trailInfo.ids[ 1 ])][3].xyz ; + let firstFront = normalize(sp1 - sp0) ; + viewDir = -normalize(globalUniform.CameraPos.xyz - sp0) ; + right = normalize(cross(firstFront,viewDir)); + }else if( vID < (vLen-1) ){ + // body + let bp0 = models[i32(trailInfo.ids[vID-1])][3].xyz ; + let bp1 = models[i32(trailInfo.ids[vID])][3].xyz ; + let bp2 = models[i32(trailInfo.ids[vID+1])][3].xyz ; + viewDir = -normalize(globalUniform.CameraPos.xyz - bp1) ; + right = getRight(bp0,bp1,bp2,viewDir) ; + }else{ + // last + let ep0 = models[i32(trailInfo.ids[u32(trailInfo.segment)-1u])][3].xyz ; + let ep1 = models[i32(trailInfo.ids[u32(trailInfo.segment)])][3].xyz ; + let endFront = normalize(ep1 - ep0) ; + viewDir = -normalize(globalUniform.CameraPos.xyz - ep1) ; + right = normalize(cross(endFront,viewDir)); + } + return normalize(right) ; + } + ` + return code; +} + + diff --git a/src/assets/shader/lighting/BRDF_frag.ts b/src/assets/shader/lighting/BRDF_frag.ts index 20154d19..dd7c08e2 100644 --- a/src/assets/shader/lighting/BRDF_frag.ts +++ b/src/assets/shader/lighting/BRDF_frag.ts @@ -3,6 +3,7 @@ export let BRDF_frag: string = /*wgsl*/ ` #include "EnvMap_frag" #include "BrdfLut_frag" #include "ColorUtil_frag" + #include "SHCommon_frag" struct FragData { Ao: f32, @@ -32,6 +33,8 @@ export let BRDF_frag: string = /*wgsl*/ ` FaceDirection:f32, ClearcoatRoughness:f32, + ClearcoatFactor:f32, + ClearcoatIor:f32, EnvColor: vec3, Irradiance: vec3, @@ -81,6 +84,8 @@ export let BRDF_frag: string = /*wgsl*/ ` return (2.0 * NoL * roughness) + 0.4; } + + fn KDisneyTerm( NoL:f32, NoV:f32 , roughness:f32) -> f32 { return (1.0 + Fd90(NoL, roughness) * pow(1.0 - NoL, 5.0)) * (1.0 + Fd90(NoV, roughness) * pow(1.0 - NoV, 5.0)); @@ -130,6 +135,14 @@ export let BRDF_frag: string = /*wgsl*/ ` return 0.5 * rcp(Vis_SmithV + Vis_SmithL); } + fn Vis_SmithJointApprox( NoV : f32 , NoL : f32 , a2 : f32 ) -> f32 + { + let a = sqrt(a2); + let Vis_SmithV = NoL * ( NoV * ( 1.0 - a ) + a ); + let Vis_SmithL = NoV * ( NoL * ( 1.0 - a ) + a ); + return 0.5 * rcp( Vis_SmithV + Vis_SmithL ); + } + fn GeometrySchlickGGX( NdotV : f32 , roughness : f32 ) -> f32 { //roughness compute ks @@ -215,13 +228,65 @@ export let BRDF_frag: string = /*wgsl*/ ` return rcp( Vis_SmithV * Vis_SmithL ); } + fn F_Function( HdotL:f32, F0:vec3f ) -> vec3f + { + var fresnel = exp2((-5.55473 * HdotL - 6.98316) * HdotL); + return mix(vec3f(fresnel),vec3f(1.0),F0); + } + + fn D_Function( NdotH:f32, roughness:f32) ->f32 + { + var a = roughness*roughness; + var a2 = a*a; + var NdotH2 = NdotH*NdotH; + var nom = a2; + var denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + return nom / denom; + } + + //G项 几何函数 + fn G_SubFunction( NdotW : f32, K : f32)->f32 + { + return NdotW / mix(NdotW,1.0,K); + } + + fn G_Function( NdotL: f32, NdotV: f32, roughness: f32)->f32 + { + var K = (1.0+roughness) * (1.0+roughness) / 8.0; + return G_SubFunction(NdotL,K) * G_SubFunction(NdotV,K); + } + + fn DGF_Function( NdotH:f32, NdotL:f32,NdotV:f32, HdotL:f32, roughness:f32, shadow:f32, F0:vec3f , lightColor:vec3f )-> vec3f + { + var D = D_Function(NdotH,roughness); + var G = G_Function(NdotL,NdotV,roughness); + var F = F_Function(HdotL,F0); + // var light_BRDF = saturate(( D * G * F ) / (4 * NdotL * NdotV + 0.001)); + let light_BRDF = ( D * G * F ) / (4.0 * NdotV * NdotL + 0.001); + return light_BRDF * lightColor * NdotL * PI * shadow; + } + + fn LightDiffuse_Function( HdotL:f32, NdotL:f32 , baseColor:vec3f, metallic:f32, shadow:f32, F0:vec3f, lightColor:vec3f) -> vec3f + { + var KS = F_Function(HdotL,F0); + var KD = (1 - KS) * (1 - metallic); + return KD * baseColor * lightColor.rgb * NdotL * shadow; + } + + fn lightContribution( NdotH:f32, NdotL:f32, NdotV:f32, HdotL:f32, roughness:f32, baseColor:vec3f, metallic:f32, shadow:f32, F0:vec3f, lightColor:vec3f ) ->vec3f + { + return LightDiffuse_Function(HdotL,NdotL,baseColor,metallic,shadow,F0,lightColor) + DGF_Function(NdotH,NdotL,NdotV,HdotL,roughness,shadow,F0,lightColor); + } + 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 , alpha); - let G = GeometrySmith(Context.NoV,Context.NoL, alpha ); + let alpha = roughness * roughness; + let a2 = alpha * alpha; + let F0 = mix(vec3(materialUniform.materialF0.rgb), albedo.rgb , metallic); + let D = D_GGX( Context.NoH , a2); + let G = Vis_SmithJointApprox(Context.NoV,Context.NoL, a2 ); let F = FresnelSchlick(Context.VoH, vec3(F0)); let specular = ( D * G * F ) / (4.0 * Context.NoV * Context.NoL + 0.001); @@ -241,7 +306,7 @@ export let BRDF_frag: string = /*wgsl*/ ` // diffuseColor = vec3f(0.0) ; var specularColor = specular * lightAtt; var col = (diffuseColor + specularColor ) ; - return (col.rgb) ; + return vec3f(col) ; } fn getSpecularDominantDir ( N : vec3 , R : vec3 , roughness : f32 ) -> vec3 @@ -255,12 +320,11 @@ export let BRDF_frag: string = /*wgsl*/ ` fn approximateSpecularIBL( specularColor:vec3 , roughness:f32 , R:vec3 , NoV:f32 ) -> vec3 { let MAX_REFLECTION_LOD = i32(textureNumLevels(prefilterMap)) ; - let mip = roughnessToMipmapLevel(roughness,MAX_REFLECTION_LOD); + let mip = roughnessToMipmapLevel(roughness,MAX_REFLECTION_LOD) * f32(MAX_REFLECTION_LOD); 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 fragData.EnvColor * (specularColor.rgb * envBRDF.x + saturate( 50.0 * specularColor.g ) * envBRDF.y) ; + return (specularColor.rgb * envBRDF.x + envBRDF.y) ; } fn fresnel_coat(n:vec3,v:vec3,ior:f32) -> f32 { @@ -334,7 +398,7 @@ export let BRDF_frag: string = /*wgsl*/ ` var clearcoatAlpha = factor * factor + fragData.ClearcoatRoughness; // var lightColor = getHDRColor( lightCC.rgb , light.linear ) ; - var att = light.intensity / LUMEN ; + var att = light.intensity ; let l = light.direction ; let NdotV = max(dot(n,v),0.0); @@ -362,16 +426,86 @@ export let BRDF_frag: string = /*wgsl*/ ` return GF; } + fn EnvBRDF_FD90( F0: vec3f , F90: vec3f , Roughness: f32, NoV: f32)-> vec3f + { + // Importance sampled preintegrated G * F + var AB = textureSampleLevel(brdflutMap, brdflutMapSampler, vec2f(NoV, Roughness), 0.0).rg; + var GF = F0 * AB.x + F90 * 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; } + + fn IBLEnv2( R:vec3f , Roughness : f32) -> vec3f + { + let MAX_REFLECTION_LOD = i32(textureNumLevels(reflectionMap)); + let mip = roughnessToMipmapLevel(Roughness,MAX_REFLECTION_LOD); + var envIBL: vec3 ; + // envIBL = textureSampleLevel(envMap, envMapSampler, R , mip * 12.0 ).rgb ; + envIBL = getReflectionsEnv(R,ORI_VertexVarying.vWorldPos.xyz, mip).rgb ; + envIBL = gammaToLiner(envIBL); + return envIBL; + } + + + fn F_indirect_Function( NdotV:f32, roughness:f32, F0:vec3f) -> vec3f + { + var fresnel = exp2((-5.55473 * NdotV - 6.98316) * NdotV); + return F0 + fresnel * saturate(1.0 - roughness - F0); + } + + + fn indirectionDiffuse_Function( NdotV:f32, normalDir:vec3f, metallic:f32, baseColor:vec3f, roughness:f32, occlusion:f32, F0:vec3f)-> vec3f + { + // var SHColor = SH9(normalDir,globalUniform.SH).rgb * globalUniform.skyExposure ; + var SHColor = fragData.Irradiance.rgb ; + + var KS = F_indirect_Function(NdotV,roughness,F0); + var KD = (1.0 - KS) * (1.0 - metallic); + return SHColor * KD * baseColor * occlusion; + // return SHColor ; + } + + fn indirectionSpec_Function( reflectDir:vec3f, roughness:f32, NdotV:f32,occlusion:f32, F0:vec3f )-> vec3f + { + var mipRoughness = roughness * (1.7 - 0.7 * roughness) ; + var env : vec3f ; + #if USE_CASTREFLECTION + env = textureSampleLevel(envMap, envMapSampler, reflectDir , mipRoughness * 12.0 ).rgb ; + #else + useSphereReflection(); + env = getReflectionsEnv(reflectDir,ORI_VertexVarying.vWorldPos.xyz, mipRoughness).rgb ; + #endif + + // env *= 0.45 ; + var indirectionCube: vec3 = globalUniform.skyExposure * env ; + var F_IndirectionLight = F_indirect_Function(NdotV,roughness,F0); + + var AB = LUT_Approx(roughness,NdotV); + // var AB = textureSampleLevel(brdflutMap, brdflutMapSampler, vec2f(NdotV, roughness), 0.0).rg; + var indirectionSpecFactor = indirectionCube.rgb * (F_IndirectionLight * AB.r + AB.g) ; + return indirectionSpecFactor * occlusion; + } + + const c0 = vec4f(-1, -0.0275, -0.572, 0.022 ); + const c1 = vec4f(1, 0.0425, 1.04, -0.04 ); + fn LUT_Approx( roughness:f32, NoV:f32 )->vec2f + { + // [ Lazarov 2013, "Getting More Physical in Call of Duty: Black Ops II" ] + // Adaptation to fit our G term. + var r = roughness * c0 + c1; + var a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y; + var AB = vec2f( -1.04, 1.04 ) * a004 + r.zw; + return saturate(AB); + } + ` + diff --git a/src/assets/shader/lighting/BsDF_frag.ts b/src/assets/shader/lighting/BsDF_frag.ts index 5cab6294..8bfc8027 100644 --- a/src/assets/shader/lighting/BsDF_frag.ts +++ b/src/assets/shader/lighting/BsDF_frag.ts @@ -141,7 +141,7 @@ export let BsDF_frag: string = /*wgsl*/ ` let clearCoatBaseColor = vec3(1.0) * materialUniform.baseColor.rgb ; let clearNormal = fragData.N ; let clearcoatRoughness = fragData.ClearcoatRoughness ; - let att = sunLight.intensity / LUMEN ; + let att = sunLight.intensity ; 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 diff --git a/src/assets/shader/lighting/BxDF_frag.ts b/src/assets/shader/lighting/BxDF_frag.ts index 274b0a74..12531cd5 100644 --- a/src/assets/shader/lighting/BxDF_frag.ts +++ b/src/assets/shader/lighting/BxDF_frag.ts @@ -1,10 +1,13 @@ +import { SHCommon_frag } from './../core/common/SHCommon_frag'; export let BxDF_frag: string = /*wgsl*/ ` #include "Clearcoat_frag" #include "BRDF_frag" #include "MathShader" #include "FastMathShader" + #include "BitUtil" #include "Common_frag" #include "GlobalUniform" + #include "SHCommon_frag" #include "PhysicMaterialUniform_frag" #include "NormalMap_frag" @@ -12,16 +15,16 @@ export let BxDF_frag: string = /*wgsl*/ ` #include "Irradiance_frag" #include "ColorUtil_frag" #include "BxdfDebug_frag" - - + #include "ReflectionCG" //ORI_ShadingInput fn initFragData() { - fragData.Albedo = ORI_ShadingInput.BaseColor ; + // fragData.Albedo = vec4f(gammaToLiner(ORI_ShadingInput.BaseColor.rgb),ORI_ShadingInput.BaseColor.w) ; + fragData.Albedo = vec4f((ORI_ShadingInput.BaseColor.rgb),ORI_ShadingInput.BaseColor.w) ; fragData.Ao = clamp( pow(ORI_ShadingInput.AmbientOcclusion,materialUniform.ao) , 0.0 , 1.0 ) ; - fragData.Roughness = clamp((ORI_ShadingInput.Roughness),0.003,1.0) ; + fragData.Roughness = clamp((ORI_ShadingInput.Roughness),0.0001,1.0) * 1.85 ; fragData.Metallic = ORI_ShadingInput.Metallic ; - fragData.Emissive = ORI_ShadingInput.EmissiveColor.rgb ; + fragData.Emissive = gammaToLiner(ORI_ShadingInput.EmissiveColor.rgb) * materialUniform.emissiveIntensity ; fragData.N = ORI_ShadingInput.Normal; let viewDir = normalize(globalUniform.CameraPos.xyz - ORI_VertexVarying.vWorldPos.xyz) ; fragData.V = viewDir ; @@ -35,7 +38,8 @@ export let BxDF_frag: string = /*wgsl*/ ` fragData.NoV = saturate(dot(fragData.N, fragData.V)) ; - fragData.F0 = mix(vec3(materialUniform.specularColor.rgb), fragData.Albedo.rgb, fragData.Metallic); + fragData.F0 = mix(vec3(0.04), fragData.Albedo.rgb , fragData.Metallic); + // fragData.F0 = gammaToLiner(fragData.F0); fragData.F = computeFresnelSchlick(fragData.NoV, fragData.F0); fragData.KD = vec3(fragData.F) ; @@ -45,26 +49,51 @@ export let BxDF_frag: string = /*wgsl*/ ` fragData.Reflectance = 1.0 ; fragData.ClearcoatRoughness = materialUniform.clearcoatRoughnessFactor ; + fragData.ClearcoatIor = materialUniform.clearcoatIor ; + fragData.ClearcoatFactor = materialUniform.clearcoatFactor; + #if USE_CLEARCOAT_ROUGHNESS - fragData.ClearcoatRoughness = getClearcoatRoughness() * materialUniform.clearcoatRoughnessFactor; + fragData.ClearcoatRoughness *= getClearcoatRoughness() ; + fragData.ClearcoatFactor *= getClearcoatWeight() ; #endif } fn BxDFShading(){ initFragData(); + let sunLight = lightBuffer[0] ; + 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 = LinearToGammaSpace(irradiance.rgb); + #if USE_CASTREFLECTION + irradiance += globalUniform.hdrExposure * (globalUniform.skyExposure * textureSampleLevel(prefilterMap, prefilterMapSampler, fragData.N.xyz, 0.8 * (MAX_REFLECTION_LOD) ).rgb); + #else + useSphereReflection(); + irradiance = getReflectionsEnv(fragData.N,ORI_VertexVarying.vWorldPos.xyz,1.0) ; + #endif + #endif fragData.Irradiance = irradiance.rgb ; + //***********lighting-PBR part********* + var F = FresnelSchlickRoughness(fragData.NoV, fragData.Albedo.rgb , fragData.Roughness); + var kS = F; + var kD = vec3(1.0) - kS; + kD = kD * (1.0 - fragData.Metallic); + //***********lighting-PBR part********* + + //***********indirect-specular part********* + var surReduction = 1.0/(fragData.Roughness * fragData.Roughness + 1.0); + var grazingTerm = saturate(1.0 - fragData.Roughness + kD); + var surfaceReduction = 1.0 / (pow(fragData.Roughness,2.0) + 1.0); + var fresnelLerp = FresnelLerp(fragData.NoV,fragData.F0.rgb,vec3(grazingTerm)) ; + var iblSpecularResult = fresnelLerp * surReduction ; + //***********indirect-specular part********* //***********lighting-PBR part********* + var diffuseColor = mix(fragData.Albedo.rgb,vec3f(0.04),fragData.Metallic); var specColor = vec3(0.0) ; let lightIndex = getCluster(); let start = max(lightIndex.start, 0.0); @@ -75,15 +104,16 @@ export let BxDF_frag: string = /*wgsl*/ ` 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) ; + specColor += pointLighting(ORI_VertexVarying.vWorldPos.xyz, light ,iblSpecularResult) ; break; } case DirectLightType: { - specColor += directLighting( fragData.Albedo.rgb ,fragData.N,fragData.V,fragData.Roughness ,fragData.Metallic, light , globalUniform.shadowBias) ; + specColor += directLighting(light,iblSpecularResult); + // specColor = iblSpecularResult; break; } case SpotLightType: { - specColor += spotLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic , light ) ; + specColor += spotLighting( ORI_VertexVarying.vWorldPos.xyz, light ,iblSpecularResult) ; break; } default: { @@ -92,66 +122,87 @@ export let BxDF_frag: string = /*wgsl*/ ` } } - 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 - 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********* - 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; - 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); - // ORI_FragmentOutput.worldPos = vec4(0.0,0.0,1.0,1.0); + // var kdLast = (1.0 - 0.04) * (1.0 - fragData.Metallic); + var iblDiffuseResult : vec3f ; + + let MAX_LOD = i32(textureNumLevels(prefilterMap)) ; + let mip = roughnessToMipmapLevel(fragData.Roughness,MAX_LOD) * f32(MAX_LOD) * 0.5; + + var indirectionDiffuse = indirectionDiffuse_Function(fragData.NoV,fragData.N,fragData.Metallic,fragData.Albedo.rgb,fragData.Roughness,fragData.Ao,fragData.F0); + iblDiffuseResult += indirectionDiffuse / 3.14; + + var indirectionSpec = indirectionSpec_Function(fragData.R,fragData.Roughness,fragData.NoV,fragData.Ao,gammaToLiner(fragData.F0)); + #if USE_CASTREFLECTION + indirectionSpec *= globalUniform.hdrExposure ; #endif - - var color = specColor + indirectResult ; + + var color = vec3f(iblDiffuseResult + indirectionSpec + specColor) ; + // var color = vec3f(indirectionDiffuse ) ; 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) ; + + for(var i:i32 = i32(start) ; i < i32(end); i += 1 ) + { + let light = getLight(i32(i)); + switch (light.lightType) { + case PointLightType: { + var lightColor = light.lightColor.rgb ; + var att = pointAtt(ORI_VertexVarying.vWorldPos.xyz, light); + clearCoatColor += ClearCoat_BRDF( color , materialUniform.clearcoatColor.rgb , fragData.ClearcoatIor , clearNormal , light.direction , fragData.V , clearcoatRoughness , lightColor, att ); + break; + } + case DirectLightType: { + var lightColor = getHDRColor( light.lightColor.rgb , light.linear ) ; + var att = max(0.0,light.intensity); + clearCoatColor += ClearCoat_BRDF( color , materialUniform.clearcoatColor.rgb , fragData.ClearcoatIor , clearNormal , light.direction , fragData.V , clearcoatRoughness , lightColor, att ); + break; + } + case SpotLightType: { + // var lightColor = light.lightColor.rgb ; + // var att = pointAtt(ORI_VertexVarying.vWorldPos.xyz, light); + // clearCoatColor += ClearCoat_BRDF( color , materialUniform.clearcoatColor.rgb , 1.5 , clearNormal , light.direction , fragData.V , clearcoatRoughness , lightColor, att ); + break; + } + default: { + break; + } + } + } + + color = clearCoatColor ; #endif - var retColor = (LinearToGammaSpace(color.rgb)); - retColor += fragData.Emissive.xyz ; - ORI_FragmentOutput.color = vec4( retColor.rgb * fragData.Albedo.a ,fragData.Albedo.a) ; + var retColor = (LinearToGammaSpace(color.rgb)); + retColor += fragData.Emissive.xyz ; + + var viewColor = vec4( retColor.rgb * fragData.Albedo.w, fragData.Albedo.a) ; + + let finalMatrix = globalUniform.projMat * globalUniform.viewMat ; + let nMat = mat3x3(finalMatrix[0].xyz,finalMatrix[1].xyz,finalMatrix[2].xyz) ; + let ORI_NORMALMATRIX = transpose(inverse( nMat )); + + var vNormal = ORI_VertexVarying.vWorldNormal.rgb ; + + let gBuffer = packNHMDGBuffer( + ORI_VertexVarying.fragCoord.z, + fragData.Albedo.rgb, + viewColor.rgb, + vec3f(fragData.Roughness,fragData.Metallic,fragData.Ao), + vNormal, + fragData.Albedo.a + ) ; + + #if USE_CASTREFLECTION + ORI_FragmentOutput.gBuffer = gBuffer ; + #else + ORI_FragmentOutput.gBuffer = gBuffer ; + ORI_FragmentOutput.color = viewColor ; + #endif } ` diff --git a/src/assets/shader/lighting/Hair_frag.ts b/src/assets/shader/lighting/Hair_frag.ts index 42b116d5..e58878eb 100644 --- a/src/assets/shader/lighting/Hair_frag.ts +++ b/src/assets/shader/lighting/Hair_frag.ts @@ -228,7 +228,7 @@ export let Hair_frag: string = /*wgsl*/ ` 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) ; + return 2.0 * PI *vec3f(S) * (lightAtt ) ; } fn BSSSRDFShading(){ @@ -265,13 +265,6 @@ export let Hair_frag: string = /*wgsl*/ ` 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: { diff --git a/src/assets/shader/lighting/LightingFunction_frag.ts b/src/assets/shader/lighting/LightingFunction_frag.ts index e1eb44dd..4d516b50 100644 --- a/src/assets/shader/lighting/LightingFunction_frag.ts +++ b/src/assets/shader/lighting/LightingFunction_frag.ts @@ -9,39 +9,44 @@ export let LightingFunction_frag: string = /*wgsl*/ ` -const LUMEN = 10.764; - - - -fn calcAttenuation( d : f32 , falloffStart : f32 , falloffEnd : f32)-> f32 -{ - // Linear falloff. - return saturate((falloffEnd-d) / (falloffEnd - falloffStart)); +const PI2 = 3.1415926 * 3.1415926 ; + +fn sampleLighting(light:LightData,direction:vec3f,iblSpecularResult:vec3f , intensity :f32 , shadow:f32 ) -> vec3f{ + var ret = vec3f(0.0); + var normalDir = fragData.N; + var viewDir = fragData.V; + + var lightDir = normalize(-direction.xyz); + var halfDir = normalize(lightDir + viewDir); + var reflectDir = normalize(reflect(-viewDir,normalDir)); + + var NdotH = max(0.00001,dot(normalDir,halfDir)); + var NdotL = max(0.00001,dot(normalDir,lightDir)); + var NdotV = max(0.00001,dot(normalDir,viewDir)); + var HdotL = max(0.00001,dot(halfDir,lightDir)); + + var baseColor = fragData.Albedo.rgb ; + var metallic = fragData.Metallic ; + var roughness = fragData.Roughness ; + + var lightColor = getHDRColor( light.lightColor.rgb , light.linear ) ; + var att = max(0.0,intensity); + + var lighting:vec3f = lightContribution(NdotH,NdotL,NdotV,HdotL,fragData.Roughness,fragData.Albedo.rgb / 3.14, metallic ,shadow,fragData.F0,lightColor.rgb); + // lighting = fragData.F0 / 3.1415926 * NdotL ; + lighting = ACESToneMapping(lighting,att); + // ret += lighting ; + return lighting ; } -fn directLighting( albedo:vec3, N:vec3, V:vec3, roughness:f32 , metallic:f32 , light:LightData , shadowBias:f32 ) -> vec3 { +fn directLighting( light:LightData , iblSpecularResult : vec3f) -> 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 - + var L = normalize(light.direction.xyz) ; #if USE_BRDF - color = simpleBRDF(albedo,N,V,L,att,lightColor,roughness,metallic) ; + var shadow = directShadowVisibility[(light.castShadow)] ; + var att = light.intensity; + color = sampleLighting(light,L,iblSpecularResult,att, shadow); #endif #endif return color; @@ -53,12 +58,12 @@ fn directDulLighting( albedo:vec3, N:vec3, V:vec3, roughness:f32 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 ; + var att = light.intensity; if(light.castShadow>=0){ #if USE_SHADOWMAPING for (var j: i32 = 0; j < 8; j += 1) { if(j == light.castShadow){ - att *= shadowStrut.directShadowVisibility[j] ; + att *= directShadowVisibility[j] ; } } #endif @@ -81,12 +86,12 @@ fn directHairLighting( albedo:vec3, N:vec3, V:vec3, roughness:f3 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 ; + var att = light.intensity; if(light.castShadow>=0){ #if USE_SHADOWMAPING for (var j: i32 = 0; j < 8; j += 1) { if(j == light.castShadow){ - att *= shadowStrut.directShadowVisibility[j] ; + att *= directShadowVisibility[j] ; } } #endif @@ -104,7 +109,7 @@ fn directHairLighting( albedo:vec3, N:vec3, V:vec3, roughness:f3 } -fn pointLighting( albedo:vec3,WP:vec3, N:vec3, V:vec3, roughness:f32 , metallic:f32 ,light:LightData ) -> vec3 { +fn pointLighting( WP:vec3, light:LightData , iblSpecularResult : vec3f ) -> vec3 { var color = vec3(0.0) ; let lightPos = light.position.xyz; var dir = lightPos.xyz - WP ; @@ -116,48 +121,65 @@ fn pointLighting( albedo:vec3,WP:vec3, N:vec3, V:vec3, rough var L = dir ; var atten = 1.0 ; atten = 1.0 - smoothstep(0.0,light.range,dist) ; - atten *= 1.0 / max(light.radius,0.001) * light.intensity / LUMEN; - if( light.castShadow >= 0 ) - { - #if USE_SHADOWMAPING - // atten *= shadowStrut.pointShadows[light.castShadow] ; - for (var j: i32 = 0; j < 8; j += 1) { - if(j == light.castShadow){ - atten *= shadowStrut.pointShadows[j] ; - } - } - #endif - } + atten *= 1.0 / max(light.radius,0.001) ; + + // if( light.castShadow >= 0 ) + // { + // #if USE_SHADOWMAPING + // for (var j: i32 = 0; j < 8; j += 1) { + // if(j == light.castShadow){ + // atten *= pointShadows[j] ; + // } + // } + // #endif + // } + + var shadow = pointShadows[i32(light.castShadow)] ; #if USE_IES_PROFILE - atten *= getLightIESProfileAtt(WP,light); + atten *= getLightIESProfileAtt(WP,light); #endif - var lightColor = light.lightColor.rgb ; - lightColor = getHDRColor(lightColor , light.linear ) ; - - #if USE_LAMBERT - color = vec3(1.0,1.0,1.0) ; - #endif + atten *= sphere_unit(light.range,light.intensity) ; - #if USE_BRDF - color = (simpleBRDF(albedo,N,V,L,atten,lightColor,roughness,metallic)) ; - #endif + color = sampleLighting(light,-L,iblSpecularResult,atten,shadow); } return color ; } +fn pointAtt( WP:vec3, light:LightData ) -> f32 { + var atten = 0.0 ; + let lightPos = light.position.xyz; + var dir = lightPos.xyz - WP ; + let dist = length(dir); + if(dist != 0.0){ + dir *= 1.0 / dist ; + } + if( abs(dist) < light.range ){ + var L = dir ; + atten = 1.0 - smoothstep(0.0,light.range,dist) ; + atten *= 1.0 / max(light.radius,0.001) ; + var shadow = pointShadows[i32(light.castShadow)] ; + #if USE_IES_PROFILE + atten *= getLightIESProfileAtt(WP,light); + #endif + atten *= sphere_unit(light.range,light.intensity) ; + } + return atten ; +} + fn getDistanceAtten( light:LightData , dist : f32 ) -> f32 { return 1.0 - smoothstep(0.0,light.range,dist) ; } -fn spotLighting( albedo:vec3,WP:vec3, N:vec3, V:vec3, roughness:f32 , metallic:f32 ,light:LightData ) -> vec3 { +fn spotLighting( WP:vec3, light:LightData , iblSpecularResult : vec3f) -> vec3 { let lightPos = light.position.xyz; var dir = lightPos.xyz - WP ; let dist = length(dir) ; if(dist != 0.0){ dir *= 1.0 / dist ; } + var color = vec3(0.0) ; if( abs(dist) < light.range * 2.0 ){ var L = dir ; @@ -167,7 +189,7 @@ fn spotLighting( albedo:vec3,WP:vec3, N:vec3, V:vec3, roughn var lightColor = light.lightColor.rgb ; atten = 1.0 - smoothstep(0.0,light.range,dist) ; - atten *= 1.0 / max(light.radius,0.1) * light.intensity / LUMEN; + atten *= 1.0 / max(light.radius,0.001) ; if(angle < light.outerCutOff){ if(angle > light.innerCutOff){ atten *= 1.0 - smoothstep(light.innerCutOff, light.outerCutOff, angle) ; @@ -176,31 +198,20 @@ fn spotLighting( albedo:vec3,WP:vec3, N:vec3, V:vec3, roughn atten = 0.0 ; } - if( light.castShadow >= 0 ) - { - #if USE_SHADOWMAPING - for (var j: i32 = 0; j < 8; j += 1) { - if(j == light.castShadow){ - atten *= shadowStrut.pointShadows[j] ; - } - } - #endif - } + var shadow = pointShadows[i32(light.castShadow)] ; #if USE_IES_PROFILE atten *= getLightIESProfileAtt(WP,light); #endif - lightColor = getHDRColor(lightColor , light.linear ) ; - - #if USE_LAMBERT - color = vec3(1.0,0.5,1.0) ; - #endif + atten *= sphere_unit(light.range, light.intensity) ; - #if USE_BRDF - color = (simpleBRDF(albedo,N,V,L,atten,lightColor,roughness,metallic)) ; - #endif + color = sampleLighting(light,-L,iblSpecularResult,atten,shadow); } return color ; } + +fn sphere_unit( radius:f32 , intensity:f32 ) -> f32 { + return intensity / (4.0 * PI2 * radius * radius) ; +} ` diff --git a/src/assets/shader/lighting/UnLit_frag.ts b/src/assets/shader/lighting/UnLit_frag.ts index 64969678..53f330f5 100644 --- a/src/assets/shader/lighting/UnLit_frag.ts +++ b/src/assets/shader/lighting/UnLit_frag.ts @@ -4,18 +4,27 @@ export let UnLit_frag: string = /*wgsl*/ ` fn UnLit(){ let alpha = ORI_ShadingInput.BaseColor.a ; - ORI_FragmentOutput.color = vec4(ORI_ShadingInput.BaseColor.rgb * alpha , alpha) ; - - #if USE_WORLDPOS - ORI_FragmentOutput.worldPos = vec4(ORI_VertexVarying.vWorldPos.xyzw); - #endif - - #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,1.0,0.0,1.0); - #endif + var viewColor = vec4(ORI_ShadingInput.BaseColor.rgb * alpha , alpha) ; + let finalMatrix = globalUniform.projMat * globalUniform.viewMat ; + let nMat = mat3x3(finalMatrix[0].xyz,finalMatrix[1].xyz,finalMatrix[2].xyz) ; + let ORI_NORMALMATRIX = transpose(inverse( nMat )); + var vNormal = normalize(ORI_NORMALMATRIX * (ORI_VertexVarying.vWorldNormal )); + let gBuffer = packNHMDGBuffer( + ORI_VertexVarying.fragCoord.z, + vec3f(0.0), + viewColor.rgb, + // vec3f(0.5), + vec3f(1.0,0.0,0.0), + vNormal, + alpha + ) ; + + #if USE_CASTREFLECTION + ORI_FragmentOutput.gBuffer = gBuffer ; + #else + ORI_FragmentOutput.gBuffer = gBuffer ; + ORI_FragmentOutput.color = viewColor ; + #endif } fn debugFragmentOut(){ diff --git a/src/assets/shader/materials/PBRLItShader.ts b/src/assets/shader/materials/PBRLItShader.ts index f553f995..6fc2cc35 100644 --- a/src/assets/shader/materials/PBRLItShader.ts +++ b/src/assets/shader/materials/PBRLItShader.ts @@ -47,21 +47,23 @@ export let PBRLItShader: string = /*wgsl*/ ` } fn frag(){ - var transformUV1 = materialUniform.transformUV1; - var transformUV2 = materialUniform.transformUV2; - - var uv = transformUV1.zw * ORI_VertexVarying.fragUV0 + transformUV1.xy; + + let baseMapOffsetSize = materialUniform.baseMapOffsetSize; + var uv = transformUV(ORI_VertexVarying.fragUV0,baseMapOffsetSize) ; #if USE_SRGB_ALBEDO ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; - ORI_ShadingInput.BaseColor = gammaToLiner(ORI_ShadingInput.BaseColor.rgb) ; + // ORI_ShadingInput.BaseColor = sRGBToLinear(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) ; + ORI_ShadingInput.BaseColor = vec4f(gammaToLiner(ORI_ShadingInput.BaseColor.rgb),ORI_ShadingInput.BaseColor.a) ; + ORI_ShadingInput.BaseColor *= vec4f(materialUniform.baseColor.rgba) ; #endif - var maskTex = textureSample(maskMap, maskMapSampler, uv ) ; + let roughnessMapOffsetSize = materialUniform.roughnessMapOffsetSize; + var uv4 = transformUV(ORI_VertexVarying.fragUV0,roughnessMapOffsetSize); + var maskTex = textureSample(maskMap, maskMapSampler, uv4 ); #if USE_ALPHA_A ORI_ShadingInput.BaseColor.a = ORI_ShadingInput.BaseColor.a * (maskTex.a) ; @@ -118,7 +120,9 @@ export let PBRLItShader: string = /*wgsl*/ ` var aoChannel:f32 = 1.0 ; #if USE_AOTEX - var aoMap = textureSample(aoMap, aoMapSampler, uv ); + let aoMapOffsetSize = materialUniform.aoMapOffsetSize; + var aoMapOffsetSizeUV = transformUV(ORI_VertexVarying.fragUV0,aoMapOffsetSize); + var aoMap = textureSample(aoMap, aoMapSampler, ORI_VertexVarying.fragUV0 ); aoChannel = aoMap.g ; #else #if USE_AO_A @@ -135,8 +139,10 @@ export let PBRLItShader: string = /*wgsl*/ ` ORI_ShadingInput.AmbientOcclusion = aoChannel ; ORI_ShadingInput.Specular = 1.0 ; + let emissiveMapOffsetSize = materialUniform.emissiveMapOffsetSize; + var emissiveUV = transformUV(ORI_VertexVarying.fragUV0,emissiveMapOffsetSize) ; #if USE_EMISSIVEMAP - var emissiveMapColor = textureSample(emissiveMap, emissiveMapSampler , ORI_VertexVarying.fragUV0.xy) ; + var emissiveMapColor = textureSample(emissiveMap, emissiveMapSampler , emissiveUV ) ; let emissiveColor = materialUniform.emissiveColor.rgb * emissiveMapColor.rgb * materialUniform.emissiveIntensity ; ORI_ShadingInput.EmissiveColor = vec4(emissiveColor.rgb,1.0); #else @@ -144,11 +150,12 @@ export let PBRLItShader: string = /*wgsl*/ ` ORI_ShadingInput.EmissiveColor = vec4(emissiveColor,1.0); #endif - - var Normal = textureSample(normalMap,normalMapSampler,uv).rgb ; + let normalMapOffsetSize = materialUniform.normalMapOffsetSize; + var nomralUV = transformUV(ORI_VertexVarying.fragUV0,normalMapOffsetSize) ; + var Normal = textureSample(normalMap,normalMapSampler,nomralUV).rgb ; 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 index 900b4134..6c08d7df 100644 --- a/src/assets/shader/materials/PBRLitSSSShader.ts +++ b/src/assets/shader/materials/PBRLitSSSShader.ts @@ -199,7 +199,7 @@ export let PBRLitSSSShader: string = /*wgsl*/ ` var sssColor = vec3f(pow(textureSample(sssMap, sssMapSampler, uv ).r,materialUniform.skinPower)) * materialUniform.skinColor.rgb ; let sunLight = lightBuffer[0] ; - let sunLightIntensity = (sunLight.intensity / LUMEN) ; + let sunLightIntensity = (sunLight.intensity ) ; 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 ) ; diff --git a/src/assets/shader/materials/ReflectionShader_shader.ts b/src/assets/shader/materials/ReflectionShader_shader.ts new file mode 100644 index 00000000..47fe593d --- /dev/null +++ b/src/assets/shader/materials/ReflectionShader_shader.ts @@ -0,0 +1,70 @@ +export let ReflectionShader_shader: string = /*wgsl*/ ` + #include "Common_vert" + #include "Common_frag" + #include "GlobalUniform" + #include "BitUtil" + #include "MathShader" + #include "ReflectionCG" + #include "ColorUtil_frag" + + struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, + baseColor: vec4, + alphaCutoff: f32, + reflectionIndex : f32, + }; + + // @group(1) @binding(0) + // var baseMapSampler: sampler; + // @group(1) @binding(1) + // var baseMap: texture_2d; + @group(2) @binding(0) + var materialUniform: MaterialUniform; + + fn vert(inputData:VertexAttributes) -> VertexOutput { + ORI_Vert(inputData) ; + return ORI_VertexOut ; + } + + fn frag(){ + var transformUV1 = materialUniform.transformUV1; + var transformUV2 = materialUniform.transformUV2; + + useSphereReflection(); + var finalColor : vec3f ; + let scale = vec2f(1.0/8.0,1.0/globalUniform.reflectionProbeMaxCount) ; + var uv = (octEncode(-ORI_VertexVarying.vWorldNormal) + 1.0) * 0.5 ; + var uv1 = uv * scale + vec2f(0.0,(materialUniform.reflectionIndex * scale.y )) ; + let gBuffer = textureSampleLevel(reflectionMap,reflectionMapSampler,uv1,0.0); + ORI_ShadingInput.BaseColor = vec4f(gBuffer.rgb,1.0) ; + UnLit(); + } + + fn UnLit(){ + var viewColor = ORI_ShadingInput.BaseColor ; + let finalMatrix = globalUniform.projMat * globalUniform.viewMat ; + let nMat = mat3x3(finalMatrix[0].xyz,finalMatrix[1].xyz,finalMatrix[2].xyz) ; + let ORI_NORMALMATRIX = transpose(inverse( nMat )); + + var vNormal = normalize(ORI_NORMALMATRIX * (ORI_VertexVarying.vWorldNormal )); + var worldNormal = vec3( (vNormal.xyz + 1.0) * 0.5); + + let gBuffer = packNHMDGBuffer( + ORI_VertexVarying.fragCoord.z, + vec3f(0.0), + viewColor.rgb, + vec3f(0.0), + vNormal, + viewColor.a + ); + + #if USE_CASTREFLECTION + ORI_FragmentOutput.gBuffer = gBuffer ; + #else + ORI_FragmentOutput.color = viewColor ; + ORI_FragmentOutput.gBuffer = gBuffer ; + #endif + } +` + diff --git a/src/assets/shader/materials/UnLit.ts b/src/assets/shader/materials/UnLit.ts index 52a4ea89..77ef33af 100644 --- a/src/assets/shader/materials/UnLit.ts +++ b/src/assets/shader/materials/UnLit.ts @@ -34,10 +34,7 @@ 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/program/BxdfDebug_frag.ts b/src/assets/shader/materials/program/BxdfDebug_frag.ts index 3b94deed..9c6271b8 100644 --- a/src/assets/shader/materials/program/BxdfDebug_frag.ts +++ b/src/assets/shader/materials/program/BxdfDebug_frag.ts @@ -2,62 +2,61 @@ export let BxdfDebug_frag: string = /*wgsl*/ ` #include "ClusterDebug_frag" fn debugPosition(){ - ORI_FragmentOutput.color = vec4(ORI_VertexVarying.vWorldPos.xyz,1.0); + //ORI_FragmentOutput.color = vec4(ORI_VertexVarying.vWorldPos.xyz,1.0); } fn debugMeshID(){ let meshIDColor = u32(round(ORI_VertexVarying.vWorldPos.w) ) ; let color = colorSet[ meshIDColor % 9u] ; - ORI_FragmentOutput.color = vec4(vec3(color.rgb),1.0); + // ORI_FragmentOutput.color = vec4(vec3(color.rgb),1.0); } fn debugNormal(){ - ORI_FragmentOutput.color = vec4(ORI_ShadingInput.Normal.xyz,1.0); + // ORI_FragmentOutput.color = vec4(ORI_ShadingInput.Normal.xyz,1.0); } fn debugUV(){ - ORI_FragmentOutput.color = vec4(ORI_VertexVarying.fragUV0.xy,0.0,1.0); + // ORI_FragmentOutput.color = vec4(ORI_VertexVarying.fragUV0.xy,0.0,1.0); } fn debugColor(){ - ORI_FragmentOutput.color = vec4(fragData.Albedo.rgb,1.0); + // ORI_FragmentOutput.color = vec4(fragData.Albedo.rgb,1.0); } fn debugDiffuse(){ - ORI_FragmentOutput.color = vec4( fragData.LightChannel.rgb,1.0); - // ORI_FragmentOutput.color = vec4(0.2,0.2,0.2,1.0); + // ORI_FragmentOutput.color = vec4( fragData.LightChannel.rgb,1.0); } fn debugAmbient(){ - ORI_FragmentOutput.color = vec4(vec3f(fragData.Alpha) ,1.0); + // ORI_FragmentOutput.color = vec4(vec3f(fragData.Alpha) ,1.0); } fn debugEmissive(){ - ORI_FragmentOutput.color = vec4(fragData.Emissive.rgb,1.0); + // ORI_FragmentOutput.color = vec4(fragData.Emissive.rgb,1.0); } fn debugEnvment(){ - ORI_FragmentOutput.color = vec4(fragData.EnvColor.rgb,1.0); + // ORI_FragmentOutput.color = vec4(fragData.EnvColor.rgb,1.0); } fn debugAo(){ - ORI_FragmentOutput.color = vec4(vec3(fragData.Ao),1.0); + // ORI_FragmentOutput.color = vec4(vec3(fragData.Ao),1.0); } fn debugRoughness(){ - ORI_FragmentOutput.color = vec4(vec3(fragData.Roughness),1.0); + // ORI_FragmentOutput.color = vec4(vec3(fragData.Roughness),1.0); } fn debugMetallic(){ - ORI_FragmentOutput.color = vec4(vec3(fragData.Metallic),1.0); + // ORI_FragmentOutput.color = vec4(vec3(fragData.Metallic),1.0); } fn debugIrradiance(){ - ORI_FragmentOutput.color = vec4(vec3(fragData.Irradiance),1.0); + // ORI_FragmentOutput.color = vec4(vec3(fragData.Irradiance),1.0); } fn debugTangent(){ - ORI_FragmentOutput.color = vec4(vec3(fragData.T),1.0); + // ORI_FragmentOutput.color = vec4(vec3(fragData.T),1.0); } fn debugFragmentOut(){ diff --git a/src/assets/shader/materials/program/Clearcoat_frag.ts b/src/assets/shader/materials/program/Clearcoat_frag.ts index f3f587cc..8a6ae755 100644 --- a/src/assets/shader/materials/program/Clearcoat_frag.ts +++ b/src/assets/shader/materials/program/Clearcoat_frag.ts @@ -10,41 +10,56 @@ export let Clearcoat_frag: string = /*wgsl*/ ` var clearCoatRoughnessMap: texture_2d; fn getClearcoatRoughness() -> f32{ - let clearcoatRoughness = textureSample(clearCoatRoughnessMap, clearCoatRoughnessMapSampler, ORI_VertexVarying.fragUV0.xy).r; + let clearcoatRoughness = textureSample(clearCoatRoughnessMap, clearCoatRoughnessMapSampler, ORI_VertexVarying.fragUV0.xy).g; return clearcoatRoughness; } + + fn getClearcoatWeight() -> f32{ + let clearcoatWeight = textureSample(clearCoatRoughnessMap, clearCoatRoughnessMapSampler, ORI_VertexVarying.fragUV0.xy).r; + return clearcoatWeight; + } #else fn getClearcoatRoughness() -> f32{ return 1.0; } + fn getClearcoatWeight() -> f32{ + return 1.0; + } #endif #if USE_CLEARCOAT - fn ClearCoat_BRDF( baseColor:vec3, clearCoatColor:vec3 , ior:f32 ,N:vec3, L:vec3 , V:vec3 , clearCoatStrength:f32, clearCoatPerceptualRoughness:f32 , att:f32) -> vec3 { + fn ClearCoat_BRDF( baseColor:vec3, clearCoatColor:vec3 , clearCoatIor:f32 ,N:vec3, L:vec3 , V:vec3 , clearCoatPerceptualRoughness:f32 ,lightColor:vec3f, att:f32) -> vec3 { var factor = clamp(clearCoatPerceptualRoughness, 0.0001, 1.0); - var clearCoatRoughness = factor * factor; - - let H = normalize(-V + L); - let R = 2.0 * dot( -V , N ) * N + V ; - let LoH = dot(L,H); - let NoV = max(dot(N,-V),0.0); - let NoL = max(dot(N,L),0.0); - let NoH = max(dot(N,H),0.00001); - - let Fr = FresnelSchlickRoughness( NoV , vec3(0.0) , clearCoatRoughness ) ; - var Fd = clearCoatColor / 3.1415926 ; - let F0 = IORToF0(ior) ; + var clearCoatRoughness = factor ; + let lightDir = -L ; + let H = normalize( V + lightDir); + // let LoH = dot(lightDir,H); + let NoV = max(dot(N,V),0.00001); + // let NoL = max(dot(N,lightDir),0.00001); + // let NoH = max(dot(N,H),0.00001); + + // let clearSpeclur = IBLEnv2(fragData.R,clearCoatRoughness); + // let F0 = IORToF0(clearCoatIor); + // let Fr = FresnelSchlickRoughness( NoV , vec3(clearCoatColor) , clearCoatRoughness ) ; + // var Fd = clearCoatColor ; // clear coat BRDF - var Dc = D_GGX(NoH,clearCoatRoughness); - var Vc = V_Kelemen(LoH) * NoL; - var Fc = F_Schlick( vec3(F0) , 1.0, NoV) * materialUniform.clearcoatFactor; - var Frc = (Dc * Vc) * Fc; + // var Dc = D_GGX(NoH,clearCoatRoughness); + // var Vc = V_Kelemen(LoH) * NoL; + // var Fc = F_Schlick2( vec3(F0) , NoV) ; + // var Frc = (Dc * Vc) * Fc; // base layer attenuation for energy compensation - let oneMinusFc = 1.0 - Fc; - let brdfSpecular = ((Fd + Fr * oneMinusFc) * oneMinusFc + Frc) * att ; - var iblSpecular = vec3(brdfSpecular); - iblSpecular += approximateSpecularIBL(vec3(1.0),clearCoatRoughness,R, NoV) * Fc ; - return vec3(mix(baseColor,iblSpecular,materialUniform.clearcoatWeight)); + // let oneMinusFc = 1.0 - Fc; + + // let brdfSpecular = clearSpeclur * ((Fd + Fr * oneMinusFc) * oneMinusFc + Frc) * att * lightColor; + var iblSpecular = vec3(0.0); + // return brdfSpecular ; + + iblSpecular = indirectionSpec_Function(fragData.R,clearCoatRoughness,NoV,1.0,(clearCoatColor * att * vec3f(IORToF0(clearCoatIor)))); + // iblSpecular = IBLEnv2(fragData.R,clearCoatRoughness); + // return mix(baseColor , brdfSpecular + iblSpecular ,fragData.ClearcoatFactor) ; + // return vec3f(baseColor + (clearCoatColor * iblSpecular) * fragData.ClearcoatFactor) ; + return mix(baseColor , (clearCoatColor * iblSpecular) , fragData.ClearcoatFactor) ; + // return iblSpecular ; } #endif ` \ No newline at end of file diff --git a/src/assets/shader/materials/program/ClusterDebug_frag.ts b/src/assets/shader/materials/program/ClusterDebug_frag.ts index e744991a..77d62ad3 100644 --- a/src/assets/shader/materials/program/ClusterDebug_frag.ts +++ b/src/assets/shader/materials/program/ClusterDebug_frag.ts @@ -17,7 +17,7 @@ export let ClusterDebug_frag: string = /*wgsl*/` #if USE_LIGHT var tileID : u32 = getClusterId3().z; let clusterDebug = vec4(colorSet[tileID % 9u], 1.0); - ORI_FragmentOutput.color = clusterDebug ; + // ORI_FragmentOutput.color = clusterDebug ; #endif } @@ -27,10 +27,10 @@ export let ClusterDebug_frag: string = /*wgsl*/` let px = f32(clusterId3.x) / clustersUniform.clusterTileX ; let py = f32(clusterId3.y) / clustersUniform.clusterTileY ; let pz = f32(clusterId3.z) / clustersUniform.clusterTileZ ; - ORI_FragmentOutput.color = vec4(px,py,pz, 1.0); + // ORI_FragmentOutput.color = vec4(px,py,pz, 1.0); var screenUV = ORI_VertexVarying.fragCoord.xy / vec2( globalUniform.windowWidth , globalUniform.windowHeight ); - ORI_FragmentOutput.color = vec4(screenUV.x,screenUV.y,0.0, 1.0); + // ORI_FragmentOutput.color = vec4(screenUV.x,screenUV.y,0.0, 1.0); // let clusterId : u32 = getClusterIndex(); // let cluster = clusterBuffer[clusterId]; @@ -52,7 +52,7 @@ export let ClusterDebug_frag: string = /*wgsl*/` let cluster : LightIndex = getCluster(); let lightCount : u32 = u32(cluster.count); let lightFactor : f32 = f32(lightCount) / f32(clustersUniform.maxNumLightsPerCluster); - ORI_FragmentOutput.color = mix(vec4(0.0, 0.0,0.0, 1.0), vec4(1.0, 1.0, 1.0, 1.0), vec4(lightFactor, lightFactor, lightFactor, lightFactor)); + // ORI_FragmentOutput.color = mix(vec4(0.0, 0.0,0.0, 1.0), vec4(1.0, 1.0, 1.0, 1.0), vec4(lightFactor, lightFactor, lightFactor, lightFactor)); #endif } #endif diff --git a/src/assets/shader/materials/program/ShadowMapping_frag.ts b/src/assets/shader/materials/program/ShadowMapping_frag.ts index 637d4ae0..eb28f8a2 100644 --- a/src/assets/shader/materials/program/ShadowMapping_frag.ts +++ b/src/assets/shader/materials/program/ShadowMapping_frag.ts @@ -6,19 +6,15 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` @group(1) @binding(auto) var pointShadowMapSampler: sampler; @group(1) @binding(auto) var pointShadowMap: texture_depth_cube_array; - struct ShadowStruct{ - directShadowVisibility: array, - pointShadows: array, - } - var shadowStrut: ShadowStruct ; + var directShadowVisibility: array; + var pointShadows: array; + var shadowWeight: f32 = 1.0 ; fn useShadow(){ - shadowStrut.directShadowVisibility = array( 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0) ; - shadowStrut.pointShadows = array( 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0) ; - #if USE_SHADOWMAPING - directShadowMaping(globalUniform.shadowBias); - pointShadowMapCompare(globalUniform.pointShadowBias); - #endif + directShadowVisibility = array( 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0) ; + pointShadows = array(1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0) ; + directShadowMaping(globalUniform.shadowBias); + pointShadowMapCompare(globalUniform.pointShadowBias); } fn calcBasicBias(shadowWorldSize:f32, shadowDepthTexSize:f32, near:f32, far:f32) -> f32{ @@ -47,7 +43,7 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` visibility = 0.0; var validCount = 0; for(var csm:i32 = 0; csm < csmCount; csm ++){ - var csmShadowBias = globalUniform.csmShadowBias[csm]; + var csmShadowBias = globalUniform.csmShadowBias[csm] * shadowBias; shadowMatrix = globalUniform.csmMatrix[csm]; let csmShadowResult = directShadowMapingIndex(light, shadowMatrix, csm, csmShadowBias); if(csmShadowResult.y < 0.5){ @@ -93,7 +89,7 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` shadowMatrix = globalUniform.shadowMatrix[shadowIndex]; visibility = directShadowMapingIndex(light, shadowMatrix, shadowIndex, shadowBias).x; #endif - shadowStrut.directShadowVisibility[i] = visibility; + directShadowVisibility[i] = visibility; } } @@ -104,37 +100,44 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` var visibility = 1.0; var isOutSideArea:f32 = 1.0; var varying_shadowUV:vec2 = vec2(0.0); - var shadowPosTmp = matrix * vec4(ORI_VertexVarying.vWorldPos.xyz, 1.0); - var shadowPos = shadowPosTmp.xyz / shadowPosTmp.w; - varying_shadowUV = shadowPos.xy * vec2(0.5, -0.5) + vec2(0.5, 0.5); - if (varying_shadowUV.x <= 1.0 - && varying_shadowUV.x >= 0.0 - && varying_shadowUV.y <= 1.0 - && varying_shadowUV.y >= 0.0 - && shadowPosTmp.z <= 1.0 - && shadowPosTmp.z >= 0.0) - { - visibility = 0.0; - isOutSideArea = 0.0; - var uvOnePixel = 1.0 / vec2(globalUniform.shadowMapSize); - var totalWeight = 0.0; - 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; - - // 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 ; + #if USE_SHADOWMAPING + var shadowPosTmp = matrix * vec4(ORI_VertexVarying.vWorldPos.xyz, 1.0); + var shadowPos = shadowPosTmp.xyz / shadowPosTmp.w; + varying_shadowUV = shadowPos.xy * vec2(0.5, -0.5) + vec2(0.5, 0.5); + if (varying_shadowUV.x <= 1.0 + && varying_shadowUV.x >= 0.0 + && varying_shadowUV.y <= 1.0 + && varying_shadowUV.y >= 0.0 + && shadowPosTmp.z <= 1.0 + && shadowPosTmp.z >= 0.0) + { + visibility = 0.0; + isOutSideArea = 0.0; + var uvOnePixel = 1.0 / vec2(globalUniform.shadowMapSize) ; + var totalWeight = 0.0; + // var NoL = (dot(normalize(ORI_VertexVarying.vWorldNormal), normalize(-light.direction))); + // let v = max(NoL, 0.0) ; + // var bias = max(0.05 * (dot(normalize(fragData.N), normalize(-light.direction)) ), -shadowBias); + var bias = -0.005 * max(dot(fragData.N, -light.direction) , 0.0 ); + bias = clamp(bias, 0, 0.01) + -shadowBias; + + // var bias = shadowBias / v; + let bound = 1 ; + for (var y = -bound; y <= bound; y++) { + for (var x = -bound; x <= bound; x++) { + var offset = vec2(f32(x), f32(y)) ; + var offsetUV = offset * uvOnePixel ; + var weight = min(length(offset),1.0) ; + var depth = textureSampleLevel(shadowMap, shadowMapSampler, varying_shadowUV + offsetUV , depthTexIndex, 0); + if ((shadowPos.z - bias ) < depth) { + visibility += weight ; + totalWeight += weight; + }else{ + totalWeight += 1.0; + } } - totalWeight += 1.0; } - } - visibility /= totalWeight; - visibility += 0.001; + visibility /= totalWeight; } return vec4(visibility, isOutSideArea, varying_shadowUV); } @@ -197,7 +200,7 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` #endif for (var j = 0; j < pointCount ; j+=1 ) { if(i32(light.castShadow) == j){ - shadowStrut.pointShadows[j] = 1.0 - shadow ; + pointShadows[j] = 1.0 - shadow ; } } #endif diff --git a/src/assets/shader/materials/uniforms/PhysicMaterialUniform_frag.ts b/src/assets/shader/materials/uniforms/PhysicMaterialUniform_frag.ts index 6aab2ff0..f0832a79 100644 --- a/src/assets/shader/materials/uniforms/PhysicMaterialUniform_frag.ts +++ b/src/assets/shader/materials/uniforms/PhysicMaterialUniform_frag.ts @@ -2,30 +2,39 @@ export let PhysicMaterialUniform_frag = /* wgsl */` #if USE_CUSTOMUNIFORM #else struct MaterialUniform { - transformUV1:vec4, - transformUV2:vec4, - baseColor: vec4, emissiveColor: vec4, materialF0: vec4, specularColor: vec4, + envIntensity: f32, normalScale: f32, roughness: f32, metallic: f32, - ao: 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, + clearcoatIor: f32, + + baseMapOffsetSize:vec4, + normalMapOffsetSize:vec4, + emissiveMapOffsetSize:vec4, + roughnessMapOffsetSize:vec4, + metallicMapOffsetSize:vec4, + aoMapOffsetSize:vec4, }; #endif diff --git a/src/assets/shader/math/MathShader.ts b/src/assets/shader/math/MathShader.ts index e92f1dee..956143b8 100644 --- a/src/assets/shader/math/MathShader.ts +++ b/src/assets/shader/math/MathShader.ts @@ -2,8 +2,62 @@ * @internal */ export let MathShader = /* wgsl */ ` + #include 'BitUtil' + // fn getViewPosition(z:f32,uv:vec2f) -> vec3f { + // let pvMatrix = globalUniform.projMat * globalUniform.viewMat ; + // let worldPos = getWorldPosition(z,uv) ; + // var viewPos = pvMatrix * worldPos ; + // return viewPos.xyz; + // } + + + + struct TBN_ret{ + tan:vec3f, + bit:vec3f, + } + + fn TBN( N:vec3f) -> mat3x3{ + //Returns the simple tangent space matrix + var Nb : vec3f; + var Nt : vec3f; + if (abs(N.y)>0.999) { + Nb = vec3f(1.0,0.0,0.0); + Nt = vec3f(0.0,0.0,1.0); + } else { + Nb = normalize(cross(N,vec3f(0.0,1.0,0.0))); + Nt = normalize(cross(Nb,N)); + } + + var mat3 = mat3x3( + Nb.x,Nt.x,N.x, + Nb.y,Nt.y,N.y, + Nb.z,Nt.z,N.z + ); + + return mat3; + } + + fn TBN_out( N : vec3f ) -> TBN_ret { + var tbn_ret : TBN_ret; + //Returns the simple tangent space directions + if (abs(N.y)>0.999) { + tbn_ret.tan = vec3f(1.0,0.0,0.0); + tbn_ret.bit = vec3f(0.0,0.0,1.0); + } else { + tbn_ret.tan = normalize(cross(N,vec3f(0.0,1.0,0.0))); + tbn_ret.bit = normalize(cross(tbn_ret.tan,N)); + } + + return tbn_ret; + } + fn ARand21( uv: vec2f) -> f32 { + //Returns 1D noise from 2D + return fract(sin(uv.x*uv.y)*403.125+cos(dot(uv,vec2f(13.18273,51.2134)))*173.137); + } + fn applyQuaternion(position:vec3, q:vec4) -> vec3{ let x:f32 = position.x; let y:f32 = position.y; @@ -66,9 +120,41 @@ fn dir_to_faceId(pt:vec3) -> i32 { return 5; } - fn convert_xyz_to_cube_uv(x:f32, y:f32, z:f32 ) -> vec2 + const us = 1.0 /6.0 ; + fn uv_2_xyz(u:f32,v:f32) -> vec3f { - var dir = vec3(x, y, z); + let face = floor(u / us); + var uu = (u - face * us) / us ; + + var uc = 2.0 * uu - 1.0; + var vc = 2.0 * v - 1.0; + var xyz = vec3f(0,0,0); + + if(face == 0.0){ + // x,y,z = 1.0,vc,-uc + xyz = vec3f(1.0,-vc,uc); + }else if(face == 1.0){ + // x,y,z = -1.0,vc,uc + xyz = vec3f(-1.0,-vc,-uc); + }else if(face == 2.0){ + // x,y,z = uc,1.0,-vc + xyz = vec3f(uc,1.0,-vc); + }else if(face == 3.0){ + // x,y,z = uc,-1.0,vc + xyz = vec3f(uc,-1.0,vc); + }else if(face == 4.0){ + // x,y,z = uc,vc,1.0 + xyz = vec3f(-uc,-vc,1.0); + }else if(face == 5.0){ + // x,y,z = -uc,vc,-1.0 + xyz = vec3f(uc,-vc,-1.0); + } + return xyz ; + } + + fn convert_xyz_to_cube_uv(x:f32, y:f32, z:f32 ) -> vec2f + { + var dir = vec3f(x, y, z); var absX = abs(dir.x); var absY = abs(dir.y); var absZ = abs(dir.z); @@ -137,7 +223,7 @@ fn dir_to_faceId(pt:vec3) -> i32 { var u = 0.5f * (uc / maxAxis + 1.0f); var v = 0.5f * (vc / maxAxis + 1.0f); - return vec2(u, v); + return vec2f(u, v); } // Returns ±1 @@ -319,4 +405,174 @@ fn dir_to_faceId(pt:vec3) -> i32 { return mat3x3(xAxis, yAxis, zAxis); } + struct SH9Struct{ + SHAr:vec4f, + SHAg:vec4f, + SHAb:vec4f, + SHBr:vec4f, + SHBg:vec4f, + SHBb:vec4f, + SHC:vec4f, + } + + fn ShadeSH9 ( normal:vec4f , sh9:SH9Struct) -> vec3f + { + var x1:vec3f = vec3f(0.0); + var x2:vec3f = vec3f(0.0); + var x3:vec3f = vec3f(0.0); + + // Linear + constant polynomial terms + x1.r = dot(sh9.SHAr,normal); + x1.g = dot(sh9.SHAg,normal); + x1.b = dot(sh9.SHAb,normal); + + // 4 of the quadratic polynomials + var vB = normal.xyzz * normal.yzzx; + x2.r = dot(sh9.SHBr,vB); + x2.g = dot(sh9.SHBg,vB); + x2.b = dot(sh9.SHBb,vB); + + // Final quadratic polynomial + var vC = normal.x*normal.x - normal.y*normal.y; + x3 = sh9.SHC.rgb * vC; + return x1 + x2 + x3; + } + + fn clipViewUV(viewRectangle:vec4f,size:vec2f,fragCoord:vec2f) -> vec2u { + let subViewUV = (fragCoord - viewRectangle.xy) / viewRectangle.zw ; + return vec2u(subViewUV*size) ; + } + + fn insideRectangle( point:vec2f , rec:vec4f) -> bool { + if( point.x > rec.x && point.y > rec.y && point.x < (rec.x + rec.z ) && point.y < (rec.y + rec.w ) ){ + return true ; + } + return false; + } + + fn convert_cube_uv_to_xyz( index:i32, u:f32, v:f32) -> vec3f + { + var ret : vec3f ; + // convert range 0 to 1 to -1 to 1 + var uc = 2.0f * u - 1.0f; + var vc = 2.0f * v - 1.0f; + switch (index) + { + case 0: { + ret.x = 1.0f; + ret.y = vc; + ret.z = -uc; + break; + } // POSITIVE X + case 1: { + ret.x = -1.0f; + ret.y = vc; + ret.z = uc; + break; + } // NEGATIVE X + case 2: { + ret.x = uc; + ret.y = 1.0f; + ret.z = -vc; + break; + } // POSITIVE Y + case 3: { + ret.x = uc; + ret.y = -1.0f; + ret.z = vc; + break; + } // NEGATIVE Y + case 4: { + ret.x = uc; + ret.y = vc; + ret.z = 1.0f; + break; + } // POSITIVE Z + case 5: { + ret.x = -uc; + ret.y = vc; + ret.z = -1.0f; + break; + } // NEGATIVE Z + default:{ + ret = vec3f(0.0); + } + } + return ret ; + } + + fn convert_cube_uv_to_normal( index:i32, u:f32, v:f32) -> vec3f + { + var ret : vec3f ; + // convert range 0 to 1 to -1 to 1 + var uc = 2.0f * u - 1.0f; + var vc = 2.0f * v - 1.0f; + switch (index) + { + case 0: { + ret.x = 1.0f; + ret.y = vc; + ret.z = -uc; + break; + } // POSITIVE X + case 1: { + ret.x = -1.0f; + ret.y = vc; + ret.z = uc; + break; + } // NEGATIVE X + case 2: { + ret.x = uc; + ret.y = 1.0f; + ret.z = -vc; + break; + } // POSITIVE Y + case 3: { + ret.x = uc; + ret.y = -1.0f; + ret.z = vc; + break; + } // NEGATIVE Y + case 4: { + ret.x = uc; + ret.y = vc; + ret.z = 1.0f; + break; + } // POSITIVE Z + case 5: { + ret.x = -uc; + ret.y = vc; + ret.z = -1.0f; + break; + } // NEGATIVE Z + default:{ + ret = vec3f(0.0); + } + } + return ret ; + } + + fn UvToDir( uv1:vec2f) -> vec3f{ + var uv = uv1 ; + uv *= vec2f(2.0*3.1415926535897932384626433832795, 3.1415926535897932384626433832795); + var theta = uv.y; + var phi = uv.x + 3.1415926535897932384626433832795 * 0.5 ; + // var phi = uv.x ; + var dir = vec3f(0.0,0.0,0.0); + dir.x = sin(phi) * sin(theta) * -1; + dir.y = cos(theta) * -1; + dir.z = cos(phi) * sin(theta); + return dir; + } + + fn DirTOUV( a_coords:vec3f ) ->vec2f + { + var coords = normalize(a_coords); + var lon = atan2(coords.z, coords.x); + var lat = acos(coords.y); + var sphereCoords = vec2f(lon, lat) * (1.0 / 3.1415926535897932384626433832795); + return vec2f(sphereCoords.x * 0.5 + 0.5 , 1.0 - sphereCoords.y); + // return vec2f(sphereCoords.y, (sphereCoords.x * 0.5 )); + } + `; diff --git a/src/assets/shader/post/FXAAShader.ts b/src/assets/shader/post/FXAAShader.ts index 660769ab..d867281a 100644 --- a/src/assets/shader/post/FXAAShader.ts +++ b/src/assets/shader/post/FXAAShader.ts @@ -1,4 +1,5 @@ export let FXAAShader: string = /*wgsl*/ ` + #include 'BitUtil' struct FragmentOutput { @location(auto) o_Target: vec4 }; @@ -8,6 +9,8 @@ export let FXAAShader: string = /*wgsl*/ ` var baseMapSampler: sampler; @group(1) @binding(1) var baseMap: texture_2d; + // @group(1) @binding(2) + // var gBuffer: texture_2d; struct MaterialUniform{ u_texel: vec2, @@ -27,7 +30,8 @@ export let FXAAShader: string = /*wgsl*/ ` } fn texture2D( uv:vec2 , offset:vec2 ) -> vec4 { - return textureSample(baseMap, baseMapSampler, uv.xy + offset ).rgba ; + let buffer = textureSample(baseMap, baseMapSampler, uv.xy + offset ).rgba ; + return buffer ; } @fragment @@ -63,6 +67,7 @@ export let FXAAShader: string = /*wgsl*/ ` var resultA = 0.5 * (texture2D(v_vTexcoord , dir * -0.166667).rgb + texture2D(v_vTexcoord , dir * 0.166667).rgb); + var resultB = resultA * 0.5 + 0.25 * (texture2D( v_vTexcoord , dir * -0.5).rgb + texture2D( v_vTexcoord , dir * 0.5).rgb); var monoB = dot(resultB.rgb, gray); diff --git a/src/assets/shader/post/GlobalFog_shader.ts b/src/assets/shader/post/GlobalFog_shader.ts index f21b7171..23ba63c3 100644 --- a/src/assets/shader/post/GlobalFog_shader.ts +++ b/src/assets/shader/post/GlobalFog_shader.ts @@ -1,199 +1,193 @@ -import { GlobalUniform } from "../core/common/GlobalUniform"; - -/** - * @internal - */ export let GlobalFog_shader = /* wgsl */ ` -var PI: f32 = 3.14159265359; + var PI: f32 = 3.14159265359; + #include "GlobalUniform" + #include "GBufferStand" + + struct LightData { + index:f32, + lightType:i32, + radius:f32, + linear:f32, + + position:vec3, + lightMatrixIndex:f32, + + direction:vec3, + quadratic:f32, + + lightColor:vec3, + intensity:f32, + + innerCutOff :f32, + outerCutOff:f32, + range :f32, + castShadow:i32, + + lightTangent:vec3, + ies:f32, + }; + + struct FogUniformData { + fogColor : vec4, + + fogType : f32 , + fogHeightScale : f32 , + start: f32, + end: f32, + + density : f32 , + ins : f32 , + falloff : f32 , + rayLength : f32 , + + scatteringExponent : f32 , + dirHeightLine : f32 , + skyFactor: f32, + skyRoughness: f32, + + overrideSkyFactor: f32, + isSkyHDR: f32, + slot0: f32, + slot1: f32, + }; + + + @group(0) @binding(2) var fogUniform: FogUniformData; + @group(0) @binding(3) var lightBuffer: array; + @group(0) @binding(4) var inTex: texture_2d; + @group(0) @binding(5) var prefilterMap: texture_cube; + @group(0) @binding(6) var prefilterMapSampler: sampler; + @group(0) @binding(7) var outTex : texture_storage_2d; + + var texSize: vec2; + var fragCoord: vec2; + var fragUV: vec2; + + var texPosition: vec4; + var texNormal: vec4; + var texColor: vec4; + + fn getGroundWithSkyColor(worldPosition:vec3, skyRoughness:f32, isHDRTexture:bool) -> vec3 + { + let rayDirection = normalize(vec3(worldPosition.xyz - globalUniform.CameraPos.xyz)); + let calcRoughness = clamp(skyRoughness, 0.0, 1.0); + let MAX_REFLECTION_LOD = f32(textureNumLevels(prefilterMap)) ; + var prefilterColor = textureSampleLevel(prefilterMap, prefilterMapSampler, rayDirection, calcRoughness * MAX_REFLECTION_LOD); + if(isHDRTexture){ + prefilterColor = vec4(LinearToGammaSpace(vec3(prefilterColor.xyz)), prefilterColor.w); + } + return prefilterColor.xyz * globalUniform.skyExposure; + } + + fn getSkyBluredColor(skyRoughness:f32, isHDRTexture:bool) -> vec3 + { + var worldPosition = vec4f(getSkyPositionFromGBuffer(fragUV), 1.0); + let rayDirection = normalize(vec3(worldPosition.xyz - globalUniform.CameraPos.xyz)); + let calcRoughness = clamp(skyRoughness, 0.0, 1.0); + let MAX_REFLECTION_LOD = f32(textureNumLevels(prefilterMap)) ; + var prefilterColor = textureSampleLevel(prefilterMap, prefilterMapSampler, rayDirection, calcRoughness * MAX_REFLECTION_LOD); + if(isHDRTexture){ + prefilterColor = vec4(LinearToGammaSpace(vec3(prefilterColor.xyz)), prefilterColor.w); + } + return prefilterColor.xyz * globalUniform.skyExposure; + } -struct FragmentOutput { - @location(auto) o_Target: vec4 -}; + @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; + } -${GlobalUniform} + fragUV = vec2(fragCoord) / vec2(texSize - 1); -#include "FastMathShader" - -struct LightData { - index:f32, - lightType:i32, - radius:f32, - linear:f32, + var gBuffer = getGBuffer( fragCoord ) ; + texNormal = vec4f(getWorldNormalFromGBuffer(gBuffer),1.0); + texPosition = vec4f(getWorldPositionFromGBuffer(gBuffer,fragUV), 1.0); + texColor = textureLoad(inTex, fragCoord, 0); - position:vec3, - lightMatrixIndex:f32, - - direction:vec3, - quadratic:f32, - - lightColor:vec3, - intensity:f32, - - innerCutOff :f32, - outerCutOff:f32, - range :f32, - castShadow:i32, - - lightTangent:vec3, - ies:f32, -}; - -struct UniformData { - fogColor : vec4, - fogType : f32 , - fogHeightScale : f32 , - start: f32, - end: f32, - density : f32 , - ins : f32 , - falloff : f32 , - rayLength : f32 , - scatteringExponent : f32 , - dirHeightLine : f32 , - skyFactor: f32, - skyRoughness: f32, - overrideSkyFactor: f32, - isSkyHDR: f32 -}; - -@group(1) @binding(0) -var positionMapSampler: sampler; -@group(1) @binding(1) -var positionMap: texture_2d; - -@group(1) @binding(2) -var colorMapSampler: sampler; -@group(1) @binding(3) -var colorMap: texture_2d; - -@group(1) @binding(4) -var normalMapSampler: sampler; -@group(1) @binding(5) -var normalMap: texture_2d; - -@group(1) @binding(6) -var prefilterMapSampler: sampler; -@group(1) @binding(7) -var prefilterMap: texture_cube; - - -@group(2) @binding(0) -var global : UniformData; -var varying_uv: vec2; - -@group(2) @binding(1) -var lightBuffer: array; - -var texPosition: vec4; -var texNormal: vec4; -var texColor: vec4; - -fn LinearToGammaSpace(linRGB: vec3) -> vec3 -{ - var linRGB1 = max(linRGB, vec3(0.0)); - linRGB1 = pow(linRGB1, vec3(0.4166666567325592)); - return max(((1.0549999475479126 * linRGB1) - vec3(0.054999999701976776)), vec3(0.0)); -} - -fn getSkyColor(worldPosition:vec3, skyRoughness:f32, isHDRTexture:bool) -> vec3 -{ - let cameraPosition = vec3(globalUniform.cameraWorldMatrix[3].xyz); - let rayDirection = normalize(vec3(worldPosition.xyz - cameraPosition)); - let calcRoughness = clamp(skyRoughness, 0.0, 1.0); - let MAX_REFLECTION_LOD = f32(textureNumLevels(prefilterMap)) ; - var prefilterColor = textureSampleLevel(prefilterMap, prefilterMapSampler, rayDirection, calcRoughness * MAX_REFLECTION_LOD); - if(isHDRTexture){ - prefilterColor = vec4(LinearToGammaSpace(vec3(prefilterColor.xyz)), prefilterColor.w); - } - return prefilterColor.xyz * globalUniform.skyExposure; -} - -@fragment -fn main(@location(auto) fragUV: vec2, @builtin(position) coord: vec4) -> FragmentOutput { - var texCoord = vec2(fragUV.x, 1.0 - fragUV.y); - texPosition = textureSample(positionMap, positionMapSampler, texCoord) ; - texNormal = textureSample(normalMap, normalMapSampler, texCoord) ; - texColor = textureSample(colorMap, colorMapSampler, texCoord) ; - - var opColor = vec3(0.0); - if(texNormal.w <= 0.5){ - //for sky - if(global.overrideSkyFactor > 0.01){ - opColor = blendSkyColor(); + var opColor = vec3(0.0); + if(getRoughnessFromGBuffer(gBuffer) <= 0.0){ + //for sky + if(fogUniform.overrideSkyFactor > 0.01){ + opColor = blendSkyColor(); + }else{ + opColor = texColor.xyz; + } }else{ - opColor = texColor.xyz; - } - }else{ - //for ground - var fogFactor = calcFogFactor(); - if(global.skyFactor > 0.01 || global.overrideSkyFactor > 0.01){ - opColor = blendGroundColor(fogFactor); - }else{ - opColor = mix(texColor.rgb, global.fogColor.xyz, fogFactor); + //for ground + var fogFactor = calcFogFactor(); + if(fogUniform.skyFactor > 0.01 || fogUniform.overrideSkyFactor > 0.01){ + opColor = blendGroundColor(fogFactor); + }else{ + } + + opColor = mix(texColor.rgb, fogUniform.fogColor.xyz, fogFactor); + let sunLight = lightBuffer[0] ; + var inScatteringValue = inScatterIng(sunLight.direction, texPosition.xyz, sunLight.lightColor); + opColor += inScatteringValue; } - let sunLight = lightBuffer[0] ; - var inScatteringValue = inScatterIng(sunLight.direction, texPosition.xyz, sunLight.lightColor); - opColor += inScatteringValue; + textureStore(outTex, fragCoord , vec4(opColor.xyz, texColor.a)); } - return FragmentOutput(vec4(opColor.xyz, texColor.a)); -} -fn calcFogFactor() -> f32 -{ - var cameraPos = globalUniform.cameraWorldMatrix[3].xyz ; - let dis = distance(cameraPos, texPosition.xyz); - var heightFactor = computeFog(dis) + cFog(-texPosition.y); - return clamp(global.ins * heightFactor,0.0,1.0); -} + fn calcFogFactor() -> f32 + { + var cameraPos = globalUniform.cameraWorldMatrix[3].xyz ; + let dis = distance(cameraPos, texPosition.xyz); + var heightFactor = computeFog(dis) + cFog(-texPosition.y); + return clamp(fogUniform.ins * heightFactor,0.0,1.0); + } - -fn blendGroundColor(fogFactor:f32) -> vec3 -{ - var skyColorBlur = getSkyColor(texPosition.xyz, global.skyRoughness, global.isSkyHDR > 0.5); - let skyFactor = clamp(global.skyFactor - global.overrideSkyFactor * 0.5, 0.0, 1.0); - var fogColor = mix(global.fogColor.xyz, skyColorBlur, skyFactor); - return mix(texColor.rgb, fogColor.rgb, fogFactor); -} - -fn blendSkyColor() -> vec3 -{ - let overrideSkyFactor = sqrt(global.overrideSkyFactor); - var skyColorBlur = getSkyColor(texPosition.xyz, overrideSkyFactor * 0.3, global.isSkyHDR > 0.5); - return mix(global.fogColor.xyz, skyColorBlur, 1.0 - overrideSkyFactor); -} - - -fn computeFog(z:f32) -> f32 -{ - var fog = 0.0; - if( global.fogType < 0.5 ){ - fog = (global.end - z) / (global.end - global.start); - }else if(global.fogType < 1.5 ){ - fog = exp2(-global.density * z); - }else if(global.fogType == 2.5 ){ - fog = global.density * z; - fog = exp2(-fog * fog); + + fn blendGroundColor(fogFactor:f32) -> vec3 + { + var skyColorBlur = getGroundWithSkyColor(texPosition.xyz, fogUniform.skyRoughness, fogUniform.isSkyHDR > 0.5); + let skyFactor = clamp(fogUniform.skyFactor - fogUniform.overrideSkyFactor * 0.5, 0.0, 1.0); + var fogColor = mix(fogUniform.fogColor.xyz, skyColorBlur, skyFactor); + return mix(texColor.rgb, fogColor.rgb, fogFactor); + } + + fn blendSkyColor() -> vec3 + { + let overrideSkyFactor = sqrt(fogUniform.overrideSkyFactor); + var skyColorBlur = getSkyBluredColor(overrideSkyFactor * 0.3, fogUniform.isSkyHDR > 0.5); + return mix(fogUniform.fogColor.xyz, skyColorBlur, 1.0 - overrideSkyFactor); + } + + + fn computeFog(z:f32) -> f32 + { + var fog = 0.0; + if( fogUniform.fogType < 0.5 ){ + fog = (fogUniform.end - z) / (fogUniform.end - fogUniform.start); + }else if(fogUniform.fogType < 1.5 ){ + fog = exp2(-fogUniform.density * z); + }else if(fogUniform.fogType == 2.5 ){ + fog = fogUniform.density * z; + fog = exp2(-fog * fog); + } + return max(fog,0.0); + } + + fn cFog(y:f32) -> f32 + { + let fogDensity = fogUniform.density * exp(fogUniform.fogHeightScale * y); + let fogFactor = (1.0 - exp2(-fogUniform.falloff)) / fogUniform.falloff ; + let fog = fogDensity * fogFactor * max(fogUniform.rayLength - fogUniform.start, 0.0); + return max(fog,0.0); + } + + fn inScatterIng(sunDir:vec3, worldPos:vec3, sunColor:vec3) -> vec3 + { + let viewDir = normalize(globalUniform.CameraPos.xyz - worldPos.xyz) ; + let VoL = saturate(dot(viewDir,sunDir)) ; + var scatter = pow(VoL,fogUniform.scatteringExponent); + scatter *= (1.0-saturate(exp2(-fogUniform.dirHeightLine))); + return vec3(scatter*sunColor); } - return max(fog,0.0); -} - - fn cFog(y:f32) -> f32 - { - let fogDensity = global.density * exp(global.fogHeightScale * y); - let fogFactor = (1.0 - exp2(-global.falloff)) / global.falloff ; - let fog = fogDensity * fogFactor * max(global.rayLength - global.start, 0.0); - return max(fog,0.0); - } - - fn inScatterIng(sunDir:vec3, worldPos:vec3, sunColor:vec3) -> vec3 - { - let viewDir = normalize(globalUniform.CameraPos.xyz - worldPos.xyz) ; - let VoL = saturate(dot(viewDir,sunDir)) ; - var scatter = pow(VoL,global.scatteringExponent); - scatter *= (1.0-saturate(exp2(-global.dirHeightLine))); - return vec3(scatter*sunColor); - } `; diff --git a/src/assets/shader/sky/AtmosphericScatteringSky_shader.ts b/src/assets/shader/sky/AtmosphericScatteringSky_shader.ts index 8ade0a29..fd6605ad 100644 --- a/src/assets/shader/sky/AtmosphericScatteringSky_shader.ts +++ b/src/assets/shader/sky/AtmosphericScatteringSky_shader.ts @@ -3,7 +3,7 @@ */ export class AtmosphericScatteringSky_shader { public static cs: string = /* wgsl */ ` - #include 'ColorUtil' + #include 'ColorUtil_frag' struct UniformData { width: f32, height: f32, diff --git a/src/assets/shader/sky/CubeSky_Shader.ts b/src/assets/shader/sky/CubeSky_Shader.ts index 67b3d6be..90f40b06 100644 --- a/src/assets/shader/sky/CubeSky_Shader.ts +++ b/src/assets/shader/sky/CubeSky_Shader.ts @@ -5,6 +5,7 @@ export class CubeSky_Shader { struct VertexOutput { @location(auto) fragUV: vec2, + @location(auto) vClipPos: vec4, @location(auto) vWorldPos: vec4, @location(auto) vWorldNormal: vec3, @builtin(position) member: vec4 @@ -21,11 +22,11 @@ export class CubeSky_Shader { ) -> VertexOutput { ORI_VertexOut.fragUV = uv; let modelMat = models.matrix[u32(index)]; - let vm = globalUniform.viewMat * modelMat; + let vm = modelMat; let normalMatrix = mat3x3(vm[0].xyz,vm[1].xyz,vm[2].xyz); ORI_VertexOut.vWorldNormal = normalize( normalMatrix * normal ); ORI_VertexOut.vWorldPos = modelMat * vec4(position.xyz,1.0) ; - + var fixProjMat = globalUniform.projMat ; fixProjMat[2].z = 1.0 ;//99999.0 / (99999.0 - 1.0) ; fixProjMat[3].z = -1.0 ;//(-1.0 * 99999.0) / (99999.0 - 1.0) ; @@ -36,6 +37,7 @@ export class CubeSky_Shader { fixViewMat[3].z = 0.0 ; var clipPos = fixProjMat * fixViewMat * ORI_VertexOut.vWorldPos; + ORI_VertexOut.vClipPos = clipPos ; ORI_VertexOut.member = clipPos; return ORI_VertexOut; } @@ -43,23 +45,16 @@ export class CubeSky_Shader { public static sky_fs_frag_wgsl: string = /* wgsl */ ` #include "GlobalUniform" + #include "MathShader" + #include "BitUtil" + #include "ColorUtil_frag" + #include "FragmentOutput" struct uniformData { exposure: f32, roughness: f32 }; - struct FragmentOutput { - @location(auto) o_Target: vec4, - #if USE_WORLDPOS - @location(auto) o_Position: vec4, - #endif - #if USEGBUFFER - @location(auto) o_Normal: vec4, - @location(auto) o_Material: vec4 - #endif - }; - @group(1) @binding(0) var baseMapSampler: sampler; @group(1) @binding(1) @@ -68,33 +63,58 @@ export class CubeSky_Shader { @group(2) @binding(0) var global: uniformData; - fn LinearToGammaSpace(linRGB: vec3) -> vec3 { - 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(auto) fragUV: vec2, @location(auto) vWorldPos: vec4, @location(auto) vWorldNormal: vec3) -> FragmentOutput { + fn main(@location(auto) fragUV: vec2,@location(auto) vClipPos: vec4, @location(auto) vWorldPos: vec4, @location(auto) vWorldNormal: vec3 , @builtin(position) fragCoord : vec4 ) -> FragmentOutput { let maxLevel: u32 = textureNumLevels(baseMap); - var textureColor:vec3 = textureSampleLevel(baseMap, baseMapSampler, normalize(vWorldPos.xyz), global.roughness * f32(maxLevel) ).xyz; + let dir = normalize(vWorldPos.xyz); + var textureColor:vec3 = textureSampleLevel(baseMap, baseMapSampler, normalize(dir.xyz), global.roughness * f32(maxLevel) ).xyz; #if IS_HDR_SKY - textureColor = LinearToGammaSpace(textureColor); + textureColor = LinearToGammaSpace(textureColor); #endif - let o_Target: vec4 =vec4(textureColor, 1.0) * globalUniform.skyExposure ; - var normal_rgba8unorm = (vWorldNormal + 1.0) * 0.5; - normal_rgba8unorm = clamp(normal_rgba8unorm, vec3(0.0), vec3(1.0)); - return FragmentOutput( - o_Target, - #if USE_WORLDPOS - vWorldPos, - #endif - #if USEGBUFFER - vec4(normal_rgba8unorm,0.0), - vec4(0.0,1.0,0.0,0.0) - #endif - ); + // let o_Target: vec4 = globalUniform.hdrExposure * vec4(textureColor, 1.0) * globalUniform.skyExposure ; + let o_Target: vec4 = vec4(textureColor, 1.0) * globalUniform.skyExposure; + let finalMatrix = globalUniform.projMat * globalUniform.viewMat ; + let nMat = mat3x3(finalMatrix[0].xyz,finalMatrix[1].xyz,finalMatrix[2].xyz) ; + let ORI_NORMALMATRIX = transpose(inverse( nMat )); + + var vNormal = (ORI_NORMALMATRIX * -vWorldNormal ); + var gBuffer = packGBuffer( + -globalUniform.far, + vec3f(0.0), + o_Target.rgb, + vec3f(0.0), + vNormal + ) ; + var fragmentOutput:FragmentOutput; + #if USE_CASTREFLECTION + fragmentOutput.gBuffer = gBuffer ; + #else + fragmentOutput.color = o_Target ; + fragmentOutput.gBuffer = gBuffer ; + #endif + return fragmentOutput; + } + + fn packGBuffer(depth:f32, albedo:vec3f,hdrLighting:vec3f,rmao:vec3f,normal:vec3f) -> vec4f{ + var gBuffer : vec4f ; + var octUVNormal = (octEncode(normalize(normal)) + 1.0) * 0.5 ; + + var yc = f32(r11g11b9_to_float(vec3f(octUVNormal,0.0))) ; + #if USE_CASTREFLECTION + var rgbm = EncodeRGBM(hdrLighting); + var zc = f32(pack4x8unorm(vec4f(rgbm.rgb,0.0))) ; + var wc = f32(pack4x8unorm(vec4f(rmao.rg,rgbm.a,0.0))); + #else + var zc = f32(vec4fToFloat_7bits(vec4f(albedo.rgb,0.0))); + var wc = f32(r22g8_to_float(vec2f(f32(0.0),rmao.g))); + #endif + + gBuffer.x = depth ; + gBuffer.y = yc ; + gBuffer.z = zc ; + gBuffer.w = wc ; + return gBuffer ; } `; diff --git a/src/assets/shader/utils/BitUtil.ts b/src/assets/shader/utils/BitUtil.ts new file mode 100644 index 00000000..eaa16959 --- /dev/null +++ b/src/assets/shader/utils/BitUtil.ts @@ -0,0 +1,108 @@ +export let BitUtil = /* wgsl */` + + const inv256:f32 = 1.0/256.0; + const inv1024:f32 = 1.0/1024.0; + + const bit7_inv128:f32 = 1.0 / 128.0; + const bit7_128:f32 = 128.0; + + const r10g10b10 = vec2i(0x3FFFFF,0xFF); + fn floatToVec3f( v:f32 ) -> vec3f { + var VPInt:i32 = bitcast(v); + var VPInt1024:i32 = VPInt%1024; + var VPInt10241024:i32 = ((VPInt-VPInt1024)/1024)%1024; + return vec3f(f32(VPInt1024),f32(VPInt10241024),f32(((VPInt-VPInt1024-VPInt10241024)/1048576)))*vec3f(inv1024); + } + + fn vec3fToFloat( v:vec3f) -> f32{ + let intv = min(vec3(floor(v*1024.)),vec3(1023)); + return bitcast(i32(intv.x+intv.y*1024+intv.z*1048576)); + } + + fn vec4fToFloat_7bits( v:vec4f) -> f32{ + //0~256 + let intv = min(vec4(floor(v*bit7_128)),vec4(127)); + return bitcast(i32(intv.x+intv.y*128+intv.z*16384+intv.w*2097152)); + } + + fn floatToVec4f_7bits( v:f32 ) -> vec4f { + var VPInt:i32 = bitcast(v); + var VPInt128:i32 = VPInt%128; + var VPInt128128:i32 = ((VPInt-VPInt128)/128)%128; + var VPInt128128128:i32 = ((VPInt-VPInt128-VPInt128128)/16384)%128; + var VPInt128128128128:i32 = ((VPInt-VPInt128-VPInt128128-VPInt128128128)/2097152)%128; + return vec4f(f32(VPInt128),f32(VPInt128128),f32(VPInt128128128),f32(VPInt128128128128))*vec4f(bit7_inv128); + } + + + + + + + const i_r11g11b11 = vec3i(0x7FF,0x7FF,0x7FF); + const f_r11g11b11 = vec3f(f32(0x7FF),f32(0x7FF),f32(0x7FF)); + fn r11g11b11_to_float( v:vec3f) -> f32{ + let iR: i32 = i32(v.r * f_r11g11b11.r); + let iG: i32 = i32(v.g * f_r11g11b11.g); + let iB: i32 = i32(v.b * f_r11g11b11.b); + return bitcast((iR << 22u) | (iG << 11u) | iB ); + } + + fn float_to_r11g11b11( v:f32 ) -> vec3f { + let iV: i32 = bitcast(v); + var r: f32 = f32((iV >> 22u) & i_r11g11b11.r) / f_r11g11b11.r; + var g: f32 = f32((iV >> 11u) & i_r11g11b11.g) / f_r11g11b11.g; + var b: f32 = f32(iV & i_r11g11b11.b) / f_r11g11b11.b ; + return vec3f(r,g,b); + } + + const i_r22g8 = vec2i(0x3FFFFF,0xFF); + const f_r22g8 = vec2f(f32(0x3FFFFF),f32(0xFF)); + fn r22g8_to_float( v:vec2f) -> f32{ + let iR: i32 = i32(v.r * f_r22g8.r); + let iG: i32 = i32(v.g * f_r22g8.g); + return bitcast((iR << 8u) | iG); + } + + fn float_to_r22g8( v:f32 ) -> vec2f { + let iV: i32 = bitcast(v); + var r: f32 = f32((iV >> 8u) & i_r22g8.r) / f_r22g8.r; + var g: f32 = f32(iV & i_r22g8.g) / f_r22g8.g ; + return vec2f(r,g); + } + + const r11g11b9 = vec3i(0x7FF,0x7FF,0x1FF); + fn r11g11b9_to_float( v:vec3f) -> f32{ + let iR: i32 = i32(v.r * f32(r11g11b9.r)); + let iG: i32 = i32(v.g * f32(r11g11b9.g)); + let iB: i32 = i32(v.b * f32(r11g11b9.b)); + return bitcast((iR << 20u) | (iG << 9u) | iB ); + } + + fn float_to_r11g11b9( v:f32 ) -> vec3f { + let iV: i32 = bitcast(v); + var r: f32 = f32((iV >> 20u) & r11g11b9.r) / f32(r11g11b9.r); + var g: f32 = f32((iV >> 9u) & r11g11b9.g) / f32(r11g11b9.g); + var b: f32 = f32(iV & r11g11b9.b) / f32(r11g11b9.b) ; + return vec3f(r,g,b); + } + + + + + fn floatToRGBA(v:f32) -> vec4f{ + var iv = bitcast(v); + var color = vec4f(0.0); + color.x = f32((iv&0x00FF0000u)>>16u)/255.0; + color.y = f32((iv&0x000FF00u)>>8u)/255.0; + color.z = f32(iv&0x000000FFu)/255.0; + return color; + } + + const bitShift:vec4f = vec4f(1.0, 1.0/256.0, 1.0/(256.0*256.0), 1.0/(256.0*256.0*256.0)); + fn RGBAToFloat(v:vec4f) -> f32 { + var f = dot(v, bitShift); + return f; + } + +` \ No newline at end of file diff --git a/src/assets/shader/utils/ColorUtil.ts b/src/assets/shader/utils/ColorUtil.ts index b2fc1803..35b003a8 100644 --- a/src/assets/shader/utils/ColorUtil.ts +++ b/src/assets/shader/utils/ColorUtil.ts @@ -1,9 +1,30 @@ export let ColorUtil: string = /*wgsl*/ ` fn getHDRColor(color: vec3, exposure: f32) -> vec3 < f32 > { - // var newColor = color * ( 1.0 / 255.0 ) ; return color * pow(2.4, exposure) ; } + // RGBM encode/decode + const kRGBMRange = 8.0; + + fn EncodeRGBM( icolor : vec3f ) ->vec4f + { + var color = icolor ; + color *= 1.0 / kRGBMRange; + var m = max(max(color.x, color.y), max(color.z, 1e-5)); + m = ceil(m * 255) / 255; + return vec4f(color / m, m); + } + + fn DecodeRGBM( rgbm : vec4f ) -> vec3f + { + return rgbm.xyz * rgbm.w * kRGBMRange; + } + + fn Luminance( LinearColor : vec3f, LuminanceFactors: vec3f ) -> f32 + { + return dot( LinearColor, LuminanceFactors ); + } + fn lambda2rgb(lambda : f32) -> vec3 < f32 > { let ultraviolet = 400.0; let infrared = 700.0; @@ -19,6 +40,11 @@ export let ColorUtil: string = /*wgsl*/ ` return 1.0 - exp(-adapted_lum * color); } + + fn acesFilm( x:vec3f) -> vec3f { + return clamp((x*(2.51*x+vec3f(0.03)))/(x*(2.43*x+vec3f(0.59))+vec3f(0.14)),vec3f(0.0),vec3f(1.0)); + } + fn ACESToneMapping(color: vec3, adapted_lum: f32) -> vec3 { let A = 2.51; @@ -50,12 +76,18 @@ export let ColorUtil: string = /*wgsl*/ ` return color2 ; } - fn LinearToGammaSpace(linRGB0: vec3) -> vec3 < f32 > { - var linRGB = max(linRGB0, vec3(0.0, 0.0, 0.0)); - linRGB.r = pow(linRGB.r, 0.416666667); - linRGB.g = pow(linRGB.g, 0.416666667); - linRGB.b = pow(linRGB.b, 0.416666667); - return max(1.055 * linRGB - 0.055, vec3(0.0, 0.0, 0.0)); + // fn LinearToGammaSpace(linRGB0: vec3) -> vec3 < f32 > { + // var linRGB = max(linRGB0, vec3(0.0, 0.0, 0.0)); + // linRGB.r = pow(linRGB.r, 0.416666667); + // linRGB.g = pow(linRGB.g, 0.416666667); + // linRGB.b = pow(linRGB.b, 0.416666667); + // return max(1.055 * linRGB - 0.055, vec3(0.0, 0.0, 0.0)); + // } + + fn LinearToGammaSpace(linRGB: vec3) -> vec3 { + var linRGB1 = max(linRGB, vec3(0.0)); + linRGB1 = pow(linRGB1, vec3(0.4166666567325592)); + return max(((1.0549999475479126 * linRGB1) - vec3(0.054999999701976776)), vec3(0.0)); } varsRGB_2_LMS_MAT: mat3x3 = mat3x3( @@ -118,4 +150,25 @@ export let ColorUtil: string = /*wgsl*/ ` // vec3 r = normalize(t.xy + u.xy, t.z); // return r; // } + + +fn packRGBA8( In : vec4f ) ->u32 +{ + let r = (u32(saturate(In.r) * 255.0) << 0u); + let g = (u32(saturate(In.g) * 255.0) << 8u); + let b = (u32(saturate(In.b) * 255.0) << 16u); + let a = (u32(saturate(In.a) * 255.0) << 24u); + return r | g | b | a; +} + +const i256:f32 = 1.0 / 255.0 ; +fn unpackRGBA8( In : u32 ) -> vec4f +{ + var Out:vec4f ; + Out.r = f32((In >> 0u) & 0xFF) * i256; + Out.g = f32((In >> 8u) & 0xFF) * i256; + Out.b = f32((In >> 16u) & 0xFF) * i256; + Out.a = f32((In >> 24u) & 0xFF) * i256; + return Out; +} ` diff --git a/src/components/ComponentBase.ts b/src/components/ComponentBase.ts index 9f661aae..f142be24 100644 --- a/src/components/ComponentBase.ts +++ b/src/components/ComponentBase.ts @@ -120,6 +120,8 @@ export class ComponentBase implements IComponent { public onCompute?(view?: View3D, command?: GPUCommandEncoder); public onGraphic?(view?: View3D); public onParentChange?(lastParent?: Object3D, currentParent?: Object3D); + public onAddChild?(child: Object3D); + public onRemoveChild?(child: Object3D); /** * diff --git a/src/components/IComponent.ts b/src/components/IComponent.ts index 7110fd43..f3704fc2 100644 --- a/src/components/IComponent.ts +++ b/src/components/IComponent.ts @@ -24,4 +24,6 @@ export interface IComponent { beforeDestroy(force?: boolean); onParentChange?(lastParent?: Object3D, currentParent?: Object3D); + onAddChild?(child: Object3D); + onRemoveChild?(child: Object3D); } \ No newline at end of file diff --git a/src/components/Transform.ts b/src/components/Transform.ts index fdd138e3..9dbe6629 100644 --- a/src/components/Transform.ts +++ b/src/components/Transform.ts @@ -10,6 +10,7 @@ import { Orientation3D } from "../math/Orientation3D"; import { Quaternion } from "../math/Quaternion"; import { Vector3 } from "../math/Vector3"; import { ComponentBase } from "./ComponentBase"; +import { Entity } from ".."; /** * The Transform component contains the position, rotation, and scaling of an object in 3D space. @@ -17,6 +18,8 @@ import { ComponentBase } from "./ComponentBase"; * @group Components */ export class Transform extends ComponentBase { + + /** * @internal */ @@ -663,11 +666,16 @@ export class Transform extends ComponentBase { } public set localPosition(v: Vector3) { - // if (this._localPos.x != v.x || this._localPos.y != v.y || this._localPos.z != v.z) { + if (this.onPositionChange) { + if (this._localPos.x != v.x || this._localPos.y != v.y || this._localPos.z != v.z) { + this.onPositionChange(this._localPos, v); + } + } this._localPos.copyFrom(v); WasmMatrix.setTranslate(this.index, v.x, v.y, v.z); this.notifyLocalChange(); - this.onPositionChange?.(); + + if (this.eventPositionChange) { this.eventDispatcher.dispatchEvent(this.eventPositionChange); @@ -683,11 +691,15 @@ export class Transform extends ComponentBase { } public set localRotation(v: Vector3) { - // if (this._localRot.x != v.x || this._localRot.y != v.y || this._localRot.z != v.z) { + if (this.onRotationChange) { + if (this._localRot.x != v.x || this._localRot.y != v.y || this._localRot.z != v.z) { + this.onRotationChange(this._localRot, v); + } + } + WasmMatrix.setRotation(this.index, v.x, v.y, v.z); this._localRot.copyFrom(v); this.notifyLocalChange(); - this.onRotationChange?.(); if (this.eventRotationChange) { this.eventDispatcher.dispatchEvent(this.eventRotationChange); diff --git a/src/components/gui/core/GUICanvas.ts b/src/components/gui/core/GUICanvas.ts index a3c74d17..62cd3e33 100644 --- a/src/components/gui/core/GUICanvas.ts +++ b/src/components/gui/core/GUICanvas.ts @@ -38,7 +38,7 @@ export class GUICanvas extends ComponentBase { } public copyComponent(from: this): this { - this.index = from.index; + from.index = from.index; return this; } } diff --git a/src/components/gui/core/GUIMaterial.ts b/src/components/gui/core/GUIMaterial.ts index a5bc8e78..7f6f3ad0 100644 --- a/src/components/gui/core/GUIMaterial.ts +++ b/src/components/gui/core/GUIMaterial.ts @@ -4,7 +4,7 @@ import { GPUCompareFunction, GPUCullMode } from "../../../gfx/graphics/webGpu/We import { Texture } from "../../../gfx/graphics/webGpu/core/texture/Texture"; import { RenderShaderPass } from "../../../gfx/graphics/webGpu/shader/RenderShaderPass"; import { Shader } from "../../../gfx/graphics/webGpu/shader/Shader"; -import { PassType } from "../../../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../../../gfx/renderJob/passRenderer/state/PassType"; import { BlendMode } from "../../../materials/BlendMode"; import { Material } from "../../../materials/Material"; import { Vector2 } from "../../../math/Vector2"; diff --git a/src/components/gui/core/GUIRenderer.ts b/src/components/gui/core/GUIRenderer.ts index f6889570..1c8d3962 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 { PassType } from "../../../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../../../gfx/renderJob/passRenderer/state/PassType"; import { MeshRenderer } from "../../renderer/MeshRenderer"; import { GUIGeometry } from "./GUIGeometry"; diff --git a/src/components/gui/core/GUIShader.ts b/src/components/gui/core/GUIShader.ts index a6c8f93f..a65d755b 100644 --- a/src/components/gui/core/GUIShader.ts +++ b/src/components/gui/core/GUIShader.ts @@ -1,6 +1,7 @@ import { GlobalUniform } from "../../../assets/shader/core/common/GlobalUniform"; import { WorldMatrixUniform } from "../../../assets/shader/core/common/WorldMatrixUniform"; -import { ColorPassFragmentOutput } from "../../../assets/shader/core/struct/ColorPassFragmentOutput"; +import { FragmentOutput } from "../../../assets/shader/core/struct/FragmentOutput"; + /** * shader code @@ -37,7 +38,7 @@ export class GUIShader { } private static readonly fs: string = /* wgsl */ ` - ${ColorPassFragmentOutput} + ${FragmentOutput} ${this.bindTextureArray()} var fragmentOutput: FragmentOutput; @@ -180,6 +181,7 @@ export class GUIShader { scissorFadeOutSize:f32, pixelRatio:f32, + v3:vec3 } diff --git a/src/components/gui/core/GUITexture.ts b/src/components/gui/core/GUITexture.ts index dee26eeb..92b4db9d 100644 --- a/src/components/gui/core/GUITexture.ts +++ b/src/components/gui/core/GUITexture.ts @@ -22,6 +22,8 @@ export class GUITexture { constructor(texture: Texture) { texture ||= Engine3D.res.whiteTexture; + texture.addressModeU = 'clamp-to-edge'; + texture.addressModeV = 'clamp-to-edge'; this.texture = texture; GUITexture._maxUid++; this._staticId = GUITexture._maxUid; diff --git a/src/components/gui/uiComponents/UIPanel.ts b/src/components/gui/uiComponents/UIPanel.ts index b3b4eda2..5881529c 100644 --- a/src/components/gui/uiComponents/UIPanel.ts +++ b/src/components/gui/uiComponents/UIPanel.ts @@ -177,6 +177,7 @@ export class UIPanel extends UIImage { } } + //clear flag panel.needUpdateGeometry = false; } diff --git a/src/components/gui/uiComponents/UITransform.ts b/src/components/gui/uiComponents/UITransform.ts index 8269e36f..ba0a6294 100644 --- a/src/components/gui/uiComponents/UITransform.ts +++ b/src/components/gui/uiComponents/UITransform.ts @@ -298,7 +298,7 @@ export class UITransform extends ComponentBase { } public beforeDestroy(force?: boolean): void { - this.transform.eventDispatcher.removeEventListener(this.transform.eventLocalChange.type, this.onTransformChange, this); + this.transform.eventDispatcher.addEventListener(this.transform.eventLocalChange.type, this.onTransformChange, this); super.beforeDestroy?.(force); } } diff --git a/src/components/lights/LightBase.ts b/src/components/lights/LightBase.ts index 48bc4f25..45c54b0d 100644 --- a/src/components/lights/LightBase.ts +++ b/src/components/lights/LightBase.ts @@ -9,6 +9,7 @@ import { LightData } from './LightData'; import { ShadowLightsCollect } from '../../gfx/renderJob/collect/ShadowLightsCollect'; import { IESProfiles } from './IESProfiles'; import { ILight } from './ILight'; +import { Engine3D } from '../../Engine3D'; /** * @internal @@ -74,19 +75,26 @@ export class LightBase extends ComponentBase implements ILight { } else { ShadowLightsCollect.removeShadowLight(this); } + + if (this.transform.view3D && Engine3D.renderJobs) { + let renderer = Engine3D.renderJobs.get(this.transform.view3D).reflectionRenderer; + if (renderer) + Engine3D.renderJobs.get(this.transform.view3D).reflectionRenderer.forceUpdate(); + } } public start(): void { this.transform.onPositionChange = () => this.onPositionChange(); - this.transform.onScaleChange = () => this.onScaleChange(); + // this.transform.onScaleChange = () => this.onScaleChange(); this.transform.onRotationChange = () => this.onRotChange(); this.onPositionChange(); this.onRotChange(); - this.onScaleChange(); + // this.onScaleChange(); } protected onPositionChange() { this.lightData.lightPosition.copyFrom(this.transform.worldPosition); + this.onChange(); } protected onRotChange() { diff --git a/src/components/lights/LightData.ts b/src/components/lights/LightData.ts index 88278cf0..efb7ed4f 100644 --- a/src/components/lights/LightData.ts +++ b/src/components/lights/LightData.ts @@ -41,13 +41,13 @@ export class LightData extends Struct { * * Light source radius */ - public radius: number = 0.5; + public radius: number = 0.001; /** * * The illumination distance of the light source, which is 0, means that the intensity of the light will not decrease due to the distance */ - public linear: number = 1.0; + public linear: number = 8.0; public lightPosition: Vector3 = new Vector3(); diff --git a/src/components/post/PostProcessingComponent.ts b/src/components/post/PostProcessingComponent.ts index 4ed3467c..82c66b4b 100644 --- a/src/components/post/PostProcessingComponent.ts +++ b/src/components/post/PostProcessingComponent.ts @@ -46,15 +46,6 @@ export class PostProcessingComponent extends ComponentBase { public addPost(c: Ctor): T { if (this._postList.has(c)) return; - if (!this._postList.has(FXAAPost)) { - let post = new FXAAPost(); - this._postList.set(FXAAPost, post); - if (this._enable) - this.activePost(); - if (c === FXAAPost) { - return post as T; - } - } let post = new c(); this._postList.set(c, post); if (this._enable) diff --git a/src/components/renderer/GlobalIlluminationComponent.ts b/src/components/renderer/GlobalIlluminationComponent.ts index 2fd56694..5f23b46d 100644 --- a/src/components/renderer/GlobalIlluminationComponent.ts +++ b/src/components/renderer/GlobalIlluminationComponent.ts @@ -1,4 +1,5 @@ import { Engine3D } from "../../Engine3D"; +import { Scene3D } from "../../core/Scene3D"; import { GlobalBindGroup } from "../../gfx/graphics/webGpu/core/bindGroups/GlobalBindGroup"; import { EntityCollect } from "../../gfx/renderJob/collect/EntityCollect"; import { DDGIIrradianceVolume } from "../../gfx/renderJob/passRenderer/ddgi/DDGIIrradianceVolume"; @@ -26,16 +27,14 @@ export class GlobalIlluminationComponent extends ComponentBase { private _debugMr: MeshRenderer[] = []; - public init(): void { + public init(scene: Scene3D): void { + scene ||= Engine3D.views[0]?.scene; Engine3D.setting.gi.enable = true; + this._volume = GlobalBindGroup.getLightEntries(scene).irradianceVolume; + this.initProbe(scene); } - public start(): void { - this._volume = GlobalBindGroup.getLightEntries(this.transform.scene3D).irradianceVolume; - this.initProbe(); - } - - private initProbe() { + private initProbe(scene: Scene3D) { let xCount: number = this._volume.setting.probeXCount; let yCount: number = this._volume.setting.probeYCount; let zCount: number = this._volume.setting.probeZCount; @@ -78,7 +77,7 @@ export class GlobalIlluminationComponent extends ComponentBase { } for (let i = 0; i < this._probes.length; i++) { - EntityCollect.instance.addGIProbe(this.transform.scene3D, this._probes[i]); + EntityCollect.instance.addGIProbe(scene, this._probes[i]); } this.object3D.transform.enable = false; diff --git a/src/components/renderer/InstanceDrawComponent.ts b/src/components/renderer/InstanceDrawComponent.ts index b34f005e..f1d61ee8 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 { PassType } from "../../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../../gfx/renderJob/passRenderer/state/PassType"; import { ClusterLightingBuffer } from "../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer"; export class InstanceDrawComponent extends RenderNode { @@ -15,6 +15,11 @@ export class InstanceDrawComponent extends RenderNode { private _keyRenderGroup: Map; private _keyBufferGroup: Map; private _keyIdsGroup: Map; + + constructor() { + super(); + } + public init(param?: any): void { this._keyRenderGroup = new Map(); this._keyBufferGroup = new Map(); @@ -80,7 +85,6 @@ export class InstanceDrawComponent extends RenderNode { } renderNode.nodeUpdate(view, passType, renderPassState, clusterLightingBuffer); }) - this.preInit = false; } diff --git a/src/components/renderer/MeshRenderer.ts b/src/components/renderer/MeshRenderer.ts index 7caf94d2..25b11edc 100644 --- a/src/components/renderer/MeshRenderer.ts +++ b/src/components/renderer/MeshRenderer.ts @@ -4,7 +4,7 @@ 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 { PassType } from '../../gfx/renderJob/passRenderer/state/RendererType'; +import { PassType } from '../../gfx/renderJob/passRenderer/state/PassType'; import { MorphTargetData } from '../anim/morphAnim/MorphTargetData'; import { RenderNode } from './RenderNode'; import { EditorInspector, RegisterComponent } from '../../util/SerializeDecoration'; @@ -54,7 +54,6 @@ export class MeshRenderer extends RenderNode { return this._geometry; } - @EditorInspector public set geometry(value: GeometryBase) { //this must use super geometry has reference in super super.geometry = value; @@ -95,7 +94,6 @@ export class MeshRenderer extends RenderNode { return this._materials[0]; } - @EditorInspector public set material(value: Material) { this.materials = [value]; } diff --git a/src/components/renderer/Reflection.ts b/src/components/renderer/Reflection.ts new file mode 100644 index 00000000..44969392 --- /dev/null +++ b/src/components/renderer/Reflection.ts @@ -0,0 +1,46 @@ + +import { View3D } from '../../core/View3D'; +import { BoundingBox } from '../../core/bound/BoundingBox'; +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 { PassType } from '../../gfx/renderJob/passRenderer/state/PassType'; +import { Vector3 } from '../../math/Vector3'; +import { RenderNode } from './RenderNode'; +import { mergeFunctions } from '../../util/Global'; + +/** + * + * Sky Box Renderer Component + * @group Components + */ +export class Reflection extends RenderNode { + public gid: number = 0; + public needUpdate: boolean = true; + public autoUpdate: boolean = false; + public radius: number = 500; + public init(): void { + super.init(); + this.addRendererMask(RendererMask.Reflection); + this.alwaysRender = true; + this.object3D.bound = new BoundingBox(Vector3.ZERO.clone(), Vector3.MAX); + + mergeFunctions(this.transform.onPositionChange, () => { + this.needUpdate = true; + }); + } + + public onEnable(): void { + EntityCollect.instance.addRenderNode(this.transform.scene3D, this); + } + + public onDisable(): void { + EntityCollect.instance.removeRenderNode(this.transform.scene3D, this); + } + + public renderPass2(view: View3D, passType: PassType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { + super.renderPass2(view, passType, rendererPassState, clusterLightingBuffer, encoder, useBundle); + } + +} diff --git a/src/components/renderer/RenderNode.ts b/src/components/renderer/RenderNode.ts index 04d46ce6..194485f6 100644 --- a/src/components/renderer/RenderNode.ts +++ b/src/components/renderer/RenderNode.ts @@ -7,13 +7,11 @@ import { GlobalBindGroup } from "../../gfx/graphics/webGpu/core/bindGroups/Globa import { ShaderReflection } from "../../gfx/graphics/webGpu/shader/value/ShaderReflectionInfo"; import { GPUContext } from "../../gfx/renderJob/GPUContext"; import { EntityCollect } from "../../gfx/renderJob/collect/EntityCollect"; -import { ShadowLightsCollect } from "../../gfx/renderJob/collect/ShadowLightsCollect"; import { RTResourceMap } from "../../gfx/renderJob/frame/RTResourceMap"; 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 { PassType } from "../../gfx/renderJob/passRenderer/state/RendererType"; import { GetCountInstanceID, UUID } from "../../util/Global"; import { Reference } from "../../util/Reference"; import { ComponentBase } from "../ComponentBase"; @@ -23,7 +21,9 @@ 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 "../.."; +import { RenderShaderCompute } from "../../gfx/graphics/webGpu/compute/RenderShaderCompute"; +import { PassType } from "../../gfx/renderJob/passRenderer/state/PassType"; +import { ProfilerUtil } from "../../util/ProfilerUtil"; /** @@ -31,6 +31,7 @@ import { RenderShaderCompute, ComputeShader } from "../.."; * @group Components */ export class RenderNode extends ComponentBase { + public instanceCount: number = 0; public lodLevel: number = 0; public alwaysRender: boolean = false; @@ -40,7 +41,7 @@ export class RenderNode extends ComponentBase { protected _geometry: GeometryBase; protected _materials: Material[] = []; protected _castShadow: boolean = true; - protected _castReflection: boolean = false; + protected _castReflection: boolean = true; protected _castGI: boolean = false; protected _rendererMask: number = RendererMask.Default; protected _inRenderer: boolean = false; @@ -50,11 +51,11 @@ export class RenderNode extends ComponentBase { protected _ignorePrefilterMap?: boolean; protected __renderOrder: number = 0;//cameraDepth + _renderOrder protected _renderOrder: number = 0; + protected _passInit: Map = new Map(); public isRenderOrderChange?: boolean; public needSortOnCameraZ?: boolean; protected _octreeBinder: { octree: Octree, entity: OctreeEntity }; - public preInit: boolean = false; /** * * The layer membership of the object. @@ -237,6 +238,7 @@ export class RenderNode extends ComponentBase { } public onDisable(): void { + this._enable = false; EntityCollect.instance.removeRenderNode(this.transform.scene3D, this); super.onDisable?.(); } @@ -314,8 +316,8 @@ export class RenderNode extends ComponentBase { if (this.castReflection) { for (let i = 0; i < this.materials.length; i++) { const mat = this.materials[i]; - if (mat.castShadow) { - PassGenerate.createShadowPass(this, mat.shader); + if (mat.castReflection) { + PassGenerate.createReflectionPass(this, mat.shader); } } } @@ -340,7 +342,6 @@ export class RenderNode extends ComponentBase { return this._castShadow; } - @EditorInspector public set castShadow(value: boolean) { this._castShadow = value; } @@ -350,7 +351,6 @@ export class RenderNode extends ComponentBase { return this._castGI; } - @EditorInspector public set castGI(value: boolean) { this._castGI = value; } @@ -377,6 +377,8 @@ export class RenderNode extends ComponentBase { continue; GPUContext.bindGeometryBuffer(renderContext.encoder, renderNode._geometry); + ProfilerUtil.viewCount_vertex(view, PassType[passType], renderNode._geometry.vertexCount); + for (let j = 0; j < passes.length; j++) { if (!passes || passes.length == 0) continue; @@ -396,16 +398,26 @@ export class RenderNode extends ComponentBase { GPUContext.bindCamera(renderContext.encoder, view.camera); GPUContext.bindGeometryBuffer(renderContext.encoder, renderNode._geometry); } - GPUContext.bindPipeline(renderContext.encoder, renderShader); + + let noneShare = GPUContext.bindPipeline(renderContext.encoder, renderShader); + if (noneShare) { + ProfilerUtil.viewCount_pipeline(view, PassType[passType]); + } let subGeometry = renderNode._geometry.subGeometries[i]; let lodInfos = subGeometry.lodLevels; let lodInfo = lodInfos[renderNode.lodLevel]; if (renderNode.instanceCount > 0) { + ProfilerUtil.viewCount_instance(view, PassType[passType], renderNode.instanceCount); + ProfilerUtil.viewCount_indices(view, PassType[passType], lodInfo.indexCount); + ProfilerUtil.viewCount_tri(view, PassType[passType], lodInfo.indexCount / 3 * renderNode.instanceCount); GPUContext.drawIndexed(renderContext.encoder, lodInfo.indexCount, renderNode.instanceCount, lodInfo.indexStart, 0, 0); } else { + ProfilerUtil.viewCount_indices(view, PassType[passType], lodInfo.indexCount); + ProfilerUtil.viewCount_tri(view, PassType[passType], lodInfo.indexCount / 3); GPUContext.drawIndexed(renderContext.encoder, lodInfo.indexCount, 1, lodInfo.indexStart, 0, worldMatrix.index); } + ProfilerUtil.viewCount_draw(view, PassType[passType],); } } } @@ -490,12 +502,17 @@ export class RenderNode extends ComponentBase { private noticeShaderChange() { if (this.enable) { this.onEnable(); - this.preInit = false; + this._passInit.forEach((v, k) => { + this._passInit.set(k, false); + }) } } + preInit(_rendererType: PassType): boolean { + return this._passInit.get(_rendererType); + } + public nodeUpdate(view: View3D, passType: PassType, renderPassState: RendererPassState, clusterLightingBuffer?: ClusterLightingBuffer) { - this.preInit = true; let node = this; let envMap = view.scene.envMap; @@ -505,7 +522,6 @@ export class RenderNode extends ComponentBase { if (passes) { for (let i = 0; i < passes.length; i++) { const pass = passes[i]; - const renderShader = pass; if (renderShader.shaderState.splitTexture) { @@ -518,9 +534,17 @@ export class RenderNode extends ComponentBase { } // if (!node._ignorePrefilterMap && renderShader.prefilterMap != envMap) { - renderShader.setTexture(`prefilterMap`, envMap); + if (!renderShader.prefilterMap) { + renderShader.setTexture(`prefilterMap`, envMap); + } // } + let reflectionEntries = GlobalBindGroup.getReflectionEntries(view.scene); + if (!renderShader.reflectionMap && reflectionEntries && reflectionEntries.reflectionMap) { + renderShader.setTexture(`reflectionMap`, reflectionEntries.reflectionMap); + renderShader.setStorageBuffer(`reflectionBuffer`, reflectionEntries.storageGPUBuffer); + } + if (renderShader.pipeline) { renderShader.apply(node._geometry, renderPassState, () => node.noticeShaderChange()); continue; @@ -567,6 +591,8 @@ export class RenderNode extends ComponentBase { } renderShader.apply(node._geometry, renderPassState); + + this._passInit.set(passType, true); } } } diff --git a/src/components/renderer/SkinnedMeshRenderer.ts b/src/components/renderer/SkinnedMeshRenderer.ts index 0ded5c18..eb00ea48 100644 --- a/src/components/renderer/SkinnedMeshRenderer.ts +++ b/src/components/renderer/SkinnedMeshRenderer.ts @@ -3,7 +3,7 @@ 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 { PassType } from "../../gfx/renderJob/passRenderer/state/PassType"; import { RendererPassState } from "../../gfx/renderJob/passRenderer/state/RendererPassState"; import { SkeletonAnimationComponent } from "../SkeletonAnimationComponent"; import { ClusterLightingBuffer } from "../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer"; diff --git a/src/components/renderer/SkinnedMeshRenderer2.ts b/src/components/renderer/SkinnedMeshRenderer2.ts index dba19a12..455f6cfd 100644 --- a/src/components/renderer/SkinnedMeshRenderer2.ts +++ b/src/components/renderer/SkinnedMeshRenderer2.ts @@ -3,7 +3,7 @@ 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 { PassType } from "../../gfx/renderJob/passRenderer/state/PassType"; import { RendererPassState } from "../../gfx/renderJob/passRenderer/state/RendererPassState"; import { ClusterLightingBuffer } from "../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer"; import { AnimatorComponent, GeometryBase, LitMaterial, Matrix4, RegisterComponent } from "../.."; diff --git a/src/components/renderer/SkyRenderer.ts b/src/components/renderer/SkyRenderer.ts index 1a0e8011..98be96a6 100644 --- a/src/components/renderer/SkyRenderer.ts +++ b/src/components/renderer/SkyRenderer.ts @@ -8,10 +8,12 @@ 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 { PassType } from '../../gfx/renderJob/passRenderer/state/RendererType'; +import { PassType } from '../../gfx/renderJob/passRenderer/state/PassType'; import { SkyMaterial } from '../../materials/SkyMaterial'; import { Vector3 } from '../../math/Vector3'; import { SphereGeometry } from '../../shape/SphereGeometry'; +import { Object3D } from '../../core/entities/Object3D'; +import { SphereReflection } from './SphereReflection'; /** * @@ -24,7 +26,6 @@ export class SkyRenderer extends MeshRenderer { */ public skyMaterial: SkyMaterial; - public init(): void { super.init(); this.castShadow = false; @@ -58,6 +59,10 @@ export class SkyRenderer extends MeshRenderer { super.onDisable(); } + public nodeUpdate(view: View3D, passType: PassType, renderPassState: RendererPassState, clusterLightingBuffer?: ClusterLightingBuffer) { + super.nodeUpdate(view, passType, renderPassState, clusterLightingBuffer); + } + 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); @@ -73,6 +78,7 @@ export class SkyRenderer extends MeshRenderer { this.skyMaterial.name = 'skyMaterial'; } this.material = this.skyMaterial; + // this.useSkyReflection(); } /** @@ -100,4 +106,14 @@ export class SkyRenderer extends MeshRenderer { this.skyMaterial.roughness = value; } + public useSkyReflection() { + let reflection = new Object3D(); + let ref = reflection.addComponent(SphereReflection); + ref.autoUpdate = false; + reflection.x = 0; + reflection.y = 300; + reflection.z = 0; + this.object3D.addChild(reflection); + } + } diff --git a/src/components/renderer/SphereReflection.ts b/src/components/renderer/SphereReflection.ts new file mode 100644 index 00000000..99a2d327 --- /dev/null +++ b/src/components/renderer/SphereReflection.ts @@ -0,0 +1,68 @@ + +import { View3D } from '../../core/View3D'; +import { BoundingBox } from '../../core/bound/BoundingBox'; +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 { PassType } from '../../gfx/renderJob/passRenderer/state/PassType'; +import { Vector3 } from '../../math/Vector3'; +import { SphereGeometry } from '../../shape/SphereGeometry'; +import { Reflection } from './Reflection'; +import { Object3D } from '../../core/entities/Object3D'; +import { MeshRenderer } from './MeshRenderer'; +import { GBufferFrame } from '../../gfx/renderJob/frame/GBufferFrame'; +import { ReflectionMaterial } from '../../materials/ReflectionMaterial'; +import { BoundingSphere } from '../../core/bound/BoundingSphere'; +import { Engine3D } from '../../Engine3D'; + + +/** + * + * Sky Box Renderer Component + * @group Components + */ +export class SphereReflection extends Reflection { + public init(): void { + super.init(); + this.castShadow = false; + this.castGI = false; + this.addRendererMask(RendererMask.Reflection); + this.alwaysRender = true; + + this.object3D.bound = new BoundingSphere(Vector3.ZERO.clone(), this.radius); + } + + public debug(index: number, scale: number = 1): void { + let obj = new Object3D(); + let mr = obj.addComponent(MeshRenderer); + mr.addMask(RendererMask.ReflectionDebug); + mr.geometry = new SphereGeometry(25, 30, 30); + // mr.material = new LitMaterial(); + + let reflectionSetting = Engine3D.setting.reflectionSetting; + let reflectionsGBufferFrame = GBufferFrame.getGBufferFrame(GBufferFrame.reflections_GBuffer, reflectionSetting.width, reflectionSetting.height); + let mat = new ReflectionMaterial(); + mat.reflectionIndex = index; + mat.baseMap = reflectionsGBufferFrame.getCompressGBufferTexture(); + mr.material = mat; + this.object3D.addChild(obj); + + obj.scaleX = scale; + obj.scaleY = scale; + obj.scaleZ = scale; + } + + public onEnable(): void { + super.onEnable(); + } + + public onDisable(): void { + super.onDisable(); + } + + public renderPass2(view: View3D, passType: PassType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { + super.renderPass2(view, passType, rendererPassState, clusterLightingBuffer, encoder, useBundle); + } + + +} diff --git a/src/core/Camera3D.ts b/src/core/Camera3D.ts index 10d20559..021979f8 100644 --- a/src/core/Camera3D.ts +++ b/src/core/Camera3D.ts @@ -20,6 +20,7 @@ import { CSM } from './csm/CSM'; * @group Components */ export class Camera3D extends ComponentBase { + /** * camera Perspective */ @@ -55,6 +56,20 @@ export class Camera3D extends ComponentBase { */ public frustum: Frustum; + public sh_bak: Float32Array = new Float32Array([ + 2.485296, 2.52417, 2.683965, 3.544894, + 0.2323964, 0.1813751, 0.08516902, -4.860471E-05, + -0.2744142, -0.04131086, 0.2248164, -0.005996059, + 0.1551732, 0.137717, 0.1002693, -0.0006728604, + 0.2209381, 0.2109673, 0.1770538, -1.395991E-05, + 0.3529238, 0.2824739, 0.1817433, -0.0005164869, + -0.1344275, -0.1289607, -0.1347626, 7.825881E-06, + 0.2125785, 0.1779549, 0.124602, 0.000503074, + -0.1039777, -0.09676537, -0.07681116, -0.0004372867, + ]); + + public sh: Float32Array = new Float32Array(36); + /** * this camera is shadow camera */ @@ -66,6 +81,7 @@ export class Camera3D extends ComponentBase { private _projectionMatrixInv: Matrix4 = new Matrix4(); private _projectionMatrix: Matrix4 = new Matrix4(); private _viewMatrix: Matrix4 = new Matrix4(); + private _viewMatrixInv: Matrix4 = new Matrix4(); private _unprojection: Matrix4 = new Matrix4(); private _pvMatrixInv: Matrix4 = new Matrix4(); private _pvMatrix: Matrix4 = new Matrix4(); @@ -73,6 +89,7 @@ export class Camera3D extends ComponentBase { private _halfh: number; private _ray: Ray; private _enableCSM: boolean = false; + public mainCamera: Camera3D; /** * @internal @@ -122,6 +139,8 @@ export class Camera3D extends ComponentBase { this.viewPort.w = webGPUContext.presentationSize[0]; this.viewPort.h = webGPUContext.presentationSize[1]; this.lookTarget = new Vector3(0, 0, 0); + + this.perspective(60, webGPUContext.aspect, 1, 1000.0); } public getShadowBias(depthTexSize: number): number { @@ -140,10 +159,20 @@ export class Camera3D extends ComponentBase { return shadowBound; } - public getCSMShadowBias(index: number, depthTexSize: number): number { - let sizeOnePixel = 2.0 * this.getCSMShadowWorldExtents(index) / depthTexSize; - let depth = this.far - this.near; - return sizeOnePixel / depth; + // public getCSMShadowBias(index: number, depthTexSize: number): number { + // let sizeOnePixel = 2.0 * this.getCSMShadowWorldExtents(index) / depthTexSize; + // let depth = this.far - this.near; + // return sizeOnePixel / depth; + // } + + public getCSMShadowBiasScale(shadowCamera: Camera3D): number { + if (shadowCamera == this) + return 1.0; + + let currentSize = this.far - this.near; + let baseCamera = this.csm.children[0].shadowCamera; + let baseSize = baseCamera.far - baseCamera.near; + return baseSize / currentSize; } public getCSMShadowWorldExtents(index: number): number { @@ -296,6 +325,27 @@ export class Camera3D extends ComponentBase { return matrix; } + public get vMatrixInv(): Matrix4 { + let matrix = this._viewMatrixInv.copyFrom(this.viewMatrix); + matrix.invert(); + return matrix; + } + + public get cameraToWorld(): Matrix4 { + let cameraToWorld = Matrix4.helpMatrix; + cameraToWorld.identity(); + cameraToWorld.copyFrom(this.projectionMatrixInv); + cameraToWorld.multiply(this.vMatrixInv); + return cameraToWorld; + } + + public get ndcToView(): Matrix4 { + let cameraToWorld = Matrix4.helpMatrix; + cameraToWorld.identity(); + cameraToWorld.copyFrom(this.projectionMatrixInv); + return cameraToWorld; + } + /** * get project invert matrix */ @@ -450,7 +500,7 @@ export class Camera3D extends ComponentBase { this._useJitterProjection = value; this._haltonSeq ||= new HaltonSeq(); this._jitterOffsetList = []; - for (let i = 0; i < 8; i++) { + for (let i = 0; i < 32; i++) { let offset = this.generateRandomOffset(); this._jitterOffsetList.push(offset); } @@ -459,7 +509,7 @@ export class Camera3D extends ComponentBase { private generateRandomOffset(): Vector2 { let offset = new Vector2(HaltonSeq.get((this._sampleIndex & 1023) + 1, 2) - 0.5, HaltonSeq.get((this._sampleIndex & 1023) + 1, 3) - 0.5); - const k_SampleCount = 8; + const k_SampleCount = 32; if (++this._sampleIndex >= k_SampleCount) this._sampleIndex = 0; return offset; diff --git a/src/core/CubeCamera.ts b/src/core/CubeCamera.ts index 6aa491a3..b570946c 100644 --- a/src/core/CubeCamera.ts +++ b/src/core/CubeCamera.ts @@ -16,6 +16,8 @@ export class CubeCamera extends Object3D { public right_camera: Camera3D; public front_camera: Camera3D; public back_camera: Camera3D; + private _near: number; + private _far: number; /** * @@ -70,4 +72,32 @@ export class CubeCamera extends Object3D { this.back_camera.type = CameraType.shadow; } + public set near(value: number) { + this._near = value; + this.up_camera.near = value; + this.down_camera.near = value; + this.left_camera.near = value; + this.right_camera.near = value; + this.front_camera.near = value; + this.back_camera.near = value; + } + + public get near() { + return this._near; + } + + + public set far(value: number) { + this._far = value; + this.up_camera.far = value; + this.down_camera.far = value; + this.left_camera.far = value; + this.right_camera.far = value; + this.front_camera.far = value; + this.back_camera.far = value; + } + + public get far() { + return this._far; + } } diff --git a/src/core/Scene3D.ts b/src/core/Scene3D.ts index 0a74dcea..652ad662 100644 --- a/src/core/Scene3D.ts +++ b/src/core/Scene3D.ts @@ -1,4 +1,5 @@ import { Engine3D } from '../Engine3D'; +import { SphereReflection } from '../components/renderer/SphereReflection'; import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; import { EntityCollect } from '../gfx/renderJob/collect/EntityCollect'; import { View3D } from './View3D'; @@ -45,6 +46,15 @@ export class Scene3D extends Object3D { this._envMap = value; if (EntityCollect.instance.sky && `map` in EntityCollect.instance.sky) EntityCollect.instance.sky.map = value; + + // let reflection = new Object3D(); + // let ref = reflection.addComponent(SphereReflection); + // ref.autoUpdate = true; + // ref.debug(0, 5); + // reflection.x = 0; + // reflection.y = 300; + // reflection.z = 0; + // this.addChild(reflection); } /** diff --git a/src/core/ViewQuad.ts b/src/core/ViewQuad.ts index f271852c..805bad0f 100644 --- a/src/core/ViewQuad.ts +++ b/src/core/ViewQuad.ts @@ -8,7 +8,7 @@ import { PlaneGeometry } from '../shape/PlaneGeometry'; import { Object3D } from './entities/Object3D'; import { RendererPassState } from '../gfx/renderJob/passRenderer/state/RendererPassState'; import { GPUContext } from '../gfx/renderJob/GPUContext'; -import { PassType } from '../gfx/renderJob/passRenderer/state/RendererType'; +import { PassType } from '../gfx/renderJob/passRenderer/state/PassType'; import { View3D } from './View3D'; import { Material } from '../materials/Material'; import { QuadShader } from '../loader/parser/prefab/mats/shader/QuadShader'; diff --git a/src/core/entities/Entity.ts b/src/core/entities/Entity.ts index 3c17bae1..50fff1ce 100644 --- a/src/core/entities/Entity.ts +++ b/src/core/entities/Entity.ts @@ -138,6 +138,7 @@ export class Entity extends CEventDispatcher { child.transform.parent = this.transform; this.entityChildren.push(child); this._numChildren = this.entityChildren.length; + this.noticeComponents(`onAddChild`, child); return child; } return null; @@ -156,6 +157,7 @@ export class Entity extends CEventDispatcher { this.entityChildren.splice(index, 1); child.transform.parent = null; this._numChildren = this.entityChildren.length; + this.noticeComponents(`onRemoveChild`, child); } } @@ -314,9 +316,6 @@ export class Entity extends CEventDispatcher { this.components.clear(); } else { ComponentCollect.waitStartComponent.forEach((v, k) => { - // v.forEach((v) => { - // v[`__start`](); - // }) while (v.length > 0) { const element = v.shift(); element[`__start`](); @@ -326,6 +325,13 @@ export class Entity extends CEventDispatcher { } } + public noticeComponents(key: keyof IComponent, data: any) { + for (let item of this.components.values()) { + let typeKey = key as string; + item[typeKey]?.(data); + } + } + /** * release current object diff --git a/src/core/entities/Object3D.ts b/src/core/entities/Object3D.ts index 7088ad32..f6363afb 100644 --- a/src/core/entities/Object3D.ts +++ b/src/core/entities/Object3D.ts @@ -61,7 +61,7 @@ export class Object3D extends Entity { ComponentCollect.appendWaitStart(instance); return instance; } - return null; + return this.components.get(c) as T; } diff --git a/src/core/geometry/GeometryBase.ts b/src/core/geometry/GeometryBase.ts index fc07e05c..b8b18ce7 100644 --- a/src/core/geometry/GeometryBase.ts +++ b/src/core/geometry/GeometryBase.ts @@ -45,6 +45,7 @@ export class GeometryBase { public bindPose: Matrix4[]; public blendShapeData: BlendShapeData; public vertexDim: number; + public vertexCount: number = 0; private _bounds: BoundingBox; private _attributeMap: Map; @@ -135,6 +136,7 @@ export class GeometryBase { this._bounds = value; } + /** * add subGeometry from lod level * @param lodLevels @see LODDescriptor @@ -156,6 +158,7 @@ export class GeometryBase { this._indicesBuffer.upload(this.getAttribute(VertexAttributeName.indices).data); this._vertexBuffer.createVertexBuffer(this._attributeMap, shaderReflection); this._vertexBuffer.updateAttributes(this._attributeMap); + this.vertexCount = this._vertexBuffer.vertexCount; } } diff --git a/src/gfx/generate/PassGenerate.ts b/src/gfx/generate/PassGenerate.ts index 416d7312..d6b278f4 100644 --- a/src/gfx/generate/PassGenerate.ts +++ b/src/gfx/generate/PassGenerate.ts @@ -1,6 +1,6 @@ import { RenderNode } from '../../components/renderer/RenderNode'; import { RendererMaskUtil, RendererMask } from '../renderJob/passRenderer/state/RendererMask'; -import { PassType } from '../renderJob/passRenderer/state/RendererType'; +import { PassType } from '../renderJob/passRenderer/state/PassType'; import { GLTFType } from '../../loader/parser/gltf/GLTFType'; import { Shader } from '../graphics/webGpu/shader/Shader'; import { SkyGBufferPass } from '../../materials/multiPass/SkyGBufferPass'; @@ -9,12 +9,14 @@ import { VertexAttributeName } from '../../core/geometry/VertexAttributeName'; import { CastShadowMaterialPass } from '../../materials/multiPass/CastShadowMaterialPass'; import { CastPointShadowMaterialPass } from '../../materials/multiPass/CastPointShadowMaterialPass'; import { DepthMaterialPass } from '../../materials/multiPass/DepthMaterialPass'; +import { RenderShaderPass } from '../..'; /** * @internal * @group GFX */ export class PassGenerate { + public static createGIPass(renderNode: RenderNode, shader: Shader) { if (RendererMaskUtil.hasMask(renderNode.rendererMask, RendererMask.Sky)) { let pass0 = shader.passShader.get(PassType.GI); @@ -160,4 +162,44 @@ export class PassGenerate { } } } + + static createReflectionPass(renderNode: RenderNode, shader: Shader) { + let colorPassList = shader.getDefaultShaders(); + for (let jj = 0; jj < colorPassList.length; jj++) { + const colorPass = colorPassList[jj]; + + let colorSubPassList = shader.getSubShaders(PassType.REFLECTION); + if (!colorSubPassList || colorSubPassList.length == 0 || colorSubPassList.length < jj) { + let pass = new RenderShaderPass(colorPass.vsName, colorPass.fsName); + pass.vsEntryPoint = colorPass.vsEntryPoint; + pass.fsEntryPoint = colorPass.fsEntryPoint; + pass.passType = PassType.REFLECTION; + + for (const state in colorPass.shaderState) { + var v = colorPass.shaderState[state]; + pass.shaderState[state] = v; + } + + for (const textureName in colorPass.textures) { + var texture = colorPass.getTexture(textureName); + pass.setTexture(textureName, texture); + } + + for (const uniformName in colorPass.uniforms) { + var value = colorPass.getUniform(uniformName); + pass.setUniform(uniformName, value); + } + + for (const defineName in colorPass.defineValue) { + var value = colorPass.defineValue[defineName]; + pass.setDefine(defineName, value); + } + + pass.setDefine("USE_CASTREFLECTION", true); + + pass.preCompile(renderNode.geometry); + shader.addRenderPass(pass); + } + } + } } diff --git a/src/gfx/generate/convert/TextureScaleCompute.ts b/src/gfx/generate/convert/TextureScaleCompute.ts new file mode 100644 index 00000000..1643a481 --- /dev/null +++ b/src/gfx/generate/convert/TextureScaleCompute.ts @@ -0,0 +1,27 @@ +import { ComputeShader, GPUContext, textureCompress } from "../../.."; +import { Texture } from "../../graphics/webGpu/core/texture/Texture"; + +export class TextureScaleCompute { + + public computeShader: ComputeShader; + + public setInputes(colorMap: Texture, inputs: Texture[], outputs: Texture[]) { + this.computeShader = new ComputeShader(textureCompress(colorMap, inputs, outputs, 8, 8, 1)); + for (let i = 0; i < inputs.length; i++) { + this.computeShader.setSamplerTexture(`source${i}Map`, inputs[i]); + } + for (let i = 0; i < outputs.length; i++) { + this.computeShader.setStorageTexture(`dest${i}Map`, outputs[i]); + } + + if (colorMap) { + this.computeShader.setSamplerTexture(`colorMap`, colorMap); + } + + this.computeShader.workerSizeX = outputs[0].width / 8; + this.computeShader.workerSizeY = outputs[0].height / 8; + this.computeShader.workerSizeZ = 1; + } + + +} \ No newline at end of file diff --git a/src/gfx/graphics/webGpu/Context3D.ts b/src/gfx/graphics/webGpu/Context3D.ts index b5bd4252..d7757266 100644 --- a/src/gfx/graphics/webGpu/Context3D.ts +++ b/src/gfx/graphics/webGpu/Context3D.ts @@ -6,7 +6,8 @@ import { CanvasConfig } from './CanvasConfig'; /** * @internal */ -class Context3D extends CEventDispatcher { +export class Context3D extends CEventDispatcher { + public adapter: GPUAdapter; public device: GPUDevice; public context: GPUCanvasContext; @@ -19,10 +20,11 @@ class Context3D extends CEventDispatcher { public canvasConfig: CanvasConfig; private _pixelRatio: number = 1.0; private _resizeEvent: CEvent; - // initSize: number[]; + public get pixelRatio() { return this._pixelRatio; } + /** * Configure canvas by CanvasConfig * @param canvasConfig @@ -33,8 +35,9 @@ class Context3D extends CEventDispatcher { if (canvasConfig && canvasConfig.canvas) { this.canvas = canvasConfig.canvas; - if (this.canvas === null) + if (this.canvas === null) { throw new Error('no Canvas') + } // check if external canvas has initial with and height style // TODO: any way to check external css style? @@ -53,29 +56,35 @@ class Context3D extends CEventDispatcher { this.canvas.style.zIndex = canvasConfig?.zIndex ? canvasConfig.zIndex.toString() : '0'; document.body.appendChild(this.canvas); } + // set canvas bg if (canvasConfig && canvasConfig.backgroundImage) { - this.canvas.style.background = `url(${canvasConfig.backgroundImage})` - this.canvas.style['background-size'] = 'cover' - this.canvas.style['background-position'] = 'center' - } else + this.canvas.style.background = `url(${canvasConfig.backgroundImage})`; + this.canvas.style['background-size'] = 'cover'; + this.canvas.style['background-position'] = 'center'; + } else { this.canvas.style.background = 'transparent'; + } + // prevent touch scroll - this.canvas.style['touch-action'] = 'none' - this.canvas.style['object-fit'] = 'cover' + this.canvas.style['touch-action'] = 'none'; + this.canvas.style['object-fit'] = 'cover'; // check webgpu support if (navigator.gpu === undefined) { throw new Error('Your browser does not support WebGPU!'); } + // request adapter this.adapter = await navigator.gpu.requestAdapter({ powerPreference: 'high-performance', // powerPreference: 'low-power', }); + if (this.adapter == null) { throw new Error('Your browser does not support WebGPU!'); } + // request device this.device = await this.adapter.requestDevice({ requiredFeatures: [ @@ -90,6 +99,7 @@ class Context3D extends CEventDispatcher { maxStorageBufferBindingSize: this.adapter.limits.maxStorageBufferBindingSize } }); + if (this.device == null) { throw new Error('Your browser does not support WebGPU!'); } @@ -114,6 +124,7 @@ class Context3D extends CEventDispatcher { this.updateSize() Texture.destroyTexture() }); + resizeObserver.observe(this.canvas); this.updateSize(); return true; diff --git a/src/gfx/graphics/webGpu/core/bindGroups/GlobalBindGroup.ts b/src/gfx/graphics/webGpu/core/bindGroups/GlobalBindGroup.ts index da27b222..36d8b92a 100644 --- a/src/gfx/graphics/webGpu/core/bindGroups/GlobalBindGroup.ts +++ b/src/gfx/graphics/webGpu/core/bindGroups/GlobalBindGroup.ts @@ -1,9 +1,8 @@ import { Camera3D } from "../../../../../core/Camera3D"; import { Scene3D } from "../../../../../core/Scene3D"; -import { Probe } from "../../../../renderJob/passRenderer/ddgi/Probe"; import { GlobalUniformGroup } from "./GlobalUniformGroup"; import { LightEntries } from "./groups/LightEntries"; -import { ProbeEntries } from "./groups/ProbeEntries"; +import { ReflectionEntries } from "./groups/ReflectionEntries"; import { MatrixBindGroup } from "./MatrixBindGroup"; /** @@ -14,13 +13,18 @@ import { MatrixBindGroup } from "./MatrixBindGroup"; export class GlobalBindGroup { private static _cameraBindGroups: Map; private static _lightEntriesMap: Map; - private static _probeEntries: ProbeEntries; + private static _reflectionEntriesMap: Map; public static modelMatrixBindGroup: MatrixBindGroup; public static init() { this.modelMatrixBindGroup = new MatrixBindGroup(); this._cameraBindGroups = new Map(); this._lightEntriesMap = new Map(); + this._reflectionEntriesMap = new Map(); + } + + public static getAllCameraGroup() { + return this._cameraBindGroups; } public static getCameraGroup(camera: Camera3D) { @@ -29,7 +33,6 @@ export class GlobalBindGroup { cameraBindGroup = new GlobalUniformGroup(this.modelMatrixBindGroup); this._cameraBindGroups.set(camera, cameraBindGroup); } - if (camera.isShadowCamera) { cameraBindGroup.setShadowCamera(camera); } else { @@ -38,6 +41,19 @@ export class GlobalBindGroup { return cameraBindGroup; } + public static updateCameraGroup(camera: Camera3D) { + let cameraBindGroup = this._cameraBindGroups.get(camera); + if (!cameraBindGroup) { + cameraBindGroup = new GlobalUniformGroup(this.modelMatrixBindGroup); + this._cameraBindGroups.set(camera, cameraBindGroup); + } + if (camera.isShadowCamera) { + cameraBindGroup.setShadowCamera(camera); + } else { + cameraBindGroup.setCamera(camera); + } + } + public static getLightEntries(scene: Scene3D): LightEntries { if (!scene) { console.log(`getLightEntries scene is null`); @@ -51,11 +67,19 @@ export class GlobalBindGroup { return this._lightEntriesMap.get(scene); } - public static updateProbes(probes: Probe[]) { - if (!this._probeEntries) { - this._probeEntries = new ProbeEntries(); - this._probeEntries.initDataUniform(probes); + public static getReflectionEntries(scene: Scene3D): ReflectionEntries { + if (!scene) { + console.log(`getLightEntries scene is null`); + } + + let reflectionEntries = this._reflectionEntriesMap.get(scene); + if (!reflectionEntries) { + reflectionEntries = new ReflectionEntries(); + this._reflectionEntriesMap.set(scene, reflectionEntries); } + return this._reflectionEntriesMap.get(scene); } + + } diff --git a/src/gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup.ts b/src/gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup.ts index 453106bf..faaaaaa4 100644 --- a/src/gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup.ts +++ b/src/gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup.ts @@ -1,9 +1,10 @@ -import { Vector3 } from "../../../../.."; +import { EntityCollect, Vector3, Vector4 } from "../../../../.."; import { Engine3D } from "../../../../../Engine3D"; import { Camera3D } from "../../../../../core/Camera3D"; import { CSM } from "../../../../../core/csm/CSM"; import { Matrix4 } from "../../../../../math/Matrix4"; import { UUID } from "../../../../../util/Global"; +import { ProfilerUtil } from "../../../../../util/ProfilerUtil"; import { Time } from "../../../../../util/Time"; import { ShadowLightsCollect } from "../../../../renderJob/collect/ShadowLightsCollect"; import { webGPUContext } from "../../Context3D"; @@ -17,6 +18,7 @@ import { MatrixBindGroup } from "./MatrixBindGroup"; * @group GFX */ export class GlobalUniformGroup { + public uuid: string; public usage: number; public globalBindGroup: GPUBindGroup; @@ -44,7 +46,7 @@ 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 = new UniformGPUBuffer(8192); + this.uniformGPUBuffer = new UniformGPUBuffer(8192 + 9 * 4 * 4); this.uniformGPUBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE; this.matrixBindGroup = matrixBindGroup; @@ -80,13 +82,12 @@ export class GlobalUniformGroup { }); } - - public setCamera(camera: Camera3D) { this.uniformGPUBuffer.setMatrix(`_projectionMatrix`, camera.projectionMatrix); this.uniformGPUBuffer.setMatrix(`_viewMatrix`, camera.viewMatrix); this.uniformGPUBuffer.setMatrix(`_cameraWorldMatrix`, camera.transform.worldMatrix); this.uniformGPUBuffer.setMatrix(`pvMatrixInv`, camera.projectionMatrixInv); + this.uniformGPUBuffer.setMatrix(`viewToWorld`, camera.cameraToWorld); let shadowLightList = ShadowLightsCollect.getDirectShadowLightWhichScene(camera.transform.scene3D); @@ -108,18 +109,31 @@ export class GlobalUniformGroup { for (let i = 0; i < CSM.Cascades; i++) { let shadowCamera: Camera3D = camera.csm.children[i].shadowCamera; this.csmMatrixRaw.set(shadowCamera.pvMatrix.rawData, i * 16); - this.csmShadowBias[i] = camera.getCSMShadowBias(i, shadowMapSize); + this.csmShadowBias[i] = camera.getCSMShadowBiasScale(shadowCamera); + // this.csmShadowBias[i] = camera.getCSMShadowBias(i, shadowMapSize); } } this.uniformGPUBuffer.setFloat32Array(`csmShadowBias`, this.csmShadowBias); this.uniformGPUBuffer.setFloat32Array(`csmMatrix`, this.csmMatrixRaw); this.uniformGPUBuffer.setFloat32Array(`shadowLights`, this.shadowLights); + let reflectionSetting = Engine3D.setting.reflectionSetting; + let reflectionCount = EntityCollect.instance.getReflections(camera.transform.scene3D).length; + this.uniformGPUBuffer.setFloat(`reflectionProbeSize`, reflectionSetting.reflectionProbeSize); + this.uniformGPUBuffer.setFloat(`reflectionProbeMaxCount`, reflectionSetting.reflectionProbeMaxCount); + this.uniformGPUBuffer.setFloat(`reflectionMapWidth`, reflectionSetting.width); + this.uniformGPUBuffer.setFloat(`reflectionMapHeight`, reflectionSetting.height); + this.uniformGPUBuffer.setFloat(`reflectionCount`, reflectionCount); + this.uniformGPUBuffer.setFloat(`test2`, ProfilerUtil.testObj.testValue2); + this.uniformGPUBuffer.setFloat(`test3`, ProfilerUtil.testObj.testValue3); + this.uniformGPUBuffer.setFloat(`test4`, ProfilerUtil.testObj.testValue4); + this.uniformGPUBuffer.setVector3(`CameraPos`, camera.transform.worldPosition); this.uniformGPUBuffer.setFloat(`frame`, Time.frame); + this.uniformGPUBuffer.setFloat32Array(`SH`, camera.sh); + 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); @@ -145,20 +159,22 @@ export class GlobalUniformGroup { this.uniformGPUBuffer.setInt32(`nDirShadowEnd`, this.dirShadowEnd); this.uniformGPUBuffer.setInt32(`nPointShadowStart`, this.pointShadowStart); this.uniformGPUBuffer.setInt32(`nPointShadowEnd`, this.pointShadowEnd); + this.uniformGPUBuffer.setVector3(`cameraForward`, camera.transform.forward); + this.uniformGPUBuffer.setVector4Array(`frustumPlanes`, camera.frustum.planes); - this.uniformGPUBuffer.setInt32(`empty1`, 0); - this.uniformGPUBuffer.setInt32(`empty2`, 0); - this.uniformGPUBuffer.setInt32(`empty3`, 0); + // new Float32Array([ + // 1.0, 1.0, 1.0, 1.0, + // 0.0, 1.0, 0.0, 1.0, + // 0.0, 0.0, 1.0, 1.0, - this.uniformGPUBuffer.setVector4Array(`frustumPlanes`, camera.frustum.planes); - // this.uniformGPUBuffer.setVector4Array(`frustumPlanes`, [ - // new Vector3(0.0, 0.0, 0.0, 0.0), - // new Vector3(1.0, 0.0, 0.0, 0.0), - // new Vector3(1.0, 1.0, 0.0, 0.0), - // new Vector3(0.0, 1.0, 0.0, 0.0), - // new Vector3(2.0, 0.0, 0.0, 0.0), - // new Vector3(2.0, 1.0, 0.0, 0.0), - // ]); + // 1.0, 0.0, 0.0, 1.0, + // 0.0, 1.0, 0.0, 1.0, + // 0.0, 0.0, 1.0, 1.0, + + // 1.0, 0.0, 0.0, 1.0, + // 0.0, 1.0, 0.0, 1.0, + // 0.0, 0.0, 1.0, 1.0, + // ])); this.uniformGPUBuffer.apply(); } @@ -168,6 +184,7 @@ export class GlobalUniformGroup { this.uniformGPUBuffer.setMatrix(`_viewMatrix`, camera.viewMatrix); this.uniformGPUBuffer.setMatrix(`_pvMatrix`, camera.pvMatrix); this.uniformGPUBuffer.setMatrix(`pvMatrixInv`, camera.projectionMatrixInv); + this.uniformGPUBuffer.setMatrix(`viewToWorld`, camera.cameraToWorld); this.csmShadowBias.fill(0.0001); this.shadowMatrixRaw.fill(0); this.csmMatrixRaw.fill(0); @@ -213,8 +230,4 @@ export class GlobalUniformGroup { this.uniformGPUBuffer.apply(); } - - public setShadowLight() { } - - } diff --git a/src/gfx/graphics/webGpu/core/bindGroups/groups/ReflectionEntries.ts b/src/gfx/graphics/webGpu/core/bindGroups/groups/ReflectionEntries.ts new file mode 100644 index 00000000..d32b6177 --- /dev/null +++ b/src/gfx/graphics/webGpu/core/bindGroups/groups/ReflectionEntries.ts @@ -0,0 +1,52 @@ + + +//TODO dynamic lights need fixed + +import { GPUContext } from "../../../../../.."; +import { Engine3D } from "../../../../../../Engine3D"; +import { View3D } from "../../../../../../core/View3D"; +import { RenderTexture } from "../../../../../../textures/RenderTexture"; +import { EntityCollect } from "../../../../../renderJob/collect/EntityCollect"; +import { GBufferFrame } from "../../../../../renderJob/frame/GBufferFrame"; +import { GPUTextureFormat } from "../../../WebGPUConst"; +import { StorageGPUBuffer } from "../../buffer/StorageGPUBuffer"; +import { Texture } from "../../texture/Texture"; + +/** + * @internal + * @group GFX + */ +export class ReflectionEntries { + public storageGPUBuffer: StorageGPUBuffer; + public reflectionMap: Texture; + + public sourceReflectionMap: RenderTexture; + count: number; + constructor() { + this.storageGPUBuffer = new StorageGPUBuffer((3 + 3) * 128); + + // let reflectionSetting = Engine3D.setting.reflectionSetting; + // let reflectionsGBufferFrame = GBufferFrame.getGBufferFrame(GBufferFrame.reflections_GBuffer, reflectionSetting.reflectionMapWidth, reflectionSetting.reflectionMapHeight); + // this.sourceReflectionMap = reflectionsGBufferFrame.getCompressGBufferTexture(); + // this.reflectionMap = new RenderTexture(this.sourceReflectionMap.width, this.sourceReflectionMap.height, this.sourceReflectionMap.format, false, undefined, 1, 0, true, false); + } + + public update(view: View3D) { + // let command = GPUContext.beginCommandEncoder(); + // GPUContext.copyTexture(command, this.sourceReflectionMap, this.reflectionMap); + // GPUContext.endCommandEncoder(command); + + this.storageGPUBuffer.clean(); + let reflections = EntityCollect.instance.getReflections(view.scene); + for (let i = 0; i < reflections.length; i++) { + const reflection = reflections[i]; + reflection.gid = i; + this.storageGPUBuffer.setFloat("gid", reflection.gid); + this.storageGPUBuffer.setVector3("worldPosition", reflection.transform.worldPosition); + this.storageGPUBuffer.setFloat("radius", reflection.radius); + this.storageGPUBuffer.setVector3("bound", reflection.transform.worldPosition); + } + this.count = reflections.length; + this.storageGPUBuffer.apply(); + } +} diff --git a/src/gfx/graphics/webGpu/core/buffer/GPUBufferBase.ts b/src/gfx/graphics/webGpu/core/buffer/GPUBufferBase.ts index 806bd4df..967be0dc 100644 --- a/src/gfx/graphics/webGpu/core/buffer/GPUBufferBase.ts +++ b/src/gfx/graphics/webGpu/core/buffer/GPUBufferBase.ts @@ -1,495 +1,592 @@ -import { ArrayBufferData } from "./ArrayBufferData"; -import { GPUBufferType } from "./GPUBufferType"; -import { Color } from "../../../../../math/Color"; -import { Matrix4 } from "../../../../../math/Matrix4"; -import { Quaternion } from "../../../../../math/Quaternion"; -import { Vector2 } from "../../../../../math/Vector2"; -import { Vector3 } from "../../../../../math/Vector3"; -import { Vector4 } from "../../../../../math/Vector4"; -import { Struct } from "../../../../../util/struct/Struct"; - -import { webGPUContext } from "../../Context3D"; -import { MemoryDO } from "../../../../../core/pool/memory/MemoryDO"; -import { MemoryInfo } from "../../../../../core/pool/memory/MemoryInfo"; - -/** - * @internal - * @group GFX - */ -export class GPUBufferBase { - public bufferType: GPUBufferType; - public buffer: GPUBuffer; - public memory: MemoryDO; - public memoryNodes: Map; - public seek: number; - public outFloat32Array: Float32Array; - public byteSize: number; - public usage: GPUBufferUsageFlags; - public visibility: number = GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE; - protected mapAsyncBuffersOutstanding = 0; - protected mapAsyncReady: GPUBuffer[]; - private _readBuffer: GPUBuffer; - private _dataView: Float32Array; - - constructor() { - this.mapAsyncReady = []; - // this.memory = new MemoryDO(); - // this.memoryNodes = new Map(); - // this._dataView = new Float32Array(this.memory.shareDataBuffer); - } - - public debug() { - } - - public reset(clean: boolean = false, size: number = 0, data?: Float32Array) { - this.seek = 0; - this.memory.reset(); - if (clean) { - this.createBuffer(this.usage, size, data); - } - } - - public setBoolean(name: string, v: boolean) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(1 * 4); - this.memoryNodes.set(name, node); - } - node.setX(v ? 1 : 0); - } - - public setFloat(name: string, v: number) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(1 * 4); - this.memoryNodes.set(name, node); - } - node.setX(v); - } - - public setInt8(name: string, v: number) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(1 * 1); - this.memoryNodes.set(name, node); - } - node.setInt8(v); - } - - public setInt16(name: string, v: number) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(1 * 2); - this.memoryNodes.set(name, node); - } - node.setInt16(v); - } - - public setInt32(name: string, v: number) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(1 * 4); - this.memoryNodes.set(name, node); - } - node.setInt32(v); - } - - public setUint8(name: string, v: number) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(1 * 1); - this.memoryNodes.set(name, node); - } - node.setUint8(v); - } - - public setUint16(name: string, v: number) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(1 * 2); - this.memoryNodes.set(name, node); - } - node.setUint16(v); - } - - public setUint32(name: string, v: number) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(1 * 4); - this.memoryNodes.set(name, node); - } - node.setUint32(v); - } - - public setVector2(name: string, v2: Vector2) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(2 * 4); - this.memoryNodes.set(name, node); - } - node.setXY(v2.x, v2.y); - } - - public setVector3(name: string, v3: Vector3) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(3 * 4); - this.memoryNodes.set(name, node); - } - node.setXYZ(v3.x, v3.y, v3.z); - } - - public setVector4(name: string, v4: Vector4 | Quaternion) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(4 * 4); - this.memoryNodes.set(name, node); - } - node.setXYZW(v4.x, v4.y, v4.z, v4.w); - } - - public setVector4Array(name: string, v4Array: Vector3[] | Vector4[] | Quaternion[]) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(4 * 4 * v4Array.length); - this.memoryNodes.set(name, node); - } - node.setVector4Array(v4Array); - } - - public setColor(name: string, color: Color) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(4 * 4); - this.memoryNodes.set(name, node); - } - node.setXYZW(color.r, color.g, color.b, color.a); - } - - public setColorArray(name: string, colorArray: Color[]) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(4 * 4 * colorArray.length); - this.memoryNodes.set(name, node); - } - node.setColorArray(colorArray); - } - - public setMatrix(name: string, mat: Matrix4) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(16 * 4); - this.memoryNodes.set(name, node); - } - node.setFloat32Array(0, mat.rawData); - } - - public setMatrixArray(name: string, mats: Matrix4[]) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(16 * 4 * mats.length); - this.memoryNodes.set(name, node); - } - for (let i = 0; i < mats.length; i++) { - const mat = mats[i]; - node.setFloat32Array(i * 16, mat.rawData); - } - } - - public setArray(name: string, data: number[]) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(data.length * 4); - this.memoryNodes.set(name, node); - } - node.setArray(0, data); - } - - public setFloat32Array(name: string, data: Float32Array) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(data.length * 4); - this.memoryNodes.set(name, node); - } - node.setFloat32Array(0, data); - } - - public setInt32Array(name: string, data: Int32Array) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(data.length * 4); - this.memoryNodes.set(name, node); - } - node.setInt32Array(0, data); - } - - - public setUint32Array(name: string, data: Uint32Array) { - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(data.length * 4); - this.memoryNodes.set(name, node); - } - node.setUint32Array(0, data); - } - - public setStruct(c: { new(): T }, index: number, data: any, property?: string) { - let ref = Struct.Ref(c); - let size = Struct.GetSize(c); - - let name = index; - let node = this.memoryNodes.get(name); - node.reset(); - - let obj = data; - if (property) { - obj = obj[property]; - } - - for (let i = 0; i < ref.length; i++) { - const att = ref[i]; - let value = obj[att.name]; - this.writeValue(node, att, value); - } - } - - private writeValue(node: MemoryInfo, att: { name: string, type: string }, value: any) { - switch (att.type) { - case `Boolean`: - node.writeFloat(value); - break; - - case `Number`: - node.writeFloat(value); - break; - - case `Float32Array`: - node.writeFloat32Array(value); - break; - - case `Vector2`: - node.writeVector2(value); - break; - - case `Vector3`: - node.writeVector3(value); - break; - - case `Vector4`: - node.writeVector4(value); - break; - - case `Color`: - node.writeRGBColor(value); - break; - - case `Array`: - node.writeArray(value); - break; - } - } - - public setStructArray(c: { new(): T }, dataList: any[], property?: string) { - let len = dataList.length; - for (let i = 0; i < len; i++) { - const data = dataList[i]; - this.setStruct(c, i, data, property); - } - } - - // public writeFloat(v: number) { - // this.memory.shareFloat32Array[this.seek] = v; - // this.seek += 1; - // } - - public clean() { - // this._dataView = new Float32Array(this.memory.shareDataBuffer); - this._dataView.fill(0, 0, this._dataView.length); - } - - public apply() { - webGPUContext.device.queue.writeBuffer(this.buffer, 0, this.memory.shareDataBuffer);//, this.memory.shareFloat32Array.byteOffset, this.memory.shareFloat32Array.byteLength); - // this.applyMapAsync(); - } - - public mapAsyncWrite(mapAsyncArray: Float32Array, len: number) { - // Upload data using mapAsync and a queue of staging buffers. - let bytesLen = len; - let device = webGPUContext.device; - if (mapAsyncArray.length > 0) { - let tBuffer: GPUBuffer = null; - while (this.mapAsyncReady.length) { - tBuffer = this.mapAsyncReady.shift(); - if (tBuffer['usedSize'] == mapAsyncArray.byteLength) - break; - tBuffer.destroy(); - this.mapAsyncBuffersOutstanding--; - tBuffer = null; - } - if (!tBuffer) { - tBuffer = device.createBuffer({ - size: mapAsyncArray.byteLength, - usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE, - mappedAtCreation: true, - }); - tBuffer['usedSize'] = mapAsyncArray.byteLength; - this.mapAsyncBuffersOutstanding++; - if (this.mapAsyncBuffersOutstanding > 10) { - // ${(this.mapAsync.value * this.mapAsyncBuffersOutstanding).toFixed(2)} - console.warn(` Warning: mapAsync requests from ${this.mapAsyncBuffersOutstanding} frames ago have not resolved yet. MB of staging buffers allocated.`); - } - } - let a = new Float32Array(mapAsyncArray.buffer, mapAsyncArray.byteOffset, len); - let b = new Float32Array(tBuffer.getMappedRange(0, len * 4)) - b.set(a); - tBuffer.unmap(); - const commandEncoder = device.createCommandEncoder(); - commandEncoder.copyBufferToBuffer(tBuffer, 0, this.buffer, 0, len * 4); - // TODO: combine this submit with the main one, but we'll have to delay calling mapAsync until after the submit. - device.queue.submit([commandEncoder.finish()]); - // TODO: use this data during rendering. - tBuffer.mapAsync(GPUMapMode.WRITE).then(() => this.mapAsyncReady.push(tBuffer)); - } - } - - public destroy(force?: boolean) { - if (this.memoryNodes) { - this.memoryNodes.forEach((v) => { - v.destroy(); - }) - } - - this.bufferType = null; - this.seek = null; - this.byteSize = null; - this.usage = null; - this.visibility = null; - - this.outFloat32Array = null; - if (this.buffer) { - this.buffer.destroy(); - } - this.buffer = null; - - if (this.memory) { - this.memory.destroy(); - } - this.memory = null; - - if (this._readBuffer) { - this._readBuffer.destroy(); - } - } - - protected createBuffer(usage: GPUBufferUsageFlags, size: number, data?: ArrayBufferData, debugLabel?: string) { - let device = webGPUContext.device; - - if (this.buffer) { - this.destroy(); - } - - this.byteSize = size * 4; - this.usage = usage; - - this.buffer = device.createBuffer({ - label: debugLabel, - size: this.byteSize, - usage: usage, - mappedAtCreation: false, - }); - - this.memory = new MemoryDO(); - this.memoryNodes = new Map(); - this._dataView = new Float32Array(this.memory.shareDataBuffer); - this.memory.allocation(this.byteSize); - if (data) { - let m = this.memory.allocation_node(data.length * 4); - m.setArrayBuffer(0, data); - this.apply(); - } - } - - public resizeBuffer(size: number, data?: ArrayBufferData) { - this.createBuffer(this.usage, size, data); - } - - protected createNewBuffer(usage: GPUBufferUsageFlags, size: number): GPUBuffer { - let device = webGPUContext.device; - let tByteSize = size * 4; - let tUsage = usage; - if (this.buffer) { - this.destroy(); - } - let buffer = device.createBuffer({ - size: tByteSize, - usage: tUsage, - mappedAtCreation: false, - }); - return buffer; - } - - protected createBufferByStruct(usage: GPUBufferUsageFlags, struct: { new(): T }, count: number) { - let structSize = Struct.GetSize(struct); - let totalLength = structSize * count; - - let device = webGPUContext.device; - this.buffer = device.createBuffer({ - label: "StructStorageGPUBuffer", - size: totalLength, - // size: totalLength * 4, - usage: usage, - mappedAtCreation: false, - }); - - this.memory = new MemoryDO(); - this.memoryNodes = new Map(); - this._dataView = new Float32Array(this.memory.shareDataBuffer); - this.memory.allocation(totalLength); - for (let i = 0; i < count; i++) { - let name = i; - - let node = this.memoryNodes.get(name); - if (!node) { - node = this.memory.allocation_node(structSize); - this.memoryNodes.set(name, node); - } - } - } - - public readBuffer(): Float32Array - public readBuffer(promise: false) : Float32Array - public readBuffer(promise: true) : Promise - public readBuffer(promise = false) { - this.outFloat32Array ||= new Float32Array(this.memory.shareDataBuffer.byteLength / 4); - - if (!this._readBuffer) { - this._readBuffer = webGPUContext.device.createBuffer({ - size: this.memory.shareDataBuffer.byteLength, - usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ, - mappedAtCreation: false, - }); - } - - let p = this.read(); - return promise ? p : this.outFloat32Array; - } - - private _readFlag: boolean = false; - private async read() { - if (!this._readFlag) { - this._readFlag = true; - - let command = webGPUContext.device.createCommandEncoder();; - command.copyBufferToBuffer(this.buffer, 0, this._readBuffer, 0, this.memory.shareDataBuffer.byteLength); - webGPUContext.device.queue.submit([command.finish()]); - - await this._readBuffer.mapAsync(GPUMapMode.READ); - const copyArrayBuffer = this._readBuffer.getMappedRange(); - this.outFloat32Array.set(new Float32Array(copyArrayBuffer), 0); - // this.memory.shareDataBuffer.set(new Float32Array(copyArrayBuffer), 0); - this._readBuffer.unmap(); - this._readFlag = false; - } - return this.outFloat32Array; - } -} +import { ArrayBufferData } from "./ArrayBufferData"; +import { GPUBufferType } from "./GPUBufferType"; +import { Color } from "../../../../../math/Color"; +import { Matrix4 } from "../../../../../math/Matrix4"; +import { Quaternion } from "../../../../../math/Quaternion"; +import { Vector2 } from "../../../../../math/Vector2"; +import { Vector3 } from "../../../../../math/Vector3"; +import { Vector4 } from "../../../../../math/Vector4"; +import { Struct } from "../../../../../util/struct/Struct"; + +import { webGPUContext } from "../../Context3D"; +import { MemoryDO } from "../../../../../core/pool/memory/MemoryDO"; +import { MemoryInfo } from "../../../../../core/pool/memory/MemoryInfo"; + +/** + * @internal + * @group GFX + */ +export class GPUBufferBase { + public bufferType: GPUBufferType; + public buffer: GPUBuffer; + public memory: MemoryDO; + public memoryNodes: Map; + public seek: number; + public outFloat32Array: Float32Array; + public byteSize: number; + public usage: GPUBufferUsageFlags; + public visibility: number = GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE; + protected mapAsyncBuffersOutstanding = 0; + protected mapAsyncReady: GPUBuffer[]; + private _readBuffer: GPUBuffer; + private _dataView: Float32Array; + + constructor() { + this.mapAsyncReady = []; + // this.memory = new MemoryDO(); + // this.memoryNodes = new Map(); + // this._dataView = new Float32Array(this.memory.shareDataBuffer); + } + + public debug() { + } + + public reset(clean: boolean = false, size: number = 0, data?: Float32Array) { + this.seek = 0; + this.memory.reset(); + if (clean) { + this.createBuffer(this.usage, size, data); + } + } + + public setBoolean(name: string, v: boolean) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(1 * 4); + this.memoryNodes.set(name, node); + } + node.setX(v ? 1 : 0); + } + + public readBoole(name: string): boolean { + let node = this.memoryNodes.get(name); + if (node) { + return node.getFloat() == 0 ? false : true; + } + return null; + } + + public setFloat(name: string, v: number) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(1 * 4); + this.memoryNodes.set(name, node); + } + node.setX(v); + } + + public getFloat(name: string): number { + let node = this.memoryNodes.get(name); + if (node) { + return node.getFloat(); + } + return null; + } + + public setInt8(name: string, v: number) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(1 * 1); + this.memoryNodes.set(name, node); + } + node.setInt8(v); + } + + public getInt8(name: string): number { + let node = this.memoryNodes.get(name); + if (node) { + return node.getInt8(); + } + return null; + } + + public setInt16(name: string, v: number) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(1 * 2); + this.memoryNodes.set(name, node); + } + node.setInt16(v); + } + + public getInt16(name: string): number { + let node = this.memoryNodes.get(name); + if (node) { + return node.getInt16(); + } + return null; + } + + public setInt32(name: string, v: number) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(1 * 4); + this.memoryNodes.set(name, node); + } + node.setInt32(v); + } + + public getInt32(name: string): number { + let node = this.memoryNodes.get(name); + if (node) { + return node.getInt32(); + } + return null; + } + + public setUint8(name: string, v: number) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(1 * 1); + this.memoryNodes.set(name, node); + } + node.setUint8(v); + } + + public getUint8(name: string): number { + let node = this.memoryNodes.get(name); + if (node) { + return node.getUint8(); + } + return null; + } + + public setUint16(name: string, v: number) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(1 * 2); + this.memoryNodes.set(name, node); + } + node.setUint16(v); + } + + public getUint16(name: string): number { + let node = this.memoryNodes.get(name); + if (node) { + return node.getUint16(); + } + return null; + } + + + public setUint32(name: string, v: number) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(1 * 4); + this.memoryNodes.set(name, node); + } + node.setUint32(v); + } + + public getUint32(name: string): number { + let node = this.memoryNodes.get(name); + if (node) { + return node.getUint32(); + } + return null; + } + + public setVector2(name: string, v2: Vector2) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(2 * 4); + this.memoryNodes.set(name, node); + } + node.setXY(v2.x, v2.y); + } + + public getVector2(name: string): Vector2 { + let node = this.memoryNodes.get(name); + if (node) { + return new Vector2(node.x, node.y); + } + return null; + } + + public setVector3(name: string, v3: Vector3) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(3 * 4); + this.memoryNodes.set(name, node); + } + node.setXYZ(v3.x, v3.y, v3.z); + } + + public getVector3(name: string): Vector3 { + let node = this.memoryNodes.get(name); + if (node) { + return new Vector3(node.x, node.y, node.z); + } + return null; + } + + public setVector4(name: string, v4: Vector4 | Quaternion) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(4 * 4); + this.memoryNodes.set(name, node); + } + node.setXYZW(v4.x, v4.y, v4.z, v4.w); + } + + public getVector4(name: string): Vector4 { + let node = this.memoryNodes.get(name); + if (node) { + return new Vector4(node.x, node.y, node.z, node.w); + } + return null; + } + + public setVector4Array(name: string, v4Array: Vector3[] | Vector4[] | Quaternion[]) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(4 * 4 * v4Array.length); + this.memoryNodes.set(name, node); + } + node.setVector4Array(v4Array); + } + + public setColor(name: string, color: Color) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(4 * 4); + this.memoryNodes.set(name, node); + } + node.setXYZW(color.r, color.g, color.b, color.a); + } + + public getColor(name: string): Color { + let node = this.memoryNodes.get(name); + if (node) { + return new Color(node.x, node.y, node.z, node.w); + } + return null; + } + + public setColorArray(name: string, colorArray: Color[]) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(4 * 4 * colorArray.length); + this.memoryNodes.set(name, node); + } + node.setColorArray(colorArray); + } + + public setMatrix(name: string, mat: Matrix4) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(16 * 4); + this.memoryNodes.set(name, node); + } + node.setFloat32Array(0, mat.rawData); + } + + public setMatrixArray(name: string, mats: Matrix4[]) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(16 * 4 * mats.length); + this.memoryNodes.set(name, node); + } + for (let i = 0; i < mats.length; i++) { + const mat = mats[i]; + node.setFloat32Array(i * 16, mat.rawData); + } + } + + public setArray(name: string, data: number[]) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(data.length * 4); + this.memoryNodes.set(name, node); + } + node.setArray(0, data); + } + + public setFloat32Array(name: string, data: Float32Array) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(data.length * 4); + this.memoryNodes.set(name, node); + } + node.setFloat32Array(0, data); + } + + public setInt32Array(name: string, data: Int32Array) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(data.length * 4); + this.memoryNodes.set(name, node); + } + node.setInt32Array(0, data); + } + + + public setUint32Array(name: string, data: Uint32Array) { + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(data.length * 4); + this.memoryNodes.set(name, node); + } + node.setUint32Array(0, data); + } + + public setStruct(c: { new(): T }, index: number, data: any, property?: string) { + let ref = Struct.Ref(c); + let size = Struct.GetSize(c); + + let name = index; + let node = this.memoryNodes.get(name); + node.reset(); + + let obj = data; + if (property) { + obj = obj[property]; + } + + for (let i = 0; i < ref.length; i++) { + const att = ref[i]; + let value = obj[att.name]; + this.writeValue(node, att, value); + } + } + + private writeValue(node: MemoryInfo, att: { name: string, type: string }, value: any) { + switch (att.type) { + case `Boolean`: + node.writeFloat(value); + break; + + case `Number`: + node.writeFloat(value); + break; + + case `Float32Array`: + node.writeFloat32Array(value); + break; + + case `Vector2`: + node.writeVector2(value); + break; + + case `Vector3`: + node.writeVector3(value); + break; + + case `Vector4`: + node.writeVector4(value); + break; + + case `Color`: + node.writeRGBColor(value); + break; + + case `Array`: + node.writeArray(value); + break; + } + } + + public setStructArray(c: { new(): T }, dataList: any[], property?: string) { + let len = dataList.length; + for (let i = 0; i < len; i++) { + const data = dataList[i]; + this.setStruct(c, i, data, property); + } + } + + // public writeFloat(v: number) { + // this.memory.shareFloat32Array[this.seek] = v; + // this.seek += 1; + // } + + public clean() { + // this._dataView = new Float32Array(this.memory.shareDataBuffer); + this._dataView.fill(0, 0, this._dataView.length); + } + + public apply() { + webGPUContext.device.queue.writeBuffer(this.buffer, 0, this.memory.shareDataBuffer);//, this.memory.shareFloat32Array.byteOffset, this.memory.shareFloat32Array.byteLength); + // this.applyMapAsync(); + } + + public mapAsyncWrite(mapAsyncArray: Float32Array, len: number) { + // Upload data using mapAsync and a queue of staging buffers. + let bytesLen = len; + let device = webGPUContext.device; + if (mapAsyncArray.length > 0) { + let tBuffer: GPUBuffer = null; + while (this.mapAsyncReady.length) { + tBuffer = this.mapAsyncReady.shift(); + if (tBuffer['usedSize'] == mapAsyncArray.byteLength) + break; + tBuffer.destroy(); + this.mapAsyncBuffersOutstanding--; + tBuffer = null; + } + if (!tBuffer) { + tBuffer = device.createBuffer({ + size: mapAsyncArray.byteLength, + usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE, + mappedAtCreation: true, + }); + tBuffer['usedSize'] = mapAsyncArray.byteLength; + this.mapAsyncBuffersOutstanding++; + if (this.mapAsyncBuffersOutstanding > 20) { + // ${(this.mapAsync.value * this.mapAsyncBuffersOutstanding).toFixed(2)} + console.warn(` Warning: mapAsync requests from ${this.mapAsyncBuffersOutstanding} frames ago have not resolved yet. MB of staging buffers allocated.`); + } + } + let a = new Float32Array(mapAsyncArray.buffer, mapAsyncArray.byteOffset, len); + let b = new Float32Array(tBuffer.getMappedRange(0, len * 4)) + b.set(a); + tBuffer.unmap(); + const commandEncoder = device.createCommandEncoder(); + commandEncoder.copyBufferToBuffer(tBuffer, 0, this.buffer, 0, len * 4); + // TODO: combine this submit with the main one, but we'll have to delay calling mapAsync until after the submit. + device.queue.submit([commandEncoder.finish()]); + // TODO: use this data during rendering. + tBuffer.mapAsync(GPUMapMode.WRITE).then(() => this.mapAsyncReady.push(tBuffer)); + } + } + + public destroy(force?: boolean) { + if (this.memoryNodes) { + this.memoryNodes.forEach((v) => { + v.destroy(); + }) + } + + this.bufferType = null; + this.seek = null; + this.byteSize = null; + this.usage = null; + this.visibility = null; + + this.outFloat32Array = null; + if (this.buffer) { + this.buffer.destroy(); + } + this.buffer = null; + + if (this.memory) { + this.memory.destroy(); + } + this.memory = null; + + if (this._readBuffer) { + this._readBuffer.destroy(); + } + } + + protected createBuffer(usage: GPUBufferUsageFlags, size: number, data?: ArrayBufferData, debugLabel?: string) { + let device = webGPUContext.device; + + if (this.buffer) { + this.destroy(); + } + + this.byteSize = size * 4; + this.usage = usage; + + this.buffer = device.createBuffer({ + label: debugLabel, + size: this.byteSize, + usage: usage, + mappedAtCreation: false, + }); + + this.memory = new MemoryDO(); + this.memoryNodes = new Map(); + this._dataView = new Float32Array(this.memory.shareDataBuffer); + this.memory.allocation(this.byteSize); + if (data) { + let m = this.memory.allocation_node(data.length * 4); + m.setArrayBuffer(0, data); + this.apply(); + } + } + + public resizeBuffer(size: number, data?: ArrayBufferData) { + this.createBuffer(this.usage, size, data); + } + + protected createNewBuffer(usage: GPUBufferUsageFlags, size: number): GPUBuffer { + let device = webGPUContext.device; + let tByteSize = size * 4; + let tUsage = usage; + if (this.buffer) { + this.destroy(); + } + let buffer = device.createBuffer({ + size: tByteSize, + usage: tUsage, + mappedAtCreation: false, + }); + return buffer; + } + + protected createBufferByStruct(usage: GPUBufferUsageFlags, struct: { new(): T }, count: number) { + let structSize = Struct.GetSize(struct); + let totalLength = structSize * count; + + let device = webGPUContext.device; + this.buffer = device.createBuffer({ + label: "StructStorageGPUBuffer", + size: totalLength, + // size: totalLength * 4, + usage: usage, + mappedAtCreation: false, + }); + + this.memory = new MemoryDO(); + this.memoryNodes = new Map(); + this._dataView = new Float32Array(this.memory.shareDataBuffer); + this.memory.allocation(totalLength); + for (let i = 0; i < count; i++) { + let name = i; + + let node = this.memoryNodes.get(name); + if (!node) { + node = this.memory.allocation_node(structSize); + this.memoryNodes.set(name, node); + } + } + } + + public readBuffer(): Float32Array + public readBuffer(promise: false) : Float32Array + public readBuffer(promise: true) : Promise + public readBuffer(promise = false) { + this.outFloat32Array ||= new Float32Array(this.memory.shareDataBuffer.byteLength / 4); + + if (!this._readBuffer) { + this._readBuffer = webGPUContext.device.createBuffer({ + size: this.memory.shareDataBuffer.byteLength, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ, + mappedAtCreation: false, + }); + } + + let p = this.read(); + return promise ? p : this.outFloat32Array; + } + + private _readFlag: boolean = false; + private async read() { + if (!this._readFlag) { + this._readFlag = true; + + let command = webGPUContext.device.createCommandEncoder();; + command.copyBufferToBuffer(this.buffer, 0, this._readBuffer, 0, this.memory.shareDataBuffer.byteLength); + webGPUContext.device.queue.submit([command.finish()]); + + await this._readBuffer.mapAsync(GPUMapMode.READ); + const copyArrayBuffer = this._readBuffer.getMappedRange(); + this.outFloat32Array.set(new Float32Array(copyArrayBuffer), 0); + // this.memory.shareDataBuffer.set(new Float32Array(copyArrayBuffer), 0); + this._readBuffer.unmap(); + this._readFlag = false; + } + return this.outFloat32Array; + } +} diff --git a/src/gfx/graphics/webGpu/core/texture/Texture.ts b/src/gfx/graphics/webGpu/core/texture/Texture.ts index 55f5350c..607a2f35 100644 --- a/src/gfx/graphics/webGpu/core/texture/Texture.ts +++ b/src/gfx/graphics/webGpu/core/texture/Texture.ts @@ -259,10 +259,12 @@ export class Texture implements GPUSamplerDescriptor { if (sizeCount > 1) { this.viewDescriptor = { + format: format, dimension: `2d-array`, }; } else { this.viewDescriptor = { + format: format, dimension: this.textureBindingLayout.viewDimension, mipLevelCount: mipLevelCount, baseMipLevel: 0 diff --git a/src/gfx/graphics/webGpu/core/texture/TextureMipmapGenerator.ts b/src/gfx/graphics/webGpu/core/texture/TextureMipmapGenerator.ts index 5dc44dd3..9de96a31 100644 --- a/src/gfx/graphics/webGpu/core/texture/TextureMipmapGenerator.ts +++ b/src/gfx/graphics/webGpu/core/texture/TextureMipmapGenerator.ts @@ -8,40 +8,45 @@ import { Texture } from './Texture'; */ export class TextureMipmapGenerator { private static mipmapShader = ` - var pos : array, 3> = array, 3>( - vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0)); - struct VertexOutput { - @builtin(position) position : vec4; - @location(0) texCoord : vec2; - }; - @vertex - fn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput { + var pos : array, 4> = array, 4>( + vec2(-1.0, 1.0), vec2(1.0, 1.0), + vec2(-1.0, -1.0), vec2(1.0, -1.0)); + + struct VertexOutput { + @builtin(position) position : vec4, + @location(0) texCoord : vec2 + }; + + @vertex + fn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput { var output : VertexOutput; output.texCoord = pos[vertexIndex] * vec2(0.5, -0.5) + vec2(0.5); output.position = vec4(pos[vertexIndex], 0.0, 1.0); return output; - } - @binding(0) @group(0) var imgSampler : sampler; - @binding(1) @group(0) var img : texture_2d; - @fragment - fn fragmentMain(@location(0) texCoord : vec2) -> @location(0) vec4 { - var outColor: vec4 = textureSample(img, imgSampler, texCoord); - return outColor ; - }`; + } + + @binding(0) @group(0) var imgSampler : sampler; + @binding(1) @group(0) var img : texture_2d; + + @fragment + fn fragmentMain(@location(0) texCoord : vec2) -> @location(0) vec4 { + var outColor: vec4 = textureSampleLevel(img, imgSampler, texCoord , 0.0 ); + return outColor; + } + `; private static pipelineCache: { [key: string]: GPURenderPipeline } = {}; private static pipeline: any; public static getMipmapPipeline(texture: Texture) { - let format = texture.format; - let device = webGPUContext.device; + let gpuDevice = webGPUContext.device; let pipeline: GPURenderPipeline = TextureMipmapGenerator.pipelineCache[texture.format]; - let mipmapShaderModule: GPUShaderModule; if (!pipeline) { - mipmapShaderModule = device.createShaderModule({ + // Create a simple shader that renders a fullscreen textured quad. + const mipmapShaderModule = gpuDevice.createShaderModule({ code: TextureMipmapGenerator.mipmapShader, }); - let textureLayout = device.createBindGroupLayout({ + let textureLayout = gpuDevice.createBindGroupLayout({ entries: [ { binding: 0, @@ -60,84 +65,24 @@ export class TextureMipmapGenerator { ], }); + // Need a separate bind group for each level to ensurev + // we're only sampling from the previous level. let layouts = webGPUContext.device.createPipelineLayout({ bindGroupLayouts: [textureLayout], }); - pipeline = GPUContext.createPipeline({ + pipeline = gpuDevice.createRenderPipeline({ layout: layouts, vertex: { module: mipmapShaderModule, entryPoint: 'vertexMain', }, - fragment: { - module: mipmapShaderModule, - entryPoint: 'fragmentMain', - targets: [{ format }], - }, - }); - TextureMipmapGenerator.pipelineCache[format] = pipeline; - } - 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) { - let gpuDevice = webGPUContext.device; - let textureDescriptor = texture.textureDescriptor; - - if (!TextureMipmapGenerator.pipeline) { - // Create a simple shader that renders a fullscreen textured quad. - const mipmapShaderModule = gpuDevice.createShaderModule({ - code: ` - var pos : array, 4> = array, 4>( - vec2(-1.0, 1.0), vec2(1.0, 1.0), - vec2(-1.0, -1.0), vec2(1.0, -1.0)); - - struct VertexOutput { - @builtin(position) position : vec4, - @location(0) texCoord : vec2 - }; - - @vertex - fn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput { - var output : VertexOutput; - output.texCoord = pos[vertexIndex] * vec2(0.5, -0.5) + vec2(0.5); - output.position = vec4(pos[vertexIndex], 0.0, 1.0); - return output; - } - - @binding(0) @group(0) var imgSampler : sampler; - @binding(1) @group(0) var img : texture_2d; - - @fragment - fn fragmentMain(@location(0) texCoord : vec2) -> @location(0) vec4 { - var outColor: vec4 = textureSampleLevel(img, imgSampler, texCoord , 0.0 ); - return outColor; - } - `, - }); - - TextureMipmapGenerator.pipeline = gpuDevice.createRenderPipeline({ - layout: `auto`, - vertex: { - module: mipmapShaderModule, - entryPoint: 'vertexMain', - }, fragment: { module: mipmapShaderModule, entryPoint: 'fragmentMain', targets: [ { - format: textureDescriptor.format, // Make sure to use the same format as the texture + format: texture.format, // Make sure to use the same format as the texture }, ], }, @@ -146,21 +91,18 @@ export class TextureMipmapGenerator { stripIndexFormat: 'uint32', }, }); + TextureMipmapGenerator.pipelineCache[texture.format] = pipeline; } + return pipeline; + } - // We'll ALWAYS be rendering minified here, so that's the only filter mode we need to set. - let sampler: GPUSampler; - if (texture.format == `rgba16float`) { - sampler = gpuDevice.createSampler({ - minFilter: `nearest`, - magFilter: `linear`, - }); - } else { - sampler = gpuDevice.createSampler({ - minFilter: GPUFilterMode.linear, - magFilter: GPUFilterMode.linear, - }); - } + // TextureDescriptor should be the descriptor that the texture was created with. + // This version only works for basic 2D textures. + public static webGPUGenerateMipmap(texture: Texture) { + let gpuDevice = webGPUContext.device; + let textureDescriptor = texture.textureDescriptor; + // let pipeline = TextureMipmapGenerator.pipeline; + let pipeline = TextureMipmapGenerator.getMipmapPipeline(texture); let srcView = texture.getGPUTexture().createView({ baseMipLevel: 0, @@ -186,14 +128,33 @@ export class TextureMipmapGenerator { ], }); + let textureLayout = gpuDevice.createBindGroupLayout({ + entries: [ + { + binding: 0, + //TODO : After adding a shadow reflection, it is necessary to know that the vertex is used | the segment is used + visibility: texture.visibility, + // use GPUSamplerBindingLayout = { type:`filtering`} error + sampler: texture.samplerBindingLayout, + }, + { + binding: 1, + //TODO : After adding a shadow reflection, it is necessary to know that the vertex is used | the segment is used + visibility: texture.visibility, + // use GPUTextureBindingLayout = { sampleType:`float`} error + texture: texture.textureBindingLayout, + }, + ], + }); + // Need a separate bind group for each level to ensurev // we're only sampling from the previous level. const bindGroup = gpuDevice.createBindGroup({ - layout: TextureMipmapGenerator.pipeline.getBindGroupLayout(0), + layout: textureLayout, entries: [ { binding: 0, - resource: sampler, + resource: texture.gpuSampler, }, { binding: 1, @@ -203,7 +164,7 @@ export class TextureMipmapGenerator { }); // Render - passEncoder.setPipeline(TextureMipmapGenerator.pipeline); + passEncoder.setPipeline(pipeline); passEncoder.setBindGroup(0, bindGroup); passEncoder.draw(4); passEncoder.end(); @@ -214,4 +175,138 @@ export class TextureMipmapGenerator { } GPUContext.endCommandEncoder(commandEncoder); } + + public static getMipmapCount(width: number, height: number) { + let w = width; + let h = 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) { + // let gpuDevice = webGPUContext.device; + // let textureDescriptor = texture.textureDescriptor; + + // if (!TextureMipmapGenerator.pipeline) { + // // Create a simple shader that renders a fullscreen textured quad. + // const mipmapShaderModule = gpuDevice.createShaderModule({ + // code: ` + // var pos : array, 4> = array, 4>( + // vec2(-1.0, 1.0), vec2(1.0, 1.0), + // vec2(-1.0, -1.0), vec2(1.0, -1.0)); + + // struct VertexOutput { + // @builtin(position) position : vec4, + // @location(0) texCoord : vec2 + // }; + + // @vertex + // fn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput { + // var output : VertexOutput; + // output.texCoord = pos[vertexIndex] * vec2(0.5, -0.5) + vec2(0.5); + // output.position = vec4(pos[vertexIndex], 0.0, 1.0); + // return output; + // } + + // @binding(0) @group(0) var imgSampler : sampler; + // @binding(1) @group(0) var img : texture_2d; + + // @fragment + // fn fragmentMain(@location(0) texCoord : vec2) -> @location(0) vec4 { + // var outColor: vec4 = textureSampleLevel(img, imgSampler, texCoord , 0.0 ); + // return outColor; + // } + // `, + // }); + + // TextureMipmapGenerator.pipeline = gpuDevice.createRenderPipeline({ + // layout: `auto`, + // vertex: { + // module: mipmapShaderModule, + // entryPoint: 'vertexMain', + // }, + // fragment: { + // module: mipmapShaderModule, + // entryPoint: 'fragmentMain', + // targets: [ + // { + // format: textureDescriptor.format, // Make sure to use the same format as the texture + // }, + // ], + // }, + // primitive: { + // topology: 'triangle-strip', + // stripIndexFormat: 'uint32', + // }, + // }); + // } + + // // We'll ALWAYS be rendering minified here, so that's the only filter mode we need to set. + // let sampler: GPUSampler; + // if (texture.format == `rgba16float`) { + // sampler = gpuDevice.createSampler({ + // minFilter: `nearest`, + // magFilter: `linear`, + // }); + // } else { + // sampler = gpuDevice.createSampler({ + // minFilter: GPUFilterMode.linear, + // magFilter: GPUFilterMode.linear, + // }); + // } + + // let srcView = texture.getGPUTexture().createView({ + // baseMipLevel: 0, + // mipLevelCount: 1, + // }); + + // // Loop through each mip level and renders the previous level's contents into it. + // const commandEncoder = GPUContext.beginCommandEncoder(); + // for (let i = 1; i < textureDescriptor.mipLevelCount; ++i) { + // const dstView = texture.getGPUTexture().createView({ + // baseMipLevel: i, // Make sure we're getting the right mip level... + // mipLevelCount: 1, // And only selecting one mip level + // }); + + // const passEncoder = commandEncoder.beginRenderPass({ + // colorAttachments: [ + // { + // view: dstView, // Render pass uses the next mip level as it's render attachment. + // clearValue: [0, 0, 0, 0], + // loadOp: `clear`, + // storeOp: 'store', + // }, + // ], + // }); + + // // Need a separate bind group for each level to ensurev + // // we're only sampling from the previous level. + // const bindGroup = gpuDevice.createBindGroup({ + // layout: TextureMipmapGenerator.pipeline.getBindGroupLayout(0), + // entries: [ + // { + // binding: 0, + // resource: sampler, + // }, + // { + // binding: 1, + // resource: srcView, + // }, + // ], + // }); + + // // Render + // passEncoder.setPipeline(TextureMipmapGenerator.pipeline); + // passEncoder.setBindGroup(0, bindGroup); + // passEncoder.draw(4); + // passEncoder.end(); + + // // The source texture view for the next iteration of the loop is the + // // destination view for this one. + // srcView = dstView; + // } + // GPUContext.endCommandEncoder(commandEncoder); + // } } diff --git a/src/gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator.ts b/src/gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator.ts index 8f83a9fc..bdac0b25 100644 --- a/src/gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator.ts +++ b/src/gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator.ts @@ -9,22 +9,23 @@ import { CResizeEvent } from '../../../../event/CResizeEvent'; * @author sirxu */ export class WebGPUDescriptorCreator { - public static bindGroupDescriptorCount: number = 0; - public static bindTextureDescriptorCount: number = 0; - public static renderPassDescriptorCount: number = 0; - public static pipelineDescriptorCount: number = 0; + private static rendererPassState: Map = new Map(); public static createRendererPassState(rtFrame: RTFrame, loadOp: GPULoadOp = null) { - let rps = new RendererPassState(); - rps.label = rtFrame.label; - rps.customSize = rtFrame.customSize; - rps.rtFrame = rtFrame; - rps.zPreTexture = rtFrame.zPreTexture; - rps.depthTexture = rtFrame.depthTexture; - rps.depthViewIndex = rtFrame.depthViewIndex; - rps.isOutTarget = rtFrame.isOutTarget; - rps.depthCleanValue = rtFrame.depthCleanValue; - rps.depthLoadOp = rtFrame.depthLoadOp; + let rps: RendererPassState = WebGPUDescriptorCreator.rendererPassState.get(rtFrame); + if (!rps) { + rps = new RendererPassState(); + rps.label = rtFrame.label; + rps.customSize = rtFrame.customSize; + rps.rtFrame = rtFrame; + rps.zPreTexture = rtFrame.zPreTexture; + rps.depthTexture = rtFrame.depthTexture; + rps.depthViewIndex = rtFrame.depthViewIndex; + rps.isOutTarget = rtFrame.isOutTarget; + rps.depthCleanValue = rtFrame.depthCleanValue; + rps.depthLoadOp = rtFrame.depthLoadOp; + WebGPUDescriptorCreator.rendererPassState.set(rtFrame, rps); + } if (rtFrame && rtFrame.renderTargets.length > 0) { rps.renderTargets = rtFrame.renderTargets; @@ -68,6 +69,7 @@ export class WebGPUDescriptorCreator { */ // static getRenderPassDescriptor(attachMentTextures: VirtualTexture[], renderPassState:RenderPassState): any { public static getRenderPassDescriptor(renderPassState: RendererPassState, loadOp: GPULoadOp = null): any { + if (renderPassState.renderPassDescriptor) return renderPassState.renderPassDescriptor; let device = webGPUContext.device; let presentationSize = webGPUContext.presentationSize; let attachMentTexture = []; @@ -128,8 +130,7 @@ export class WebGPUDescriptorCreator { label: 'renderPassDescriptor not writeDepth', }; } - - this.renderPassDescriptorCount++; + renderPassState.renderPassDescriptor = renderPassDescriptor; return renderPassDescriptor; } @@ -142,6 +143,7 @@ export class WebGPUDescriptorCreator { * @returns */ public static getRenderBundleDescriptor(renderPassState: RendererPassState): GPURenderBundleEncoderDescriptor { + if (renderPassState.renderBundleEncoderDescriptor) return renderPassState.renderBundleEncoderDescriptor; let presentationSize = webGPUContext.presentationSize; let attachMentTexture = []; let size = []; @@ -168,7 +170,7 @@ export class WebGPUDescriptorCreator { colorFormats: attachMentTexture, }; } - this.renderPassDescriptorCount++; - return renderPassDescriptor; + renderPassState.renderBundleEncoderDescriptor = renderPassDescriptor; + return renderPassState.renderBundleEncoderDescriptor; } } diff --git a/src/gfx/graphics/webGpu/shader/ComputeShader.ts b/src/gfx/graphics/webGpu/shader/ComputeShader.ts index 80cfb4fd..6625ec1c 100644 --- a/src/gfx/graphics/webGpu/shader/ComputeShader.ts +++ b/src/gfx/graphics/webGpu/shader/ComputeShader.ts @@ -257,7 +257,7 @@ export class ComputeShader extends ShaderPassBase { shaderModule.getCompilationInfo().then((e) => { if (e.messages.length > 0) { - console.log(this._destCS); + console.warn('[shader error]', e, this._destCS); } }); diff --git a/src/gfx/graphics/webGpu/shader/RenderShaderPass.ts b/src/gfx/graphics/webGpu/shader/RenderShaderPass.ts index c419d428..87b81c10 100644 --- a/src/gfx/graphics/webGpu/shader/RenderShaderPass.ts +++ b/src/gfx/graphics/webGpu/shader/RenderShaderPass.ts @@ -25,7 +25,7 @@ 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 { PassType } from "../../../renderJob/passRenderer/state/PassType"; import { Vector4 } from "../../../../math/Vector4"; import { PipelinePool } from "../PipelinePool"; @@ -70,6 +70,7 @@ export class RenderShaderPass extends ShaderPassBase { public envMap: Texture; public prefilterMap: Texture; + public reflectionMap: Texture; protected _sourceVS: string; protected _sourceFS: string; @@ -288,6 +289,8 @@ export class RenderShaderPass extends ShaderPassBase { this.envMap = texture; } else if (name == "prefilterMap") { this.prefilterMap = texture; + } else if (name == "reflectionMap") { + this.reflectionMap = texture; } texture.bindStateChange(() => { this._textureChange = true; @@ -393,6 +396,11 @@ export class RenderShaderPass extends ShaderPassBase { this.defineValue[`USEGBUFFER`] = false; } + if (Engine3D.setting.render.useCompressGBuffer) { + this.defineValue[`USE_COMPRESSGBUFFER`] = true; + } else { + this.defineValue[`USE_COMPRESSGBUFFER`] = false; + } //*********************************/ //*********************************/ diff --git a/src/gfx/graphics/webGpu/shader/Shader.ts b/src/gfx/graphics/webGpu/shader/Shader.ts index 6fdb3997..40528b1f 100644 --- a/src/gfx/graphics/webGpu/shader/Shader.ts +++ b/src/gfx/graphics/webGpu/shader/Shader.ts @@ -6,7 +6,7 @@ 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 { PassType } from "../../../renderJob/passRenderer/state/PassType"; import { Color } from "../../../../math/Color"; import { Vector2 } from "../../../../math/Vector2"; import { Vector3 } from "../../../../math/Vector3"; @@ -85,6 +85,17 @@ export class Shader { } } + public hasDefine(arg0: string) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + let has = rd.hasDefine(arg0); + if (has) + return has; + } + } + return false + } + public deleteDefine(arg0: string) { for (const pass of this.passShader) { for (const rd of pass[1]) { diff --git a/src/gfx/graphics/webGpu/shader/value/ShaderState.ts b/src/gfx/graphics/webGpu/shader/value/ShaderState.ts index eb301609..81368159 100644 --- a/src/gfx/graphics/webGpu/shader/value/ShaderState.ts +++ b/src/gfx/graphics/webGpu/shader/value/ShaderState.ts @@ -8,7 +8,7 @@ import { GPUCompareFunction, GPUCullMode, GPUPrimitiveTopology } from '../../Web */ export class ShaderState { public blendMode?: BlendMode = BlendMode.NONE; - public depthCompare?: GPUCompareFunction = GPUCompareFunction.less; + public depthCompare?: GPUCompareFunction = GPUCompareFunction.less_equal; public depthWriteEnabled?: boolean = true; public frontFace?: GPUFrontFace = `ccw`; public cullMode?: GPUCullMode = GPUCullMode.back; @@ -20,7 +20,7 @@ export class ShaderState { public acceptGI: boolean = false; public acceptShadow: boolean = false; public castShadow: boolean = false; - public castReflection: boolean = false; + public castReflection: boolean = true; public receiveEnv: boolean = false; public renderLayer: number = 1000; public renderOrder: number = 2000; diff --git a/src/gfx/renderJob/GPUContext.ts b/src/gfx/renderJob/GPUContext.ts index 4ff2857d..5251c17c 100644 --- a/src/gfx/renderJob/GPUContext.ts +++ b/src/gfx/renderJob/GPUContext.ts @@ -3,6 +3,7 @@ import { GeometryBase } from "../../core/geometry/GeometryBase"; import { ProfilerUtil } from "../../util/ProfilerUtil"; import { webGPUContext } from "../graphics/webGpu/Context3D"; import { GlobalBindGroup } from "../graphics/webGpu/core/bindGroups/GlobalBindGroup"; +import { Texture } from "../graphics/webGpu/core/texture/Texture"; import { ComputeShader } from "../graphics/webGpu/shader/ComputeShader"; import { RenderShaderPass } from "../graphics/webGpu/shader/RenderShaderPass"; import { RendererPassState } from "./passRenderer/state/RendererPassState"; @@ -32,7 +33,7 @@ export class GPUContext { if (GPUContext.lastShader != renderShader) { GPUContext.lastShader = renderShader; } else { - return; + return false; } if (GPUContext.lastPipeline != renderShader.pipeline) { @@ -46,6 +47,7 @@ export class GPUContext { encoder.setBindGroup(i, bindGroup); } } + return true; } /** @@ -97,7 +99,8 @@ export class GPUContext { */ public static createPipeline(gpuRenderPipeline: GPURenderPipelineDescriptor) { ProfilerUtil.countStart("GPUContext", "pipeline"); - return webGPUContext.device.createRenderPipeline(gpuRenderPipeline); + let pipeline: GPURenderPipeline = webGPUContext.device.createRenderPipeline(gpuRenderPipeline); + return pipeline; } /** @@ -145,11 +148,14 @@ export class GPUContext { this.cleanCache(); this.renderPassCount++; this.lastRenderPassState = renderPassState; + if (renderPassState.depthTexture) { + let depth = renderPassState.renderPassDescriptor.depthStencilAttachment; + depth.view = renderPassState.depthTexture.getGPUView() as any; + } if (renderPassState.renderTargets && renderPassState.renderTargets.length > 0) { for (let i = 0; i < renderPassState.renderTargets.length; ++i) { const renderTarget = renderPassState.renderTargets[i]; let att = renderPassState.renderPassDescriptor.colorAttachments[i]; - if (renderPassState.multisample > 0 && renderPassState.renderTargets.length == 1) { att.view = renderPassState.multiTexture.createView(); att.resolveTarget = renderTarget.getGPUView(); @@ -220,4 +226,24 @@ export class GPUContext { } computePass.end(); } + + public static copyTexture(command: GPUCommandEncoder, source: Texture, dest: Texture) { + command.copyTextureToTexture( + { + texture: source.getGPUTexture(), + mipLevel: 0, + origin: { x: 0, y: 0, z: 0 }, + }, + { + texture: dest.getGPUTexture(), + mipLevel: 0, + origin: { x: 0, y: 0, z: 0 }, + }, + { + width: dest.width, + height: dest.height, + depthOrArrayLayers: 1, + }, + ); + } } diff --git a/src/gfx/renderJob/collect/EntityBatchCollect.ts b/src/gfx/renderJob/collect/EntityBatchCollect.ts index b2c7f6cd..3657199f 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 { PassType } from '../passRenderer/state/RendererType'; +import { PassType } from '../passRenderer/state/PassType'; import { RenderGroup } from './RenderGroup'; /** * @internal diff --git a/src/gfx/renderJob/collect/EntityCollect.ts b/src/gfx/renderJob/collect/EntityCollect.ts index 3f7ee751..8ce2ea57 100644 --- a/src/gfx/renderJob/collect/EntityCollect.ts +++ b/src/gfx/renderJob/collect/EntityCollect.ts @@ -1,6 +1,7 @@ import { Engine3D } from '../../../Engine3D'; import { ILight } from '../../../components/lights/ILight'; +import { Reflection } from '../../../components/renderer/Reflection'; import { RenderNode } from '../../../components/renderer/RenderNode'; import { Camera3D } from '../../../core/Camera3D'; import { Scene3D } from '../../../core/Scene3D'; @@ -32,6 +33,7 @@ export class EntityCollect { private _op_RenderNodes: Map; private _tr_RenderNodes: Map; private _octreeRenderNodes: Map; + private _reflections: Map; private _graphics: Graphic3DBatchRenderer[]; @@ -68,6 +70,7 @@ export class EntityCollect { this._op_RenderNodes = new Map(); this._tr_RenderNodes = new Map(); + this._reflections = new Map(); this._graphics = []; @@ -103,6 +106,17 @@ export class EntityCollect { let isTransparent: boolean = renderNode.renderOrder >= 3000; if (renderNode.hasMask(RendererMask.Sky)) { this.sky = renderNode; + } else if (renderNode.hasMask(RendererMask.Reflection)) { + this.removeRenderNode(root, renderNode); + let maps = this._reflections.get(root); + if (!maps) { + maps = []; + this._reflections.set(root, maps); + maps.push(renderNode as Reflection); + } + if (!maps.includes(renderNode as Reflection)) { + maps.push(renderNode as Reflection); + } } else if (renderNode instanceof Graphic3DBatchRenderer) { if (this._graphics.indexOf(renderNode) == -1) { this._graphics.push(renderNode); @@ -157,6 +171,14 @@ export class EntityCollect { renderNode.detachSceneOctree(); if (renderNode.hasMask(RendererMask.Sky)) { this.sky = null; + } else if (renderNode.hasMask(RendererMask.Reflection)) { + let maps = this._reflections.get(root); + if (maps) { + let index = maps.indexOf(renderNode as Reflection); + if (index != -1) { + maps.splice(index, 1); + } + } } else if (!RenderLayerUtil.hasMask(renderNode.renderLayer, RenderLayer.None)) { } else { @@ -225,6 +247,11 @@ export class EntityCollect { return list ? list : []; } + public getReflections(root: Scene3D) { + let list = this._reflections.get(root); + return list ? list : []; + } + // sort renderers by renderOrder and camera depth public autoSortRenderNodes(scene: Scene3D): this { let renderList: RenderNode[] = this._tr_RenderNodes.get(scene); diff --git a/src/gfx/renderJob/collect/RenderGroup.ts b/src/gfx/renderJob/collect/RenderGroup.ts index 9881c139..89deeca4 100644 --- a/src/gfx/renderJob/collect/RenderGroup.ts +++ b/src/gfx/renderJob/collect/RenderGroup.ts @@ -1,5 +1,5 @@ import { RenderNode } from '../../../components/renderer/RenderNode'; -import { PassType } from '../passRenderer/state/RendererType'; +import { PassType } from '../passRenderer/state/PassType'; /** * @internal * @group Post diff --git a/src/gfx/renderJob/collect/ShadowLightsCollect.ts b/src/gfx/renderJob/collect/ShadowLightsCollect.ts index 38e40c50..47b56e02 100644 --- a/src/gfx/renderJob/collect/ShadowLightsCollect.ts +++ b/src/gfx/renderJob/collect/ShadowLightsCollect.ts @@ -4,6 +4,7 @@ import { Scene3D } from '../../../core/Scene3D'; import { View3D } from '../../../core/View3D'; import { CameraUtil } from '../../../util/CameraUtil'; import { GlobalBindGroup } from '../../graphics/webGpu/core/bindGroups/GlobalBindGroup'; +import { GlobalUniformGroup } from '../../graphics/webGpu/core/bindGroups/GlobalUniformGroup'; /** * @internal * @group Lights @@ -20,7 +21,7 @@ export class ShadowLightsCollect { public static init() { this.directionLightList = new Map(); this.pointLightList = new Map(); - this.shadowLights = new Map; + this.shadowLights = new Map(); } public static createBuffer(view: View3D) { @@ -158,7 +159,7 @@ export class ShadowLightsCollect { 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); @@ -177,8 +178,6 @@ export class ShadowLightsCollect { } nDirShadowEnd = directionLightList.length; } - globalUniform.dirShadowStart = nDirShadowStart; - globalUniform.dirShadowEnd = nDirShadowEnd; if (pointLightList) { nPointShadowStart = nDirShadowEnd; @@ -191,8 +190,13 @@ export class ShadowLightsCollect { nPointShadowEnd = nPointShadowStart + pointLightList.length; } - globalUniform.pointShadowStart = nPointShadowStart; - globalUniform.pointShadowEnd = nPointShadowEnd; - globalUniform.shadowLights = shadowLights; + let cameraGroup = GlobalBindGroup.getAllCameraGroup(); + cameraGroup.forEach((group: GlobalUniformGroup) => { + group.dirShadowStart = nDirShadowStart; + group.dirShadowEnd = nDirShadowEnd; + group.pointShadowStart = nPointShadowStart; + group.pointShadowEnd = nPointShadowEnd; + group.shadowLights = shadowLights; + }); } } diff --git a/src/gfx/renderJob/config/RTResourceConfig.ts b/src/gfx/renderJob/config/RTResourceConfig.ts index 687e12ca..3a271fed 100644 --- a/src/gfx/renderJob/config/RTResourceConfig.ts +++ b/src/gfx/renderJob/config/RTResourceConfig.ts @@ -1,4 +1,5 @@ export class RTResourceConfig { + public static compressGBufferTex_NAME: string = 'compressGBufferTex_NAME'; public static colorBufferTex_NAME: string = 'colorBufferTex'; public static positionBufferTex_NAME: string = 'positionBufferTex'; public static normalBufferTex_NAME: string = 'normalBufferTex'; diff --git a/src/gfx/renderJob/config/RenderLayer.ts b/src/gfx/renderJob/config/RenderLayer.ts index 5340db92..e1184eda 100644 --- a/src/gfx/renderJob/config/RenderLayer.ts +++ b/src/gfx/renderJob/config/RenderLayer.ts @@ -7,6 +7,7 @@ export enum RenderLayer { None = 1 << 1, StaticBatch = 1 << 2, DynamicBatch = 1 << 3, + Hiden = 1 << 4, } /** diff --git a/src/gfx/renderJob/frame/GBufferFrame.ts b/src/gfx/renderJob/frame/GBufferFrame.ts index cd1ff214..f32be552 100644 --- a/src/gfx/renderJob/frame/GBufferFrame.ts +++ b/src/gfx/renderJob/frame/GBufferFrame.ts @@ -8,46 +8,42 @@ import { RTFrame } from "./RTFrame"; import { RTResourceMap } from "./RTResourceMap"; export class GBufferFrame extends RTFrame { + public static colorPass_GBuffer: string = "ColorPassGBuffer"; + public static reflections_GBuffer: string = "reflections_GBuffer"; public static gBufferMap: Map = new Map(); - public static bufferTexture: boolean = false; + // public static bufferTexture: boolean = false; + + private _colorBufferTex: RenderTexture; + private _compressGBufferTex: RenderTexture; + constructor() { super([], []); } - crateGBuffer(key: string, rtWidth: number, rtHeight: number) { + createGBuffer(key: string, rtWidth: number, rtHeight: number, autoResize: boolean = true, outColor: boolean = true) { let attachments = this.renderTargets; let reDescriptors = this.rtDescriptors; - 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.rgba16float, false); - let materialBufferTex = RTResourceMap.createRTTexture(key + RTResourceConfig.materialBufferTex_NAME, rtWidth, rtHeight, GPUTextureFormat.rgba8unorm, false); - - if (GBufferFrame.bufferTexture) { - attachments.push(colorBufferTex); - attachments.push(positionBufferTex); - attachments.push(normalBufferTex); - attachments.push(materialBufferTex); + if (outColor) { + let colorDec = new RTDescriptor(); + colorDec.loadOp = 'clear'; + this._colorBufferTex = RTResourceMap.createRTTexture(key + RTResourceConfig.colorBufferTex_NAME, rtWidth, rtHeight, GPUTextureFormat.rgba16float, true); + attachments.push(this._colorBufferTex); + reDescriptors.push(colorDec); } - let colorRTDes = new RTDescriptor(); - colorRTDes.loadOp = `clear`; + this._compressGBufferTex = new RenderTexture(rtWidth, rtHeight, GPUTextureFormat.rgba32float, false, undefined, 1, 0, true, true); + attachments.push(this._compressGBufferTex); + + this.depthTexture = new RenderTexture(rtWidth, rtHeight, GPUTextureFormat.depth24plus, false, undefined, 1, 0, true, true); + this.depthTexture.name = key + `_depthTexture`; - let depthTexture = new RenderTexture(rtWidth, rtHeight, GPUTextureFormat.depth24plus, false); - depthTexture.name = `depthTexture`; let depthDec = new RTDescriptor(); depthDec.loadOp = `load`; - this.depthTexture = depthTexture; - if (GBufferFrame.bufferTexture) { - reDescriptors.push(colorRTDes); - reDescriptors.push(new RTDescriptor()); - reDescriptors.push(new RTDescriptor()); - reDescriptors.push(new RTDescriptor()); - } - } + let compressGBufferRTDes: RTDescriptor; + compressGBufferRTDes = new RTDescriptor(); - public getColorMap() { - return this.renderTargets[0]; + reDescriptors.push(compressGBufferRTDes); } public getPositionMap() { @@ -58,19 +54,30 @@ export class GBufferFrame extends RTFrame { return this.renderTargets[2]; } - public getMaterialMap() { - return this.renderTargets[3]; + public getColorTexture() { + return this._colorBufferTex; + } + + public getCompressGBufferTexture() { + return this._compressGBufferTex; } /** * @internal */ - public static getGBufferFrame(key: string): GBufferFrame { + public static getGBufferFrame(key: string, fixedWidth: number = 0, fixedHeight: number = 0, outColor: boolean = true): GBufferFrame { let gBuffer: GBufferFrame; if (!GBufferFrame.gBufferMap.has(key)) { gBuffer = new GBufferFrame(); let size = webGPUContext.presentationSize; - gBuffer.crateGBuffer(key, size[0], size[1]); + // gBuffer.createGBuffer(key, size[0], size[1]); + gBuffer.createGBuffer( + key, + fixedWidth == 0 ? size[0] : fixedWidth, + fixedHeight == 0 ? size[1] : fixedHeight, + fixedWidth != 0 && fixedHeight != 0, + outColor + ); GBufferFrame.gBufferMap.set(key, gBuffer); } else { gBuffer = GBufferFrame.gBufferMap.get(key); diff --git a/src/gfx/renderJob/frame/GBufferFrameA.ts b/src/gfx/renderJob/frame/GBufferFrameA.ts new file mode 100644 index 00000000..83f06a10 --- /dev/null +++ b/src/gfx/renderJob/frame/GBufferFrameA.ts @@ -0,0 +1,116 @@ + +import { Engine3D } from "../../.."; +import { RenderTexture } from "../../../textures/RenderTexture"; +import { webGPUContext } from "../../graphics/webGpu/Context3D"; +import { GPUTextureFormat } from "../../graphics/webGpu/WebGPUConst"; +import { RTDescriptor } from "../../graphics/webGpu/descriptor/RTDescriptor"; +import { RTResourceConfig } from "../config/RTResourceConfig"; +import { RTFrame } from "./RTFrame"; +import { RTResourceMap } from "./RTResourceMap"; + +export class GBufferFrameA 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.renderTargets; + let reDescriptors = this.rtDescriptors; + 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.rgba16float, false); + let materialBufferTex = RTResourceMap.createRTTexture(key + RTResourceConfig.materialBufferTex_NAME, rtWidth, rtHeight, GPUTextureFormat.rgba16float, false); + let compressGBufferTex = RTResourceMap.createRTTexture(key + RTResourceConfig.compressGBufferTex_NAME, rtWidth, rtHeight, GPUTextureFormat.rgba32float, false); + + let useCompressGBuffer = Engine3D.setting.render.useCompressGBuffer; + if (GBufferFrameA.bufferTexture) { + if (useCompressGBuffer) { + // attachments.push(colorBufferTex); + // attachments.push(positionBufferTex); + // attachments.push(normalBufferTex); + attachments.push(compressGBufferTex); + } else { + attachments.push(colorBufferTex); + attachments.push(positionBufferTex); + attachments.push(normalBufferTex); + attachments.push(materialBufferTex); + } + } + + let colorRTDes = new RTDescriptor(); + colorRTDes.loadOp = `clear`; + + let compressGBufferRTDes: RTDescriptor; + if (useCompressGBuffer) { + compressGBufferRTDes = new RTDescriptor(); + compressGBufferRTDes.loadOp = `clear`; + } + + let depthTexture = new RenderTexture(rtWidth, rtHeight, GPUTextureFormat.depth24plus, false); + depthTexture.name = `depthTexture`; + + let depthDec = new RTDescriptor(); + depthDec.loadOp = `load`; + + this.depthTexture = depthTexture; + + if (GBufferFrameA.bufferTexture) { + if (useCompressGBuffer) { + // reDescriptors.push(colorRTDes); + // reDescriptors.push(new RTDescriptor()); + // reDescriptors.push(new RTDescriptor()); + reDescriptors.push(compressGBufferRTDes); + } else { + reDescriptors.push(colorRTDes); + reDescriptors.push(new RTDescriptor()); + reDescriptors.push(new RTDescriptor()); + reDescriptors.push(new RTDescriptor()); + } + } + } + + public getColorMap() { + return this.renderTargets[0]; + } + + public getPositionMap() { + return this.renderTargets[1]; + } + + public getNormalMap() { + return this.renderTargets[2]; + } + + public getMaterialMap() { + return this.renderTargets[3]; + } + + public getAlbedoMap() { + return this.renderTargets[3]; + } + + + /** + * @internal + */ + public static getGBufferFrame(key: string): GBufferFrameA { + let gBuffer: GBufferFrameA; + if (!GBufferFrameA.gBufferMap.has(key)) { + gBuffer = new GBufferFrameA(); + let size = webGPUContext.presentationSize; + gBuffer.crateGBuffer(key, size[0], size[1]); + GBufferFrameA.gBufferMap.set(key, gBuffer); + } else { + gBuffer = GBufferFrameA.gBufferMap.get(key); + } + return gBuffer; + } + + public clone() { + let gBufferFrame = new GBufferFrameA(); + this.clone2Frame(gBufferFrame); + return gBufferFrame; + } +} \ No newline at end of file diff --git a/src/gfx/renderJob/jobs/ForwardRenderJob.ts b/src/gfx/renderJob/jobs/ForwardRenderJob.ts index 99b1aedd..c1b77590 100644 --- a/src/gfx/renderJob/jobs/ForwardRenderJob.ts +++ b/src/gfx/renderJob/jobs/ForwardRenderJob.ts @@ -28,7 +28,6 @@ export class ForwardRenderJob extends RendererJob { let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); { - let debugTextures = []; let colorPassRenderer = new ColorPassRenderer(); if (Engine3D.setting.render.zPrePass) { @@ -37,36 +36,15 @@ 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); - // this.ddgiProbeRenderer.clusterLightingRender = this.clusterLightingRender; this.ddgiProbeRenderer.setInputTexture([ this.shadowMapPassRenderer.depth2DArrayTexture, this.pointLightShadowRenderer.cubeArrayTexture ]); - colorPassRenderer.setIrradiance(this.ddgiProbeRenderer.irradianceColorMap, this.ddgiProbeRenderer.irradianceDepthMap); - this.rendererMap.addRenderer(this.ddgiProbeRenderer); - - debugTextures.push( - this.ddgiProbeRenderer.positionMap, - this.ddgiProbeRenderer.normalMap, - this.ddgiProbeRenderer.colorMap, - this.ddgiProbeRenderer.lightingPass.lightingTexture, - this.ddgiProbeRenderer.irradianceColorMap, - this.ddgiProbeRenderer.irradianceDepthMap, - ); - } - - if (this.postRenderer) { - this.postRenderer.setDebugTexture(debugTextures); } this.rendererMap.addRenderer(colorPassRenderer); diff --git a/src/gfx/renderJob/jobs/RenderMap.ts b/src/gfx/renderJob/jobs/RenderMap.ts index b0969e21..dc7ebcc5 100644 --- a/src/gfx/renderJob/jobs/RenderMap.ts +++ b/src/gfx/renderJob/jobs/RenderMap.ts @@ -1,7 +1,7 @@ import { Camera3D } from "../../../core/Camera3D"; import { Scene3D } from "../../../core/Scene3D"; import { RendererBase } from "../passRenderer/RendererBase"; -import { PassType } from "../passRenderer/state/RendererType"; +import { PassType } from "../passRenderer/state/PassType"; export class RendererMap { diff --git a/src/gfx/renderJob/jobs/RendererJob.ts b/src/gfx/renderJob/jobs/RendererJob.ts index c477566a..d45fb2ab 100644 --- a/src/gfx/renderJob/jobs/RendererJob.ts +++ b/src/gfx/renderJob/jobs/RendererJob.ts @@ -17,6 +17,10 @@ import { PostBase } from '../post/PostBase'; import { RendererBase } from '../passRenderer/RendererBase'; import { Ctor } from '../../../util/Global'; import { DDGIProbeRenderer } from '../passRenderer/ddgi/DDGIProbeRenderer'; +import { ReflectionRenderer } from '../passRenderer/cubeRenderer/ReflectionRenderer'; +import { PassType } from '../passRenderer/state/PassType'; +import { ProfilerUtil } from '../../../util/ProfilerUtil'; +import { FXAAPost } from '../post/FXAAPost'; /** * render jobs @@ -54,6 +58,11 @@ export class RendererJob { */ public clusterLightingRender: ClusterLightingRender; + /** + * @internal + */ + public reflectionRenderer: ReflectionRenderer; + /** * @internal */ @@ -67,7 +76,10 @@ export class RendererJob { /** * @internal */ - public colorPassRenderer: ColorPassRenderer; + public get colorPassRenderer(): ColorPassRenderer { + let renderer = this.rendererMap.getRenderer(PassType.COLOR); + return renderer as ColorPassRenderer; + } /** * @internal @@ -90,6 +102,8 @@ export class RendererJob { this.clusterLightingRender = this.addRenderer(ClusterLightingRender, view); + this.reflectionRenderer = this.addRenderer(ReflectionRenderer, view); + if (Engine3D.setting.render.zPrePass) { this.depthPassRenderer = this.addRenderer(PreDepthPassRenderer); } @@ -97,6 +111,8 @@ export class RendererJob { this.shadowMapPassRenderer = new ShadowMapPassRenderer(); this.pointLightShadowRenderer = new PointLightShadowRenderer(); + + this.addPost(new FXAAPost()); } public addRenderer(c: Ctor, param?: any): T { @@ -151,22 +167,15 @@ export class RendererJob { this.pauseRender = false; } - /** - * @internal - */ - public enablePost(gbufferFrame: GBufferFrame) { - this.postRenderer = this.addRenderer(PostRenderer); - this.postRenderer.setRenderStates(gbufferFrame); - } - /** * Add a post processing special effects task * @param post */ public addPost(post: PostBase): PostBase | PostBase[] { if (!this.postRenderer) { - GBufferFrame.bufferTexture = true; - this.enablePost(GBufferFrame.getGBufferFrame('ColorPassGBuffer')); + let gbufferFrame = GBufferFrame.getGBufferFrame('ColorPassGBuffer'); + this.postRenderer = this.addRenderer(PostRenderer); + this.postRenderer.setRenderStates(gbufferFrame); } if (post instanceof PostBase) { @@ -195,11 +204,12 @@ export class RendererJob { public renderFrame() { let view = this._view; + ProfilerUtil.startView(view); GlobalBindGroup.getLightEntries(view.scene).update(view); + GlobalBindGroup.getReflectionEntries(view.scene).update(view); this.occlusionSystem.update(view.camera, view.scene); - this.clusterLightingRender.render(view, this.occlusionSystem); if (this.shadowMapPassRenderer) { @@ -225,10 +235,10 @@ export class RendererJob { for (let i = 0; i < passList.length; i++) { const renderer = passList[i]; renderer.compute(view, this.occlusionSystem); - renderer.render(view, this.occlusionSystem, this.clusterLightingRender.clusterLightingBuffer); + renderer.render(view, this.occlusionSystem, this.clusterLightingRender.clusterLightingBuffer, false); } - if (this.postRenderer && this.postRenderer.postList.length > 0) { + if (this.postRenderer && this.postRenderer.postList.size > 0) { this.postRenderer.render(view); } diff --git a/src/gfx/renderJob/passRenderer/RenderContext.ts b/src/gfx/renderJob/passRenderer/RenderContext.ts index ff25bc0d..4d7c698c 100644 --- a/src/gfx/renderJob/passRenderer/RenderContext.ts +++ b/src/gfx/renderJob/passRenderer/RenderContext.ts @@ -1,3 +1,4 @@ +import { ProfilerUtil } from "../../.."; import { WebGPUDescriptorCreator } from "../../graphics/webGpu/descriptor/WebGPUDescriptorCreator"; import { GPUContext } from "../GPUContext"; import { RTFrame } from "../frame/RTFrame"; @@ -11,7 +12,6 @@ export class RenderContext { constructor(rtFrame: RTFrame) { this.rtFrame = rtFrame; - this.rendererPassStates = []; } @@ -29,16 +29,12 @@ export class RenderContext { let splitRtFrame = this.rtFrame.clone(); for (const iterator of splitRtFrame.rtDescriptors) { iterator.loadOp = `load`; - // iterator.storeOp = `discard`; } splitRtFrame.depthLoadOp = depth_loadOp; let splitRendererPassState = WebGPUDescriptorCreator.createRendererPassState(splitRtFrame, color_loadOp); this.rendererPassStates.push(splitRendererPassState); return splitRendererPassState; } else { - // 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); diff --git a/src/gfx/renderJob/passRenderer/RendererBase.ts b/src/gfx/renderJob/passRenderer/RendererBase.ts index 71d53154..10dbb16d 100644 --- a/src/gfx/renderJob/passRenderer/RendererBase.ts +++ b/src/gfx/renderJob/passRenderer/RendererBase.ts @@ -13,7 +13,7 @@ import { EntityCollect } from "../collect/EntityCollect"; import { RTFrame } from "../frame/RTFrame"; import { OcclusionSystem } from "../occlusion/OcclusionSystem"; import { RendererPassState } from "./state/RendererPassState"; -import { PassType } from "./state/RendererType"; +import { PassType } from "./state/PassType"; import { RenderContext } from "./RenderContext"; import { ClusterLightingBuffer } from "./cluster/ClusterLightingBuffer"; import { RenderTexture } from "../../.."; @@ -35,6 +35,8 @@ export class RendererBase extends CEventDispatcher { protected _rendererType: PassType; protected _rtFrame: RTFrame; + + public get passType(): PassType { return this._rendererType; } @@ -60,17 +62,28 @@ export class RendererBase extends CEventDispatcher { } this.splitRendererPassState = WebGPUDescriptorCreator.createRendererPassState(splitRtFrame); } - this.renderContext = new RenderContext(rtFrame); + } + public getRenderContext(rtFrame: RTFrame) { + this._rtFrame = rtFrame; + // if (rtFrame) { + // this.rendererPassState = WebGPUDescriptorCreator.createRendererPassState(rtFrame); + // let splitRtFrame = rtFrame.clone(); + // splitRtFrame.depthLoadOp = "load"; + // for (const iterator of splitRtFrame.rtDescriptors) { + // iterator.loadOp = `load`; + // } + // this.splitRendererPassState = WebGPUDescriptorCreator.createRendererPassState(splitRtFrame); + // } + let renderContext = new RenderContext(rtFrame); + return renderContext; } public setIrradiance(probeIrradianceMap: RenderTexture, probeDepthMap: RenderTexture) { this.rendererPassState.irradianceBuffer = [probeIrradianceMap, probeDepthMap]; } - - public compute(view: View3D, occlusionSystem: OcclusionSystem) { } public render(view: View3D, occlusionSystem: OcclusionSystem, clusterLightingBuffer: ClusterLightingBuffer, maskTr: boolean = false) { @@ -80,6 +93,7 @@ export class RendererBase extends CEventDispatcher { let scene = view.scene; this.rendererPassState.camera3D = camera; + let collectInfo = EntityCollect.instance.getRenderNodes(scene, camera); // this.compute(collectInfo, scene, occlusionSystem); @@ -198,32 +212,4 @@ export class RendererBase extends CEventDispatcher { renderNode.renderPass2(view, this._rendererType, this.rendererPassState, clusterLightingBuffer, encoder); } } - - public setDebugTexture(textures: Texture[]) { - for (let i = 0; i < textures.length; i++) { - let tex = textures[i]; - let vs = "Quad_vert_wgsl"; - let fs = "Quad_frag_wgsl"; - switch (tex.format) { - case GPUTextureFormat.rgba8sint: - case GPUTextureFormat.rgba8uint: - case GPUTextureFormat.rgba8unorm: - case GPUTextureFormat.rgba16float: - case GPUTextureFormat.rgba32float: - fs = `Quad_frag_wgsl`; - break; - - case GPUTextureFormat.depth24plus: - case GPUTextureFormat.depth32float: - fs = `Quad_depth2d_frag_wgsl`; - if (tex.textureBindingLayout.viewDimension == `cube`) { - fs = `Quad_depthCube_frag_wgsl`; - } - break; - } - let viewQuad = new ViewQuad(vs, fs, new RTFrame([], [])); - this.debugTextures.push(textures[i]); - this.debugViewQuads.push(viewQuad); - } - } } diff --git a/src/gfx/renderJob/passRenderer/cluster/ClusterLightingRender.ts b/src/gfx/renderJob/passRenderer/cluster/ClusterLightingRender.ts index c58c7f94..e4957c89 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 { PassType } from '../state/RendererType'; +import { PassType } from '../state/PassType'; import { ILight } from '../../../../components/lights/ILight'; import { ClusterLightingBuffer } from './ClusterLightingBuffer'; import { ClusterBoundsSource_cs } from '../../../../assets/shader/cluster/ClusterBoundsSource_cs'; diff --git a/src/gfx/renderJob/passRenderer/color/ColorPassRenderer.ts b/src/gfx/renderJob/passRenderer/color/ColorPassRenderer.ts index 6d403766..12090064 100644 --- a/src/gfx/renderJob/passRenderer/color/ColorPassRenderer.ts +++ b/src/gfx/renderJob/passRenderer/color/ColorPassRenderer.ts @@ -1,3 +1,4 @@ +import { GlobalBindGroup } from "../../../.."; import { Engine3D } from "../../../../Engine3D"; import { RenderNode } from "../../../../components/renderer/RenderNode"; import { View3D } from "../../../../core/View3D"; @@ -10,7 +11,7 @@ import { OcclusionSystem } from "../../occlusion/OcclusionSystem"; import { RenderContext } from "../RenderContext"; import { RendererBase } from "../RendererBase"; import { ClusterLightingBuffer } from "../cluster/ClusterLightingBuffer"; -import { PassType } from "../state/RendererType"; +import { PassType } from "../state/PassType"; /** * @internal @@ -27,31 +28,28 @@ export class ColorPassRenderer extends RendererBase { public render(view: View3D, occlusionSystem: OcclusionSystem, clusterLightingBuffer?: ClusterLightingBuffer, maskTr: boolean = false) { this.renderContext.clean(); + let scene = view.scene; let camera = view.camera; + GlobalBindGroup.updateCameraGroup(camera); + this.rendererPassState.camera3D = camera; + let collectInfo = EntityCollect.instance.getRenderNodes(scene, camera); let op_bundleList = this.renderBundleOp(view, collectInfo, occlusionSystem, clusterLightingBuffer); let tr_bundleList = maskTr ? [] : this.renderBundleTr(view, collectInfo, occlusionSystem, clusterLightingBuffer); - ProfilerUtil.start("colorPass Renderer"); { - ProfilerUtil.start("ColorPass Draw Opaque"); - this.renderContext.beginOpaqueRenderPass(); - - let command = this.renderContext.command; let renderPassEncoder = this.renderContext.encoder; - // renderPassEncoder.setViewport(camera.viewPort.x, camera.viewPort.y, camera.viewPort.width, camera.viewPort.height, 0.0, 1.0); - // renderPassEncoder.setScissorRect(camera.viewPort.x, camera.viewPort.y, camera.viewPort.width, camera.viewPort.height); + // // renderPassEncoder.setViewport(camera.viewPort.x, camera.viewPort.y, camera.viewPort.width, camera.viewPort.height, 0.0, 1.0); + // // renderPassEncoder.setScissorRect(camera.viewPort.x, camera.viewPort.y, camera.viewPort.width, camera.viewPort.height); - // renderPassEncoder.setViewport(view.viewPort.x, view.viewPort.y, view.viewPort.width, view.viewPort.height, 0.0, 1.0); - // renderPassEncoder.setScissorRect(view.viewPort.x, view.viewPort.y, view.viewPort.width, view.viewPort.height); - - GPUContext.bindCamera(renderPassEncoder, camera); + // // renderPassEncoder.setViewport(view.viewPort.x, view.viewPort.y, view.viewPort.width, view.viewPort.height, 0.0, 1.0); + // // renderPassEncoder.setScissorRect(view.viewPort.x, view.viewPort.y, view.viewPort.width, view.viewPort.height); if (op_bundleList.length > 0) { // GPUContext.bindCamera(renderPassEncoder,camera); @@ -68,7 +66,7 @@ export class ColorPassRenderer extends RendererBase { if (!maskTr && EntityCollect.instance.sky) { GPUContext.bindCamera(renderPassEncoder, camera); - if (!EntityCollect.instance.sky.preInit) { + if (!EntityCollect.instance.sky.preInit(this._rendererType)) { EntityCollect.instance.sky.nodeUpdate(view, this._rendererType, this.rendererPassState, clusterLightingBuffer); } EntityCollect.instance.sky.renderPass2(view, this._rendererType, this.rendererPassState, clusterLightingBuffer, renderPassEncoder); @@ -77,17 +75,14 @@ export class ColorPassRenderer extends RendererBase { if (collectInfo.opaqueList) { GPUContext.bindCamera(renderPassEncoder, camera); this.drawNodes(view, this.renderContext, collectInfo.opaqueList, occlusionSystem, clusterLightingBuffer); - this.renderContext.endRenderPass(); - ProfilerUtil.end("ColorPass Draw Opaque"); } + // this.renderContext.endRenderPass(); + } { - ProfilerUtil.start("ColorPass Draw Transparent"); + // this.renderContext.beginTransparentRenderPass(); - this.renderContext.beginTransparentRenderPass(); - - let command = this.renderContext.command; let renderPassEncoder = this.renderContext.encoder; if (tr_bundleList.length > 0) { @@ -102,24 +97,18 @@ export class ColorPassRenderer extends RendererBase { let graphicsList = EntityCollect.instance.getGraphicList(); for (let i = 0; i < graphicsList.length; i++) { const graphic3DRenderNode = graphicsList[i]; - let matrixIndex = graphic3DRenderNode.transform.worldMatrix.index; graphic3DRenderNode.nodeUpdate(view, this._rendererType, this.splitRendererPassState, clusterLightingBuffer); 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"); } - ProfilerUtil.end("colorPass Renderer"); + // ProfilerUtil.end("colorPass Renderer"); } public drawNodes(view: View3D, renderContext: RenderContext, nodes: RenderNode[], occlusionSystem: OcclusionSystem, clusterLightingBuffer: ClusterLightingBuffer) { @@ -129,7 +118,7 @@ export class ColorPassRenderer extends RendererBase { let nodeMap = renderList[1]; for (const iterator of nodeMap) { let node = iterator[1]; - if (node.preInit) { + if (node.preInit(this._rendererType)) { node.nodeUpdate(view, this._rendererType, this.rendererPassState, clusterLightingBuffer); break; } @@ -145,7 +134,7 @@ export class ColorPassRenderer extends RendererBase { if (!renderNode.enable) continue; - if (!renderNode.preInit) { + if (!renderNode.preInit(this._rendererType)) { renderNode.nodeUpdate(view, this._rendererType, this.rendererPassState, clusterLightingBuffer); } renderNode.renderPass(view, this.passType, this.renderContext); diff --git a/src/gfx/renderJob/passRenderer/cubeRenderer/ReflectionRenderer.ts b/src/gfx/renderJob/passRenderer/cubeRenderer/ReflectionRenderer.ts new file mode 100644 index 00000000..e901c37e --- /dev/null +++ b/src/gfx/renderJob/passRenderer/cubeRenderer/ReflectionRenderer.ts @@ -0,0 +1,222 @@ +import { Camera3D } from '../../../../core/Camera3D'; +import { CubeCamera } from '../../../../core/CubeCamera'; +import { Engine3D } from '../../../../Engine3D'; +import { EntityCollect } from '../../collect/EntityCollect'; +import { GPUContext } from '../../GPUContext'; +import { OcclusionSystem } from '../../occlusion/OcclusionSystem'; +import { RendererBase } from '../RendererBase'; +import { PassType } from '../state/PassType'; +import { View3D } from '../../../../core/View3D'; +import { GBufferFrame } from '../../frame/GBufferFrame'; +import { ClusterLightingBuffer } from '../cluster/ClusterLightingBuffer'; +import { RenderContext } from '../RenderContext'; +import { RenderNode } from '../../../../components/renderer/RenderNode'; +import { RendererMask } from '../state/RendererMask'; +import { PreFilteredEnvironment_cs } from '../../../../assets/shader/compute/PreFilteredEnvironment_cs'; +import { ComputeShader } from '../../../graphics/webGpu/shader/ComputeShader'; +import { VirtualTexture } from '../../../../textures/VirtualTexture'; +import { GPUTextureFormat } from '../../../graphics/webGpu/WebGPUConst'; +import { UniformGPUBuffer } from '../../../graphics/webGpu/core/buffer/UniformGPUBuffer'; +import { GlobalBindGroup } from '../../../graphics/webGpu/core/bindGroups/GlobalBindGroup'; +import { Time } from '../../../../util/Time'; + +/** + * @internal + * @group Post + */ +export class ReflectionRenderer extends RendererBase { + private cubeCamera: CubeCamera; + public gBuffer: GBufferFrame; + + public sizeW: number = 0; + public sizeH: number = 0; + + public probeSize = 64; + public probeCount = 32; + public mipCount = 8; + public preFilteredEnvironmentCompute: ComputeShader; + public outTexture: VirtualTexture; + public preFilteredEnvironmentUniform: UniformGPUBuffer; + + private onChange: boolean = true; + private needUpdate: boolean = true; + /** + * + * @param volume + */ + constructor() { + super(); + + this.passType = PassType.REFLECTION; + + this.cubeCamera = new CubeCamera(0.01, 5000); + let mipmap = 1;// TextureMipmapGenerator.getMipmapCount(this.sizeW, this.sizeH); + + this.probeSize = Engine3D.setting.reflectionSetting.reflectionProbeSize; + this.probeCount = Engine3D.setting.reflectionSetting.reflectionProbeMaxCount; + this.sizeW = Engine3D.setting.reflectionSetting.width; + this.sizeH = Engine3D.setting.reflectionSetting.height; + + this.gBuffer = GBufferFrame.getGBufferFrame(GBufferFrame.reflections_GBuffer, this.sizeW, this.sizeH, false); + this.setRenderStates(this.gBuffer); + + this.outTexture = new VirtualTexture(this.probeSize * this.mipCount, this.sizeH, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING, 1, 0, mipmap); + this.outTexture.name = 'texture_AAA'; + + this.preFilteredEnvironmentUniform = new UniformGPUBuffer(4 + this.probeCount * 4); + this.preFilteredEnvironmentUniform.setFloat("probeSize", this.probeSize); + this.preFilteredEnvironmentUniform.setFloat("probeCount", this.probeCount); + this.preFilteredEnvironmentUniform.setFloat("width", this.sizeW); + this.preFilteredEnvironmentUniform.setFloat("height", this.sizeH); + this.preFilteredEnvironmentUniform.apply(); + + this.preFilteredEnvironmentCompute = new ComputeShader(PreFilteredEnvironment_cs); + this.preFilteredEnvironmentCompute.setSamplerTexture("inputTex", this.gBuffer.getCompressGBufferTexture()); + this.preFilteredEnvironmentCompute.setStorageTexture("outputTexture", this.outTexture); + this.preFilteredEnvironmentCompute.setUniformBuffer("uniformData", this.preFilteredEnvironmentUniform); + } + + public forceUpdate() { + this.onChange = true; + } + + public compute(view: View3D, occlusionSystem: OcclusionSystem): void { + if (this.needUpdate) { + this.needUpdate = false; + let reflectionEntries = GlobalBindGroup.getReflectionEntries(view.scene); + reflectionEntries.reflectionMap = this.outTexture; + + this.preFilteredEnvironmentCompute.workerSizeX = Math.ceil(this.probeSize * this.mipCount / 16); + this.preFilteredEnvironmentCompute.workerSizeY = Math.ceil(this.sizeH / 16); + this.preFilteredEnvironmentCompute.workerSizeZ = this.mipCount * reflectionEntries.count; + + let command = GPUContext.beginCommandEncoder(); + GPUContext.computeCommand( + command, + [ + this.preFilteredEnvironmentCompute + ] + ); + GPUContext.endCommandEncoder(command); + } + } + + public render(view: View3D, occlusionSystem: OcclusionSystem, clusterLightingBuffer?: ClusterLightingBuffer, maskTr: boolean = false, hasPost: boolean = false): void { + this.renderContext.clean(); + let spaceX = this.probeSize; + let spaceY = this.probeSize; + + let reflections = EntityCollect.instance.getReflections(view.scene); + + for (let i = 0; i < reflections.length; i++) { + let reflection = reflections[i]; + if (reflection.autoUpdate && (reflection.needUpdate || this.onChange) || Time.frame < 10) { + reflection.needUpdate = false; + this.needUpdate = true; + this.renderContext.beginOpaqueRenderPass(); + let encoder = this.renderContext.encoder; + + let offsetY = i * spaceY; + reflections[i].transform.updateWorldMatrix(); + let worldPos = reflections[i].transform.worldPosition; + this.cubeCamera.x = worldPos.x; + this.cubeCamera.y = worldPos.y; + this.cubeCamera.z = worldPos.z; + this.cubeCamera.far = 10000;// view.camera.far; + this.cubeCamera.transform.updateWorldMatrix(); + + encoder.setViewport(spaceX * 0, offsetY, spaceX, spaceY, 0.0, 1.0); + this.renderOnce(view, this.cubeCamera.right_camera, encoder, occlusionSystem, clusterLightingBuffer, maskTr); + + encoder.setViewport(spaceX * 1, offsetY, spaceX, spaceY, 0.0, 1.0); + this.renderOnce(view, this.cubeCamera.left_camera, encoder, occlusionSystem, clusterLightingBuffer, maskTr); + + encoder.setViewport(spaceX * 2, offsetY, spaceX, spaceY, 0.0, 1.0); + this.renderOnce(view, this.cubeCamera.up_camera, encoder, occlusionSystem, clusterLightingBuffer, maskTr); + + encoder.setViewport(spaceX * 3, offsetY, spaceX, spaceY, 0.0, 1.0); + this.renderOnce(view, this.cubeCamera.down_camera, encoder, occlusionSystem, clusterLightingBuffer, maskTr); + + encoder.setViewport(spaceX * 4, offsetY, spaceX, spaceY, 0.0, 1.0); + this.renderOnce(view, this.cubeCamera.front_camera, encoder, occlusionSystem, clusterLightingBuffer, maskTr); + + encoder.setViewport(spaceX * 5, offsetY, spaceX, spaceY, 0.0, 1.0); + this.renderOnce(view, this.cubeCamera.back_camera, encoder, occlusionSystem, clusterLightingBuffer, maskTr); + this.renderContext.endRenderPass(); + } + } + + + this.onChange = false; + } + + public renderOnce(view: View3D, camera: Camera3D, encoder, occlusionSystem: OcclusionSystem, clusterLightingBuffer?: ClusterLightingBuffer, maskTr: boolean = false) { + let scene = view.scene; + camera.transform.scene3D = scene; + this.rendererPassState.camera3D = camera; + let collectInfo = EntityCollect.instance.getRenderNodes(scene, camera); + { + let renderPassEncoder = encoder; + GlobalBindGroup.updateCameraGroup(camera); + + if (!maskTr && EntityCollect.instance.sky) { + GPUContext.bindCamera(renderPassEncoder, camera); + if (!EntityCollect.instance.sky.preInit(PassType.REFLECTION)) { + EntityCollect.instance.sky.nodeUpdate(view, PassType.REFLECTION, this.rendererPassState, clusterLightingBuffer); + } + EntityCollect.instance.sky.renderPass2(view, PassType.REFLECTION, this.rendererPassState, clusterLightingBuffer, renderPassEncoder); + } + + if (collectInfo.opaqueList) { + GPUContext.bindCamera(renderPassEncoder, camera); + this.drawNodes(view, this.renderContext, collectInfo.opaqueList, occlusionSystem, clusterLightingBuffer); + } + + if (!maskTr && collectInfo.transparentList) { + GPUContext.bindCamera(renderPassEncoder, camera); + this.drawNodes(view, this.renderContext, collectInfo.transparentList, occlusionSystem, clusterLightingBuffer); + } + } + } + + public drawNodes(view: View3D, renderContext: RenderContext, nodes: RenderNode[], occlusionSystem: OcclusionSystem, clusterLightingBuffer: ClusterLightingBuffer) { + let viewRenderList = EntityCollect.instance.getRenderShaderCollect(view); + if (viewRenderList) { + for (const renderList of viewRenderList) { + let nodeMap = renderList[1]; + for (const iterator of nodeMap) { + let node = iterator[1]; + if (node.hasMask(RendererMask.ReflectionDebug)) + continue; + if (node.preInit(PassType.REFLECTION)) { + node.nodeUpdate(view, PassType.REFLECTION, this.rendererPassState, clusterLightingBuffer); + break; + } + } + } + + // for (let i = Engine3D.setting.render.drawOpMin; i < Math.min(nodes.length, Engine3D.setting.render.drawOpMax); ++i) { + for (let i = 0; i < nodes.length; i++) { + let renderNode = nodes[i]; + // if (!occlusionSystem.renderCommitTesting(view.camera, renderNode)) + // continue; + if (renderNode.hasMask(RendererMask.ReflectionDebug)) + continue; + if (!renderNode.transform.enable) + continue; + if (!renderNode.enable) + continue; + + if (!renderNode.preInit(PassType.REFLECTION)) { + renderNode.nodeUpdate(view, PassType.REFLECTION, this.rendererPassState, clusterLightingBuffer); + } + renderNode.renderPass(view, PassType.REFLECTION, this.renderContext); + } + } + } + + + protected occlusionRenderNodeTest(i: number, id: number, occlusionSystem: OcclusionSystem): boolean { + return true;//occlusionSystem.zDepthRenderNodeTest(id) > 0; + } +} diff --git a/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceComputePass.ts b/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceComputePass.ts index 1881d27d..162a8090 100644 --- a/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceComputePass.ts +++ b/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceComputePass.ts @@ -76,5 +76,6 @@ export class DDGIIrradianceComputePass { this.computeShader.workerSizeY = setting.octRTSideSize / 8; this.computeShader.workerSizeZ = probes.length; GPUContext.computeCommand(command, [this.computeShader]); + GPUContext.endCommandEncoder(command); } } diff --git a/src/gfx/renderJob/passRenderer/ddgi/DDGILightingPass.ts b/src/gfx/renderJob/passRenderer/ddgi/DDGILightingPass.ts index bb9f06ce..0e221327 100644 --- a/src/gfx/renderJob/passRenderer/ddgi/DDGILightingPass.ts +++ b/src/gfx/renderJob/passRenderer/ddgi/DDGILightingPass.ts @@ -65,5 +65,7 @@ export class DDGILightingPass { this.computeShader.workerSizeY = giSetting.probeSourceTextureSize / 8; this.computeShader.workerSizeZ = 1; GPUContext.computeCommand(command, [this.computeShader]); + GPUContext.endCommandEncoder(command); + } } diff --git a/src/gfx/renderJob/passRenderer/ddgi/DDGIMultiBouncePass.ts b/src/gfx/renderJob/passRenderer/ddgi/DDGIMultiBouncePass.ts index 46246116..991e9ea9 100644 --- a/src/gfx/renderJob/passRenderer/ddgi/DDGIMultiBouncePass.ts +++ b/src/gfx/renderJob/passRenderer/ddgi/DDGIMultiBouncePass.ts @@ -52,5 +52,7 @@ export class DDGIMultiBouncePass { this.computerShader.workerSizeY = probeSourceSize / 8; this.computerShader.workerSizeZ = probesCount; GPUContext.computeCommand(command, [this.computerShader]); + GPUContext.endCommandEncoder(command); + } } diff --git a/src/gfx/renderJob/passRenderer/ddgi/DDGIProbeRenderer.ts b/src/gfx/renderJob/passRenderer/ddgi/DDGIProbeRenderer.ts index 7dae7b77..ca47dcdc 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 { PassType } from '../state/RendererType'; +import { PassType } from '../state/PassType'; import { DDGIIrradianceComputePass } from './DDGIIrradianceComputePass'; import { DDGIIrradianceVolume } from './DDGIIrradianceVolume'; import { DDGIMultiBouncePass } from './DDGIMultiBouncePass'; @@ -114,7 +114,6 @@ export class DDGIProbeRenderer extends RendererBase { } - public updateProbe(view: View3D, probe: Probe, encoder: GPURenderPassEncoder,) { let lights = EntityCollect.instance.getLights(view.scene); let cubeSize = this.volume.setting.probeSize; // cubeSize * 2 * 2 * 2; @@ -198,7 +197,7 @@ export class DDGIProbeRenderer extends RendererBase { let nodeMap = renderList[1]; for (const iterator of nodeMap) { let node = iterator[1]; - if (node.preInit) { + if (node.preInit(this.passType)) { node.nodeUpdate(view, this.passType, this.rendererPassState, null); break; } @@ -208,7 +207,7 @@ export class DDGIProbeRenderer extends RendererBase { for (let i = drawMin; i < drawMax; ++i) { let renderNode = collectInfo.opaqueList[i]; if (renderNode.enable && renderNode.transform.enable) { - if (!renderNode.preInit) { + if (!renderNode.preInit(this.passType)) { renderNode.nodeUpdate(view, this.passType, this.rendererPassState, null); } renderNode.renderPass2(view, this.passType, this.rendererPassState, null, encoder); @@ -216,7 +215,7 @@ export class DDGIProbeRenderer extends RendererBase { } if (EntityCollect.instance.sky) { - if (!EntityCollect.instance.sky.preInit) { + if (!EntityCollect.instance.sky.preInit(this.passType)) { EntityCollect.instance.sky.nodeUpdate(view, this.passType, this.rendererPassState, null); } EntityCollect.instance.sky.renderPass2(view, this.passType, this.rendererPassState, null, encoder); @@ -228,7 +227,7 @@ export class DDGIProbeRenderer extends RendererBase { for (let i = drawMin; i < drawMax; ++i) { let renderNode = collectInfo.transparentList[i]; if (renderNode.enable && renderNode.transform.enable) { - if (!renderNode.preInit) { + if (!renderNode.preInit(this.passType)) { renderNode.nodeUpdate(view, this.passType, this.rendererPassState, null); } renderNode.renderPass2(view, this.passType, this.rendererPassState, null, encoder); diff --git a/src/gfx/renderJob/passRenderer/graphic/Graphic3DBatchRenderer.ts b/src/gfx/renderJob/passRenderer/graphic/Graphic3DBatchRenderer.ts index 7092f2e3..5fbc857b 100644 --- a/src/gfx/renderJob/passRenderer/graphic/Graphic3DBatchRenderer.ts +++ b/src/gfx/renderJob/passRenderer/graphic/Graphic3DBatchRenderer.ts @@ -3,7 +3,7 @@ import { View3D } from "../../../../core/View3D"; import { Color } from "../../../../math/Color"; import { Vector3 } from "../../../../math/Vector3"; import { RendererPassState } from "../state/RendererPassState"; -import { PassType } from "../state/RendererType"; +import { PassType } from "../state/PassType"; import { Graphics3DShape } from "./Graphics3DShape"; import { ClusterLightingBuffer } from "../cluster/ClusterLightingBuffer"; import { GeometryBase, Graphic3DFixedRenderMaterial, VertexAttributeName } from "../../../.."; @@ -119,7 +119,7 @@ export class Graphic3DBatchRenderer extends RenderNode { let count = offset / 4; let indexCount = count; this.geometry.subGeometries[0].lodLevels[0].indexCount = indexCount; - + this.mDirtyData = false; } diff --git a/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts b/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts index 4383922c..f45f0c1e 100644 --- a/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts +++ b/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts @@ -1,18 +1,13 @@ -import { Vector2, Vector3, mergeFunctions } from "../../../../.."; -import { graphicTrailCompute } from "../../../../../assets/shader/graphic/GraphicTrailCompute"; import { MeshRenderer } from "../../../../../components/renderer/MeshRenderer"; import { View3D } from "../../../../../core/View3D"; import { Object3D } from "../../../../../core/entities/Object3D"; import { GeometryBase } from "../../../../../core/geometry/GeometryBase"; -import { UnLitMaterial } from "../../../../../materials/UnLitMaterial"; import { UnLitTexArrayMaterial } from "../../../../../materials/UnLitTexArrayMaterial"; import { Color } from "../../../../../math/Color"; +import { Vector3 } from "../../../../../math/Vector3"; import { Vector4 } from "../../../../../math/Vector4"; -import { BoxGeometry } from "../../../../../shape/BoxGeometry"; -import { TrailGeometry } from "../../../../../shape/TrailGeometry"; import { BitmapTexture2DArray } from "../../../../../textures/BitmapTexture2DArray"; import { GeometryUtil } from "../../../../../util/GeometryUtil"; -import { GlobalBindGroup } from "../../../../graphics/webGpu/core/bindGroups/GlobalBindGroup"; import { StorageGPUBuffer } from "../../../../graphics/webGpu/core/buffer/StorageGPUBuffer"; import { ComputeShader } from "../../../../graphics/webGpu/shader/ComputeShader"; import { GPUContext } from "../../../GPUContext"; @@ -65,6 +60,10 @@ export class Graphic3DMeshRenderer extends MeshRenderer { this.geometry = GeometryUtil.mergeNumber(source, num); } + public startSpark() { + + } + public setTextureID(i: number, id: number) { this.transformBuffer.setFloat("texId_" + i, id); this._onChange = true; diff --git a/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DRibbonRenderer.ts b/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DRibbonRenderer.ts index becabf9a..f55d1581 100644 --- a/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DRibbonRenderer.ts +++ b/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DRibbonRenderer.ts @@ -1,4 +1,3 @@ -import { NonSerialize, StructStorageGPUBuffer, Vector3 } from "../../../../.."; import { graphicTrailCompute } from "../../../../../assets/shader/graphic/GraphicTrailCompute"; import { MeshRenderer } from "../../../../../components/renderer/MeshRenderer"; import { View3D } from "../../../../../core/View3D"; @@ -11,9 +10,11 @@ import { Vector4 } from "../../../../../math/Vector4"; import { TrailGeometry } from "../../../../../shape/TrailGeometry"; import { BitmapTexture2DArray } from "../../../../../textures/BitmapTexture2DArray"; import { GeometryUtil } from "../../../../../util/GeometryUtil"; +import { NonSerialize } from "../../../../../util/SerializeDecoration"; import { Struct } from "../../../../../util/struct/Struct"; import { GlobalBindGroup } from "../../../../graphics/webGpu/core/bindGroups/GlobalBindGroup"; import { StorageGPUBuffer } from "../../../../graphics/webGpu/core/buffer/StorageGPUBuffer"; +import { StructStorageGPUBuffer } from "../../../../graphics/webGpu/core/buffer/StructStorageGPUBuffer"; import { ComputeShader } from "../../../../graphics/webGpu/shader/ComputeShader"; import { GPUContext } from "../../../GPUContext"; diff --git a/src/gfx/renderJob/passRenderer/post/PostRenderer.ts b/src/gfx/renderJob/passRenderer/post/PostRenderer.ts index 27ecbf35..4f3352e7 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 { PassType } from "../state/RendererType"; +import { PassType } from "../state/PassType"; /** @@ -16,13 +16,13 @@ import { PassType } from "../state/RendererType"; */ export class PostRenderer extends RendererBase { public finalQuadView: ViewQuad; - public postList: PostBase[]; + public postList: Map; constructor() { super(); this._rendererType = PassType.POST; - this.postList = []; + this.postList = new Map(); this.initRenderer(); } @@ -34,30 +34,39 @@ export class PostRenderer extends RendererBase { public attachPost(view: View3D, post: PostBase) { post.postRenderer = this; - let has = this.postList.indexOf(post) != -1; + let clsName = post.constructor.name; + let has = this.postList.get(clsName); if (!has) { - this.postList.push(post); + this.postList.set(clsName, post); post.onAttach(view); } } public detachPost(view: View3D, post: PostBase): boolean { - let index = this.postList.indexOf(post); - if (index >= 0) { - this.postList.splice(index, 1); + let clsName = post.constructor.name; + let has = this.postList.get(clsName); + if (has) { + this.postList.delete(clsName); post.onDetach(view); post.postRenderer = null; } - return index >= 0; + return has != null; } public render(view: View3D) { + + this.postList.forEach((v) => { + if (v.enable) { + v.compute(view); + } + }); + let command = GPUContext.beginCommandEncoder(); - for (let i = 0; i < this.postList.length; i++) { - const post = this.postList[i]; - if (!post.enable) continue; - post.render(view, command); - } + this.postList.forEach((v) => { + if (v.enable) { + v.render(view, command); + } + }); let lastTexture = GPUContext.lastRenderPassState.getLastRenderTexture(); this.finalQuadView.renderToViewQuad(view, this.finalQuadView, command, lastTexture); diff --git a/src/gfx/renderJob/passRenderer/preDepth/PreDepthPassRenderer.ts b/src/gfx/renderJob/passRenderer/preDepth/PreDepthPassRenderer.ts index 321c5213..79afcd36 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 { PassType } from "../state/RendererType"; +import { PassType } from "../state/PassType"; import { ZCullingCompute } from "./ZCullingCompute"; /** @@ -79,7 +79,7 @@ export class PreDepthPassRenderer extends RendererBase { let nodeMap = renderList[1]; for (const iterator of nodeMap) { let node = iterator[1]; - if (node.preInit) { + if (node.preInit(this._rendererType)) { node.nodeUpdate(view, this._rendererType, this.rendererPassState, null); break; } @@ -110,7 +110,7 @@ export class PreDepthPassRenderer extends RendererBase { continue; if (!renderNode.enable) continue; - if (!renderNode.preInit) { + if (!renderNode.preInit(this._rendererType)) { renderNode.nodeUpdate(view, this._rendererType, this.rendererPassState); } renderNode.renderPass2(view, this._rendererType, this.rendererPassState, clusterLightingBuffer, encoder); diff --git a/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts b/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts index dd595303..ebaa6c09 100644 --- a/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts +++ b/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts @@ -19,14 +19,17 @@ 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 { PassType } from '../state/RendererType'; +import { PassType } from '../state/PassType'; import { ILight } from '../../../../components/lights/ILight'; import { Reference } from '../../../../util/Reference'; +import { GlobalBindGroup } from '../../../graphics/webGpu/core/bindGroups/GlobalBindGroup'; +import { RenderContext } from '../RenderContext'; +import { ClusterLightingBuffer } from '../cluster/ClusterLightingBuffer'; type CubeShadowMapInfo = { cubeCamera: CubeCamera, depthTexture: VirtualTexture[], - rendererPassState: RendererPassState[] + renderContext: RenderContext[] } /** @@ -61,26 +64,26 @@ export class PointLightShadowRenderer extends RendererBase { let camera = new PointShadowCubeCamera(view.camera.near, view.camera.far, 90, true); camera.label = lightBase.name; let depths: VirtualTexture[] = []; - let rendererPassStates: RendererPassState[] = []; + let renderContext: RenderContext[] = []; for (let i = 0; i < 6; i++) { let depthTexture = new VirtualTexture(this.shadowSize, this.shadowSize, this.cubeArrayTexture.format, false); let rtFrame = new RTFrame([this.colorTexture], [new RTDescriptor()]); depthTexture.name = `shadowDepthTexture_` + lightBase.name + i + "_face"; + depths[i] = depthTexture; + rtFrame.depthTexture = depthTexture; rtFrame.label = "shadowRender" rtFrame.customSize = true; - let rendererPassState = WebGPUDescriptorCreator.createRendererPassState(rtFrame); - rendererPassStates[i] = rendererPassState; - depths[i] = depthTexture; + renderContext[i] = this.getRenderContext(rtFrame); - Engine3D.getRenderJob(view).postRenderer?.setDebugTexture([depthTexture]); + // Engine3D.getRenderJob(view).postRenderer?.setDebugTexture([depthTexture]); } cubeShadowMapInfo = { - cubeCamera: camera, + cubeCamera: camera as any as CubeCamera, depthTexture: depths, - rendererPassState: rendererPassStates, + renderContext: renderContext, } this._shadowCameraDic.set(lightBase, cubeShadowMapInfo); } @@ -96,6 +99,7 @@ export class PointLightShadowRenderer extends RendererBase { let camera = view.camera; let scene = view.scene; + // return ; // if (!Engine3D.engineSetting.Shadow.needUpdate) return; // if (!(Time.frame % Engine3D.engineSetting.Shadow.updateFrameRate == 0)) return; @@ -110,6 +114,7 @@ export class PointLightShadowRenderer extends RendererBase { let light = shadowLight[si]; if (light.lightData.lightType == LightType.DirectionLight) continue; + // if (light.lightData.castShadowIndex > -1 && (light.needUpdateShadow || this._forceUpdate || Time.frame < 5)) { if (light.lightData.castShadowIndex > -1 && (light.needUpdateShadow || this._forceUpdate || Time.frame < 5 || light.realTimeShadow)) { light.needUpdateShadow = false; @@ -176,75 +181,130 @@ export class PointLightShadowRenderer extends RendererBase { private renderSceneOnce(face: number, cubeShadowMapInfo: CubeShadowMapInfo, view: View3D, shadowCamera: Camera3D, collectInfo: CollectInfo, occlusionSystem: OcclusionSystem) { - this.rendererPassState = cubeShadowMapInfo.rendererPassState[face]; - let command = GPUContext.beginCommandEncoder(); - let encoder = GPUContext.beginRenderPass(command, this.rendererPassState); + let renderContext = cubeShadowMapInfo.renderContext[face]; + renderContext.clean(); + renderContext.beginOpaqueRenderPass(); - encoder.setViewport(0, 0, this.shadowSize, this.shadowSize, 0.0, 1.0); - encoder.setScissorRect(0, 0, this.shadowSize, this.shadowSize); + renderContext.encoder.setViewport(0, 0, this.shadowSize, this.shadowSize, 0.0, 1.0); + renderContext.encoder.setScissorRect(0, 0, this.shadowSize, this.shadowSize); shadowCamera.onUpdate(); shadowCamera.transform.updateWorldMatrix(true); - let viewRenderList = EntityCollect.instance.getRenderShaderCollect(view); - for (const renderList of viewRenderList) { - let nodeMap = renderList[1]; - for (const iterator of nodeMap) { - let node = iterator[1]; - if (node.preInit) { - node.nodeUpdate(view, this._rendererType, this.rendererPassState, null); - break; - } + for (const iterator of collectInfo.opaqueList) { + let node = iterator; + if (node.preInit(this._rendererType)) { + node.nodeUpdate(view, this._rendererType, renderContext.rendererPassState, null); + break; } } - this.drawShadowRenderNodes(view, shadowCamera, encoder, collectInfo.opaqueList, occlusionSystem); - this.drawShadowRenderNodes(view, shadowCamera, encoder, collectInfo.transparentList, occlusionSystem); + this.drawShadowRenderNodes(view, shadowCamera, renderContext, collectInfo.opaqueList, occlusionSystem); + this.drawShadowRenderNodes(view, shadowCamera, renderContext, collectInfo.transparentList, occlusionSystem); - GPUContext.endPass(encoder); - GPUContext.endCommandEncoder(command); + renderContext.endRenderPass(); } - protected drawShadowRenderNodes(view: View3D, shadowCamera: Camera3D, encoder: GPURenderPassEncoder, nodes: RenderNode[], occlusionSystem: OcclusionSystem) { - GPUContext.bindCamera(encoder, shadowCamera); - if (nodes) { + protected drawShadowRenderNodes(view: View3D, shadowCamera: Camera3D, renderContext: RenderContext, nodes: RenderNode[], occlusionSystem: OcclusionSystem) { + GlobalBindGroup.updateCameraGroup(shadowCamera); + GPUContext.bindCamera(renderContext.encoder, shadowCamera); + + let scene = view.scene; + let camera = view.camera; + + this.drawNodes(view, shadowCamera, renderContext, nodes, occlusionSystem, null); + + // if (nodes) { + // for (let i = Engine3D.setting.render.drawOpMin; i < Math.min(nodes.length, Engine3D.setting.render.drawOpMax); ++i) { + // let renderNode = nodes[i]; + // let matrixIndex = renderNode.transform.worldMatrix.index; + // if (!renderNode.transform.enable) + // continue; + // // if (!occlusionSystem.renderCommitTesting(shadowCamera, renderNode)) + // // continue; + // if (!renderNode.enable) + // continue; + + // if (!renderNode.castShadow) + // continue; + + // if (!renderNode.preInit(this._rendererType)) { + // renderNode.nodeUpdate(view, this._rendererType, this.rendererPassState); + // } + + // for (let material of renderNode.materials) { + // let passes = material.getPass(this._rendererType); + // if (!passes || passes.length == 0) + // continue; + + // GPUContext.bindGeometryBuffer(encoder, renderNode.geometry); + // let worldMatrix = renderNode.object3D.transform._worldMatrix; + // for (let pass of passes) { + // const renderShader = pass; + // if (renderShader.pipeline) { + // renderShader.setUniformFloat("cameraFar", shadowCamera.far); + // renderShader.setUniformVector3("lightWorldPos", shadowCamera.transform.worldPosition); + // renderShader.materialDataUniformBuffer.apply(); + + // GPUContext.bindPipeline(encoder, renderShader); + // let subGeometries = renderNode.geometry.subGeometries; + // for (const subGeometry of subGeometries) { + // let lodInfos = subGeometry.lodLevels; + // let lodInfo = lodInfos[renderNode.lodLevel]; + // GPUContext.drawIndexed(encoder, lodInfo.indexCount, 1, lodInfo.indexStart, 0, worldMatrix.index); + // } + // } + // } + // } + // } + // } + } + + public drawNodes(view: View3D, camera: Camera3D, renderContext: RenderContext, nodes: RenderNode[], occlusionSystem: OcclusionSystem, clusterLightingBuffer: ClusterLightingBuffer) { + + let viewRenderList = EntityCollect.instance.getRenderShaderCollect(view); + if (viewRenderList) { + for (const renderList of viewRenderList) { + let nodeMap = renderList[1]; + for (const iterator of nodeMap) { + let node = iterator[1]; + if (node.preInit(this._rendererType)) { + node.nodeUpdate(view, this._rendererType, renderContext.rendererPassState, clusterLightingBuffer); + break; + } + } + } + for (let i = Engine3D.setting.render.drawOpMin; i < Math.min(nodes.length, Engine3D.setting.render.drawOpMax); ++i) { let renderNode = nodes[i]; - let matrixIndex = renderNode.transform.worldMatrix.index; + // if (!occlusionSystem.renderCommitTesting(view.camera, renderNode)) + // continue; if (!renderNode.transform.enable) continue; - // if (!occlusionSystem.renderCommitTesting(shadowCamera, renderNode)) - // continue; if (!renderNode.enable) continue; - if (!renderNode.preInit) { - renderNode.nodeUpdate(view, this._rendererType, this.rendererPassState); + if (!renderNode.castShadow) + continue; + + if (!renderNode.preInit(this._rendererType)) { + renderNode.nodeUpdate(view, this._rendererType, renderContext.rendererPassState, clusterLightingBuffer); } for (let material of renderNode.materials) { let passes = material.getPass(this._rendererType); if (!passes || passes.length == 0) continue; - - GPUContext.bindGeometryBuffer(encoder, renderNode.geometry); - let worldMatrix = renderNode.object3D.transform._worldMatrix; for (let pass of passes) { const renderShader = pass; if (renderShader.pipeline) { - renderShader.setUniformFloat("cameraFar", shadowCamera.far); - renderShader.setUniformVector3("lightWorldPos", shadowCamera.transform.worldPosition); + renderShader.setUniformFloat("cameraFar", camera.far); + renderShader.setUniformVector3("lightWorldPos", camera.transform.worldPosition); renderShader.materialDataUniformBuffer.apply(); - - GPUContext.bindPipeline(encoder, renderShader); - let subGeometries = renderNode.geometry.subGeometries; - for (const subGeometry of subGeometries) { - let lodInfos = subGeometry.lodLevels; - let lodInfo = lodInfos[renderNode.lodLevel]; - GPUContext.drawIndexed(encoder, lodInfo.indexCount, 1, lodInfo.indexStart, 0, worldMatrix.index); - } } } } + + renderNode.renderPass(view, this.passType, renderContext); } } } diff --git a/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts b/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts index 5e6641da..24ee4c01 100644 --- a/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts +++ b/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts @@ -14,13 +14,14 @@ import { ShadowLightsCollect } from "../../collect/ShadowLightsCollect"; import { RTFrame } from "../../frame/RTFrame"; import { OcclusionSystem } from "../../occlusion/OcclusionSystem"; import { RendererPassState } from "../state/RendererPassState"; -import { PassType } from "../state/RendererType"; +import { PassType } from "../state/PassType"; 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 { VirtualTexture } from "../../../../textures/VirtualTexture"; +import { GlobalBindGroup } from "../../../graphics/webGpu/core/bindGroups/GlobalBindGroup"; /** * @internal @@ -36,6 +37,7 @@ export class ShadowMapPassRenderer extends RendererBase { super(); this.setShadowMap(Engine3D.setting.shadow.shadowSize, CSM.Cascades); this.passType = PassType.SHADOW; + } setShadowMap(size: number, cascades: number) { @@ -86,7 +88,8 @@ export class ShadowMapPassRenderer extends RendererBase { let nodeMap = renderList[1]; for (const iterator of nodeMap) { let node = iterator[1]; - if (node.preInit) { + + if (node.preInit(this._rendererType)) { node.nodeUpdate(view, this._rendererType, this.rendererPassState, null); break; } @@ -168,6 +171,7 @@ export class ShadowMapPassRenderer extends RendererBase { occlusionSystem.update(shadowCamera, view.scene); occlusionSystem.collect(collectInfo, shadowCamera); } + GlobalBindGroup.updateCameraGroup(shadowCamera); GPUContext.bindCamera(encoder, shadowCamera); let op_bundleList = this.renderShadowBundleOp(view, shadowCamera, state); let tr_bundleList = this.renderShadowBundleTr(view, shadowCamera, state); @@ -227,6 +231,7 @@ export class ShadowMapPassRenderer extends RendererBase { protected recordShadowRenderBundleNode(view: View3D, shadowCamera: Camera3D, encoder, nodes: RenderNode[], clusterLightingBuffer?: ClusterLightingBuffer) { + GlobalBindGroup.updateCameraGroup(shadowCamera); GPUContext.bindCamera(encoder, shadowCamera); if (nodes) { GPUContext.bindGeometryBuffer(encoder, nodes[0].geometry); @@ -240,6 +245,7 @@ export class ShadowMapPassRenderer extends RendererBase { } protected drawShadowRenderNodes(view: View3D, shadowCamera: Camera3D, encoder: GPURenderPassEncoder, nodes: RenderNode[], clusterLightingBuffer?: ClusterLightingBuffer) { + GlobalBindGroup.updateCameraGroup(shadowCamera); GPUContext.bindCamera(encoder, shadowCamera); if (nodes) { for (let i = Engine3D.setting.render.drawOpMin; i < Math.min(nodes.length, Engine3D.setting.render.drawOpMax); ++i) { @@ -253,6 +259,9 @@ export class ShadowMapPassRenderer extends RendererBase { if (!renderNode.castShadow) { continue; } + if (!renderNode.preInit(this._rendererType)) { + renderNode.nodeUpdate(view, this._rendererType, this.rendererPassState, clusterLightingBuffer); + } renderNode.renderPass2(view, this._rendererType, this.rendererPassState, clusterLightingBuffer, encoder); } } diff --git a/src/gfx/renderJob/passRenderer/state/RendererType.ts b/src/gfx/renderJob/passRenderer/state/PassType.ts similarity index 83% rename from src/gfx/renderJob/passRenderer/state/RendererType.ts rename to src/gfx/renderJob/passRenderer/state/PassType.ts index d85c9d92..18a1200c 100644 --- a/src/gfx/renderJob/passRenderer/state/RendererType.ts +++ b/src/gfx/renderJob/passRenderer/state/PassType.ts @@ -3,7 +3,7 @@ */ export enum PassType { COLOR = 1 << 0, - NORMAL = 1 << 1, + REFLECTION = 1 << 1, POSITION = 1 << 2, GRAPHIC = 1 << 3, @@ -13,5 +13,4 @@ export enum PassType { POINT_SHADOW = 1 << 7, POST = 1 << 8, DEPTH = 1 << 9, - REFLECTION = 1 << 10 } diff --git a/src/gfx/renderJob/passRenderer/state/RendererMask.ts b/src/gfx/renderJob/passRenderer/state/RendererMask.ts index 9c02ab28..702e6b64 100644 --- a/src/gfx/renderJob/passRenderer/state/RendererMask.ts +++ b/src/gfx/renderJob/passRenderer/state/RendererMask.ts @@ -11,6 +11,8 @@ export enum RendererMask { MorphTarget = 1 << 5, Terrain = 1 << 6, UI = 1 << 7, + Reflection = 1 << 8, + ReflectionDebug = 1 << 9, } /** diff --git a/src/gfx/renderJob/passRenderer/state/RendererPassState.ts b/src/gfx/renderJob/passRenderer/state/RendererPassState.ts index 7b9a97e1..437b62c2 100644 --- a/src/gfx/renderJob/passRenderer/state/RendererPassState.ts +++ b/src/gfx/renderJob/passRenderer/state/RendererPassState.ts @@ -31,7 +31,6 @@ export class RendererPassState { public renderBundleEncoderDescriptor: GPURenderBundleEncoderDescriptor; public depthLoadOp: GPULoadOp; - getLastRenderTexture() { if (this.renderTargets) { return this.renderTargets.length > 0 ? this.renderTargets[0] : Engine3D.res.redTexture; diff --git a/src/gfx/renderJob/post/BloomPost.ts b/src/gfx/renderJob/post/BloomPost.ts index e015c9cf..e88d2a09 100644 --- a/src/gfx/renderJob/post/BloomPost.ts +++ b/src/gfx/renderJob/post/BloomPost.ts @@ -120,6 +120,14 @@ export class BloomPost extends PostBase { Engine3D.setting.render.postProcessing.bloom.bloomIntensity = value; } + public get hdr(): number { + return Engine3D.setting.render.postProcessing.bloom.hdr; + } + + public set hdr(value: number) { + Engine3D.setting.render.postProcessing.bloom.hdr = value; + } + private createThreshouldCompute() { this.thresholdCompute = new ComputeShader(threshold); @@ -182,8 +190,6 @@ export class BloomPost extends PostBase { compute.workerSizeZ = 1; this.upSampleComputes.push(compute); - - // Graphics.Blit(RT_BloomDown[i - 1], RT_BloomDown[i], new Material(Shader.Find("Shaders/downSample"))); } } @@ -205,25 +211,22 @@ export class BloomPost extends PostBase { 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]; + let [screenWidth, screenHeight] = webGPUContext.presentationSize; + let usage = GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING; - this.RT_threshold = new VirtualTexture(screenWidth, screenHeight, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); + this.RT_threshold = new VirtualTexture(screenWidth, screenHeight, GPUTextureFormat.rgba16float, false, usage); const N = setting.downSampleStep; { - let downSize = 2; this.RT_BloomDown = []; - + let w = Math.ceil(screenWidth / 4); + let h = Math.ceil(screenHeight / 4); 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_BloomDown[i] = new VirtualTexture(w, h, GPUTextureFormat.rgba16float, false, usage); + w = Math.ceil(w / 2); + h = Math.ceil(h / 2); } } @@ -232,7 +235,7 @@ export class BloomPost extends PostBase { 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); + this.RT_BloomUp[i] = new VirtualTexture(w, h, GPUTextureFormat.rgba16float, false, usage); } } @@ -266,6 +269,7 @@ export class BloomPost extends PostBase { this.bloomSetting.setFloat('upSampleBlurSigma', cfg.upSampleBlurSigma); this.bloomSetting.setFloat('luminanceThreshole', cfg.luminanceThreshole); this.bloomSetting.setFloat('bloomIntensity', cfg.bloomIntensity); + this.bloomSetting.setFloat('hdr', cfg.hdr); this.bloomSetting.apply(); @@ -276,18 +280,16 @@ export class BloomPost extends PostBase { public onResize() { let cfg = Engine3D.setting.render.postProcessing.bloom; - let presentationSize = webGPUContext.presentationSize; - let screenWidth = presentationSize[0]; - let screenHeight = presentationSize[1]; + let [screenWidth, screenHeight] = webGPUContext.presentationSize; this.RT_threshold.resize(screenWidth, screenHeight); + const N = cfg.downSampleStep; - let downSize = 2; - // + let w = Math.ceil(screenWidth / 4); + let h = Math.ceil(screenHeight / 4); for (let i = 0; i < N; i++) { - let w = Math.ceil(screenWidth / downSize); - let h = Math.ceil(screenHeight / downSize); this.RT_BloomDown[i].resize(w, h); - downSize *= 2; + w = Math.ceil(w / 2); + h = Math.ceil(h / 2); } for (let i = 0; i < N - 1; i++) { diff --git a/src/gfx/renderJob/post/DepthOfFieldPost.ts b/src/gfx/renderJob/post/DepthOfFieldPost.ts index 67dc413b..695cd9f9 100644 --- a/src/gfx/renderJob/post/DepthOfFieldPost.ts +++ b/src/gfx/renderJob/post/DepthOfFieldPost.ts @@ -123,10 +123,8 @@ export class DepthOfFieldPost extends PostBase { this.blurSettings.push(blurSetting); blurCompute.setUniformBuffer('blurSetting', blurSetting); - let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); - - blurCompute.setSamplerTexture(RTResourceConfig.positionBufferTex_NAME, rtFrame.getPositionMap()); - blurCompute.setSamplerTexture(RTResourceConfig.normalBufferTex_NAME, rtFrame.getNormalMap()); + let rtFrame = GBufferFrame.getGBufferFrame(GBufferFrame.colorPass_GBuffer); + blurCompute.setSamplerTexture(`gBufferTexture`, rtFrame.getCompressGBufferTexture()); let input = i % 2 == 0 ? this.blurTexture1 : this.blurTexture2; let output = i % 2 == 1 ? this.blurTexture1 : this.blurTexture2; @@ -166,6 +164,7 @@ export class DepthOfFieldPost extends PostBase { blur2Dec ]); } + /** * @internal */ diff --git a/src/gfx/renderJob/post/FXAAPost.ts b/src/gfx/renderJob/post/FXAAPost.ts index 031cf277..ecd79a1c 100644 --- a/src/gfx/renderJob/post/FXAAPost.ts +++ b/src/gfx/renderJob/post/FXAAPost.ts @@ -1,12 +1,13 @@ import { ShaderLib } from '../../../assets/shader/ShaderLib'; 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 { PostBase } from './PostBase'; import { View3D } from '../../../core/View3D'; -import { FXAAShader } from '../../..'; +import { FXAAShader } from '../../../assets/shader/post/FXAAShader'; +import { ViewQuad } from '../../../core/ViewQuad'; +import { RenderTexture } from '../../../textures/RenderTexture'; /** * FXAA(fast approximate antialiasing) * A deformation anti-aliasing method that pays more attention to performance. @@ -15,24 +16,32 @@ import { FXAAShader } from '../../..'; * @group Post Effects */ export class FXAAPost extends PostBase { + postQuad: ViewQuad; + renderTexture: RenderTexture; constructor() { super(); - let presentationSize = webGPUContext.presentationSize; - + let [w, h] = webGPUContext.presentationSize; ShaderLib.register("FXAA_Shader", FXAAShader); - let rt = this.createRTTexture(`FXAAPost`, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float); - 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); + this.renderTexture = this.createRTTexture(`FXAAPost`, w, h, GPUTextureFormat.rgba16float); + this.postQuad = this.createViewQuad(`fxaa`, 'FXAA_Shader', this.renderTexture); + this.postQuad.quadShader.setUniform("u_texel", new Vector2(1.0 / w, 1.0 / h)); + this.postQuad.quadShader.setUniform("u_strength", 4); + } + + public onResize() { + let [w, h] = webGPUContext.presentationSize; + this.renderTexture.resize(w, h); } + /** * @internal */ onAttach(view: View3D,) { Engine3D.setting.render.postProcessing.fxaa.enable = true; } + /** * @internal */ diff --git a/src/gfx/renderJob/post/GBufferPost.ts b/src/gfx/renderJob/post/GBufferPost.ts new file mode 100644 index 00000000..bb54f2a0 --- /dev/null +++ b/src/gfx/renderJob/post/GBufferPost.ts @@ -0,0 +1,180 @@ +import { VirtualTexture } from '../../../textures/VirtualTexture'; +import { GlobalBindGroup } from '../../graphics/webGpu/core/bindGroups/GlobalBindGroup'; +import { StorageGPUBuffer } from '../../graphics/webGpu/core/buffer/StorageGPUBuffer'; +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 { Time } from '../../../util/Time'; +import { clamp } from '../../../math/MathUtil'; +import { View3D } from '../../../core/View3D'; +import { RTDescriptor } from '../../graphics/webGpu/descriptor/RTDescriptor'; +import { GBufferFrame } from '../frame/GBufferFrame'; +import { RTFrame } from '../frame/RTFrame'; +import { GTAO_cs } from '../../../assets/shader/compute/GTAO_cs'; +import { CResizeEvent } from '../../../event/CResizeEvent'; +import { TextureScaleCompute } from '../../generate/convert/TextureScaleCompute'; +import { RenderTexture } from '../../../textures/RenderTexture'; +import { SSGI2_cs } from '../../../assets/shader/compute/SSGI2_cs'; +import { Denoising_cs } from '../../../assets/shader/compute/utils/Denoising_cs'; +import { Combine_cs, TestComputeLoadBuffer, Vector3, mergeFunctions } from '../../..'; + +/** + * Ground base Ambient Occlusion + * Let the intersection of the object and the object imitate the effect of the light being cross-occluded + * ``` + * gtao setting + * let cfg = {@link Engine3D.setting.render.postProcessing.gtao}; + *``` + * @group Post Effects + */ +export class GBufferPost extends PostBase { + /** + * @internal + */ + outTexture: VirtualTexture; + + /** + * @internal + */ + rendererPassState: RendererPassState; + rtFrame: RTFrame; + view: View3D; + gBufferTexture: RenderTexture; + testCompute: ComputeShader; + private _state: number = 0; + private _state1: number = 256; + private _state2: number = 256; + uniformBuffer: UniformGPUBuffer; + currentRenderTexture: RenderTexture; + constructor() { + super(); + } + + /** + * @internal + */ + onAttach(view: View3D,) { + this.view = view; + } + + /** + * @internal + */Render + onDetach(view: View3D,) { + // Engine3D.setting.render.useCompressGBuffer = false; + } + + /** + * check state + */ + public set state(v: number) { + this._state = v; + this.uniformBuffer.setInt32("state", v); + this.uniformBuffer.apply(); + } + + public get state(): number { + return this._state; + } + + public set size1(v: number) { + this._state1 = v; + this.uniformBuffer.setInt32("state1", v); + this.uniformBuffer.apply(); + } + + public get size1(): number { + return this._state1; + } + + public set size2(v: number) { + this._state2 = v; + this.uniformBuffer.setInt32("state2", v); + this.uniformBuffer.apply(); + } + + public get size2(): number { + return this._state2; + } + + private createResource() { + let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); + this.currentRenderTexture = rtFrame.getColorTexture(); + this.gBufferTexture = rtFrame.getCompressGBufferTexture(); + + let [w, h] = webGPUContext.presentationSize; + + this.outTexture = new VirtualTexture(w, h, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); + this.outTexture.name = 'outTexture'; + + let testDec = new RTDescriptor(); + testDec.loadOp = `load`; + this.rtFrame = new RTFrame([ + this.outTexture + ], [ + testDec + ]); + } + + private createCompute() { + this.uniformBuffer = new UniformGPUBuffer(4); + this.uniformBuffer.setInt32("state", this._state); + + let globalUniform = GlobalBindGroup.getCameraGroup(this.view.camera); + let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); + let gBufferTexture = rtFrame.getCompressGBufferTexture(); + + let reflectionSetting = Engine3D.setting.reflectionSetting; + let reflectionsGBufferFrame = GBufferFrame.getGBufferFrame(GBufferFrame.reflections_GBuffer, reflectionSetting.width, reflectionSetting.height); + let reflectionsGBufferTexture = reflectionsGBufferFrame.getCompressGBufferTexture(); + + let envMap = Engine3D.renderJobs.get(this.view).reflectionRenderer.outTexture; + + this.testCompute = new ComputeShader(TestComputeLoadBuffer); + this.testCompute.setUniformBuffer('globalUniform', globalUniform.uniformGPUBuffer); + this.testCompute.setUniformBuffer('uniformData', this.uniformBuffer); + this.testCompute.setSamplerTexture("gBufferTexture", gBufferTexture); + this.testCompute.setSamplerTexture("currentRenderTexture", this.currentRenderTexture); + this.testCompute.setSamplerTexture("reflectionsGBufferTexture", reflectionsGBufferTexture); + this.testCompute.setSamplerTexture("envMap", envMap); + this.testCompute.setStorageTexture("outputTexture", this.outTexture); + + this.testCompute.workerSizeX = Math.ceil(this.outTexture.width / 16); + this.testCompute.workerSizeY = Math.ceil(this.outTexture.height / 16); + this.testCompute.workerSizeZ = 1; + } + + public render(view: View3D, command: GPUCommandEncoder): void { + + } + + public compute(view: View3D): void { + if (!this.testCompute) { + this.createResource(); + this.createCompute(); + this.onResize(); + + this.rendererPassState = WebGPUDescriptorCreator.createRendererPassState(this.rtFrame, null); + this.rendererPassState.label = "test"; + } + + let command = GPUContext.beginCommandEncoder(); + GPUContext.computeCommand(command, [this.testCompute]); + GPUContext.endCommandEncoder(command); + GPUContext.lastRenderPassState = this.rendererPassState; + } + + public onResize() { + let [w, h] = webGPUContext.presentationSize; + this.outTexture.resize(w, h); + + this.testCompute.workerSizeX = Math.ceil(this.outTexture.width / 16); + this.testCompute.workerSizeY = Math.ceil(this.outTexture.height / 16); + } +} \ No newline at end of file diff --git a/src/gfx/renderJob/post/GTAOPost.ts b/src/gfx/renderJob/post/GTAOPost.ts index cf4c6409..9b6675f9 100644 --- a/src/gfx/renderJob/post/GTAOPost.ts +++ b/src/gfx/renderJob/post/GTAOPost.ts @@ -17,7 +17,6 @@ import { RTDescriptor } from '../../graphics/webGpu/descriptor/RTDescriptor'; import { GBufferFrame } from '../frame/GBufferFrame'; import { RTFrame } from '../frame/RTFrame'; import { GTAO_cs } from '../../../assets/shader/compute/GTAO_cs'; -import { CResizeEvent } from '../../../event/CResizeEvent'; /** * Ground base Ambient Occlusion @@ -153,8 +152,6 @@ export class GTAOPost extends PostBase { } private createCompute() { - let setting = Engine3D.setting.render.postProcessing.gtao; - this.gtaoCompute = new ComputeShader(GTAO_cs); let gtaoSetting: UniformGPUBuffer = new UniformGPUBuffer(4 * 2); //vector4 * 2 @@ -169,11 +166,8 @@ export class GTAOPost extends PostBase { this.aoBuffer = new StorageGPUBuffer(this.gtaoTexture.width * this.gtaoTexture.height); this.gtaoCompute.setStorageBuffer('aoBuffer', this.aoBuffer); - let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); - //setting.usePosFloat32 ? RTResourceMap.getTexture(RTResourceConfig.positionBufferTex_NAME): - let posTexture = rtFrame.getPositionMap(); - this.gtaoCompute.setSamplerTexture(`posTex`, posTexture); - this.gtaoCompute.setSamplerTexture(`normalTex`, rtFrame.renderTargets[2]); + let rtFrame = GBufferFrame.getGBufferFrame(GBufferFrame.colorPass_GBuffer); + this.gtaoCompute.setSamplerTexture(`gBufferTexture`, rtFrame.getCompressGBufferTexture()); this.autoSetColorTexture('inTex', this.gtaoCompute); this.gtaoCompute.setStorageTexture(`outTex`, this.gtaoTexture); @@ -181,31 +175,19 @@ export class GTAOPost extends PostBase { } private createResource() { - let presentationSize = webGPUContext.presentationSize; - let w = presentationSize[0]; - let h = presentationSize[1]; - - // RTResourceMap.createRTTextures( - // [RTResourceConfig.colorBufferTex_NAME, RTResourceConfig.positionBufferTex_NAME, RTResourceConfig.normalBufferTex_NAME, RTResourceConfig.materialBufferTex_NAME], - // [GPUTextureFormat.rgba16float, GPUTextureFormat.rgba16float, GPUTextureFormat.rgba8unorm, GPUTextureFormat.rgba8unorm], - // ); - + let [w, h] = webGPUContext.presentationSize; this.gtaoTexture = new VirtualTexture(w, h, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); this.gtaoTexture.name = 'gtaoTex'; let gtaoDec = new RTDescriptor(); - // gtaoDec.clearValue = [1, 1, 1, 1]; gtaoDec.loadOp = `load`; - this.rtFrame = new RTFrame([ - this.gtaoTexture - ], [ - gtaoDec - ]); + this.rtFrame = new RTFrame([this.gtaoTexture], [gtaoDec]); } private randomCount: number = 0; private randomDirection(): Float32Array { - this.randomCount++; - if (this.randomCount > 1) this.randomCount = 0; + // this.randomCount++; + // if (this.randomCount > 1) this.randomCount = 0; + this.randomCount = 0; let offsetAngle = (Math.PI * 2 * this.randomCount) / 16; let angleSegment = (Math.PI * 2) / 8; for (let i = 0; i < 8; i++) { @@ -255,11 +237,8 @@ export class GTAOPost extends PostBase { } public onResize() { - let presentationSize = webGPUContext.presentationSize; - let w = presentationSize[0]; - let h = presentationSize[1]; + let [w, h] = webGPUContext.presentationSize; this.gtaoTexture.resize(w, h); - this.gtaoCompute.workerSizeX = Math.ceil(this.gtaoTexture.width / 8); this.gtaoCompute.workerSizeY = Math.ceil(this.gtaoTexture.height / 8); this.gtaoCompute.workerSizeZ = 1; diff --git a/src/gfx/renderJob/post/GlobalFog.ts b/src/gfx/renderJob/post/GlobalFog.ts index 16a9fe3a..9dc6056f 100644 --- a/src/gfx/renderJob/post/GlobalFog.ts +++ b/src/gfx/renderJob/post/GlobalFog.ts @@ -1,10 +1,8 @@ import { GlobalFog_shader } from '../../../assets/shader/post/GlobalFog_shader'; import { ShaderLib } from '../../../assets/shader/ShaderLib'; -import { ViewQuad } from '../../../core/ViewQuad'; import { Engine3D } from '../../../Engine3D'; import { Color } from '../../../math/Color'; import { VirtualTexture } from '../../../textures/VirtualTexture'; -import { UniformNode } from '../../graphics/webGpu/core/uniforms/UniformNode'; import { GPUTextureFormat } from '../../graphics/webGpu/WebGPUConst'; import { webGPUContext } from '../../graphics/webGpu/Context3D'; import { PostBase } from './PostBase'; @@ -14,6 +12,14 @@ import { SkyRenderer } from '../../../components/renderer/SkyRenderer'; import { EntityCollect } from '../collect/EntityCollect'; import { GlobalFogSetting } from '../../../setting/post/GlobalFogSetting'; import { Texture } from '../../graphics/webGpu/core/texture/Texture'; +import { RTDescriptor } from '../../graphics/webGpu/descriptor/RTDescriptor'; +import { RTFrame } from '../frame/RTFrame'; +import { ComputeShader } from '../../graphics/webGpu/shader/ComputeShader'; +import { UniformGPUBuffer } from '../../graphics/webGpu/core/buffer/UniformGPUBuffer'; +import { GPUContext } from '../GPUContext'; +import { RendererPassState } from '../passRenderer/state/RendererPassState'; +import { WebGPUDescriptorCreator } from '../../graphics/webGpu/descriptor/WebGPUDescriptorCreator'; +import { GlobalBindGroup } from '../../graphics/webGpu/core/bindGroups/GlobalBindGroup'; /** * screen space fog * @group Post Effects @@ -22,49 +28,75 @@ export class GlobalFog extends PostBase { /** * @internal */ - viewQuad: ViewQuad; - /** - * @internal - */ - rtTexture: VirtualTexture; - _globalFog: GlobalFogSetting; + private fogSetting: GlobalFogSetting; + public fogOpTexture: VirtualTexture; + private fogCompute: ComputeShader; + private fogUniform: UniformGPUBuffer; + private rendererPassState: RendererPassState; constructor() { super(); - let globalFog = this._globalFog = Engine3D.setting.render.postProcessing.globalFog; + this.fogSetting = Engine3D.setting.render.postProcessing.globalFog; + } - let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); + private createCompute(view: View3D) { + ShaderLib.register("GlobalFog_shader", GlobalFog_shader); + this.fogCompute = new ComputeShader(GlobalFog_shader); - let presentationSize = webGPUContext.presentationSize; + this.fogUniform = new UniformGPUBuffer(4 * 5); //vector4 * 5 + this.fogCompute.setUniformBuffer('fogUniform', this.fogUniform); - ShaderLib.register("GlobalFog_shader", GlobalFog_shader); - let shaderUniforms = { - isSkyHDR: new UniformNode(0), - }; - - this.rtTexture = this.createRTTexture(`GlobalFog`, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float); - 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(); - this.setInputTexture(ptex, ntex); + let rtFrame = GBufferFrame.getGBufferFrame(GBufferFrame.colorPass_GBuffer); + this.fogCompute.setSamplerTexture('gBufferTexture', rtFrame.getCompressGBufferTexture()); + this.fogCompute.setSamplerTexture('inTex', rtFrame.getColorTexture()); + this._lastSkyTexture = this.getSkyTexture(); + this.fogCompute.setSamplerTexture(`prefilterMap`, this._lastSkyTexture); + this.fogCompute.setStorageTexture(`outTex`, this.fogOpTexture); + + this.rendererPassState = WebGPUDescriptorCreator.createRendererPassState(this.rtFrame, null); + this.rendererPassState.label = "FOG"; + + let lightUniformEntries = GlobalBindGroup.getLightEntries(view.scene); + this.fogCompute.setStorageBuffer(`lightBuffer`, lightUniformEntries.storageGPUBuffer); + } + + private uploadSetting() { + let fogUniform = this.fogUniform; + let globalFog = this.fogSetting; + + fogUniform.setColor("fogColor", globalFog.fogColor); + + fogUniform.setFloat("fogType", globalFog.fogType); + fogUniform.setFloat("fogHeightScale", globalFog.fogHeightScale); + fogUniform.setFloat("start", globalFog.start); + fogUniform.setFloat("end", globalFog.end); + + fogUniform.setFloat("density", globalFog.density); + fogUniform.setFloat("ins", globalFog.ins); + fogUniform.setFloat("falloff", globalFog.falloff); + fogUniform.setFloat("rayLength", globalFog.rayLength); + + fogUniform.setFloat("scatteringExponent", globalFog.scatteringExponent); + fogUniform.setFloat("dirHeightLine", globalFog.dirHeightLine); + fogUniform.setFloat("skyFactor", globalFog.skyFactor); + fogUniform.setFloat("skyRoughness", globalFog.skyRoughness); + + fogUniform.setFloat("overrideSkyFactor", globalFog.overrideSkyFactor); + fogUniform.setFloat("isSkyHDR", 0); + + fogUniform.apply(); + this.fogCompute.setUniformBuffer('fogUniform', this.fogUniform); + } + + rtFrame: RTFrame; + + private createResource() { + let [w, h] = webGPUContext.presentationSize; + this.fogOpTexture = new VirtualTexture(w, h, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); + this.fogOpTexture.name = 'fogTex'; + let fogDesc = new RTDescriptor(); + fogDesc.loadOp = `load`; + this.rtFrame = new RTFrame([this.fogOpTexture], [fogDesc]); } /** @@ -81,131 +113,107 @@ export class GlobalFog extends PostBase { } public set fogType(v: number) { - this._globalFog.fogType = v; - this.viewQuad.quadShader.setUniform('fogType', v); + this.fogSetting.fogType = v; } public get fogType() { - return this._globalFog.fogType; + return this.fogSetting.fogType; } public set fogHeightScale(v: number) { - this._globalFog.fogHeightScale = v; - this.viewQuad.quadShader.setUniform('fogHeightScale', v); + this.fogSetting.fogHeightScale = v; } public get fogHeightScale() { - return this.viewQuad.quadShader.getUniform('fogHeightScale'); + return this.fogSetting.fogHeightScale; } public set start(v: number) { - this._globalFog.start = v; - this.viewQuad.quadShader.setUniform('start', v); + this.fogSetting.start = v; } public get start() { - return this.viewQuad.quadShader.getUniform('start'); + return this.fogSetting.start; } public set end(v: number) { - this._globalFog.end = v; - this.viewQuad.quadShader.setUniform('end', v); + this.fogSetting.end = v; } public get end() { - return this.viewQuad.quadShader.getUniform('end'); + return this.fogSetting.end; } public set ins(v: number) { - this._globalFog.ins = v; - this.viewQuad.quadShader.setUniform('ins', v); + this.fogSetting.ins = v; } public get ins() { - return this.viewQuad.quadShader.getUniform('ins'); + return this.fogSetting.ins; } public set density(v: number) { - this._globalFog.density = v; - this.viewQuad.quadShader.setUniform('density', v); + this.fogSetting.density = v; } public get density() { - return this.viewQuad.quadShader.getUniform('density'); + return this.fogSetting.density; } public set skyRoughness(v: number) { - this._globalFog.skyRoughness = v; - this.viewQuad.quadShader.setUniform('skyRoughness', v); + this.fogSetting.skyRoughness = v; } public get skyRoughness() { - return this._globalFog.skyRoughness; + return this.fogSetting.skyRoughness; } public set skyFactor(v: number) { - this._globalFog.skyFactor = v; - this.viewQuad.quadShader.setUniform('skyFactor', v); + this.fogSetting.skyFactor = v; } public get skyFactor() { - return this._globalFog.skyFactor; + return this.fogSetting.skyFactor; } public set overrideSkyFactor(v: number) { - this._globalFog.overrideSkyFactor = v; - this.viewQuad.quadShader.setUniform('overrideSkyFactor', v); + this.fogSetting.overrideSkyFactor = v; } public get overrideSkyFactor() { - return this._globalFog.overrideSkyFactor; + return this.fogSetting.overrideSkyFactor; } /** * @internal */ public get fogColor(): Color { - return this._globalFog.fogColor; + return this.fogSetting.fogColor; } /** * @internal */ public set fogColor(value: Color) { - this._globalFog.fogColor.copyFrom(value); - this.viewQuad.quadShader.setUniformColor('fogColor', value); + this.fogSetting.fogColor.copyFrom(value); } public set falloff(v: number) { - this._globalFog.falloff = v; - this.viewQuad.quadShader.setUniform('falloff', v); + this.fogSetting.falloff = v; } public get falloff() { - return this.viewQuad.quadShader.getUniform('falloff'); + return this.fogSetting.falloff; } public set rayLength(v: number) { - this._globalFog.rayLength = v; - this.viewQuad.quadShader.setUniform('rayLength', v); + this.fogSetting.rayLength = v; } public get rayLength() { - return this._globalFog.rayLength; + return this.fogSetting.rayLength; } public set scatteringExponent(v: number) { - this._globalFog.scatteringExponent = v; - this.viewQuad.quadShader.setUniform('scatteringExponent', v); + this.fogSetting.scatteringExponent = v; } public get scatteringExponent() { - return this._globalFog.scatteringExponent; + return this.fogSetting.scatteringExponent; } public set dirHeightLine(v: number) { - this._globalFog.dirHeightLine = v; - this.viewQuad.quadShader.setUniform('dirHeightLine', v); + this.fogSetting.dirHeightLine = v; } public get dirHeightLine() { - return this._globalFog.dirHeightLine; + return this.fogSetting.dirHeightLine; } - /** - * @internal - */ - public setInputTexture(positionMap: VirtualTexture, normalMap: VirtualTexture) { - const pass = this.viewQuad.quadShader; - pass.setTexture('positionMap', positionMap); - pass.setTexture('normalMap', normalMap); - this._lastSkyTexture = this.getSkyTexture(); - pass.setTexture(`prefilterMap`, this._lastSkyTexture); - } private _lastSkyTexture: Texture; private getSkyTexture(): Texture { @@ -220,15 +228,35 @@ export class GlobalFog extends PostBase { * @internal */ render(view: View3D, command: GPUCommandEncoder) { - const pass = this.viewQuad.quadShader; + if (!this.fogCompute) { + this.createResource(); + this.createCompute(view); + this.onResize(); + + + let globalUniform = GlobalBindGroup.getCameraGroup(view.camera); + this.fogCompute.setUniformBuffer('globalUniform', globalUniform.uniformGPUBuffer); + } + let skyTexture = this.getSkyTexture(); if (skyTexture != this._lastSkyTexture) { this._lastSkyTexture = skyTexture; - pass.setTexture(`prefilterMap`, this._lastSkyTexture); + this.fogCompute.setSamplerTexture(`prefilterMap`, this._lastSkyTexture); } - pass.setTexture('colorMap', this.getOutTexture()); - pass.setUniformFloat('isSkyHDR', skyTexture.isHDRTexture ? 1 : 0); - this.viewQuad.renderTarget(view, this.viewQuad, command); + this.fogCompute.setUniformFloat('isSkyHDR', skyTexture.isHDRTexture ? 1 : 0); + + this.uploadSetting(); + GPUContext.computeCommand(command, [this.fogCompute]); + GPUContext.lastRenderPassState = this.rendererPassState; + + } + + public onResize() { + let [w, h] = webGPUContext.presentationSize; + this.fogOpTexture.resize(w, h); + this.fogCompute.workerSizeX = Math.ceil(this.fogOpTexture.width / 8); + this.fogCompute.workerSizeY = Math.ceil(this.fogOpTexture.height / 8); + this.fogCompute.workerSizeZ = 1; } } diff --git a/src/gfx/renderJob/post/GodRayPost.ts b/src/gfx/renderJob/post/GodRayPost.ts index 38a5e314..a39cb8f6 100644 --- a/src/gfx/renderJob/post/GodRayPost.ts +++ b/src/gfx/renderJob/post/GodRayPost.ts @@ -98,8 +98,6 @@ export class GodRayPost extends PostBase { private createCompute(view: View3D) { - let setting = Engine3D.setting.render.postProcessing.godRay; - this.godRayCompute = new ComputeShader(GodRay_cs); let godRaySetting: UniformGPUBuffer = new UniformGPUBuffer(4 * 3); //vector4 * 2 @@ -108,10 +106,8 @@ export class GodRayPost extends PostBase { this.historyGodRayData = new StorageGPUBuffer(4 * this.godRayTexture.width * this.godRayTexture.height); this.godRayCompute.setStorageBuffer('historyGodRayData', this.historyGodRayData); - let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); - - this.godRayCompute.setSamplerTexture(`posTex`, rtFrame.renderTargets[1]); - this.godRayCompute.setSamplerTexture(`normalTex`, rtFrame.renderTargets[2]); + let rtFrame = GBufferFrame.getGBufferFrame(GBufferFrame.colorPass_GBuffer); + this.godRayCompute.setSamplerTexture(`gBufferTexture`, rtFrame.getCompressGBufferTexture()); this.autoSetColorTexture('inTex', this.godRayCompute); this.godRayCompute.setStorageTexture(`outTex`, this.godRayTexture); @@ -125,9 +121,7 @@ export class GodRayPost extends PostBase { private createResource() { let presentationSize = webGPUContext.presentationSize; - let w = presentationSize[0]; - let h = presentationSize[1]; - + let [w, h] = presentationSize; this.godRayTexture = new VirtualTexture(w, h, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); this.godRayTexture.name = 'godRayTexture'; let gtaoDec = new RTDescriptor(); @@ -137,9 +131,7 @@ export class GodRayPost extends PostBase { public onResize() { let presentationSize = webGPUContext.presentationSize; - let w = presentationSize[0]; - let h = presentationSize[1]; - + let [w, h] = presentationSize; this.godRayTexture.resize(w, h); this.historyGodRayData.resizeBuffer(4 * this.godRayTexture.width * this.godRayTexture.height); this.godRayCompute.setStorageBuffer('historyGodRayData', this.historyGodRayData); @@ -174,8 +166,7 @@ export class GodRayPost extends PostBase { this.godRaySetting.setFloat('rayMarchCount', setting.rayMarchCount); let presentationSize = webGPUContext.presentationSize; - let w = presentationSize[0]; - let h = presentationSize[1]; + let [w, h] = presentationSize; this.godRaySetting.setFloat('viewPortWidth', w); this.godRaySetting.setFloat('viewPortHeight', h); this.godRaySetting.setFloat('blendColor', setting.blendColor ? 1 : 0); diff --git a/src/gfx/renderJob/post/OutlinePost.ts b/src/gfx/renderJob/post/OutlinePost.ts index 84d58c5b..2bb1b9ea 100644 --- a/src/gfx/renderJob/post/OutlinePost.ts +++ b/src/gfx/renderJob/post/OutlinePost.ts @@ -19,6 +19,7 @@ import { OutlineCalcOutline_cs } from '../../../assets/shader/compute/OutlineCal import { Outline_cs } from '../../../assets/shader/compute/Outline_cs'; import { OutLineBlendColor_cs } from '../../../assets/shader/compute/OutLineBlendColor_cs'; import { OutlinePostSlot, outlinePostData } from '../../../io/OutlinePostData'; +import { GlobalBindGroup } from '../../graphics/webGpu/core/bindGroups/GlobalBindGroup'; /** @@ -95,6 +96,7 @@ export class OutlinePost extends PostBase { * @internal */ private rtFrame: RTFrame; + private view: View3D; constructor() { super(); @@ -104,6 +106,7 @@ export class OutlinePost extends PostBase { * @internal */ onAttach(view: View3D,) { + this.view = view; Engine3D.setting.render.postProcessing.outline.enable = true; } @@ -162,15 +165,18 @@ export class OutlinePost extends PostBase { } private createCompute() { - let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); - let visibleMap = rtFrame.getPositionMap(); + let rtFrame = GBufferFrame.getGBufferFrame(GBufferFrame.colorPass_GBuffer); this.calcWeightCompute = new ComputeShader(OutlineCalcOutline_cs); + + let globalUniform = GlobalBindGroup.getCameraGroup(this.view.camera); + + this.calcWeightCompute.setUniformBuffer('globalUniform', globalUniform.uniformGPUBuffer); this.calcWeightCompute.setStorageBuffer('outlineSetting', this.outlineSetting); this.calcWeightCompute.setStorageBuffer('slotsBuffer', this.slotsBuffer); this.calcWeightCompute.setStorageBuffer(`weightBuffer`, this.weightBuffer); this.calcWeightCompute.setStorageBuffer(`entitiesBuffer`, this.entitiesBuffer); - this.calcWeightCompute.setSamplerTexture(`indexTexture`, visibleMap); + this.calcWeightCompute.setSamplerTexture(`gBufferTexture`, rtFrame.getCompressGBufferTexture()); this.calcWeightCompute.workerSizeX = Math.ceil(this.lowTex.width / 8); this.calcWeightCompute.workerSizeY = Math.ceil(this.lowTex.height / 8); diff --git a/src/gfx/renderJob/post/SSGIPost.ts b/src/gfx/renderJob/post/SSGIPost.ts new file mode 100644 index 00000000..483aef17 --- /dev/null +++ b/src/gfx/renderJob/post/SSGIPost.ts @@ -0,0 +1,305 @@ +import { VirtualTexture } from '../../../textures/VirtualTexture'; +import { GlobalBindGroup } from '../../graphics/webGpu/core/bindGroups/GlobalBindGroup'; +import { StorageGPUBuffer } from '../../graphics/webGpu/core/buffer/StorageGPUBuffer'; +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 { Time } from '../../../util/Time'; +import { clamp } from '../../../math/MathUtil'; +import { View3D } from '../../../core/View3D'; +import { RTDescriptor } from '../../graphics/webGpu/descriptor/RTDescriptor'; +import { GBufferFrame } from '../frame/GBufferFrame'; +import { RTFrame } from '../frame/RTFrame'; +import { GTAO_cs } from '../../../assets/shader/compute/GTAO_cs'; +import { CResizeEvent } from '../../../event/CResizeEvent'; +import { TextureScaleCompute } from '../../generate/convert/TextureScaleCompute'; +import { RenderTexture } from '../../../textures/RenderTexture'; +import { SSGI2_cs } from '../../../assets/shader/compute/SSGI2_cs'; +import { Denoising_cs } from '../../../assets/shader/compute/utils/Denoising_cs'; +import { Combine_cs, Vector3, mergeFunctions } from '../../..'; + +/** + * Ground base Ambient Occlusion + * Let the intersection of the object and the object imitate the effect of the light being cross-occluded + * ``` + * gtao setting + * let cfg = {@link Engine3D.setting.render.postProcessing.gtao}; + *``` + * @group Post Effects + */ +export class SSGIPost extends PostBase { + /** + * @internal + */ + outTexture: VirtualTexture; + newTexture: VirtualTexture; + oldTexture: VirtualTexture; + combineTexture: VirtualTexture; + + /** + * @internal + */ + rendererPassState: RendererPassState; + /** + * @internal + */ + ssgiCompute: ComputeShader; + delayCompute: ComputeShader; + combineCompute: ComputeShader; + + rtFrame: RTFrame; + textureScaleSmallCompute: TextureScaleCompute; + textureScaleBigCompute: TextureScaleCompute; + view: View3D; + colorTexture: RenderTexture; + posTexture: RenderTexture; + normalTexture: RenderTexture; + gBufferTexture: RenderTexture; + lastPosTexture: RenderTexture; + public downSampleCofe: number = 1.0; + // public downSampleCofe: number = 0.5; + debugChanal: string = "0"; + + public updateBuffer: StorageGPUBuffer; + constructor() { + super(); + + this.updateBuffer = new StorageGPUBuffer(8 * 4); + this.updateBuffer.setFloat("frameCount", 10); + this.updateBuffer.setFloat("indirectIns", 1.5); + this.updateBuffer.setFloat("delay", 0.02); + this.updateBuffer.setFloat("colorIns", 1.0); + this.updateBuffer.setFloat("d1", 0.03); + this.updateBuffer.apply(); + } + + /** + * @internal + */ + onAttach(view: View3D,) { + this.view = view; + // Engine3D.setting.render.useCompressGBuffer = true; + + + view.camera.transform.onPositionChange = view.camera.transform.onPositionChange ? + mergeFunctions(view.camera.transform.onPositionChange, (a, b) => this.onCameraChange(a, b)) : (a, b) => this.onCameraChange(a, b); + } + + onCameraChange(oldPos: Vector3, newPos: Vector3) { + console.log("a",); + let p = Vector3.distance(oldPos, newPos); + p = Math.min(0.45, p) + 0.01; + this.updateBuffer.setFloat("delay", p); + } + /** + * @internal + */Render + onDetach(view: View3D,) { + // Engine3D.setting.render.useCompressGBuffer = false; + } + + set ins(v: number) { + this.updateBuffer.setFloat("indirectIns", v); + this.updateBuffer.apply(); + } + + get ins(): number { + return this.updateBuffer.getFloat("indirectIns"); + } + + set delay(v: number) { + this.updateBuffer.setFloat("delay", v); + this.updateBuffer.apply(); + } + + get delay(): number { + return this.updateBuffer.getFloat("delay"); + } + + + set colorIns(v: number) { + this.updateBuffer.setFloat("colorIns", v); + this.updateBuffer.apply(); + } + + get colorIns(): number { + return this.updateBuffer.getFloat("colorIns"); + } + + set frameCount(v: number) { + this.updateBuffer.setFloat("frameCount", v); + this.updateBuffer.apply(); + } + + get frameCount(): number { + return this.updateBuffer.getFloat("frameCount"); + } + + set d1(v: number) { + this.updateBuffer.setFloat("d1", v); + this.updateBuffer.apply(); + } + + get d1(): number { + return this.updateBuffer.getFloat("d1"); + } + + + private createResource() { + let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); + this.gBufferTexture = rtFrame.getCompressGBufferTexture(); + + let presentationSize = webGPUContext.presentationSize; + let w = presentationSize[0]; + let h = presentationSize[1]; + + this.lastPosTexture = new VirtualTexture(w, h, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); + this.lastPosTexture.name = 'lastPosTexture'; + + this.outTexture = new VirtualTexture(w, h, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); + this.outTexture.name = 'outTexture'; + + let inW = Math.floor(w * this.downSampleCofe); + let inH = Math.floor(h * this.downSampleCofe); + + this.newTexture = new VirtualTexture(inW, inH, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); + this.newTexture.name = 'newTexture'; + + this.oldTexture = new VirtualTexture(inW, inH, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); + this.oldTexture.name = 'oldTexture'; + + this.combineTexture = new VirtualTexture(inW, inH, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); + this.combineTexture.name = 'combineTexture'; + + let ssgiDec = new RTDescriptor(); + // gtaoDec.clearValue = [1, 1, 1, 1]; + ssgiDec.loadOp = `load`; + this.rtFrame = new RTFrame([ + this.outTexture + ], [ + ssgiDec + ]); + } + + + private createCompute() { + this.ssgiCompute = new ComputeShader(SSGI2_cs); + this.delayCompute = new ComputeShader(Denoising_cs); + this.combineCompute = new ComputeShader(Combine_cs); + + let globalUniform = GlobalBindGroup.getCameraGroup(this.view.camera); + { + this.ssgiCompute.setSamplerTexture(`gBufferTexture`, this.gBufferTexture); + this.ssgiCompute.setSamplerTexture(`combineTexture`, this.combineTexture); + this.ssgiCompute.setSamplerTexture(`oldTexture`, this.oldTexture); + this.ssgiCompute.setStorageTexture(`newTexture`, this.newTexture); + this.ssgiCompute.setUniformBuffer('globalUniform', globalUniform.uniformGPUBuffer); + this.ssgiCompute.setStorageBuffer('updateBuffer', this.updateBuffer); + this.autoSetColorTexture('inTex', this.ssgiCompute); + } + + { + this.delayCompute.setSamplerTexture(`newTexture`, this.newTexture); + this.delayCompute.setSamplerTexture(`oldTexture`, this.oldTexture); + this.delayCompute.setStorageTexture(`combineTexture`, this.combineTexture); + this.delayCompute.setStorageBuffer('updateBuffer', this.updateBuffer); + } + + { + this.combineCompute.setSamplerTexture(`inputBTexture`, this.combineTexture); + this.combineCompute.setSamplerTexture(`gBufferTexture`, this.gBufferTexture); + this.combineCompute.setUniformBuffer('globalUniform', globalUniform.uniformGPUBuffer); + this.combineCompute.setStorageTexture(`outTexture`, this.outTexture); + this.combineCompute.setStorageBuffer(`updateBuffer`, this.updateBuffer); + } + + { + this.textureScaleBigCompute = new TextureScaleCompute(); + this.textureScaleBigCompute.setInputes( + null, + // this.colorTexture, + [this.combineTexture], + [this.outTexture]); + } + + } + + public render(view: View3D, command: GPUCommandEncoder): void { + + } + + private frame: number = 0; + + public compute(view: View3D): void { + if (!this.ssgiCompute) { + this.createResource(); + this.createCompute(); + this.onResize(); + + this.rendererPassState = WebGPUDescriptorCreator.createRendererPassState(this.rtFrame, null); + this.rendererPassState.label = "SSGI"; + } + + this.frameCount = this.frame; + this.frame++; + + let command = GPUContext.beginCommandEncoder(); + // GPUContext.copyTexture(command, this.albedoTexture, this.outTexture); + switch (parseInt(this.debugChanal)) { + case 0: + // GPUContext.copyTexture(command, this.oldTexture, this.combineTexture); + GPUContext.copyTexture(command, this.combineTexture, this.oldTexture); + // GPUContext.computeCommand(command, [this.ssgiCompute, this.delayCompute, this.textureScaleBigCompute.computeShader]); + GPUContext.computeCommand(command, [this.ssgiCompute, this.delayCompute, this.combineCompute]); + // GPUContext.copyTexture(command, this.posTexture, this.lastPosTexture); + break; + case 1: + GPUContext.copyTexture(command, this.posTexture, this.lastPosTexture); + GPUContext.copyTexture(command, this.lastPosTexture, this.outTexture); + break; + case 2: + GPUContext.copyTexture(command, this.normalTexture, this.outTexture); + break; + case 3: + GPUContext.copyTexture(command, this.posTexture, this.outTexture); + break; + case 4: + GPUContext.copyTexture(command, this.colorTexture, this.outTexture); + break; + case 5: + GPUContext.copyTexture(command, this.gBufferTexture, this.outTexture); + break; + default: + break; + } + + GPUContext.lastRenderPassState = this.rendererPassState; + + this.updateBuffer.setFloat("delay", 0.01); + } + + public onResize() { + let presentationSize = webGPUContext.presentationSize; + let w = presentationSize[0]; + let h = presentationSize[1]; + this.outTexture.resize(w, h); + + this.ssgiCompute.workerSizeX = Math.ceil(this.newTexture.width / 16); + this.ssgiCompute.workerSizeY = Math.ceil(this.newTexture.height / 16); + this.ssgiCompute.workerSizeZ = 1; + + this.delayCompute.workerSizeX = Math.ceil(this.combineTexture.width / 16); + this.delayCompute.workerSizeY = Math.ceil(this.combineTexture.height / 16); + this.delayCompute.workerSizeZ = 1; + + this.combineCompute.workerSizeX = Math.ceil(this.outTexture.width / 16); + this.combineCompute.workerSizeY = Math.ceil(this.outTexture.height / 16); + this.combineCompute.workerSizeZ = 1; + } +} \ No newline at end of file diff --git a/src/gfx/renderJob/post/SSRPost.ts b/src/gfx/renderJob/post/SSRPost.ts index e3e77256..8095ceaf 100644 --- a/src/gfx/renderJob/post/SSRPost.ts +++ b/src/gfx/renderJob/post/SSRPost.ts @@ -9,12 +9,10 @@ import { ComputeShader } from '../../graphics/webGpu/shader/ComputeShader'; import { GPUTextureFormat } from '../../graphics/webGpu/WebGPUConst'; import { webGPUContext } from '../../graphics/webGpu/Context3D'; import { GPUContext } from '../GPUContext'; -import { RTResourceMap } from '../frame/RTResourceMap'; import { RendererPassState } from '../passRenderer/state/RendererPassState'; import { PostBase } from './PostBase'; import { clamp } from '../../../math/MathUtil'; import { EntityCollect } from '../collect/EntityCollect'; -import { RTResourceConfig } from '../config/RTResourceConfig'; import { RTDescriptor } from '../../graphics/webGpu/descriptor/RTDescriptor'; import { RTFrame } from '../frame/RTFrame'; import { GBufferFrame } from '../frame/GBufferFrame'; @@ -57,7 +55,7 @@ export class SSRPost extends PostBase { /** * @internal */ - ssrUniformBuffer: StorageGPUBuffer; + ssrUniformBuffer: UniformGPUBuffer; /** * @internal */ @@ -69,19 +67,16 @@ export class SSRPost extends PostBase { /** * @internal */ - isKernelFloat32Array: Float32Array; rtFrame: RTFrame; historyPosition: StorageGPUBuffer; + view: View3D; - constructor() { - super(); - } /** * @internal */ public onAttach(view: View3D,) { + this.view = view; Engine3D.setting.render.postProcessing.ssr.enable = true; - this.debug(); } /** * @internal @@ -158,19 +153,19 @@ export class SSRPost extends PostBase { setting.powDotRN = value; } - private debug() { - } - private createRayTraceShader() { + let globalUniform = GlobalBindGroup.getCameraGroup(this.view.camera); + this.SSR_RayTraceCompute = new ComputeShader(SSR_RayTrace_cs); - this.SSR_RayTraceCompute.setStorageBuffer('ssrUniform', this.ssrUniformBuffer); + this.SSR_RayTraceCompute.setUniformBuffer('globalUniform', globalUniform.uniformGPUBuffer); + this.SSR_RayTraceCompute.setUniformBuffer('ssrUniform', this.ssrUniformBuffer); this.SSR_RayTraceCompute.setStorageBuffer(`rayTraceBuffer`, this.rayTraceData); this.SSR_RayTraceCompute.setStorageBuffer(`historyPosition`, this.historyPosition); let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); - this.SSR_RayTraceCompute.setSamplerTexture("zBufferTexture", rtFrame.getPositionMap()); - this.SSR_RayTraceCompute.setSamplerTexture(RTResourceConfig.normalBufferTex_NAME, rtFrame.renderTargets[2]); - this.SSR_RayTraceCompute.setSamplerTexture(RTResourceConfig.materialBufferTex_NAME, rtFrame.renderTargets[3]); + let gBufferTexture = rtFrame.getCompressGBufferTexture(); + + this.SSR_RayTraceCompute.setSamplerTexture("gBufferTexture", gBufferTexture); if (EntityCollect.instance.sky instanceof SkyRenderer) this.SSR_RayTraceCompute.setSamplerTexture(`prefilterMap`, EntityCollect.instance.sky.map); @@ -187,8 +182,8 @@ export class SSRPost extends PostBase { this.SSR_IS_Compute.setStorageBuffer(`rayTraceBuffer`, this.rayTraceData); this.SSR_IS_Compute.setStorageBuffer(`ssrColorData`, this.ssrColorData); this.SSR_IS_Compute.setStorageBuffer(`historyPosition`, this.historyPosition); + this.SSR_IS_Compute.setSamplerTexture(`colorMap`, this.getOutTexture()); - this.autoSetColorTexture('colorMap', this.SSR_IS_Compute); this.SSR_IS_Compute.setStorageTexture(`outTex`, this.isRetTexture); this.SSR_IS_Compute.workerSizeX = Math.ceil(this.isRetTexture.width / 8); @@ -197,10 +192,17 @@ export class SSRPost extends PostBase { } private createBlendShader(input: VirtualTexture): void { + let globalUniform = GlobalBindGroup.getCameraGroup(this.view.camera); this.SSR_Blend_Compute = new ComputeShader(SSR_BlendColor_cs); this.SSR_Blend_Compute.setStorageBuffer(`rayTraceBuffer`, this.rayTraceData); - this.autoSetColorTexture('colorMap', this.SSR_Blend_Compute); + this.SSR_Blend_Compute.setUniformBuffer('globalUniform', globalUniform.uniformGPUBuffer); + + let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); + let gBufferTexture = rtFrame.getCompressGBufferTexture(); + + this.SSR_Blend_Compute.setSamplerTexture("gBufferTexture", gBufferTexture); + this.SSR_Blend_Compute.setSamplerTexture("colorMap", this.getOutTexture()); this.SSR_Blend_Compute.setSamplerTexture(`ssrMap`, input); this.SSR_Blend_Compute.setStorageTexture(`outTex`, this.finalTexture); @@ -210,13 +212,8 @@ export class SSRPost extends PostBase { } private createResource() { - let presentationSize = webGPUContext.presentationSize; - let w = presentationSize[0]; - let h = presentationSize[1]; - // RTResourceMap.createRTTextures( - // [RTResourceConfig.colorBufferTex_NAME, RTResourceConfig.positionBufferTex_NAME, RTResourceConfig.normalBufferTex_NAME, RTResourceConfig.materialBufferTex_NAME], - // [GPUTextureFormat.rgba16float, GPUTextureFormat.rgba16float, GPUTextureFormat.rgba8unorm, GPUTextureFormat.rgba8unorm], - // ); + let [w, h] = webGPUContext.presentationSize; + this.finalTexture = new VirtualTexture(w, h, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING); this.finalTexture.name = 'ssrOutTex'; let rtDec = new RTDescriptor(); @@ -262,7 +259,6 @@ export class SSRPost extends PostBase { this.createISShader(); this.createRayTraceShader(); this.createBlendShader(this.isRetTexture); - let presentTexture = this.finalTexture; this.rendererPassState = WebGPUDescriptorCreator.createRendererPassState(this.rtFrame, null); let standUniform = GlobalBindGroup.getCameraGroup(view.camera); @@ -291,9 +287,8 @@ export class SSRPost extends PostBase { } public onResize(): void { - let presentationSize = webGPUContext.presentationSize; - let w = presentationSize[0]; - let h = presentationSize[1]; + let [w, h] = webGPUContext.presentationSize; + let ssrWidth = Math.ceil(w * Engine3D.setting.render.postProcessing.ssr.pixelRatio); let ssrHeight = Math.ceil(h * Engine3D.setting.render.postProcessing.ssr.pixelRatio); diff --git a/src/gfx/renderJob/post/TAAPost.ts b/src/gfx/renderJob/post/TAAPost.ts index ad4d16f3..7fbbf4ed 100644 --- a/src/gfx/renderJob/post/TAAPost.ts +++ b/src/gfx/renderJob/post/TAAPost.ts @@ -95,7 +95,7 @@ export class TAAPost extends PostBase { } public set jitterSeedCount(value: number) { - value = clamp(value, 2, 8); + value = clamp(value, 2, 32); value = Math.round(value); let setting = Engine3D.setting.render.postProcessing.taa; setting.jitterSeedCount = value; @@ -118,7 +118,7 @@ export class TAAPost extends PostBase { } public set sharpFactor(value: number) { - value = clamp(value, 0.1, 0.9); + value = clamp(value, 0.1, 0.99); let setting = Engine3D.setting.render.postProcessing.taa; setting.sharpFactor = value; } @@ -129,7 +129,7 @@ export class TAAPost extends PostBase { } public set sharpPreBlurFactor(value: number) { - value = clamp(value, 0.1, 0.9); + value = clamp(value, 0.1, 0.99); let setting = Engine3D.setting.render.postProcessing.taa; setting.sharpPreBlurFactor = value; } @@ -150,18 +150,17 @@ export class TAAPost extends PostBase { private createCompute(view: View3D) { let computeShader = new ComputeShader(TAA_cs); - let cfg = Engine3D.setting.render.postProcessing.taa; let taaSetting: UniformGPUBuffer = new UniformGPUBuffer(16 * 2 + 4 * 3); //matrix + 3 * vector4 let standUniform = GlobalBindGroup.getCameraGroup(view.camera); - computeShader.setUniformBuffer('standUniform', standUniform.uniformGPUBuffer); + computeShader.setUniformBuffer('globalUniform', standUniform.uniformGPUBuffer); computeShader.setUniformBuffer('taaData', taaSetting); computeShader.setStorageBuffer(`preColorBuffer`, this.preColorBuffer); - let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); + let rtFrame = GBufferFrame.getGBufferFrame(GBufferFrame.colorPass_GBuffer); computeShader.setSamplerTexture(`preColorTex`, this.preColorTex); - computeShader.setSamplerTexture(`posTex`, rtFrame.getPositionMap()); + computeShader.setSamplerTexture(`gBufferTexture`, rtFrame.getCompressGBufferTexture()); this.autoSetColorTexture('inTex', computeShader); computeShader.setStorageTexture(`outTex`, this.taaTexture); @@ -194,9 +193,7 @@ export class TAAPost extends PostBase { this.preProjMatrix = new Matrix4().identity(); this.preViewMatrix = new Matrix4().identity(); - let presentationSize = webGPUContext.presentationSize; - let w = presentationSize[0]; - let h = presentationSize[1]; + let [w, h] = webGPUContext.presentationSize; this.preColorBuffer = new StorageGPUBuffer(w * h * 4, GPUBufferUsage.COPY_SRC); @@ -256,9 +253,7 @@ export class TAAPost extends PostBase { } public onResize(): void { - let presentationSize = webGPUContext.presentationSize; - let w = presentationSize[0]; - let h = presentationSize[1]; + let [w, h] = webGPUContext.presentationSize; this.preColorBuffer.resizeBuffer(w * h * 4); diff --git a/src/index.ts b/src/index.ts index 457e8789..28acd9a2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,20 +23,30 @@ 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/PreFilteredEnvironment_cs copy" +export * from "./assets/shader/compute/PreFilteredEnvironment_cs" export * from "./assets/shader/compute/PreIntegratedLut" export * from "./assets/shader/compute/SSAO_cs" +export * from "./assets/shader/compute/SSGI2_cs" export * from "./assets/shader/compute/SSR_BlendColor_cs" export * from "./assets/shader/compute/SSR_IS_cs" export * from "./assets/shader/compute/SSR_RayTrace_cs" export * from "./assets/shader/compute/TAACopyTex_cs" export * from "./assets/shader/compute/TAASharpTex_cs" export * from "./assets/shader/compute/TAA_cs" +export * from "./assets/shader/compute/utils/Combine_cs" +export * from "./assets/shader/compute/utils/Denoising_cs" +export * from "./assets/shader/compute/utils/TestComputeLoadBuffer" +export * from "./assets/shader/compute/utils/TextureCompress" +export * from "./assets/shader/compute/utils/tw" export * from "./assets/shader/core/base/Common_frag" export * from "./assets/shader/core/base/Common_vert" export * from "./assets/shader/core/common/BrdfLut_frag" export * from "./assets/shader/core/common/EnvMap_frag" +export * from "./assets/shader/core/common/GBufferStand" export * from "./assets/shader/core/common/GlobalUniform" export * from "./assets/shader/core/common/InstanceUniform" +export * from "./assets/shader/core/common/SHCommon_frag" export * from "./assets/shader/core/common/WorldMatrixUniform" export * from "./assets/shader/core/inline/Inline_vert" export * from "./assets/shader/core/pass/CastShadow_pass" @@ -48,20 +58,24 @@ export * from "./assets/shader/core/pass/ZPassShader_fs" export * from "./assets/shader/core/pass/ZPassShader_vs" export * from "./assets/shader/core/struct/ClusterLight" export * from "./assets/shader/core/struct/ColorPassFragmentOutput" +export * from "./assets/shader/core/struct/FragmentOutput" 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/env/ReflectionCG" export * from "./assets/shader/glsl/Quad_glsl" export * from "./assets/shader/glsl/Sky_glsl" export * from "./assets/shader/glsl/post/LUT_glsl" export * from "./assets/shader/graphic/Graphic3DShader" +export * from "./assets/shader/graphic/GraphicDecCompute" export * from "./assets/shader/graphic/GraphicDynamicCompute" export * from "./assets/shader/graphic/GraphicFaceComput2" export * from "./assets/shader/graphic/GraphicFaceCompute" export * from "./assets/shader/graphic/GraphicFaceCompute3" export * from "./assets/shader/graphic/GraphicLineCompute" export * from "./assets/shader/graphic/GraphicTrailCompute" +export * from "./assets/shader/graphic/GraphicTrailCompute2" export * from "./assets/shader/lighting/BRDF_frag" export * from "./assets/shader/lighting/BsDF_frag" export * from "./assets/shader/lighting/BxDF_frag" @@ -82,6 +96,7 @@ 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/ReflectionShader_shader" export * from "./assets/shader/materials/UnLit" export * from "./assets/shader/materials/UnLitTextureArray" export * from "./assets/shader/materials/program/BxdfDebug_frag" @@ -101,6 +116,7 @@ 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/BitUtil" export * from "./assets/shader/utils/ColorUtil" export * from "./assets/shader/utils/GenerayRandomDir" export * from "./components/AtmosphericComponent" @@ -183,10 +199,12 @@ export * from "./components/renderer/GlobalIlluminationComponent" export * from "./components/renderer/InstanceDrawComponent" export * from "./components/renderer/MeshFilter" export * from "./components/renderer/MeshRenderer" +export * from "./components/renderer/Reflection" export * from "./components/renderer/RenderNode" export * from "./components/renderer/SkinnedMeshRenderer" export * from "./components/renderer/SkinnedMeshRenderer2" export * from "./components/renderer/SkyRenderer" +export * from "./components/renderer/SphereReflection" export * from "./components/shape/BoxColliderShape" export * from "./components/shape/CapsuleColliderShape" export * from "./components/shape/ColliderShape" @@ -253,6 +271,7 @@ export * from "./gfx/generate/convert/IBLEnvMapCreator" export * from "./gfx/generate/convert/MergeRGBACreator" export * from "./gfx/generate/convert/TextureCubeStdCreator" export * from "./gfx/generate/convert/TextureCubeUtils" +export * from "./gfx/generate/convert/TextureScaleCompute" export * from "./gfx/graphics/webGpu/CanvasConfig" export * from "./gfx/graphics/webGpu/Context3D" export * from "./gfx/graphics/webGpu/PipelinePool" @@ -265,6 +284,7 @@ export * from "./gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup" export * from "./gfx/graphics/webGpu/core/bindGroups/MatrixBindGroup" export * from "./gfx/graphics/webGpu/core/bindGroups/groups/LightEntries" export * from "./gfx/graphics/webGpu/core/bindGroups/groups/ProbeEntries" +export * from "./gfx/graphics/webGpu/core/bindGroups/groups/ReflectionEntries" export * from "./gfx/graphics/webGpu/core/buffer/ArrayBufferData" export * from "./gfx/graphics/webGpu/core/buffer/ComputeGPUBuffer" export * from "./gfx/graphics/webGpu/core/buffer/GPUBufferBase" @@ -317,6 +337,7 @@ export * from "./gfx/renderJob/collect/ShadowLightsCollect" export * from "./gfx/renderJob/config/RTResourceConfig" export * from "./gfx/renderJob/config/RenderLayer" export * from "./gfx/renderJob/frame/GBufferFrame" +export * from "./gfx/renderJob/frame/GBufferFrameA" export * from "./gfx/renderJob/frame/ProbeGBufferFrame" export * from "./gfx/renderJob/frame/RTFrame" export * from "./gfx/renderJob/frame/RTResourceMap" @@ -330,6 +351,7 @@ export * from "./gfx/renderJob/passRenderer/cluster/ClusterConfig" export * from "./gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer" export * from "./gfx/renderJob/passRenderer/cluster/ClusterLightingRender" export * from "./gfx/renderJob/passRenderer/color/ColorPassRenderer" +export * from "./gfx/renderJob/passRenderer/cubeRenderer/ReflectionRenderer" export * from "./gfx/renderJob/passRenderer/ddgi/DDGIIrradianceComputePass" export * from "./gfx/renderJob/passRenderer/ddgi/DDGIIrradianceGPUBufferReader" export * from "./gfx/renderJob/passRenderer/ddgi/DDGIIrradianceVolume" @@ -356,17 +378,19 @@ export * from "./gfx/renderJob/passRenderer/preDepth/PreDepthPassRenderer" export * from "./gfx/renderJob/passRenderer/preDepth/ZCullingCompute" export * from "./gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer" export * from "./gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer" +export * from "./gfx/renderJob/passRenderer/state/PassType" 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/GBufferPost" export * from "./gfx/renderJob/post/GTAOPost" export * from "./gfx/renderJob/post/GlobalFog" export * from "./gfx/renderJob/post/GodRayPost" export * from "./gfx/renderJob/post/OutlinePost" export * from "./gfx/renderJob/post/PostBase" +export * from "./gfx/renderJob/post/SSGIPost" export * from "./gfx/renderJob/post/SSRPost" export * from "./gfx/renderJob/post/TAAPost" export * from "./io/InputSystem" @@ -398,6 +422,7 @@ export * from "./loader/parser/gis/GeoJsonParser" export * from "./loader/parser/gis/GeoJsonUtil.ts" export * from "./loader/parser/gltf/GLBParser" export * from "./loader/parser/gltf/GLTFInfo" +export * from "./loader/parser/gltf/GLTFMaterial" export * from "./loader/parser/gltf/GLTFParser" export * from "./loader/parser/gltf/GLTFSubParser" export * from "./loader/parser/gltf/GLTFSubParserCamera" @@ -435,6 +460,7 @@ 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/ReflectionShader" export * from "./loader/parser/prefab/mats/shader/SkyShader" export * from "./loader/parser/prefab/mats/shader/StandShader" export * from "./loader/parser/prefab/mats/shader/UnLitShader" @@ -462,6 +488,7 @@ export * from "./materials/LitMaterial" export * from "./materials/Material" export * from "./materials/MaterialRegister" export * from "./materials/PhysicMaterial" +export * from "./materials/ReflectionMaterial" export * from "./materials/SkyMaterial" export * from "./materials/UnLitMaterial" export * from "./materials/UnLitTexArrayMaterial" @@ -477,6 +504,7 @@ export * from "./math/Bezier2D" export * from "./math/Bezier3D" export * from "./math/BiMap" export * from "./math/Color" +export * from "./math/ColorGradient" export * from "./math/CubicBezierCurve" export * from "./math/CubicBezierPath" export * from "./math/HaltonSeq" @@ -529,6 +557,7 @@ export * from "./setting/LoaderSetting" export * from "./setting/MaterialSetting" export * from "./setting/OcclusionQuerySetting" export * from "./setting/PickSetting" +export * from "./setting/ReflectionSetting" export * from "./setting/RenderSetting" export * from "./setting/ShadowSetting" export * from "./setting/SkySetting" @@ -538,6 +567,7 @@ export * from "./setting/post/GTAOSetting" export * from "./setting/post/GlobalFogSetting" export * from "./setting/post/GodRaySetting" export * from "./setting/post/OutlineSetting" +export * from "./setting/post/SSGISetting" export * from "./setting/post/SSRSetting" export * from "./setting/post/TAASetting" export * from "./shape/BoxGeometry" @@ -571,6 +601,7 @@ export * from "./util/BoundUtil" export * from "./util/BytesArray" export * from "./util/CameraUtil" export * from "./util/Convert" +export * from "./util/DelayUtil" export * from "./util/GeometryUtil" export * from "./util/Global" export * from "./util/KelvinUtil" @@ -586,3 +617,11 @@ export * from "./util/ZSorterUtil" export * from "./util/struct/Struct" export * from "./util/struct/StructValue" export * from "./util/struct/Vector3Struct" +export * from "./util/transformUtil/Object3DTransformTools" +export * from "./util/transformUtil/RotationControlComponents" +export * from "./util/transformUtil/ScaleControlComponents" +export * from "./util/transformUtil/TransformAxisEnum" +export * from "./util/transformUtil/TransformControllerBaseComponent" +export * from "./util/transformUtil/TransformMode" +export * from "./util/transformUtil/TransformSpaceMode" +export * from "./util/transformUtil/TranslationControlComponents" diff --git a/src/io/InputSystem.ts b/src/io/InputSystem.ts index d2c62163..d40fbb3b 100644 --- a/src/io/InputSystem.ts +++ b/src/io/InputSystem.ts @@ -85,6 +85,7 @@ export class InputSystem extends CEventDispatcher { protected _keyEvent3d: KeyEvent; protected _pointerEvent3D: PointerEvent3D; protected _windowsEvent3d: CEvent; + mouseLock: boolean = false; @@ -94,9 +95,18 @@ export class InputSystem extends CEventDispatcher { */ public initCanvas(canvas: HTMLCanvasElement) { this.canvas = canvas; - // canvas.style.position = 'absolute'; - // canvas.style.zIndex = '0'; - canvas.onpointerdown = (ev: PointerEvent) => { + + // canvas.onpointerdown = (ev: PointerEvent) => { + // if (ev.button == 0) { + // this.mouseStart(ev); + // } else if (ev.button == 1) { + // this.middleDown(ev); + // } else if (ev.button == 2) { + // this.mouseStart(ev); + // } + // } + + canvas.onmousedown = (ev: MouseEvent) => { if (ev.button == 0) { this.mouseStart(ev); } else if (ev.button == 1) { @@ -105,6 +115,7 @@ export class InputSystem extends CEventDispatcher { this.mouseStart(ev); } } + canvas.onpointerup = (ev: PointerEvent) => { if (ev.button == 0) { this.mouseEnd(ev); @@ -146,6 +157,14 @@ export class InputSystem extends CEventDispatcher { true, ); + // let input = document.createElement(`input`); + // input.setSelectionRange(-1000, 1000); + // input.style.zIndex = `9999` + // input.style.width = `9999px` + // input.style.height = `9999px` + // input.style.position = `absolute` + // input.focus(); + // document.body.append(input); canvas.addEventListener(`wheel`, (e: WheelEvent) => this.mouseWheel(e), { passive: false }); @@ -171,12 +190,42 @@ export class InputSystem extends CEventDispatcher { this._windowsEvent3d = new CEvent(); } + public useMouseLock() { + if (this.mouseLock) return; + this.canvas.requestPointerLock(); + this.mouseLock = true; + document.addEventListener("mousemove", (e) => this.onMouseLockMove(e), false); + } + public releaseMouseLock() { + this.mouseLock = false; + document.exitPointerLock(); + document.removeEventListener("mousemove", (e) => this.onMouseLockMove(e), false); + } - private _gp: boolean = false; + public onMouseLockMove(e: MouseEvent) { + // console.log(e.movementX, e.movementY); + this.mouseLastX = this.mouseX; + this.mouseLastY = this.mouseY; + this.mouseX = e.clientX - this.canvasX; /*- Input.canvas.x + Input.canvas.offsetX*/ + this.mouseY = e.clientY - this.canvasY; /*- Input.canvas.y + Input.canvas.offsetY*/ + this.mouseOffsetX = e.movementX; + this.mouseOffsetY = e.movementY; + this._pointerEvent3D.reset(); + this._pointerEvent3D.type = PointerEvent3D.POINTER_MOVE; + this._pointerEvent3D.ctrlKey = e.ctrlKey; + this._pointerEvent3D.altKey = e.altKey; + this._pointerEvent3D.shiftKey = e.shiftKey; + this._pointerEvent3D.mouseX = this.mouseX; + this._pointerEvent3D.mouseY = this.mouseY; + + this._pointerEvent3D.movementX = e.movementX; + this._pointerEvent3D.movementY = e.movementY; + this.dispatchEvent(this._pointerEvent3D); + } private onPinch(x1: number, y1: number, x2: number, y2: number) { this._oldPosition1 = new Vector3(x1, y1); @@ -219,7 +268,7 @@ export class InputSystem extends CEventDispatcher { this.dispatchEvent(this._pointerEvent3D); } - private middleDown(e: PointerEvent) { + private middleDown(e: PointerEvent | MouseEvent) { this._pointerEvent3D.reset(); this._pointerEvent3D.mouseCode = e.button; this._pointerEvent3D.mouseX = e.clientX - this.canvasX; @@ -229,10 +278,10 @@ export class InputSystem extends CEventDispatcher { this._pointerEvent3D.ctrlKey = e.ctrlKey; this._pointerEvent3D.altKey = e.altKey; this._pointerEvent3D.shiftKey = e.shiftKey; - this._pointerEvent3D.pointerId = e.pointerId; - this._pointerEvent3D.pointerType = e.pointerType; - this._pointerEvent3D.isPrimary = e.isPrimary; - this._pointerEvent3D.pressure = e.pressure; + this._pointerEvent3D.pointerId = e[`pointerId`] ? e[`pointerId`] : 0; + this._pointerEvent3D.pointerType = e[`pointerType`] ? e[`pointerType`] : 0; + this._pointerEvent3D.isPrimary = e[`isPrimary`] ? e[`isPrimary`] : 0; + this._pointerEvent3D.pressure = e[`pressure`] ? e[`pressure`] : 0; this.dispatchEvent(this._pointerEvent3D); } @@ -300,7 +349,8 @@ export class InputSystem extends CEventDispatcher { } - private mouseStart(e: PointerEvent) { + private mouseStart(e: PointerEvent | MouseEvent) { + this.isMouseDown = true; this.mouseLastX = this.mouseX; @@ -318,10 +368,10 @@ export class InputSystem extends CEventDispatcher { this._pointerEvent3D.metaKey = e.metaKey; this._pointerEvent3D.altKey = e.altKey; this._pointerEvent3D.shiftKey = e.shiftKey; - this._pointerEvent3D.pointerId = e.pointerId; - this._pointerEvent3D.pointerType = e.pointerType; - this._pointerEvent3D.isPrimary = e.isPrimary; - this._pointerEvent3D.pressure = e.pressure; + this._pointerEvent3D.pointerId = e[`pointerId`] ? e[`pointerId`] : 0; + this._pointerEvent3D.pointerType = e[`pointerType`] ? e[`pointerType`] : 0; + this._pointerEvent3D.isPrimary = e[`isPrimary`] ? e[`isPrimary`] : 0; + this._pointerEvent3D.pressure = e[`pressure`] ? e[`pressure`] : 0; this._pointerEvent3D.mouseX = this.mouseX; this._pointerEvent3D.mouseY = this.mouseY; // if (!this._mouseStatus[this._touchEvent3d.mouseCode]) { diff --git a/src/io/picker/PickCompute.ts b/src/io/picker/PickCompute.ts index cd4e23cd..ad0dfdc2 100644 --- a/src/io/picker/PickCompute.ts +++ b/src/io/picker/PickCompute.ts @@ -17,13 +17,12 @@ export class PickCompute { constructor() { } public init() { - let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); + let rtFrame = GBufferFrame.getGBufferFrame(GBufferFrame.colorPass_GBuffer); this._computeShader = new ComputeShader(Picker_cs); this._outBuffer = new ComputeGPUBuffer(32); this._computeShader.setStorageBuffer('outBuffer', this._outBuffer); - this._computeShader.setSamplerTexture('positionMap', rtFrame.getPositionMap()); - this._computeShader.setSamplerTexture('normalMap', rtFrame.getNormalMap()); + this._computeShader.setSamplerTexture('gBufferTexture', rtFrame.getCompressGBufferTexture()); } compute(view: View3D) { diff --git a/src/loader/LoaderBase.ts b/src/loader/LoaderBase.ts index b27c748e..3cdf6393 100644 --- a/src/loader/LoaderBase.ts +++ b/src/loader/LoaderBase.ts @@ -155,7 +155,7 @@ export class LoaderBase { } if (receivedArr.length > 0) { for (let i = 0; i < chunks.length; i++) { - // console.log(receivedArr[i]); + console.log(receivedArr[i]); if (loaderFunctions && loaderFunctions.onProgress) { loaderFunctions.onProgress.call(this, receivedArr[i], receivedLength, url); } diff --git a/src/loader/parser/gltf/GLTFMaterial.ts b/src/loader/parser/gltf/GLTFMaterial.ts new file mode 100644 index 00000000..fa1f3e95 --- /dev/null +++ b/src/loader/parser/gltf/GLTFMaterial.ts @@ -0,0 +1,25 @@ +import { Texture, Vector4 } from "../../.."; + +export class GLTFMaterial { + name: string + defines: string[]; + doubleSided: boolean; + baseColorFactor: [1, 1, 1, 1]; + emissiveFactor: number; + metallicFactor: number; + roughnessFactor: number; + alphaCutoff: number; + enableBlend: boolean; + baseColorTexture: Texture; + metallicRoughnessTexture: Texture; + normalTexture: Texture; + occlusionTexture: Texture; + emissiveTexture: Texture; + extensions: any; + baseMapOffsetSize: Vector4; + normalMapOffsetSize: Vector4; + emissiveMapOffsetSize: Vector4; + roughnessMapOffsetSize: Vector4; + metallicMapOffsetSize: Vector4; + aoMapOffsetSize: Vector4; +} \ No newline at end of file diff --git a/src/loader/parser/gltf/GLTFSubParserConverter.ts b/src/loader/parser/gltf/GLTFSubParserConverter.ts index b9eb2134..642f90e6 100644 --- a/src/loader/parser/gltf/GLTFSubParserConverter.ts +++ b/src/loader/parser/gltf/GLTFSubParserConverter.ts @@ -1,4 +1,4 @@ -import { LitMaterial, Material } from "../../.."; +import { GLTFMaterial, LitMaterial, Material } from "../../.."; import { Engine3D } from "../../../Engine3D"; import { SkeletonAnimationComponent } from "../../../components/SkeletonAnimationComponent"; import { DirectLight } from "../../../components/lights/DirectLight"; @@ -174,31 +174,54 @@ export class GLTFSubParserConverter { this.gltf.resources[materialKey] = newMat; // newMat.doubleSided newMat.name = md.name; - 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)); - if (`enableBlend` in primitive.material) { - if (primitive.material[`enableBlend`]) { - physicMaterial.blendMode = BlendMode.SOFT_ADD; + let gltfMat = md as GLTFMaterial; + if (gltfMat) { + const { baseColorTexture, baseColorFactor, metallicFactor, roughnessFactor, doubleSided, metallicRoughnessTexture, normalTexture, occlusionTexture, emissiveTexture, emissiveFactor, enableBlend, alphaCutoff } = gltfMat; + + let physicMaterial = (newMat = this.applyMaterialExtensions(gltfMat, newMat)); + if (`enableBlend` in gltfMat) { + if (gltfMat[`enableBlend`]) { + let defines = gltfMat.defines; + if (defines?.includes('ALPHA_BLEND')) { + physicMaterial.blendMode = BlendMode.ALPHA; + } else { + physicMaterial.blendMode = BlendMode.NORMAL; + } + physicMaterial.castShadow = false; } else { physicMaterial.blendMode = BlendMode.NONE; } } - if (`alphaCutoff` in primitive.material && alphaCutoff > 0 && alphaCutoff < 1) { + if (`alphaCutoff` in gltfMat && alphaCutoff > 0 && alphaCutoff < 1) { physicMaterial.setUniformFloat("alphaCutoff", alphaCutoff); physicMaterial.blendMode = BlendMode.NORMAL; physicMaterial.transparent = true; + // physicMaterial.castShadow = false; // physicMaterial.depthWriteEnabled = false; } - if (primitive.material.transformUV1) { - physicMaterial.setUniformVector4("uvTransform_1", primitive.material.transformUV1); + if (gltfMat.baseMapOffsetSize) { + physicMaterial.setUniformVector4("baseMapOffsetSize", gltfMat.baseMapOffsetSize); + } + if (gltfMat.normalMapOffsetSize) { + physicMaterial.setUniformVector4("normalMapOffsetSize", gltfMat.normalMapOffsetSize); + } + if (gltfMat.emissiveMapOffsetSize) { + physicMaterial.setUniformVector4("emissiveMapOffsetSize", gltfMat.emissiveMapOffsetSize); + } + if (gltfMat.roughnessMapOffsetSize) { + physicMaterial.setUniformVector4("roughnessMapOffsetSize", gltfMat.roughnessMapOffsetSize); + } + if (gltfMat.metallicMapOffsetSize) { + physicMaterial.setUniformVector4("metallicMapOffsetSize", gltfMat.metallicMapOffsetSize); } - if (primitive.material.transformUV2) { - physicMaterial.setUniformVector4("uvTransform_2", primitive.material.transformUV2); + if (gltfMat.aoMapOffsetSize) { + physicMaterial.setUniformVector4("aoMapOffsetSize", gltfMat.aoMapOffsetSize); } + + physicMaterial.setUniformColor("baseColor", new Color(baseColorFactor[0], baseColorFactor[1], baseColorFactor[2], baseColorFactor[3])); physicMaterial.setUniformFloat("roughness", roughnessFactor); physicMaterial.setUniformFloat("metallic", metallicFactor); @@ -218,7 +241,8 @@ export class GLTFSubParserConverter { } if (occlusionTexture && (metallicRoughnessTexture != occlusionTexture)) { - physicMaterial.setTexture("aoMap", occlusionTexture); + // physicMaterial.setTexture("aoMap", occlusionTexture); + // physicMaterial.shader.getDefaultColorShader().setDefine(`USE_AOTEX`, true); } if (emissiveTexture) { @@ -229,7 +253,15 @@ export class GLTFSubParserConverter { if (!physicMaterial.shader.getTexture("emissiveMap")) { physicMaterial.shader.setTexture("emissiveMap", Engine3D.res.whiteTexture); } + physicMaterial.shader.setDefine('USE_EMISSIVEMAP', true); physicMaterial.setUniformColor("emissiveColor", new Color(emissiveFactor[0], emissiveFactor[1], emissiveFactor[2], emissiveFactor[3])); + if (physicMaterial.blendMode != BlendMode.NONE) { + physicMaterial.blendMode = BlendMode.ADD; + } + let emissiveIntensity = mat.getUniformFloat('emissiveIntensity') + if (!emissiveIntensity || emissiveIntensity <= 0) { + mat.setUniformFloat('emissiveIntensity', 1.0); + } } } } @@ -359,6 +391,14 @@ export class GLTFSubParserConverter { } private createGeometryBase(name: string, attribArrays: any, primitive: any): GeometryBase { + if ('indices' in attribArrays) { + let bigIndices = attribArrays[`indices`].data.length > 65534; + if (bigIndices) { + attribArrays[`indices`].data = new Uint32Array(attribArrays[`indices`].data); + } else { + attribArrays[`indices`].data = new Uint16Array(attribArrays[`indices`].data); + } + } let geometry = new GeometryBase(); geometry.name = name; @@ -417,9 +457,11 @@ export class GLTFSubParserConverter { } private applyMaterialExtensions(dmaterial: any, mat: Material): Material { - KHR_materials_clearcoat.apply(this.gltf, dmaterial, mat); - KHR_materials_unlit.apply(this.gltf, dmaterial, mat); - KHR_materials_emissive_strength.apply(this.gltf, dmaterial, mat); + if (dmaterial.extensions) { + KHR_materials_clearcoat.apply(this.gltf, dmaterial, mat); + KHR_materials_unlit.apply(this.gltf, dmaterial, mat); + KHR_materials_emissive_strength.apply(this.gltf, dmaterial, mat); + } return mat; } diff --git a/src/loader/parser/gltf/GLTFSubParserMaterial.ts b/src/loader/parser/gltf/GLTFSubParserMaterial.ts index a6c161ff..aaed89ea 100644 --- a/src/loader/parser/gltf/GLTFSubParserMaterial.ts +++ b/src/loader/parser/gltf/GLTFSubParserMaterial.ts @@ -1,6 +1,7 @@ import { Engine3D } from "../../../Engine3D"; import { Vector4 } from "../../../math/Vector4"; import { GLTF_Info } from "./GLTFInfo"; +import { GLTFMaterial } from "./GLTFMaterial"; import { GLTFParser } from "./GLTFParser"; import { GLTFSubParser } from "./GLTFSubParser"; @@ -31,7 +32,7 @@ export class GLTFSubParserMaterial { return material.dmaterial; let { name, pbrMetallicRoughness, normalTexture, occlusionTexture, emissiveTexture, emissiveFactor, alphaMode, alphaCutoff, doubleSided, extensions } = material; - const dmaterial = { + const dmaterial: GLTFMaterial = { name, defines: [], doubleSided: !!doubleSided, @@ -44,9 +45,15 @@ export class GLTFSubParserMaterial { normalTexture: null, occlusionTexture: null, emissiveTexture: null, - transformUV1: null, - transformUV2: null, extensions: null, + baseMapOffsetSize: null, + normalMapOffsetSize: null, + emissiveMapOffsetSize: null, + roughnessMapOffsetSize: null, + metallicMapOffsetSize: null, + aoMapOffsetSize: null, + metallicFactor: 0, + roughnessFactor: 1 }; if (pbrMetallicRoughness) { @@ -64,12 +71,13 @@ export class GLTFSubParserMaterial { if (ext) { let KHR_texture_transform = ext.KHR_texture_transform; if (KHR_texture_transform) { - dmaterial.transformUV1 = new Vector4( + let offsetSize = new Vector4( KHR_texture_transform.offset ? KHR_texture_transform.offset[0] : 0.0, KHR_texture_transform.offset ? KHR_texture_transform.offset[1] : 0.0, KHR_texture_transform.scale ? KHR_texture_transform.scale[0] : 1.0, KHR_texture_transform.scale ? KHR_texture_transform.scale[1] : 1.0, ); + dmaterial.baseMapOffsetSize = offsetSize; } } const texture = await this.parseTexture(baseColorTexture.index); @@ -80,7 +88,44 @@ export class GLTFSubParserMaterial { } } + if (normalTexture) { + //extensions:{KHR_texture_transform: {…}} + let ext = normalTexture.extensions; + if (ext) { + let KHR_texture_transform = ext.KHR_texture_transform; + if (KHR_texture_transform) { + let offsetSize = new Vector4( + KHR_texture_transform.offset ? KHR_texture_transform.offset[0] : 0.0, + KHR_texture_transform.offset ? KHR_texture_transform.offset[1] : 0.0, + KHR_texture_transform.scale ? KHR_texture_transform.scale[0] : 1.0, + KHR_texture_transform.scale ? KHR_texture_transform.scale[1] : 1.0, + ); + dmaterial.normalMapOffsetSize = offsetSize; + } + } + const texture = await this.parseTexture(normalTexture.index); + if (texture) { + dmaterial.normalTexture = texture; + } else { + dmaterial.normalTexture = Engine3D.res.normalTexture; + } + } + if (metallicRoughnessTexture) { + let ext = metallicRoughnessTexture.extensions; + if (ext) { + let KHR_texture_transform = ext.KHR_texture_transform; + if (KHR_texture_transform) { + let offsetSize = new Vector4( + KHR_texture_transform.offset ? KHR_texture_transform.offset[0] : 0.0, + KHR_texture_transform.offset ? KHR_texture_transform.offset[1] : 0.0, + KHR_texture_transform.scale ? KHR_texture_transform.scale[0] : 1.0, + KHR_texture_transform.scale ? KHR_texture_transform.scale[1] : 1.0, + ); + dmaterial.roughnessMapOffsetSize = offsetSize; + } + } + const texture = await this.parseTexture(metallicRoughnessTexture.index); if (texture) { dmaterial.metallicRoughnessTexture = texture; diff --git a/src/loader/parser/gltf/extends/KHR_materials_emissive_strength.ts b/src/loader/parser/gltf/extends/KHR_materials_emissive_strength.ts index e47d6cb9..ba0760f8 100644 --- a/src/loader/parser/gltf/extends/KHR_materials_emissive_strength.ts +++ b/src/loader/parser/gltf/extends/KHR_materials_emissive_strength.ts @@ -6,7 +6,7 @@ export class KHR_materials_emissive_strength { public static apply(gltf: any, dmaterial: any, tMaterial: any) { let extensions = dmaterial.extensions; if (extensions && extensions[`KHR_materials_emissive_strength`]) { - tMaterial.emissiveIntensity = extensions[`KHR_materials_emissive_strength`].emissiveStrength * 0.5; + tMaterial.emissiveIntensity = extensions[`KHR_materials_emissive_strength`].emissiveStrength; if (tMaterial.emissiveMap == Engine3D.res.blackTexture) { tMaterial.emissiveMap = Engine3D.res.whiteTexture; } diff --git a/src/loader/parser/prefab/PrefabMaterialParser.ts b/src/loader/parser/prefab/PrefabMaterialParser.ts index 900e99b5..4e297d2f 100644 --- a/src/loader/parser/prefab/PrefabMaterialParser.ts +++ b/src/loader/parser/prefab/PrefabMaterialParser.ts @@ -23,7 +23,7 @@ export class PrefabMaterialParser extends ParserBase { let id = matBytes.readUTF(); let renderType = matBytes.readUTF(); let defines = matBytes.readStringArray(); - let uvTransform_1 = matBytes.readVector4(); + let transformUV1 = matBytes.readVector4(); let uvTransform_2 = matBytes.readVector4(); let shaderName = matBytes.readUTF(); let properties: KV[] = []; @@ -55,7 +55,7 @@ export class PrefabMaterialParser extends ParserBase { let mat = MaterialUtilities.GetMaterial(shaderName); mat.name = matName; - // mat.uvTransform_1 = uvTransform_1; + // mat.transformUV1 = transformUV1; // mat.uvTransform_2 = uvTransform_2; // mat.roughness = 1; // mat.metallic = 1; diff --git a/src/loader/parser/prefab/mats/shader/LitShader.ts b/src/loader/parser/prefab/mats/shader/LitShader.ts index c6612406..3e1f592f 100644 --- a/src/loader/parser/prefab/mats/shader/LitShader.ts +++ b/src/loader/parser/prefab/mats/shader/LitShader.ts @@ -26,7 +26,7 @@ export class LitShader extends Shader { shaderState.acceptGI = true; shaderState.useLight = true; this.setDefine('USE_BRDF', true); - this.setDefine('USE_AO_R', 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); diff --git a/src/loader/parser/prefab/mats/shader/ReflectionShader.ts b/src/loader/parser/prefab/mats/shader/ReflectionShader.ts new file mode 100644 index 00000000..10f44458 --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/ReflectionShader.ts @@ -0,0 +1,96 @@ +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"; + + +export class ReflectionShader extends Shader { + + constructor() { + super(); + let colorShader = new RenderShaderPass('ReflectionShader_shader', 'ReflectionShader_shader'); + 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/StandShader.ts b/src/loader/parser/prefab/mats/shader/StandShader.ts index 2dc3f3ea..ae3fc388 100644 --- a/src/loader/parser/prefab/mats/shader/StandShader.ts +++ b/src/loader/parser/prefab/mats/shader/StandShader.ts @@ -7,7 +7,6 @@ import { RegisterShader } from "../../../../../util/SerializeDecoration"; import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; -@RegisterShader export class StandShader extends Shader { constructor() { @@ -25,7 +24,7 @@ export class StandShader extends Shader { shaderState.acceptGI = true; shaderState.useLight = true; this.setDefine('USE_BRDF', true); - this.setDefine('USE_AO_R', 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); @@ -35,8 +34,7 @@ export class StandShader extends Shader { 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)); @@ -57,6 +55,14 @@ export class StandShader extends Shader { this.setUniformFloat(`clearcoatRoughnessFactor`, 0.0); this.setUniformColor(`clearcoatColor`, new Color(1, 1, 1)); this.setUniformFloat(`clearcoatWeight`, 0.0); + this.setUniformFloat(`clearcoatIor`, 1.5); + + this.setUniformVector4(`baseMapOffsetSize`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`normalMapOffsetSize`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`emissiveMapOffsetSize`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`roughnessMapOffsetSize`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`metallicMapOffsetSize`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`aoMapOffsetSize`, new Vector4(0, 0, 1, 1)); this.baseMap = Engine3D.res.whiteTexture; this.normalMap = Engine3D.res.normalTexture; @@ -122,14 +128,14 @@ export class StandShader extends Shader { /** * get transformUV1 */ - public get uvTransform_1(): Vector4 { + public get transformUV1(): Vector4 { return this.getDefaultColorShader().uniforms[`transformUV1`].vector4; } /** * set transformUV1 */ - public set uvTransform_1(value: Vector4) { + public set transformUV1(value: Vector4) { // this.getDefaultColorShader().uniforms[`transformUV1`].v4 = value; this.getDefaultColorShader().setUniform(`transformUV1`, value); } diff --git a/src/materials/BlendMode.ts b/src/materials/BlendMode.ts index 9806770f..f1cd092d 100644 --- a/src/materials/BlendMode.ts +++ b/src/materials/BlendMode.ts @@ -103,6 +103,7 @@ export class BlendFactor { case BlendMode.ALPHA: blend.color.srcFactor = `src-alpha`; blend.color.dstFactor = `one-minus-src-alpha`; + blend.color.operation = 'add'; // blend.alpha.srcFactor = `one`; // blend.alpha.dstFactor = `one`; diff --git a/src/materials/GlassMaterial.ts b/src/materials/GlassMaterial.ts index f4388a84..483c2cd2 100644 --- a/src/materials/GlassMaterial.ts +++ b/src/materials/GlassMaterial.ts @@ -4,7 +4,7 @@ import { GlassShader } from '../assets/shader/materials/GlassShader'; 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'; +import { PassType } from '../gfx/renderJob/passRenderer/state/PassType'; /** * GlassMaterial @@ -48,7 +48,7 @@ export class GlassMaterial extends Material { // 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.transformUV1 && (ret.transformUV1 = new Vector4().copyFrom(this.transformUV1)); // this.uvTransform_2 && (ret.uvTransform_2 = new Vector4().copyFrom(this.uvTransform_2)); // ret.baseColor = this.baseColor.clone(); // ret.emissiveColor = this.emissiveColor.clone(); diff --git a/src/materials/LitMaterial.ts b/src/materials/LitMaterial.ts index ae7128ba..227e1ee3 100644 --- a/src/materials/LitMaterial.ts +++ b/src/materials/LitMaterial.ts @@ -1,3 +1,4 @@ +import { Vector4 } from ".."; import { Engine3D } from "../Engine3D"; import { Texture } from "../gfx/graphics/webGpu/core/texture/Texture"; import { RenderShaderPass } from "../gfx/graphics/webGpu/shader/RenderShaderPass"; @@ -22,8 +23,7 @@ export class LitMaterial extends Material { 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`)); @@ -44,12 +44,21 @@ export class LitMaterial extends Material { colorPass.setUniform(`clearcoatRoughnessFactor`, sourceShader.getUniform(`clearcoatRoughnessFactor`)); colorPass.setUniform(`clearcoatColor`, sourceShader.getUniform(`clearcoatColor`)); colorPass.setUniform(`clearcoatWeight`, sourceShader.getUniform(`clearcoatWeight`)); + colorPass.setUniform(`clearcoatIor`, sourceShader.getUniform(`clearcoatIor`)); 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`)); + colorPass.setTexture(`empty`, sourceShader.getTexture(`empty`)); + + colorPass.setUniform(`baseMapOffsetSize`, sourceShader.getUniform(`baseMapOffsetSize`)); + colorPass.setUniform(`normalMapOffsetSize`, sourceShader.getUniform(`normalMapOffsetSize`)); + colorPass.setUniform(`emissiveMapOffsetSize`, sourceShader.getUniform(`emissiveMapOffsetSize`)); + colorPass.setUniform(`roughnessMapOffsetSize`, sourceShader.getUniform(`roughnessMapOffsetSize`)); + colorPass.setUniform(`metallicMapOffsetSize`, sourceShader.getUniform(`metallicMapOffsetSize`)); + colorPass.setUniform(`aoMapOffsetSize`, sourceShader.getUniform(`aoMapOffsetSize`)); return litMaterial; } @@ -141,6 +150,15 @@ export class LitMaterial extends Material { return this.shader.getUniformFloat(`clearcoatRoughnessFactor`); } + public set ior(value: number) { + this.shader.setUniformFloat(`clearcoatIor`, value); + } + + public get ior() { + return this.shader.getUniformFloat(`clearcoatIor`); + } + + public set alphaCutoff(value: number) { this.shader.setUniform(`alphaCutoff`, value); } diff --git a/src/materials/Material.ts b/src/materials/Material.ts index b01dfab3..b2aa4999 100644 --- a/src/materials/Material.ts +++ b/src/materials/Material.ts @@ -2,7 +2,7 @@ import { StorageGPUBuffer } from "../gfx/graphics/webGpu/core/buffer/StorageGPUB 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 { PassType } from "../gfx/renderJob/passRenderer/state/PassType"; import { Shader } from "../gfx/graphics/webGpu/shader/Shader"; import { Color } from "../math/Color"; import { Vector2 } from "../math/Vector2"; @@ -74,6 +74,14 @@ export class Material { } } + public get castReflection(): boolean { + return this._defaultSubShader.shaderState.castReflection; + } + + public set castReflection(value: boolean) { + this._defaultSubShader.shaderState.castReflection = value; + } + public get blendMode(): BlendMode { return this._defaultSubShader.blendMode; } diff --git a/src/materials/PhysicMaterial.ts b/src/materials/PhysicMaterial.ts index 856a825d..35e9028e 100644 --- a/src/materials/PhysicMaterial.ts +++ b/src/materials/PhysicMaterial.ts @@ -36,8 +36,6 @@ export class PhysicMaterial extends Material { public setDefault() { 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)); @@ -54,10 +52,19 @@ export class PhysicMaterial extends Material { colorPass.setUniformFloat(`emissiveIntensity`, 0.0); colorPass.setUniformFloat(`alphaCutoff`, 0.0); colorPass.setUniformFloat(`ior`, 1.5); + colorPass.setUniformFloat(`empty`, 1.5); colorPass.setUniformFloat(`clearcoatFactor`, 0.0); colorPass.setUniformFloat(`clearcoatRoughnessFactor`, 0.0); colorPass.setUniformColor(`clearcoatColor`, new Color(1, 1, 1)); colorPass.setUniformFloat(`clearcoatWeight`, 0.0); + colorPass.setUniformFloat(`empty`, 0.0); + + colorPass.setUniformVector4(`baseMapOffsetSize`, new Vector4(0, 0, 1, 1)); + colorPass.setUniformVector4(`normalMapOffsetSize`, new Vector4(0, 0, 1, 1)); + colorPass.setUniformVector4(`emissiveMapOffsetSize`, new Vector4(0, 0, 1, 1)); + colorPass.setUniformVector4(`roughnessMapOffsetSize`, new Vector4(0, 0, 1, 1)); + colorPass.setUniformVector4(`metallicMapOffsetSize`, new Vector4(0, 0, 1, 1)); + colorPass.setUniformVector4(`aoMapOffsetSize`, new Vector4(0, 0, 1, 1)); } @@ -120,31 +127,57 @@ export class PhysicMaterial extends Material { /** * get transformUV1 */ - public get uvTransform_1(): Vector4 { - return this.shader.getDefaultColorShader().uniforms[`transformUV1`].vector4; + public get baseMapUVOffsetSize(): Vector4 { + return this.shader.getDefaultColorShader().uniforms[`baseMapOffsetSize`].vector4; + } + + /** + * set transformUV1 + */ + public set baseMapUVOffsetSize(value: Vector4) { + this.shader.getDefaultColorShader().setUniform(`baseMapOffsetSize`, value); + } + + /** + * get transformUV1 + */ + public get normalMapUVOffsetSize(): Vector4 { + return this.shader.getDefaultColorShader().uniforms[`normalMapOffsetSize`].vector4; } /** * set transformUV1 */ - public set uvTransform_1(value: Vector4) { - // this.shader.getDefaultColorShader().uniforms[`transformUV1`].v4 = value; - this.shader.getDefaultColorShader().setUniform(`transformUV1`, value); + public set normalMapUVOffsetSize(value: Vector4) { + this.shader.getDefaultColorShader().setUniform(`normalMapOffsetSize`, value); } /** - * get transformUV2 + * get transformUV1 */ - public get uvTransform_2(): Vector4 { - return this.shader.getDefaultColorShader().uniforms[`transformUV2`].vector4; + public get emissiveMapUVOffsetSize(): Vector4 { + return this.shader.getDefaultColorShader().uniforms[`emissiveMapOffsetSize`].vector4; } /** - * set transformUV2 + * set transformUV1 + */ + public set emissiveMapUVOffsetSize(value: Vector4) { + this.shader.getDefaultColorShader().setUniform(`emissiveMapOffsetSize`, value); + } + + /** + * get transformUV1 + */ + public get pbrMetallicMapUVOffsetSize(): Vector4 { + return this.shader.getDefaultColorShader().uniforms[`roughnessMapOffsetSize`].vector4; + } + + /** + * set transformUV1 */ - public set uvTransform_2(value: Vector4) { - // this.shader.getDefaultColorShader().uniforms[`transformUV2`].v4 = value; - this.shader.getDefaultColorShader().setUniform(`transformUV2`, value); + public set pbrMetallicMapUVOffsetSize(value: Vector4) { + this.shader.getDefaultColorShader().setUniform(`roughnessMapOffsetSize`, value); } public get depthWriteEnabled(): boolean { diff --git a/src/materials/ReflectionMaterial.ts b/src/materials/ReflectionMaterial.ts new file mode 100644 index 00000000..e957d958 --- /dev/null +++ b/src/materials/ReflectionMaterial.ts @@ -0,0 +1,69 @@ +import { Engine3D } from '../Engine3D'; +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 { Material } from './Material'; +import { PassType } from '../gfx/renderJob/passRenderer/state/PassType'; +import { Shader, UnLitShader } from '..'; +import { ReflectionShader } from '../loader/parser/prefab/mats/shader/ReflectionShader'; + +/** + * Unlit Mateiral + * A non glossy surface material without specular highlights. + * @group Material + */ +export class ReflectionMaterial extends Material { + /** + * @constructor + */ + constructor() { + super(); + this.shader = new ReflectionShader(); + // default value + this.baseMap = Engine3D.res.whiteTexture; + this.setDefine("USE_CUSTOMUNIFORM", true); + this.reflectionIndex = 0; + } + + 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); + } + + public set reflectionIndex(i: number) { + this.shader.setUniformFloat(`reflectionIndex`, i); + } + + /** + * 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/SkyMaterial.ts b/src/materials/SkyMaterial.ts index f8f807fa..7540faa7 100644 --- a/src/materials/SkyMaterial.ts +++ b/src/materials/SkyMaterial.ts @@ -1,6 +1,6 @@ import { Engine3D } from "../Engine3D"; import { Texture } from "../gfx/graphics/webGpu/core/texture/Texture"; -import { PassType } from "../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../gfx/renderJob/passRenderer/state/PassType"; import { SkyShader } from "../loader/parser/prefab/mats/shader/SkyShader"; import { Vector3 } from "../math/Vector3"; import { Material } from "./Material"; diff --git a/src/materials/UnLitMaterial.ts b/src/materials/UnLitMaterial.ts index ac508c98..e22212d9 100644 --- a/src/materials/UnLitMaterial.ts +++ b/src/materials/UnLitMaterial.ts @@ -4,7 +4,7 @@ import { RenderShaderPass } from '../gfx/graphics/webGpu/shader/RenderShaderPass import { Color } from '../math/Color'; import { Vector4 } from '../math/Vector4'; import { Material } from './Material'; -import { PassType } from '../gfx/renderJob/passRenderer/state/RendererType'; +import { PassType } from '../gfx/renderJob/passRenderer/state/PassType'; import { Shader, UnLitShader } from '..'; /** diff --git a/src/materials/multiPass/CastPointShadowMaterialPass.ts b/src/materials/multiPass/CastPointShadowMaterialPass.ts index e7b5903b..3f04de2f 100644 --- a/src/materials/multiPass/CastPointShadowMaterialPass.ts +++ b/src/materials/multiPass/CastPointShadowMaterialPass.ts @@ -1,5 +1,5 @@ import { RenderShaderPass } from "../../gfx/graphics/webGpu/shader/RenderShaderPass"; -import { PassType } from "../../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../../gfx/renderJob/passRenderer/state/PassType"; import { Vector3 } from "../../math/Vector3"; /** diff --git a/src/materials/multiPass/CastShadowMaterialPass.ts b/src/materials/multiPass/CastShadowMaterialPass.ts index 97b3047d..72f23e97 100644 --- a/src/materials/multiPass/CastShadowMaterialPass.ts +++ b/src/materials/multiPass/CastShadowMaterialPass.ts @@ -1,5 +1,5 @@ import { RenderShaderPass } from '../../gfx/graphics/webGpu/shader/RenderShaderPass'; -import { PassType } from '../../gfx/renderJob/passRenderer/state/RendererType'; +import { PassType } from '../../gfx/renderJob/passRenderer/state/PassType'; import { Vector3 } from '../../math/Vector3'; /** diff --git a/src/materials/multiPass/GBufferPass.ts b/src/materials/multiPass/GBufferPass.ts index 8765f466..1807e0bc 100644 --- a/src/materials/multiPass/GBufferPass.ts +++ b/src/materials/multiPass/GBufferPass.ts @@ -2,7 +2,7 @@ import { Color } from '../../math/Color'; import { BlendMode } from '../BlendMode'; import { Engine3D } from '../../Engine3D'; import { RenderShaderPass } from '../../gfx/graphics/webGpu/shader/RenderShaderPass'; -import { PassType } from '../..'; +import { PassType } from '../../gfx/renderJob/passRenderer/state/PassType'; /** * @internal diff --git a/src/materials/multiPass/SkyGBufferPass.ts b/src/materials/multiPass/SkyGBufferPass.ts index 33d30cd0..63e8f122 100644 --- a/src/materials/multiPass/SkyGBufferPass.ts +++ b/src/materials/multiPass/SkyGBufferPass.ts @@ -1,7 +1,7 @@ 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'; +import { PassType } from '../../gfx/renderJob/passRenderer/state/PassType'; /** * @internal diff --git a/src/math/Color.ts b/src/math/Color.ts index ce917fcb..2152539f 100644 --- a/src/math/Color.ts +++ b/src/math/Color.ts @@ -345,7 +345,7 @@ export class Color { ret.g = (c2.g - c1.g) * v + c1.g; ret.b = (c2.b - c1.b) * v + c1.b; ret.a = (c2.a - c1.a) * v + c1.a; - return target; + return ret; } diff --git a/src/math/ColorGradient.ts b/src/math/ColorGradient.ts new file mode 100644 index 00000000..3ad4a141 --- /dev/null +++ b/src/math/ColorGradient.ts @@ -0,0 +1,21 @@ +import { Color } from "./Color"; + +export class ColorGradient { + private colorArray: Color[]; + + public constructor(array: Color[]) { + this.colorArray = array; + } + + public getColor(p: number) { + let s = p * this.colorArray.length; + let i = Math.floor(s); + let k = Math.min(i + 1, this.colorArray.length - 1); + + let c1 = this.colorArray[i]; + let c2 = this.colorArray[k]; + + return Color.lerp(s - i, c1, c2); + } + +} \ No newline at end of file diff --git a/src/setting/EngineSetting.ts b/src/setting/EngineSetting.ts index 932afe8e..209adc37 100644 --- a/src/setting/EngineSetting.ts +++ b/src/setting/EngineSetting.ts @@ -1,3 +1,4 @@ +import { ReflectionSetting } from ".."; import { GlobalIlluminationSetting } from "./GlobalIlluminationSetting"; import { LightSetting } from "./LightSetting"; import { LoaderSetting } from "./LoaderSetting"; @@ -54,4 +55,9 @@ export type EngineSetting = { * loader setting */ loader: LoaderSetting; + + /** + * reflectionSetting setting + */ + reflectionSetting: ReflectionSetting } \ No newline at end of file diff --git a/src/setting/ReflectionSetting.ts b/src/setting/ReflectionSetting.ts new file mode 100644 index 00000000..1a0ccc76 --- /dev/null +++ b/src/setting/ReflectionSetting.ts @@ -0,0 +1,10 @@ +export type ReflectionSetting = { + + reflectionProbeSize: number; + reflectionProbeMaxCount: number; + + width: number; + height: number; + + enable: boolean; +} \ No newline at end of file diff --git a/src/setting/RenderSetting.ts b/src/setting/RenderSetting.ts index d86f95a7..34692434 100644 --- a/src/setting/RenderSetting.ts +++ b/src/setting/RenderSetting.ts @@ -25,6 +25,7 @@ export type RenderSetting = { drawTrMax: number; zPrePass: boolean; useLogDepth: boolean; + useCompressGBuffer: boolean; gi: boolean; /** * post effect @@ -42,6 +43,7 @@ export type RenderSetting = { ssr?: SSRSetting; taa?: TAASetting; gtao?: GTAOSetting; + ssgi?: GTAOSetting; outline?: OutlineSetting; globalFog?: GlobalFogSetting; godRay?: GodRaySetting; diff --git a/src/setting/post/BloomSetting.ts b/src/setting/post/BloomSetting.ts index 11b75e6e..6cbf1eb3 100644 --- a/src/setting/post/BloomSetting.ts +++ b/src/setting/post/BloomSetting.ts @@ -12,4 +12,5 @@ export type BloomSetting = { upSampleBlurSigma: number; luminanceThreshole: number; bloomIntensity: number; + hdr: number; }; \ No newline at end of file diff --git a/src/setting/post/SSGISetting.ts b/src/setting/post/SSGISetting.ts new file mode 100644 index 00000000..fda99111 --- /dev/null +++ b/src/setting/post/SSGISetting.ts @@ -0,0 +1,8 @@ + +/** + * Setting of GTAO + * @group Setting + */ +export type SSGISetting = { + enable: boolean; +}; \ No newline at end of file diff --git a/src/shape/SphereGeometry.ts b/src/shape/SphereGeometry.ts index 53913108..2ea5a44c 100644 --- a/src/shape/SphereGeometry.ts +++ b/src/shape/SphereGeometry.ts @@ -85,13 +85,13 @@ export class SphereGeometry extends GeometryBase { let ui = 0; for (j = 0; j <= _segmentsH; ++j) { var horAngle: number = (Math.PI * j) / _segmentsH; - var z: number = -_radius * Math.cos(horAngle); + var y: number = _radius * Math.cos(horAngle); var ringRadius: number = _radius * Math.sin(horAngle); for (i = 0; i <= _segmentsW; ++i) { var verAngle: number = (2 * Math.PI * i) / _segmentsW; var x: number = ringRadius * Math.cos(verAngle); - var y: number = ringRadius * Math.sin(verAngle); + var z: number = ringRadius * Math.sin(verAngle); var normLen: number = 1 / Math.sqrt(x * x + y * y + z * z); let index = i * _segmentsW + j; position_arr[pi++] = x; @@ -103,7 +103,7 @@ export class SphereGeometry extends GeometryBase { normal_arr[ni++] = z * normLen; uv_arr[ui++] = i / _segmentsW; - uv_arr[ui++] = 1.0 - j / _segmentsH; + uv_arr[ui++] = j / _segmentsH; if (i > 0 && j > 0) { var a: number = (_segmentsW + 1) * j + i; diff --git a/src/textures/RenderTexture.ts b/src/textures/RenderTexture.ts index 26277ec6..4738656b 100644 --- a/src/textures/RenderTexture.ts +++ b/src/textures/RenderTexture.ts @@ -48,14 +48,13 @@ export class RenderTexture extends Texture { this.resize(width, height); - if (autoResize) { + if (this.autoResize) { webGPUContext.addEventListener(CResizeEvent.RESIZE, (e) => { let { width, height } = e.data; this.resize(width, height); this._textureChange = true; }, this); } - } public resize(width, height) { @@ -112,7 +111,7 @@ export class RenderTexture extends Texture { this.minFilter = 'linear'; this.magFilter = 'linear'; this.mipmapFilter = `linear`; - this.maxAnisotropy = 16; + // this.maxAnisotropy = 16; this.addressModeU = GPUAddressMode.clamp_to_edge; this.addressModeV = GPUAddressMode.clamp_to_edge; diff --git a/src/textures/VirtualTexture.ts b/src/textures/VirtualTexture.ts index de342f78..d134890d 100644 --- a/src/textures/VirtualTexture.ts +++ b/src/textures/VirtualTexture.ts @@ -30,7 +30,7 @@ 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?: GPUFlagsConstant, numberLayer: number = 1, sampleCount: number = 0, clear: boolean = true) { + constructor(width: number, height: number, format: GPUTextureFormat = GPUTextureFormat.rgba8unorm, useMipMap: boolean = false, usage?: GPUFlagsConstant, numberLayer: number = 1, sampleCount: number = 0, mipmapCount: number = 1) { super(width, height, numberLayer); let device = webGPUContext.device; this.name = UUID(); @@ -39,6 +39,7 @@ export class VirtualTexture extends Texture { this.sampleCount = sampleCount; this.format = format; this.numberLayer = numberLayer; + this.mipmapCount = mipmapCount; if (usage != undefined) { this.usage = usage; @@ -59,7 +60,7 @@ export class VirtualTexture extends Texture { this.width = width; this.height = height; - this.createTextureDescriptor(width, height, 1, this.format, this.usage, this.numberLayer, this.sampleCount); + this.createTextureDescriptor(width, height, this.mipmapCount, this.format, this.usage, this.numberLayer, this.sampleCount); this.useMipmap = false; this.visibility = GPUShaderStage.COMPUTE | GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT; @@ -95,13 +96,17 @@ export class VirtualTexture extends Texture { if (this.sampleCount > 0) { this.textureBindingLayout.multisampled = true; } - this.minFilter = 'linear'; + // this.minFilter = 'linear'; + // this.magFilter = 'linear'; + + 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.mipmapFilter = `nearest`; + this.maxAnisotropy = 1; + + this.addressModeU = GPUAddressMode.mirror_repeat; + this.addressModeV = GPUAddressMode.mirror_repeat; this.gpuSampler = device.createSampler(this); } diff --git a/src/util/DelayUtil.ts b/src/util/DelayUtil.ts new file mode 100644 index 00000000..261a773a --- /dev/null +++ b/src/util/DelayUtil.ts @@ -0,0 +1,26 @@ +export let setTimeDelay = async function (ms: number) { + + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve(true); + }, ms); + }) + +}; + + +export let setFrameDelay = async function (frame: number) { + return new Promise((resolve, reject) => { + frame = Math.max(1, frame); + let callback = function () { + if (frame < 0) { + resolve(true); + } else { + requestAnimationFrame(callback); + } + frame--; + } + requestAnimationFrame(callback); + }) + +}; \ No newline at end of file diff --git a/src/util/Object3DUtil.ts b/src/util/Object3DUtil.ts index 66e1c663..ecfdbb6e 100644 --- a/src/util/Object3DUtil.ts +++ b/src/util/Object3DUtil.ts @@ -4,21 +4,34 @@ import { BoxGeometry } from '../shape/BoxGeometry'; import { SphereGeometry } from '../shape/SphereGeometry'; import { LitMaterial } from '../materials/LitMaterial'; import { Color } from '../math/Color'; -import { Material } from '..'; +import { PointLight } from '../components/lights/PointLight'; +import { PlaneGeometry } from '../shape/PlaneGeometry'; +import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; +import { Vector3 } from '../math/Vector3'; +import { BlendMode } from '../materials/BlendMode'; +import { Material } from '../materials/Material'; export class Object3DUtil { private static boxGeo: BoxGeometry; + private static planeGeo: PlaneGeometry; private static sphere: SphereGeometry; private static material: LitMaterial; + private static materialMap: Map; + private static initHeap() { if (!this.boxGeo) this.boxGeo = new BoxGeometry(); + if (!this.planeGeo) + this.planeGeo = new PlaneGeometry(1, 1, 1, 1, Vector3.UP); if (!this.sphere) this.sphere = new SphereGeometry(1, 35, 35); if (!this.material) { this.material = new LitMaterial(); } + if (!this.materialMap) { + this.materialMap = new Map(); + } } public static get CubeMesh() { @@ -33,7 +46,6 @@ export class Object3DUtil { public static GetCube() { this.initHeap(); - let obj = new Object3D(); let renderer = obj.addComponent(MeshRenderer); renderer.geometry = this.boxGeo; @@ -42,6 +54,30 @@ export class Object3DUtil { return obj; } + public static GetMaterial(tex: Texture) { + let mat = this.materialMap.get(tex); + if (!mat) { + mat = new LitMaterial(); + mat.baseMap = tex; + this.materialMap.set(tex, mat); + } + return mat.clone(); + } + + public static GetPlane(tex: Texture) { + this.initHeap(); + let obj = new Object3D(); + let renderer = obj.addComponent(MeshRenderer); + renderer.geometry = this.planeGeo; + let cloneMat = this.GetMaterial(tex); + cloneMat.blendMode = BlendMode.ADD; + cloneMat.castShadow = false; + renderer.material = cloneMat; + renderer.castGI = false; + renderer.castReflection = false; + return obj; + } + public static GetSingleCube(sizeX: number, sizeY: number, sizeZ: number, r: number, g: number, b: number) { this.initHeap(); @@ -92,4 +128,21 @@ export class Object3DUtil { renderer.material = mat; return obj; } + + public static GetPointLight(pos: Vector3, rotation: Vector3, radius: number, r: number, g: number, b: number, intensity: number = 1, castShadow: boolean = true) { + let lightObj = new Object3D(); + let light = lightObj.addComponent(PointLight); + light.lightColor = new Color(r, g, b, 1); + light.intensity = intensity; + light.range = radius; + light.at = 8; + light.radius = 0; + light.castShadow = castShadow; + lightObj.localPosition = pos; + lightObj.localRotation = rotation; + + let sp = this.GetSingleSphere(0.1, 1, 1, 1); + lightObj.addChild(sp); + return light; + } } diff --git a/src/util/ProfilerUtil.ts b/src/util/ProfilerUtil.ts index a79a9f07..4b29a326 100644 --- a/src/util/ProfilerUtil.ts +++ b/src/util/ProfilerUtil.ts @@ -1,99 +1,187 @@ +import { View3D } from "../core/View3D" +import { PassType } from "../gfx/renderJob/passRenderer/state/PassType" + export type ProfilerLabel2 = { - lable:string , - start:number , - end:number , - total:number , - count:number , + lable: string, + start: number, + end: number, + total: number, + count: number, } export type ProfilerLabel = { - lable:string , - start:number , - end:number , - total:number , - count:number , - child:Map + lable: string, + start: number, + end: number, + total: number, + count: number, + child: Map +} + +export type ProfilerDraw = { + [key: string]: { + vertexCount: number, + indicesCount: number, + triCount: number, + instanceCount: number, + drawCount: number, + pipelineCount: number, + } } export class ProfilerUtil { - private static profilerLabelMap:Map = new Map(); - public static start(id:string){ + private static profilerLabelMap: Map = new Map(); + + public static viewMap: Map = new Map(); + + public static testObj = { + testValue1: 0, + testValue2: 0, + testValue3: 0, + testValue4: 0, + } + + public static startView(view: View3D) { + let countInfo = this.viewMap.get(view); + if (!countInfo) { + countInfo = {} + for (const key in PassType) { + let i = parseInt(key); + if (i >= 0) { + } else { + countInfo[key] = { + vertexCount: 0, + indicesCount: 0, + instanceCount: 0, + triCount: 0, + drawCount: 0, + pipelineCount: 0 + } + } + } + this.viewMap.set(view, countInfo) + } + + for (const key in PassType) { + let i = parseInt(key); + if (i >= 0) { + } else { + countInfo[key].vertexCount = 0; + countInfo[key].indicesCount = 0; + countInfo[key].triCount = 0; + countInfo[key].instanceCount = 0; + countInfo[key].drawCount = 0; + countInfo[key].pipelineCount = 0; + } + } + } + + public static viewCount(view: View3D): ProfilerDraw { + this.startView(view); + return this.viewMap.get(view); + } + + public static viewCount_vertex(view: View3D, pass: string, v: number) { + this.viewMap.get(view)[pass].vertexCount += v; + } + + public static viewCount_indices(view: View3D, pass: string, v: number) { + this.viewMap.get(view)[pass].indicesCount += v; + } + + public static viewCount_tri(view: View3D, pass: string, v: number) { + this.viewMap.get(view)[pass].triCount += v; + } + + public static viewCount_instance(view: View3D, pass: string, v: number) { + this.viewMap.get(view)[pass].instanceCount += v; + } + + public static viewCount_draw(view: View3D, pass: string) { + this.viewMap.get(view)[pass].drawCount++; + } + + public static viewCount_pipeline(view: View3D, pass: string) { + this.viewMap.get(view)[pass].pipelineCount++; + } + + public static start(id: string) { let profilerLabel = this.profilerLabelMap.get(id); - if(!profilerLabel){ + if (!profilerLabel) { profilerLabel = { - lable : id , - start : 0 , - end : 0, - total: 0 , - count : 0 , - child :new Map() + lable: id, + start: 0, + end: 0, + total: 0, + count: 0, + child: new Map() } - this.profilerLabelMap.set(id,profilerLabel); + this.profilerLabelMap.set(id, profilerLabel); } - profilerLabel.start = performance.now() ; - profilerLabel.end = performance.now() ; - profilerLabel.count = 0 ; + profilerLabel.start = performance.now(); + profilerLabel.end = performance.now(); + profilerLabel.count = 0; profilerLabel.child.clear(); } - public static end( id:string ){ + public static end(id: string) { let profilerLabel = this.profilerLabelMap.get(id); - if(profilerLabel){ - profilerLabel.end = performance.now() ; - profilerLabel.total = profilerLabel.end - profilerLabel.start ; + if (profilerLabel) { + profilerLabel.end = performance.now(); + profilerLabel.total = profilerLabel.end - profilerLabel.start; } } - public static countStart( id:string , id2:string = "" ){ + public static countStart(id: string, id2: string = "") { let profilerLabel = this.profilerLabelMap.get(id); - if(profilerLabel){ - profilerLabel.count++ ; - if(id2 != "" ){ + if (profilerLabel) { + profilerLabel.count++; + if (id2 != "") { let node = profilerLabel.child.get(id2); - if(!node){ + if (!node) { node = { - lable : id2 , - start : 0 , - end : 0, - total: 0 , - count : 0 , + lable: id2, + start: 0, + end: 0, + total: 0, + count: 0, } } - node.start = performance.now() ; - node.end = performance.now() ; - node.count = 0 ; - profilerLabel.child.set(id2,node); + node.start = performance.now(); + node.end = performance.now(); + node.count = 0; + profilerLabel.child.set(id2, node); } } } - public static countEnd( id:string , id2:string ){ + public static countEnd(id: string, id2: string) { let profilerLabel = this.profilerLabelMap.get(id); - if(profilerLabel){ - if(id2 != "" ){ + if (profilerLabel) { + if (id2 != "") { let node = profilerLabel.child.get(id2); - if(!node){ + if (!node) { node = { - lable : id2 , - start : 0 , - end : 0, - total: 0 , - count : 0 , + lable: id2, + start: 0, + end: 0, + total: 0, + count: 0, } } - node.end = performance.now() ; - node.total = node.end - node.start ; - node.count++ ; + node.end = performance.now(); + node.total = node.end - node.start; + node.count++; } } } - public static print(id:string){ + public static print(id: string) { let profilerLabel = this.profilerLabelMap.get(id); - if(profilerLabel){ - console.log( "performance" , id , profilerLabel.total + " ms" ); + if (profilerLabel) { + console.log("performance", id, profilerLabel.total + " ms"); } } } diff --git a/src/util/transformUtil/Object3DTransformTools.ts b/src/util/transformUtil/Object3DTransformTools.ts new file mode 100644 index 00000000..64ac4028 --- /dev/null +++ b/src/util/transformUtil/Object3DTransformTools.ts @@ -0,0 +1,178 @@ +import { TransformControllerBaseComponent } from "./TransformControllerBaseComponent"; +import { ScaleControlComponents } from "./ScaleControlComponents"; +import { TransformMode } from "./TransformMode"; +import { TransformSpaceMode } from "./TransformSpaceMode"; +import { Object3D } from "../../core/entities/Object3D"; +import { RotationControlComponents } from "./RotationControlComponents"; +import { TranslationControlComponents } from "./TranslationControlComponents"; +import { Scene3D } from "../../core/Scene3D"; +import { KeyEvent } from "../../event/eventConst/KeyEvent"; +import { PointerEvent3D } from "../../event/eventConst/PointerEvent3D"; +import { Engine3D } from "../../Engine3D"; +import { KeyCode } from "../../event/KeyCode"; + + + + + + + +/** + * Object3D transform controller + * @group Controller + */ +export class Object3DTransformTools extends Object3D { + private static _instance: Object3DTransformTools; + public static get instance(): Object3DTransformTools { + if (!this._instance) { + this._instance = new Object3DTransformTools(); + } + return this._instance; + } + + protected mTarget: Object3D; + protected mTransformMode = TransformMode.NONE; + protected mTransformSpaceType = TransformSpaceMode.Global; + protected mControllers: TransformControllerBaseComponent[]; + public mXObj: Object3D; + public mYObj: Object3D; + public mZObj: Object3D; + constructor() { + super(); + this.mControllers = [null, null, null]; + this.mControllers[TransformMode.Scale] = this.addComponent(ScaleControlComponents); + this.mControllers[TransformMode.Rotation] = this.addComponent(RotationControlComponents); + this.mControllers[TransformMode.Translation] = this.addComponent(TranslationControlComponents); + this.mControllers[TransformMode.Scale].enable = false; + this.mControllers[TransformMode.Rotation].enable = false; + this.mControllers[TransformMode.Translation].enable = false; + + this.mXObj = new Object3D(); + this.mYObj = new Object3D(); + this.mZObj = new Object3D(); + + this.mXObj.addChild(this.mYObj); + this.mYObj.addChild(this.mZObj); + } + + public get transformMode(): TransformMode { + return this.mTransformMode; + } + + public get transformSpaceMode(): TransformSpaceMode { + return this.mTransformSpaceType; + } + + public active(scene: Scene3D) { + scene.addChild(this); + scene.addChild(this.mXObj); + } + + public unActive(scene: Scene3D) { + scene.removeChild(this); + } + + public get target(): Object3D { + return this.mTarget; + } + + public selectObject(obj: Object3D, transformMode?: TransformMode, spaceMode?: TransformSpaceMode) { + if (this.mTarget != obj) { + if (obj) { + // obj.addChild(this); + this.activate(); + } else { + // this.mTarget.removeChild(this); + this.unactivate(); + } + this.mTarget = obj; + this.mXObj.localPosition = obj.transform.worldPosition.clone(); + } + if (transformMode != undefined) { + this.selectTransformMode(transformMode); + } + if (spaceMode != undefined) { + this.selectTransformSpaceMode(spaceMode); + } + } + + public selectTransformMode(transformMode: TransformMode) { + if (this.mTransformMode == transformMode) + return; + if (this.mTransformMode != TransformMode.NONE) + this.mControllers[this.mTransformMode].enable = false; + + this.mTransformMode = transformMode; + + if (this.mTransformMode != TransformMode.NONE) + this.mControllers[this.mTransformMode].enable = true; + } + + public selectTransformSpaceMode(spaceMode: TransformSpaceMode) { + if (this.mTransformSpaceType == spaceMode) + return; + this.mTransformSpaceType = spaceMode; + + if (this.mTransformMode != TransformMode.NONE) + this.mControllers[this.mTransformMode].reset(); + } + + protected activate() { + Engine3D.inputSystem.addEventListener(KeyEvent.KEY_DOWN, this.onKeyDown, this); + Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_DOWN, this.onMouseDown, this, null, 99999); + Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_MOVE, this.onMouseMove, this, null, 99999); + Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_UP, this.onMouseUp, this, null, 99999); + } + + protected unactivate() { + Engine3D.inputSystem.removeEventListener(KeyEvent.KEY_DOWN, this.onKeyDown, this); + Engine3D.inputSystem.removeEventListener(PointerEvent3D.POINTER_DOWN, this.onMouseDown, this); + Engine3D.inputSystem.removeEventListener(PointerEvent3D.POINTER_MOVE, this.onMouseMove, this); + Engine3D.inputSystem.removeEventListener(PointerEvent3D.POINTER_UP, this.onMouseUp, this); + } + + protected onKeyDown(e: KeyEvent) { + switch (e.keyCode) { + case KeyCode.Key_R: + this.selectTransformMode(TransformMode.Scale); + this.selectTransformSpaceMode(TransformSpaceMode.Local); + break; + case KeyCode.Key_E: + this.selectTransformMode(TransformMode.Rotation); + this.selectTransformSpaceMode(TransformSpaceMode.Global); + break; + case KeyCode.Key_W: + this.selectTransformMode(TransformMode.Translation); + this.selectTransformSpaceMode(TransformSpaceMode.Global); + break; + case KeyCode.Key_A: + this.selectTransformSpaceMode(TransformSpaceMode.Local); + break; + case KeyCode.Key_S: + this.selectTransformSpaceMode(TransformSpaceMode.Global); + break; + } + } + + protected onMouseDown(e: PointerEvent3D) { + if (this.mTransformMode != TransformMode.NONE) + this.mControllers[this.mTransformMode].onMouseDown(e); + } + + protected onMouseMove(e: PointerEvent3D) { + if (this.mTransformMode != TransformMode.NONE) { + this.mControllers[this.mTransformMode].onMouseMove(e); + } + } + + protected onMouseUp(e: PointerEvent3D) { + if (this.mTransformMode != TransformMode.NONE) + this.mControllers[this.mTransformMode].onMouseUp(e); + } +} + + + + + + diff --git a/src/util/transformUtil/RotationControlComponents.ts b/src/util/transformUtil/RotationControlComponents.ts new file mode 100644 index 00000000..adca33a1 --- /dev/null +++ b/src/util/transformUtil/RotationControlComponents.ts @@ -0,0 +1,233 @@ +import { Engine3D } from "../../Engine3D"; +import { ColliderComponent } from "../../components/ColliderComponent"; +import { MeshRenderer } from "../../components/renderer/MeshRenderer"; +import { BoxColliderShape } from "../../components/shape/BoxColliderShape"; +import { HitInfo } from "../../components/shape/ColliderShape"; +import { Object3D } from "../../core/entities/Object3D"; +import { PointerEvent3D } from "../../event/eventConst/PointerEvent3D"; +import { GPUCompareFunction } from "../../gfx/graphics/webGpu/WebGPUConst"; +import { UnLitMaterial } from "../../materials/UnLitMaterial"; +import { Color } from "../../math/Color"; +import { Matrix4 } from "../../math/Matrix4"; +import { Orientation3D } from "../../math/Orientation3D"; +import { Quaternion } from "../../math/Quaternion"; +import { Vector3 } from "../../math/Vector3"; +import { CylinderGeometry } from "../../shape/CylinderGeometry"; +import { PlaneGeometry } from "../../shape/PlaneGeometry"; +import { TorusGeometry } from "../../shape/TorusGeometry"; +import { TransformAxisEnum } from "./TransformAxisEnum"; +import { TransformControllerBaseComponent } from "./TransformControllerBaseComponent"; + +export class RotationControlComponents extends TransformControllerBaseComponent { + + protected applyLocalTransform(currentAxis: TransformAxisEnum, offset: Vector3, distance: number) { + if (this.currentAxis == TransformAxisEnum.X || this.currentAxis == TransformAxisEnum.XY || this.currentAxis == TransformAxisEnum.XZ) { + // this.target.rotationX += 1; + } + if (this.currentAxis == TransformAxisEnum.Y || this.currentAxis == TransformAxisEnum.XY || this.currentAxis == TransformAxisEnum.YZ) { + // this.target.rotationY += 1; + + Matrix4.help_matrix_0.copyFrom(this.mX.transform.worldMatrix); + + Matrix4.help_matrix_1.identity(); + Matrix4.help_matrix_1.createByRotation(1, Vector3.Y_AXIS); + + Matrix4.help_matrix_2.multiplyMatrices(Matrix4.help_matrix_1, Matrix4.help_matrix_0); + Matrix4.help_matrix_2.invert(); + + Matrix4.help_matrix_1.multiplyMatrices(Matrix4.help_matrix_2, Matrix4.help_matrix_0); + let trs = Matrix4.help_matrix_1.decompose(); + + this.mX.rotationX += trs[1].x; + this.mY.rotationY += trs[1].y; + this.mZ.rotationZ += trs[1].z; + } + if (this.currentAxis == TransformAxisEnum.Z || this.currentAxis == TransformAxisEnum.XZ || this.currentAxis == TransformAxisEnum.YZ) { + // this.target.rotationZ += 1; + } + } + + protected getAngle(): number { + const scene3D = this.object3D.transform.scene3D; + const camera = scene3D.view.camera; + const pos = this.mZ.transform.worldPosition; + let ray = camera.screenPointToRay(Engine3D.inputSystem.mouseX, Engine3D.inputSystem.mouseY); + + if (this.currentAxis == TransformAxisEnum.X) { + let screenPoint = camera.worldToScreenPoint(pos); + Vector3.HELP_1.set(screenPoint.x, screenPoint.y, 0); + Vector3.HELP_2.set(Engine3D.inputSystem.mouseX, Engine3D.inputSystem.mouseY, 0); + let vec3 = Vector3.HELP_2.subtract(Vector3.HELP_1); + let angle = Vector3.getAngle(Vector3.X_AXIS, vec3); + if (vec3.y > 0) { + angle = 360 - angle; + } + if (camera.transform.worldPosition.x - pos.x > 0) { + angle = 360 - angle; + } + return angle; + } + + if (this.currentAxis == TransformAxisEnum.Y) { + let screenPoint = camera.worldToScreenPoint(pos); + Vector3.HELP_1.set(screenPoint.x, screenPoint.y, 0); + Vector3.HELP_2.set(Engine3D.inputSystem.mouseX, Engine3D.inputSystem.mouseY, 0); + let vec3 = Vector3.HELP_2.subtract(Vector3.HELP_1); + let angle = Vector3.getAngle(Vector3.X_AXIS, vec3); + if (vec3.y > 0) { + angle = 360 - angle; + } + if (camera.transform.worldPosition.y - pos.y > 0) { + angle = 360 - angle; + } + return angle; + } + + if (this.currentAxis == TransformAxisEnum.Z) { + let screenPoint = camera.worldToScreenPoint(pos); + Vector3.HELP_1.set(screenPoint.x, screenPoint.y, 0); + Vector3.HELP_2.set(Engine3D.inputSystem.mouseX, Engine3D.inputSystem.mouseY, 0); + let vec3 = Vector3.HELP_2.subtract(Vector3.HELP_1); + let angle = Vector3.getAngle(Vector3.X_AXIS, vec3); + if (vec3.y > 0) { + angle = 360 - angle; + } + if (camera.transform.worldPosition.z - pos.z > 0) { + angle = 360 - angle; + } + return angle; + } + + return 0; + } + + protected mLastAngle = 0; + protected applyGlobalTransform(currentAxis: TransformAxisEnum, offset: Vector3, distance: number) { + if (this.currentAxis == TransformAxisEnum.X || this.currentAxis == TransformAxisEnum.Y || this.currentAxis == TransformAxisEnum.Z) { + let angle = this.getAngle(); + Matrix4.help_matrix_0.identity(); + + switch (this.currentAxis) { + case TransformAxisEnum.X: + Matrix4.help_matrix_0.createByRotation((this.mLastAngle - angle), Vector3.X_AXIS); + break; + case TransformAxisEnum.Y: + Matrix4.help_matrix_0.createByRotation((this.mLastAngle - angle), Vector3.Y_AXIS); + break; + case TransformAxisEnum.Z: + Matrix4.help_matrix_0.createByRotation((this.mLastAngle - angle), Vector3.Z_AXIS); + break; + } + + Matrix4.help_matrix_1.copyFrom(this.mX.transform.worldMatrix); + Matrix4.help_matrix_1.append(Matrix4.help_matrix_0); + + if (this.mX.parent) { + Matrix4.help_matrix_2.copyFrom(this.mX.parent.worldMatrix); + Matrix4.help_matrix_2.invert(); + Matrix4.help_matrix_1.multiply(Matrix4.help_matrix_2); + } + + let trs = Matrix4.help_matrix_1.decompose(Orientation3D.QUATERNION); + let rot = trs[1]; + Quaternion.HELP_0.set(rot.x, rot.y, rot.z, rot.w); + + this.mLastAngle = angle; + this.mX.transform.localRotQuat = Quaternion.HELP_0; + } + } + + public onMouseDown(e: PointerEvent3D): void { + super.onMouseDown(e); + if (this.currentAxis != TransformAxisEnum.NONE) { + this.mAxis[TransformAxisEnum.X].getComponent(MeshRenderer).enable = false; + this.mAxis[TransformAxisEnum.Y].getComponent(MeshRenderer).enable = false; + this.mAxis[TransformAxisEnum.Z].getComponent(MeshRenderer).enable = false; + this.mAxis[this.currentAxis].getComponent(MeshRenderer).enable = true; + this.mLastAngle = this.getAngle(); + } + } + + public onMouseUp(e: PointerEvent3D): void { + super.onMouseUp(e); + if (this.currentAxis == TransformAxisEnum.NONE) { + this.mAxis[TransformAxisEnum.X].getComponent(MeshRenderer).enable = true; + this.mAxis[TransformAxisEnum.Y].getComponent(MeshRenderer).enable = true; + this.mAxis[TransformAxisEnum.Z].getComponent(MeshRenderer).enable = true; + } + } + + protected createCustomAxis(axis: TransformAxisEnum): Object3D { + let axisObj = this.createAxis(axis); + + // let arrowsObj = this.createArrows(axis); + // axisObj.addChild(arrowsObj); + + return axisObj; + } + + protected createAxis(axis: TransformAxisEnum): Object3D { + let r = 0, g = 0, b = 0; + + let obj = new Object3D(); + + switch (axis) { + case TransformAxisEnum.X: + r = 1; + obj.rotationZ = 90; + break; + case TransformAxisEnum.Y: + g = 1; + // obj.rotationY = 90; + break; + case TransformAxisEnum.Z: + b = 1; + obj.rotationX = 90; + break; + } + + let mr = obj.addComponent(MeshRenderer); + mr.geometry = new TorusGeometry(20, 0.4); + mr.material = this.mAxisMaterial[axis]; + + let collider = obj.addComponent(ColliderComponent); + let colliderShape = new BoxColliderShape(); // new TorusColliderShape(20, 0.2); + colliderShape.setFromCenterAndSize(new Vector3(), new Vector3(40, 0.4, 40)); + collider.shape = colliderShape; + return obj; + } + + protected pickAxis(): { intersectPoint?: Vector3; distance: number; obj: Object3D; axis: TransformAxisEnum } { + const scene3D = this.object3D.transform.scene3D; + const camera = scene3D.view.camera; + let ray = camera.screenPointToRay(Engine3D.inputSystem.mouseX, Engine3D.inputSystem.mouseY); + + let intersect: HitInfo; + let lastResult: { intersectPoint?: Vector3; distance: number; obj: Object3D; axis: TransformAxisEnum }; + + for (let i = 0; i <= TransformAxisEnum.MAX; i++) { + let collider = this.mAxisCollider[i]; + if (!collider) { + continue; + } + intersect = collider.rayPick(ray); + if (intersect) { + let distance = Vector3.distance(intersect.intersectPoint, collider.shape.center); + if (distance > 20 + 0.8 || distance < 20 - 0.8) { + continue; + } + + if (!lastResult || lastResult.distance > intersect.distance) { + lastResult = { + axis: i, + obj: collider.object3D, + distance: intersect.distance, + intersectPoint: intersect.intersectPoint, + } + } + } + } + return lastResult; + } +} + diff --git a/src/util/transformUtil/ScaleControlComponents.ts b/src/util/transformUtil/ScaleControlComponents.ts new file mode 100644 index 00000000..86b77729 --- /dev/null +++ b/src/util/transformUtil/ScaleControlComponents.ts @@ -0,0 +1,139 @@ +import { ColliderComponent } from "../../components/ColliderComponent"; +import { MeshRenderer } from "../../components/renderer/MeshRenderer"; +import { BoxColliderShape } from "../../components/shape/BoxColliderShape"; +import { Object3D } from "../../core/entities/Object3D"; +import { GPUCompareFunction } from "../../gfx/graphics/webGpu/WebGPUConst"; +import { UnLitMaterial } from "../../materials/UnLitMaterial"; +import { Color } from "../../math/Color"; +import { Vector3 } from "../../math/Vector3"; +import { BoxGeometry } from "../../shape/BoxGeometry"; +import { TransformAxisEnum } from "./TransformAxisEnum"; +import { TransformControllerBaseComponent } from "./TransformControllerBaseComponent"; + +export class ScaleControlComponents extends TransformControllerBaseComponent { + + public init(param?: any): void { + super.init(param); + + let boxXYZMaterial = new UnLitMaterial(); + boxXYZMaterial.doubleSide = true; + boxXYZMaterial.baseColor = new Color(0.9, 0.9, 0.9); + boxXYZMaterial.depthCompare = GPUCompareFunction.always; + this.mAxisColor[TransformAxisEnum.XYZ] = boxXYZMaterial.baseColor; + this.mAxisMaterial[TransformAxisEnum.XYZ] = boxXYZMaterial; + + let boxXYZ = new Object3D(); + let mr = boxXYZ.addComponent(MeshRenderer); + mr.geometry = new BoxGeometry(2, 2, 2); + mr.material = this.mAxisMaterial[TransformAxisEnum.XYZ]; + + let collider = boxXYZ.addComponent(ColliderComponent); + let boxShape = new BoxColliderShape(); + boxShape.setFromCenterAndSize(new Vector3(0, 0, 0), new Vector3(2, 2, 2)); + collider.shape = boxShape; + + this.mContainer.addChild(this.mAxis[TransformAxisEnum.XYZ] = boxXYZ); + + this.mAxisCollider[TransformAxisEnum.XYZ] = boxXYZ.getComponent(ColliderComponent); + } + + protected applyLocalTransform(currentAxis: TransformAxisEnum, offset: Vector3, distance: number) { + switch (this.currentAxis) { + case TransformAxisEnum.XYZ: + { + let v = 0; + if (Math.abs(offset.x) > Math.abs(offset.y)) { + if (Math.abs(offset.x) > Math.abs(offset.z)) { + v = offset.x; + } else { + v = offset.z; + } + } else { + v = offset.y; + } + this.mX.scaleX += v; + this.mX.scaleY += v; + this.mX.scaleZ += v; + } + break; + default: + { + this.mX.transform.worldMatrix.transformVector(offset, offset); + + if (this.currentAxis == TransformAxisEnum.X || this.currentAxis == TransformAxisEnum.XY || this.currentAxis == TransformAxisEnum.XZ) { + this.mX.scaleX = Math.abs(this.mX.scaleX + offset.x); + } + if (this.currentAxis == TransformAxisEnum.Y || this.currentAxis == TransformAxisEnum.XY || this.currentAxis == TransformAxisEnum.YZ) { + this.mX.scaleY = Math.abs(this.mX.scaleY + offset.y); + } + if (this.currentAxis == TransformAxisEnum.Z || this.currentAxis == TransformAxisEnum.XZ || this.currentAxis == TransformAxisEnum.YZ) { + this.mX.scaleZ = Math.abs(this.mX.scaleZ + offset.z); + } + } + break; + } + } + + protected applyGlobalTransform(currentAxis: TransformAxisEnum, offset: Vector3, distance: number) { + let value = Vector3.HELP_0; + value.set(0, 0, 0); + + if (this.currentAxis == TransformAxisEnum.X || this.currentAxis == TransformAxisEnum.XY || this.currentAxis == TransformAxisEnum.XZ) { + value.x = offset.x; + } + if (this.currentAxis == TransformAxisEnum.Y || this.currentAxis == TransformAxisEnum.XY || this.currentAxis == TransformAxisEnum.YZ) { + value.y = offset.y; + } + if (this.currentAxis == TransformAxisEnum.Z || this.currentAxis == TransformAxisEnum.XZ || this.currentAxis == TransformAxisEnum.YZ) { + value.z = offset.z; + } + + this.mX.transform.worldMatrix.transformVector(value, Vector3.HELP_1); + this.mX.scaleX += Vector3.HELP_1.x; + this.mX.scaleY += Vector3.HELP_1.y; + this.mX.scaleZ += Vector3.HELP_1.z; + } + + protected createCustomAxis(axis: TransformAxisEnum): Object3D { + let axisObj = super.createAxis(axis); + + let arrowsObj = this.createBox(axis); + axisObj.addChild(arrowsObj); + + return axisObj; + } + + protected createBox(axis: TransformAxisEnum): Object3D { + let r = 0, g = 0, b = 0; + + let obj = new Object3D(); + + switch (axis) { + case TransformAxisEnum.X: + r = 1; + obj.rotationZ = -90; + break; + case TransformAxisEnum.Y: + g = 1; + // obj.rotationY = -90; + break; + case TransformAxisEnum.Z: + b = 1; + obj.rotationX = 90; + break; + } + + let w = 0.2 + r * 20; + let h = 0.2 + g * 20; + let d = 0.2 + b * 20; + + obj.x = w * 0.5; + obj.y = h * 0.5; + obj.z = d * 0.5; + + let mr = obj.addComponent(MeshRenderer); + mr.geometry = new BoxGeometry(2, 2, 2); + mr.material = this.mAxisMaterial[axis]; + return obj; + } +} \ No newline at end of file diff --git a/src/util/transformUtil/TransformAxisEnum.ts b/src/util/transformUtil/TransformAxisEnum.ts new file mode 100644 index 00000000..f6b7cf81 --- /dev/null +++ b/src/util/transformUtil/TransformAxisEnum.ts @@ -0,0 +1,14 @@ +/** + * @internal + */ +export enum TransformAxisEnum { + X, + Y, + Z, + XY, + XZ, + YZ, + XYZ, + MAX, + NONE, +} \ No newline at end of file diff --git a/src/util/transformUtil/TransformControllerBaseComponent.ts b/src/util/transformUtil/TransformControllerBaseComponent.ts new file mode 100644 index 00000000..9b780013 --- /dev/null +++ b/src/util/transformUtil/TransformControllerBaseComponent.ts @@ -0,0 +1,345 @@ +import { Engine3D } from "../../Engine3D"; +import { ColliderComponent } from "../../components/ColliderComponent"; +import { ComponentBase } from "../../components/ComponentBase"; +import { MeshRenderer } from "../../components/renderer/MeshRenderer"; +import { BoxColliderShape } from "../../components/shape/BoxColliderShape"; +import { HitInfo } from "../../components/shape/ColliderShape"; +import { View3D } from "../../core/View3D"; +import { Object3D } from "../../core/entities/Object3D"; +import { MouseCode } from "../../event/MouseCode"; +import { PointerEvent3D } from "../../event/eventConst/PointerEvent3D"; +import { GPUCompareFunction } from "../../gfx/graphics/webGpu/WebGPUConst"; +import { UnLitMaterial } from "../../materials/UnLitMaterial"; +import { Color } from "../../math/Color"; +import { Matrix4 } from "../../math/Matrix4"; +import { Vector3 } from "../../math/Vector3"; +import { BoxGeometry } from "../../shape/BoxGeometry"; +import { TransformAxisEnum } from "./TransformAxisEnum"; +import { Object3DTransformTools } from "./Object3DTransformTools"; +import { TransformSpaceMode } from "./TransformSpaceMode"; + +export class TransformControllerBaseComponent extends ComponentBase { + protected mAxis: Object3D[]; + protected mAxisColor: Color[]; + protected mContainer: Object3D; + protected mAxisMaterial: UnLitMaterial[]; + protected mAxisCollider: ColliderComponent[]; + + + constructor() { + super(); + this._enable = false; + this.mAxis = new Array(TransformAxisEnum.MAX); + this.mAxisColor = new Array(TransformAxisEnum.MAX); + this.mAxisMaterial = new Array(TransformAxisEnum.MAX); + this.mAxisCollider = new Array(TransformAxisEnum.MAX); + + + } + + public get target(): Object3D { + return (this.object3D as Object3DTransformTools).target; + } + + public get mX(): Object3D { + return (this.object3D as Object3DTransformTools).mXObj; + } + + public get mY(): Object3D { + return (this.object3D as Object3DTransformTools).mYObj; + } + + public get mZ(): Object3D { + return (this.object3D as Object3DTransformTools).mZObj; + } + + public get transformSpaceMode(): TransformSpaceMode { + return (this.object3D as Object3DTransformTools).transformSpaceMode; + } + + public init(param?: any): void { + this.mContainer = new Object3D(); + + let xAxisMaterial = new UnLitMaterial(); + xAxisMaterial.baseColor = new Color(1, 0, 0); + xAxisMaterial.depthCompare = GPUCompareFunction.always; + this.mAxisColor[TransformAxisEnum.X] = xAxisMaterial.baseColor; + this.mAxisMaterial[TransformAxisEnum.X] = xAxisMaterial; + + let yAxisMaterial = new UnLitMaterial(); + yAxisMaterial.baseColor = new Color(0, 1, 0); + yAxisMaterial.depthCompare = GPUCompareFunction.always; + this.mAxisColor[TransformAxisEnum.Y] = yAxisMaterial.baseColor; + this.mAxisMaterial[TransformAxisEnum.Y] = yAxisMaterial; + + let zAxisMaterial = new UnLitMaterial(); + zAxisMaterial.baseColor = new Color(0, 0, 1); + zAxisMaterial.depthCompare = GPUCompareFunction.always; + this.mAxisColor[TransformAxisEnum.Z] = zAxisMaterial.baseColor; + this.mAxisMaterial[TransformAxisEnum.Z] = zAxisMaterial; + + let axisX = this.createCustomAxis(TransformAxisEnum.X); + let axisY = this.createCustomAxis(TransformAxisEnum.Y); + let axisZ = this.createCustomAxis(TransformAxisEnum.Z); + + this.mContainer.addChild(this.mAxis[TransformAxisEnum.X] = axisX); + this.mContainer.addChild(this.mAxis[TransformAxisEnum.Y] = axisY); + this.mContainer.addChild(this.mAxis[TransformAxisEnum.Z] = axisZ); + + this.mAxisCollider[TransformAxisEnum.X] = axisX.getComponent(ColliderComponent); + this.mAxisCollider[TransformAxisEnum.Y] = axisY.getComponent(ColliderComponent); + this.mAxisCollider[TransformAxisEnum.Z] = axisZ.getComponent(ColliderComponent); + } + + public start(): void { + // this.object3D.addChild(this.mContainer); + } + + public onEnable(view?: View3D) { + // console.warn('onEnable'); + this.object3D.addChild(this.mContainer); + // Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_DOWN, this.onMouseDown, this, null, 99999); + // Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_MOVE, this.onMouseMove, this, null, 99999); + // Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_UP, this.onMouseUp, this, null, 99999); + this.reset(); + } + + public onDisable(view?: View3D) { + // console.warn('onDisable'); + this.object3D.removeChild(this.mContainer); + // Engine3D.inputSystem.removeEventListener(PointerEvent3D.POINTER_DOWN, this.onMouseDown, this); + // Engine3D.inputSystem.removeEventListener(PointerEvent3D.POINTER_MOVE, this.onMouseMove, this); + // Engine3D.inputSystem.removeEventListener(PointerEvent3D.POINTER_UP, this.onMouseUp, this); + } + + public reset() { + // if (!this.target) { + // return; + // } + + switch (this.transformSpaceMode) { + case TransformSpaceMode.Local: + { + let targetInvWorldMatrix = Matrix4.help_matrix_0.copyFrom(this.mX.transform.worldMatrix); + // targetInvWorldMatrix.invert(); + + let resultTRS = targetInvWorldMatrix.decompose(); + + this.object3D.scaleX = 1.0; + this.object3D.scaleY = 1.0; + this.object3D.scaleZ = 1.0; + // console.warn(`scale(${resultTRS[2].x}, ${resultTRS[2].y}, ${resultTRS[2].z})`); + + this.object3D.rotationX = resultTRS[1].x; + this.object3D.rotationY = resultTRS[1].y; + this.object3D.rotationZ = resultTRS[1].z; + // console.warn(`rotation(${resultTRS[1].x}, ${resultTRS[1].y}, ${resultTRS[1].z})`); + + this.object3D.x = resultTRS[0].x; + this.object3D.y = resultTRS[0].y; + this.object3D.z = resultTRS[0].z; + } + break; + case TransformSpaceMode.Global: + { + this.object3D.scaleX = 1.0; + this.object3D.scaleY = 1.0; + this.object3D.scaleZ = 1.0; + + this.object3D.rotationX = 0; + this.object3D.rotationY = 0; + this.object3D.rotationZ = 0; + + const pos = this.mX.transform.worldPosition;; + this.object3D.x = pos.x; + this.object3D.y = pos.y; + this.object3D.z = pos.z; + } + break; + } + } + + protected pickAxis(): { intersectPoint?: Vector3; distance: number; obj: Object3D; axis: TransformAxisEnum } { + const scene3D = this.object3D.transform.scene3D; + const camera = scene3D.view.camera; + let ray = camera.screenPointToRay(Engine3D.inputSystem.mouseX, Engine3D.inputSystem.mouseY); + + let intersect: HitInfo; + let lastResult: { intersectPoint?: Vector3; distance: number; obj: Object3D; axis: TransformAxisEnum }; + + for (let i = 0; i <= TransformAxisEnum.MAX; i++) { + let collider = this.mAxisCollider[i]; + if (!collider) { + continue; + } + intersect = collider.rayPick(ray); + if (intersect) { + if (!lastResult || lastResult.distance > intersect.distance || i == TransformAxisEnum.XYZ) { + lastResult = { + axis: i, + obj: collider.object3D, + distance: intersect.distance, + intersectPoint: intersect.intersectPoint, + } + + if (i == TransformAxisEnum.XYZ) { + break; + } + } + } + } + return lastResult; + } + + protected currentAxis = TransformAxisEnum.NONE; + protected beginPoint: Vector3 = new Vector3(); + protected beginMousePos: Vector3 = new Vector3(); + protected currentPoint: Vector3 = new Vector3(); + public onMouseDown(e: PointerEvent3D): void { + if (e.mouseCode != MouseCode.MOUSE_LEFT) { + return; + } + let result = this.pickAxis(); + if (!result) { + return; + } + this.currentAxis = result.axis; + e.stopImmediatePropagation(); + + const scene3D = this.object3D.transform.scene3D; + const camera = scene3D.view.camera; + let screenPoint = camera.worldToScreenPoint(this.mX.transform.worldPosition); + let pos = camera.screenPointToWorld(Engine3D.inputSystem.mouseX, Engine3D.inputSystem.mouseY, screenPoint.z); + this.beginPoint.copyFrom(pos); + this.beginMousePos.x = Engine3D.inputSystem.mouseX; + this.beginMousePos.y = Engine3D.inputSystem.mouseY; + } + + protected lastMoveObj: Object3D; + protected lastMoveAxis: TransformAxisEnum; + public onMouseMove(e: PointerEvent3D): void { + if (this.currentAxis == TransformAxisEnum.NONE) { + let mat = this.lastMoveObj.getComponent(MeshRenderer).material; + if (this.lastMoveObj && "baseColor" in mat) { + mat.baseColor = this.mAxisColor[this.lastMoveAxis]; + this.lastMoveObj = null; + if (this.lastMoveAxis == TransformAxisEnum.XYZ) { + this.mAxis[TransformAxisEnum.X].getComponent(MeshRenderer).material.setUniformColor("baseColor", this.mAxisColor[TransformAxisEnum.X]); + this.mAxis[TransformAxisEnum.Y].getComponent(MeshRenderer).material.setUniformColor("baseColor", this.mAxisColor[TransformAxisEnum.Y]); + this.mAxis[TransformAxisEnum.Z].getComponent(MeshRenderer).material.setUniformColor("baseColor", this.mAxisColor[TransformAxisEnum.Z]); + } + this.lastMoveAxis = TransformAxisEnum.NONE; + } + let result = this.pickAxis(); + if (!result) { + return; + } + + mat.setUniformColor("baseColor", new Color(1, 1, 1)); + this.lastMoveObj = result.obj; + this.lastMoveAxis = result.axis; + if (this.lastMoveAxis == TransformAxisEnum.XYZ) { + this.mAxis[TransformAxisEnum.X].getComponent(MeshRenderer).material.setUniformColor("baseColor", new Color(1, 1, 1)); + this.mAxis[TransformAxisEnum.Y].getComponent(MeshRenderer).material.setUniformColor("baseColor", new Color(1, 1, 1)); + this.mAxis[TransformAxisEnum.Z].getComponent(MeshRenderer).material.setUniformColor("baseColor", new Color(1, 1, 1)); + } + } else { + const scene3D = this.object3D.transform.scene3D; + const camera = scene3D.view.camera; + let screenPoint = camera.worldToScreenPoint(this.mX.transform.worldPosition); + let pos = camera.screenPointToWorld(Engine3D.inputSystem.mouseX, Engine3D.inputSystem.mouseY, screenPoint.z); + + this.currentPoint.copyFrom(pos); + let offset = pos.subtract(this.beginPoint); + + Vector3.HELP_0.set(Engine3D.inputSystem.mouseX, Engine3D.inputSystem.mouseY, 0); + let distance = Vector3.distance(Vector3.HELP_0, this.beginMousePos); + this.beginMousePos.copyFrom(Vector3.HELP_0); + + switch (this.transformSpaceMode) { + case TransformSpaceMode.Local: + this.applyLocalTransform(this.currentAxis, offset, distance); + break; + case TransformSpaceMode.Global: + this.applyGlobalTransform(this.currentAxis, offset, distance); + break; + } + + this.beginPoint.copyFrom(pos); + + this.reset(); + } + } + + public onMouseUp(e: PointerEvent3D): void { + if (e.mouseCode != MouseCode.MOUSE_LEFT) { + return; + } + this.currentAxis = TransformAxisEnum.NONE; + this.reset(); + } + + public onUpdate(view?: View3D) { + let distance = Vector3.distance(view.camera.transform.worldPosition, this.object3D.transform.worldPosition); + let scale = distance / 100.0; + this.mContainer.scaleX = this.mContainer.scaleY = this.mContainer.scaleZ = scale; + if (this.mX) { + const pos = this.mX.transform.worldPosition;; + this.object3D.x = pos.x; + this.object3D.y = pos.y; + this.object3D.z = pos.z; + } + } + + protected applyLocalTransform(currentAxis: TransformAxisEnum, offset: Vector3, distance: number) { + console.warn("not imp"); + } + + protected applyGlobalTransform(currentAxis: TransformAxisEnum, offset: Vector3, distance: number) { + console.warn("not imp"); + } + + protected createCustomAxis(axis: TransformAxisEnum): Object3D { + let axisObj = this.createAxis(axis); + + // let arrowsObj = this.createArrows(axis); + // axisObj.addChild(arrowsObj); + + return axisObj; + } + + protected createAxis(axis: TransformAxisEnum): Object3D { + let r = 0, g = 0, b = 0; + + switch (axis) { + case TransformAxisEnum.X: + r = 1; + break; + case TransformAxisEnum.Y: + g = 1; + break; + case TransformAxisEnum.Z: + b = 1; + break; + } + + let w = 0.4 + r * 20; + let h = 0.4 + g * 20; + let d = 0.4 + b * 20; + + let obj = new Object3D(); + obj.x = w * 0.5; + obj.y = h * 0.5; + obj.z = d * 0.5; + + let mr = obj.addComponent(MeshRenderer); + mr.geometry = new BoxGeometry(w, h, d); + mr.material = this.mAxisMaterial[axis]; + + let collider = obj.addComponent(ColliderComponent); + let boxShape = new BoxColliderShape(); + boxShape.setFromCenterAndSize(new Vector3(0, 0, 0), new Vector3(w + 1, h + 1, d + 1)); + collider.shape = boxShape; + return obj; + } +} \ No newline at end of file diff --git a/src/util/transformUtil/TransformMode.ts b/src/util/transformUtil/TransformMode.ts new file mode 100644 index 00000000..bef1b925 --- /dev/null +++ b/src/util/transformUtil/TransformMode.ts @@ -0,0 +1,9 @@ +/** + * @internal + */ +export enum TransformMode { + Scale, + Rotation, + Translation, + NONE, +} \ No newline at end of file diff --git a/src/util/transformUtil/TransformSpaceMode.ts b/src/util/transformUtil/TransformSpaceMode.ts new file mode 100644 index 00000000..7180dfd9 --- /dev/null +++ b/src/util/transformUtil/TransformSpaceMode.ts @@ -0,0 +1,7 @@ +/** + * @internal + */ +export enum TransformSpaceMode { + Local, + Global, +} \ No newline at end of file diff --git a/src/util/transformUtil/TranslationControlComponents.ts b/src/util/transformUtil/TranslationControlComponents.ts new file mode 100644 index 00000000..abe79be3 --- /dev/null +++ b/src/util/transformUtil/TranslationControlComponents.ts @@ -0,0 +1,185 @@ +import { ColliderComponent } from "../../components/ColliderComponent"; +import { MeshRenderer } from "../../components/renderer/MeshRenderer"; +import { BoxColliderShape } from "../../components/shape/BoxColliderShape"; +import { Object3D } from "../../core/entities/Object3D"; +import { GPUCompareFunction } from "../../gfx/graphics/webGpu/WebGPUConst"; +import { UnLitMaterial } from "../../materials/UnLitMaterial"; +import { Color } from "../../math/Color"; +import { Matrix4 } from "../../math/Matrix4"; +import { Orientation3D } from "../../math/Orientation3D"; +import { Vector3 } from "../../math/Vector3"; +import { CylinderGeometry } from "../../shape/CylinderGeometry"; +import { PlaneGeometry } from "../../shape/PlaneGeometry"; +import { TransformAxisEnum } from "./TransformAxisEnum"; +import { TransformControllerBaseComponent } from "./TransformControllerBaseComponent"; + +export class TranslationControlComponents extends TransformControllerBaseComponent { + + public init(param?: any): void { + super.init(param); + + let xyPlaneMaterial = new UnLitMaterial(); + xyPlaneMaterial.doubleSide = true; + xyPlaneMaterial.baseColor = new Color(0, 0, 1); + xyPlaneMaterial.depthCompare = GPUCompareFunction.always; + this.mAxisColor[TransformAxisEnum.XY] = xyPlaneMaterial.baseColor; + this.mAxisMaterial[TransformAxisEnum.XY] = xyPlaneMaterial; + + let xzPlaneMaterial = new UnLitMaterial(); + xzPlaneMaterial.doubleSide = true; + xzPlaneMaterial.baseColor = new Color(0, 1, 0); + xzPlaneMaterial.depthCompare = GPUCompareFunction.always; + this.mAxisColor[TransformAxisEnum.XZ] = xzPlaneMaterial.baseColor; + this.mAxisMaterial[TransformAxisEnum.XZ] = xzPlaneMaterial; + + let yzPlaneMaterial = new UnLitMaterial(); + yzPlaneMaterial.doubleSide = true; + yzPlaneMaterial.baseColor = new Color(1, 0, 0); + yzPlaneMaterial.depthCompare = GPUCompareFunction.always; + this.mAxisColor[TransformAxisEnum.YZ] = yzPlaneMaterial.baseColor; + this.mAxisMaterial[TransformAxisEnum.YZ] = yzPlaneMaterial; + + let planeXY = this.createPlane(TransformAxisEnum.XY); + let planeXZ = this.createPlane(TransformAxisEnum.XZ); + let planeYZ = this.createPlane(TransformAxisEnum.YZ); + + this.mContainer.addChild(this.mAxis[TransformAxisEnum.XY] = planeXY); + this.mContainer.addChild(this.mAxis[TransformAxisEnum.XZ] = planeXZ); + this.mContainer.addChild(this.mAxis[TransformAxisEnum.YZ] = planeYZ); + + this.mAxisCollider[TransformAxisEnum.XY] = planeXY.getComponent(ColliderComponent); + this.mAxisCollider[TransformAxisEnum.XZ] = planeXZ.getComponent(ColliderComponent); + this.mAxisCollider[TransformAxisEnum.YZ] = planeYZ.getComponent(ColliderComponent); + } + + protected applyLocalTransform(currentAxis: TransformAxisEnum, offset: Vector3, distance: number) { + Matrix4.help_matrix_0.copyFrom(this.mX.transform.worldMatrix).invert(); + Matrix4.help_matrix_0.transformVector(offset, Vector3.HELP_0); + + if (!(this.currentAxis == TransformAxisEnum.X || this.currentAxis == TransformAxisEnum.XY || this.currentAxis == TransformAxisEnum.XZ)) { + Vector3.HELP_0.x = 0; + } + if (!(this.currentAxis == TransformAxisEnum.Y || this.currentAxis == TransformAxisEnum.XY || this.currentAxis == TransformAxisEnum.YZ)) { + Vector3.HELP_0.y = 0; + } + if (!(this.currentAxis == TransformAxisEnum.Z || this.currentAxis == TransformAxisEnum.XZ || this.currentAxis == TransformAxisEnum.YZ)) { + Vector3.HELP_0.z = 0; + } + + this.mX.transform.worldMatrix.transformVector(Vector3.HELP_0, Vector3.HELP_1); + + this.mX.x += Vector3.HELP_1.x; + this.mX.y += Vector3.HELP_1.y; + this.mX.z += Vector3.HELP_1.z; + + // this.target.localPosition = this.mX.transform.worldPosition.clone(); + } + + protected applyGlobalTransform(currentAxis: TransformAxisEnum, offset: Vector3, distance: number) { + Matrix4.help_matrix_0.identity(); + + if (this.currentAxis == TransformAxisEnum.X || this.currentAxis == TransformAxisEnum.XY || this.currentAxis == TransformAxisEnum.XZ) { + Matrix4.help_matrix_0.appendTranslation(offset.x, 0, 0); + } + if (this.currentAxis == TransformAxisEnum.Y || this.currentAxis == TransformAxisEnum.XY || this.currentAxis == TransformAxisEnum.YZ) { + Matrix4.help_matrix_0.appendTranslation(0, offset.y, 0); + } + if (this.currentAxis == TransformAxisEnum.Z || this.currentAxis == TransformAxisEnum.XZ || this.currentAxis == TransformAxisEnum.YZ) { + Matrix4.help_matrix_0.appendTranslation(0, 0, offset.z); + } + + Matrix4.help_matrix_1.copyFrom(this.mX.transform.worldMatrix); + Matrix4.help_matrix_1.append(Matrix4.help_matrix_0); + + if (this.mX.parent) { + Matrix4.help_matrix_2.copyFrom(this.mX.parent.worldMatrix); + Matrix4.help_matrix_2.invert(); + Matrix4.help_matrix_1.multiply(Matrix4.help_matrix_2); + } + + let trs = Matrix4.help_matrix_1.decompose(Orientation3D.QUATERNION); + + this.mX.transform.localPosition = trs[0]; + + console.log(this.target.localPosition); + + // this.target.localPosition = this.mX.transform.worldPosition.clone(); + } + + protected createCustomAxis(axis: TransformAxisEnum): Object3D { + let axisObj = super.createAxis(axis); + + let arrowsObj = this.createArrows(axis); + axisObj.addChild(arrowsObj); + + return axisObj; + } + + protected createArrows(axis: TransformAxisEnum): Object3D { + let r = 0, g = 0, b = 0; + + let obj = new Object3D(); + + switch (axis) { + case TransformAxisEnum.X: + r = 1; + obj.rotationZ = -90; + break; + case TransformAxisEnum.Y: + g = 1; + obj.rotationY = -90; + break; + case TransformAxisEnum.Z: + b = 1; + obj.rotationX = 90; + break; + } + + let w = 0.2 + r * 20; + let h = 0.2 + g * 20; + let d = 0.2 + b * 20; + + obj.x = w * 0.5; + obj.y = h * 0.5; + obj.z = d * 0.5; + + let mr = obj.addComponent(MeshRenderer); + mr.geometry = new CylinderGeometry(0, 1, 4); + mr.material = this.mAxisMaterial[axis]; + return obj; + } + + protected createPlane(axis: TransformAxisEnum): Object3D { + let obj = new Object3D(); + + let mr = obj.addComponent(MeshRenderer); + mr.material = this.mAxisMaterial[axis]; + + let collider = obj.addComponent(ColliderComponent); + let boxShape = new BoxColliderShape(); + collider.shape = boxShape; + + switch (axis) { + case TransformAxisEnum.XY: + mr.geometry = new PlaneGeometry(4, 4, 1, 1, Vector3.Z_AXIS); + obj.x = 8; + obj.y = 8; + boxShape.setFromCenterAndSize(new Vector3(0, 0, 0), new Vector3(4, 4, 0.1)); + break; + case TransformAxisEnum.XZ: + mr.geometry = new PlaneGeometry(4, 4, 1, 1, Vector3.Y_AXIS); + obj.x = 8; + obj.z = 8; + boxShape.setFromCenterAndSize(new Vector3(0, 0, 0), new Vector3(4, 0.1, 4)); + break; + case TransformAxisEnum.YZ: + mr.geometry = new PlaneGeometry(4, 4, 1, 1, Vector3.X_AXIS); + obj.y = 8; + obj.z = 8; + boxShape.setFromCenterAndSize(new Vector3(0, 0, 0), new Vector3(0.1, 4, 4)); + break; + } + + return obj; + } +} \ No newline at end of file diff --git a/test/components/PostEffects_GlobalFog.test.ts b/test/components/PostEffects_GlobalFog.test.ts index fa95ddfa..639f0ad2 100644 --- a/test/components/PostEffects_GlobalFog.test.ts +++ b/test/components/PostEffects_GlobalFog.test.ts @@ -14,7 +14,7 @@ await test('Post GlobalFog test', async () => { let fog = postProcessing.addPost(GlobalFog); await delay(500) let dest = Math.floor(window.innerWidth * window.devicePixelRatio); - let src = fog.rtTexture?.width; + let src = fog.fogOpTexture?.width; expect(src).tobe(dest) Engine3D.pause() })