diff --git a/.github/workflows/generate-oh-sdk-cache.yml b/.github/workflows/generate-oh-sdk-cache.yml new file mode 100644 index 00000000000..4e4c609de1c --- /dev/null +++ b/.github/workflows/generate-oh-sdk-cache.yml @@ -0,0 +1,80 @@ +name: Generate OH SDK Cache + +on: + workflow_dispatch: + inputs: + oh_sdk_version: + description: 'Openharmony SDK version' + type: string + default: '9' + required: true + +jobs: + generate_oh_sdk_cache: + name: "Generate OH SDK cache" + runs-on: ubuntu-latest + steps: + - uses: actions/setup-java@v3 + id: setup-jdk + with: + distribution: 'zulu' + java-version: '17' + + - name: Get oh sdk cache directory path + id: oh-sdk-cache-dir-path + run: | + echo "cache dir: " + echo "dir=$HOME/openharmony" >> $GITHUB_OUTPUT + + - name: Output cache dir + run: | + echo "Output cache dir: ${{ steps.oh-sdk-cache-dir-path.outputs.dir }}" + + - name: Cache OH SDK + id: cache-oh-sdk + uses: actions/cache@v3 + env: + cache-name: cache-oh-sdk-${{ github.event.inputs.oh_sdk_version }} + with: + path: ${{ steps.oh-sdk-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-build-${{ env.cache-name }} + + - name: Add package.json + run: | + echo "{}" > package.json + echo "{\"name\": \"tests\",\"lockfileVersion\": 3,\"requires\": true,\"packages\": {}}" > package-lock.json + - uses: actions/setup-node@v3 + with: + node-version: 14 + cache: 'npm' + + - if: ${{ steps.cache-oh-sdk.outputs.cache-hit != 'true' }} + name: No Cache found, install oh sdk + continue-on-error: false + run: | + if [ ! -d "$HOME/openharmony" ]; then + mkdir -p $HOME/openharmony + echo "Download commandline-tools-linux.zip ..." + curl -o commandline-tools-linux.zip "https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_package_901_9/b1/v3/E6zhv5UFQ2-inIwNJhTN6Q/commandline-tools-linux-2.0.0.2.zip?HW-CC-KV=V1&HW-CC-Date=20230621T074401Z&HW-CC-Expire=315360000&HW-CC-Sign=621224257B02079B1E76C0A56FDF21483400B1E3556213F88DC79BC9BE7D595D" + echo "Unzip commandline-tools-linux.zip ..." + unzip commandline-tools-linux.zip -d $HOME/openharmony > /dev/null + cd $HOME/openharmony + ls -l + cd command-line-tools + echo "=============== PATCHING sdkmanager/bin/sdkmgr file ===============" + sed -i "s@-Dfile.encoding=UTF-8@-Dfile.encoding=UTF-8 -Duser.country=CN@g" ./sdkmanager/bin/sdkmgr + cd bin + ./sdkmgr list + echo "=============== INSTALL HOS toolchains:${{ github.event.inputs.oh_sdk_version }} ===============" + ./sdkmgr install toolchains:${{ github.event.inputs.oh_sdk_version }} --accept-license > /dev/null + echo "=============== INSTALL OH SDK ets:${{ github.event.inputs.oh_sdk_version }} ===============" + ./sdkmgr install OpenHarmony/ets:${{ github.event.inputs.oh_sdk_version }} --accept-license > /dev/null + echo "=============== INSTALL OH SDK js:${{ github.event.inputs.oh_sdk_version }} ===============" + ./sdkmgr install OpenHarmony/js:${{ github.event.inputs.oh_sdk_version }} --accept-license > /dev/null + echo "=============== INSTALL OH SDK native:${{ github.event.inputs.oh_sdk_version }} ===============" + ./sdkmgr install OpenHarmony/native:${{ github.event.inputs.oh_sdk_version }} --accept-license > /dev/null + echo "=============== INSTALL OH SDK toolchains:${{ github.event.inputs.oh_sdk_version }} ===============" + ./sdkmgr install OpenHarmony/toolchains:${{ github.event.inputs.oh_sdk_version }} --accept-license > /dev/null + echo "=============== INSTALL OH SDK DONE ===============" + ./sdkmgr list + fi \ No newline at end of file diff --git a/.github/workflows/generate-vulkan-sdk-cache.yml b/.github/workflows/generate-vulkan-sdk-cache.yml new file mode 100644 index 00000000000..2904d1a9493 --- /dev/null +++ b/.github/workflows/generate-vulkan-sdk-cache.yml @@ -0,0 +1,22 @@ +name: Generate Vulkan SDK Cache + +on: + workflow_dispatch: + inputs: + vulkan_sdk_version: + description: 'Vulkan SDK version' + type: string + default: '1.2.189.0' + required: true + +jobs: + generate_vulkan_sdk_cache: + name: "Generate Vulkan SDK cache" + runs-on: windows-2019 + steps: + - name: Setup Vulkan SDK + uses: humbletim/setup-vulkan-sdk@v1.2.0 + with: + vulkan-query-version: ${{ github.event.inputs.vulkan_sdk_version }} + vulkan-components: Vulkan-Headers, Vulkan-Loader + vulkan-use-cache: true \ No newline at end of file diff --git a/.github/workflows/native-bindings.yml b/.github/workflows/native-bindings.yml index faa4fede9c1..2a896a8a9db 100644 --- a/.github/workflows/native-bindings.yml +++ b/.github/workflows/native-bindings.yml @@ -27,6 +27,8 @@ jobs: ndk-version: r21e add-to-path: false - name: Generate decorators + env: + ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} run: | cd native echo "Generate compile_commands.json & ninja target" diff --git a/.github/workflows/native-compile-platforms.yml b/.github/workflows/native-compile-platforms.yml index addaa8c96d2..f3d63c303c1 100644 --- a/.github/workflows/native-compile-platforms.yml +++ b/.github/workflows/native-compile-platforms.yml @@ -84,7 +84,7 @@ jobs: COCOS_ENGINE_DEV: 1 run: | NATIVE_ROOT=$GITHUB_WORKSPACE/native - ANDORID_NDK=$ANDROID_NDK_LATEST_HOME + ANDROID_NDK=${{ steps.setup-ndk.outputs.ndk-path }} NATIVE_DIR=$GITHUB_WORKSPACE/templates/android-template echo "Compiling Android ... " cd $GITHUB_WORKSPACE/templates/ @@ -111,7 +111,7 @@ jobs: ASSET_DIR=$GITHUB_WORKSPACE/templates/android/build/build-android/ - sed -i "s@^PROP_NDK_PATH.*@PROP_NDK_PATH=$ANDORID_NDK@g" gradle.properties + sed -i "s@^PROP_NDK_PATH.*@PROP_NDK_PATH=$ANDROID_NDK@g" gradle.properties sed -i "s@^APPLICATION_ID.*@APPLICATION_ID=com.cocos.android@g" gradle.properties sed -i "s@^RES_PATH.*@RES_PATH=$ASSET_DIR@g" gradle.properties sed -i "s@^COCOS_ENGINE_PATH.*@COCOS_ENGINE_PATH=$NATIVE_ROOT@g" gradle.properties @@ -122,7 +122,7 @@ jobs: sed -i "s@^PROP_APP_ABI.*@PROP_APP_ABI=arm64-v8a@g" gradle.properties echo "Compile Android - cmake ..." - echo "ANDORID_NDK ${ANDROID_NDK} or ${ANDROID_NDK_HOME}" + echo "ANDROID_NDK ${ANDROID_NDK} or ${ANDROID_NDK_HOME}" # ./gradlew :CocosGame:assembleDebug --quiet ./gradlew :CocosGame:assembleRelease --quiet echo "Compile Android Debug Done!" @@ -133,6 +133,25 @@ jobs: (! contains(github.event.pull_request.body, '[X] does not change any runtime related code or build configuration')) runs-on: ubuntu-latest steps: + - name: Before free space + run: | + df -h + + - name: Free Disk Space (Ubuntu) + uses: jlumbroso/free-disk-space@d5af243ce7bacb67384aa6c5b1fc5f169e30903e + with: + tool-cache: true + android: false + dotnet: true + haskell: true + large-packages: true + docker-images: true + swap-storage: true + + - name: After free space + run: | + df -h + - uses: actions/checkout@v2 - name: Download external libraries shell: bash @@ -154,7 +173,7 @@ jobs: COCOS_ENGINE_DEV: 1 run: | NATIVE_ROOT=$GITHUB_WORKSPACE/native - ANDORID_NDK=$ANDROID_NDK_LATEST_HOME + ANDROID_NDK=${{ steps.setup-ndk.outputs.ndk-path }} NATIVE_DIR=$GITHUB_WORKSPACE/templates/android-template echo "Compiling Android ... " cd $GITHUB_WORKSPACE/templates/ @@ -185,7 +204,7 @@ jobs: ASSET_DIR=$GITHUB_WORKSPACE/templates/android/build/build-android/ - sed -i "s@^PROP_NDK_PATH.*@PROP_NDK_PATH=$ANDORID_NDK@g" gradle.properties + sed -i "s@^PROP_NDK_PATH.*@PROP_NDK_PATH=$ANDROID_NDK@g" gradle.properties sed -i "s@^APPLICATION_ID.*@APPLICATION_ID=com.cocos.android@g" gradle.properties sed -i "s@^RES_PATH.*@RES_PATH=$ASSET_DIR@g" gradle.properties sed -i "s@^COCOS_ENGINE_PATH.*@COCOS_ENGINE_PATH=$NATIVE_ROOT@g" gradle.properties @@ -196,10 +215,161 @@ jobs: sed -i "s@^PROP_APP_ABI.*@PROP_APP_ABI=armeabi-v7a:arm64-v8a@g" gradle.properties echo "Compile Android - cmake ..." - echo "ANDORID_NDK ${ANDROID_NDK} or ${ANDROID_NDK_HOME}" + echo "ANDROID_NDK ${ANDROID_NDK} or ${ANDROID_NDK_HOME}" ./gradlew :CocosGame:assembleDebug --quiet echo "Compile Android Debug Done!" + compile_openharmony: + name: "Openharmony" + if: + (! contains(github.event.pull_request.body, '[X] does not change any runtime related code or build configuration')) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Download external libraries + shell: bash + run: | + EXT_VERSION=`node ./.github/workflows/get-native-external-version.js` + git clone --branch $EXT_VERSION --depth 1 https://github.com/cocos/cocos-engine-external native/external + - uses: actions/setup-java@v3 + id: setup-jdk + with: + distribution: 'zulu' + java-version: '17' + - name: Get oh sdk cache directory path + id: oh-sdk-cache-dir-path + run: | + echo "cache dir: " + echo "dir=$HOME/openharmony" >> $GITHUB_OUTPUT + + - name: Output cache dir + run: | + echo "Output cache dir: ${{ steps.oh-sdk-cache-dir-path.outputs.dir }}" + + - name: Cache OH SDK + id: cache-oh-sdk + uses: actions/cache@v3 + env: + cache-name: cache-oh-sdk-9 + with: + path: ${{ steps.oh-sdk-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-build-${{ env.cache-name }} + + - name: Add package.json + run: | + echo "{}" > package.json + echo "{\"name\": \"tests\",\"lockfileVersion\": 3,\"requires\": true,\"packages\": {}}" > package-lock.json + - uses: actions/setup-node@v3 + with: + node-version: 14 + cache: 'npm' + + - if: ${{ steps.cache-oh-sdk.outputs.cache-hit != 'true' }} + name: No Cache found, install oh sdk + continue-on-error: false + run: | + if [ ! -d "$HOME/openharmony" ]; then + mkdir -p $HOME/openharmony + echo "Download commandline-tools-linux.zip ..." + curl -o commandline-tools-linux.zip "https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_package_901_9/b1/v3/E6zhv5UFQ2-inIwNJhTN6Q/commandline-tools-linux-2.0.0.2.zip?HW-CC-KV=V1&HW-CC-Date=20230621T074401Z&HW-CC-Expire=315360000&HW-CC-Sign=621224257B02079B1E76C0A56FDF21483400B1E3556213F88DC79BC9BE7D595D" + echo "Unzip commandline-tools-linux.zip ..." + unzip commandline-tools-linux.zip -d $HOME/openharmony > /dev/null + cd $HOME/openharmony + ls -l + cd command-line-tools + echo "=============== PATCHING sdkmanager/bin/sdkmgr file ===============" + sed -i "s@-Dfile.encoding=UTF-8@-Dfile.encoding=UTF-8 -Duser.country=CN@g" ./sdkmanager/bin/sdkmgr + cd bin + ./sdkmgr list + echo "=============== INSTALL HOS toolchains:9 ===============" + ./sdkmgr install toolchains:9 --accept-license > /dev/null + echo "=============== INSTALL OH SDK ets:9 ===============" + ./sdkmgr install OpenHarmony/ets:9 --accept-license > /dev/null + echo "=============== INSTALL OH SDK js:9 ===============" + ./sdkmgr install OpenHarmony/js:9 --accept-license > /dev/null + echo "=============== INSTALL OH SDK native:9 ===============" + ./sdkmgr install OpenHarmony/native:9 --accept-license > /dev/null + echo "=============== INSTALL OH SDK toolchains:9 ===============" + ./sdkmgr install OpenHarmony/toolchains:9 --accept-license > /dev/null + echo "=============== INSTALL OH SDK DONE ===============" + ./sdkmgr list + fi + + - name: Compile for Openharmony + run: | + which node + which npm + which java + node -v + npm -v + java --version + echo "=============== list files in oh sdk ($HOME/openharmony) ===============" + pushd $HOME/openharmony + ls -l + popd + + NATIVE_ROOT=$GITHUB_WORKSPACE/native + echo "Compiling Openharmony ... " + + cd $GITHUB_WORKSPACE/templates/openharmony + + echo "message(STATUS \"hook before \${CC_TARGET_NAME}\")" >> Pre-Sample.cmake + echo "message(STATUS \"hook after \${CC_TARGET_NAME}\")" >> Post-Sample.cmake + + mkdir -p build-oh/proj + touch build-oh/proj/cfg.cmake + echo "set(CC_USE_GLES3 ON)" >> build-oh/proj/cfg.cmake + echo "set(CC_USE_VULKAN OFF)" >> build-oh/proj/cfg.cmake + echo "set(CC_USE_GLES2 ON)" >> build-oh/proj/cfg.cmake + echo "set(USE_WEBSOCKET_SERVER OFF)" >> build-oh/proj/cfg.cmake + echo "set(CMAKE_CXX_STANDARD_REQUIRED ON)" >> build-oh/proj/cfg.cmake + echo "set(COCOS_X_PATH $NATIVE_ROOT)" >> build-oh/proj/cfg.cmake + echo "set(CC_EXECUTABLE_NAME \"\")" >> build-oh/proj/cfg.cmake + + echo "=============== cat build-oh/proj/cfg.cmake ===============" + cat build-oh/proj/cfg.cmake + + mkdir -p build-oh/assets + + ASSET_DIR=$GITHUB_WORKSPACE/templates/openharmony/build-oh + + echo "=============== HACK ./entry/build-profile.json5 ===============" + sed -i "s@[^-]DRES_DIR[^=]@$ASSET_DIR@g" ./entry/build-profile.json5 + sed -i "s@[^-]DCOMMON_DIR[^=]@$GITHUB_WORKSPACE/templates/common@g" ./entry/build-profile.json5 + # To speedup CI, compile arm64-v8a only + sed -i "s@\"armeabi-v7a\",@@g" ./entry/build-profile.json5 + + echo "entry/build-profile.json5: " + cat ./entry/build-profile.json5 + + echo "=============== HACK ./hvigor/hvigor-wrapper.js ===============" + sed -i "s@HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,\[\"install\"\]@HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,\[\"install\", \"--lockfile=false\"\]@g" ./hvigor/hvigor-wrapper.js + + echo "=============== SET NPM OH REGISTRY ===============" + echo "@ohos:registry=https://repo.harmonyos.com/npm/" >> ~/.npmrc + npm config get @ohos:registry + npm config get registry + + echo "=============== UPDATE local.properties ===============" + echo "nodejs.dir=/usr/bin" >> local.properties + echo "hwsdk.dir=$HOME/openharmony/hwsdk" >> local.properties + + echo "=============== UPDATE ./hvigor/hvigor-config.json5 ===============" + echo "{\"hvigorVersion\":\"3.0.2\",\"dependencies\":{\"@ohos/hvigor-ohos-plugin\":\"3.0.2\"}}" > ./hvigor/hvigor-config.json5 + + echo "=============== Do not import game.ts for cocos_worker.ts ===============" + sed -i "s@import . launchEngine .@const window = globalThis;//@g" ./entry/src/main/ets/workers/cocos_worker.ts + sed -i 's@launchEngine().then@/*@g' ./entry/src/main/ets/workers/cocos_worker.ts + sed -i 's@window.oh.postMessage@*/window.oh.postMessage@g' ./entry/src/main/ets/workers/cocos_worker.ts + + echo "=============== EXECUTE hvigorw ===============" + ./hvigorw clean -i + ./hvigorw --stop-daemon -i + ./hvigorw assembleHap -p debuggable=true --no-daemon -d + #./hvigorw default@ProcessLibs -p debuggable=true --no-daemon -d + echo "=============== EXECUTE hvigorw DONE ===============" + + compile_mac_x86_64: name: "MacOS x86_64" if: diff --git a/.gitignore b/.gitignore index 229c3ea39a6..7ba394514c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ -/lib +lib/ +.turbo/ /bin /web.config .idea diff --git a/EngineErrorMap.md b/EngineErrorMap.md index 2302385d19e..0b373c2aa2c 100644 --- a/EngineErrorMap.md +++ b/EngineErrorMap.md @@ -168,6 +168,14 @@ Expected 'data' dict, but not found. Config file: %s Please load the resource first : %s +### 1102 + +Effect settings not found, effects will not be imported. + +### 1103 + +Success to load scene: %s + ### 1200 cocos2d: Director: Error in gettimeofday diff --git a/cc.config.json b/cc.config.json index ad9f279be52..cb74327075f 100644 --- a/cc.config.json +++ b/cc.config.json @@ -187,6 +187,7 @@ "modules": ["custom-pipeline"], "dependentAssets": [ "15049ccd-4dd7-451e-a8ae-af66735c929e", + "521c5f6e-1a26-42e2-8108-4400c912d9bf", "4c3ce6de-e6d1-47f7-aa36-36b9b58f72d3", "4361db28-3f24-44cc-8e51-32ee5fd651ac", "cafd95c9-c558-46f9-9812-1224b65c09ee", @@ -677,6 +678,12 @@ "type": "boolean", "value": false, "internal": true + }, + "CULL_MESHOPT": { + "comment": "An internal constant to indicate whether we cull the meshopt wasm module and asm.js module.", + "type": "boolean", + "value": true, + "internal": true } }, diff --git a/cocos/2d/components/mask.ts b/cocos/2d/components/mask.ts index a01247055d4..4cb13d13d42 100644 --- a/cocos/2d/components/mask.ts +++ b/cocos/2d/components/mask.ts @@ -456,11 +456,9 @@ export class Mask extends Component { protected _removeMaskNode (): void { if (this._sprite) { - this._sprite.destroy(); this._sprite = null; } if (this._graphics) { - this._graphics.destroy(); this._graphics = null; } } diff --git a/cocos/2d/components/sprite.ts b/cocos/2d/components/sprite.ts index e6d958d3814..4af575e7e5d 100644 --- a/cocos/2d/components/sprite.ts +++ b/cocos/2d/components/sprite.ts @@ -27,7 +27,7 @@ import { ccclass, help, executionOrder, menu, tooltip, displayOrder, type, range import { BUILD, EDITOR } from 'internal:constants'; import { SpriteAtlas } from '../assets/sprite-atlas'; import { SpriteFrame } from '../assets/sprite-frame'; -import { Vec2, cclegacy, ccenum, clamp, warn } from '../../core'; +import { Vec2, cclegacy, ccenum, clamp } from '../../core'; import { IBatcher } from '../renderer/i-batcher'; import { UIRenderer, InstanceMaterialType } from '../framework/ui-renderer'; import { PixelFormat } from '../../asset/assets/asset-enum'; @@ -480,9 +480,9 @@ export class Sprite extends UIRenderer { public __preload (): void { this.changeMaterialForDefine(); super.__preload(); - this._applySpriteSize(); if (EDITOR) { + this._resized(); this.node.on(NodeEventType.SIZE_CHANGED, this._resized, this); } } @@ -526,7 +526,7 @@ export class Sprite extends UIRenderer { */ public changeSpriteFrameFromAtlas (name: string): void { if (!this._atlas) { - warn('SpriteAtlas is null.'); + console.warn('SpriteAtlas is null.'); return; } const sprite = this._atlas.getSpriteFrame(name); diff --git a/cocos/3d/assets/mesh.ts b/cocos/3d/assets/mesh.ts index d064d93ddb0..5011a6e09d8 100644 --- a/cocos/3d/assets/mesh.ts +++ b/cocos/3d/assets/mesh.ts @@ -28,11 +28,11 @@ import { Asset } from '../../asset/assets/asset'; import { IDynamicGeometry } from '../../primitive/define'; import { BufferBlob } from '../misc/buffer-blob'; import { Skeleton } from './skeleton'; -import { geometry, cclegacy, sys, warnID, Mat4, Quat, Vec3, assertIsTrue, murmurhash2_32_gc, errorID } from '../../core'; +import { geometry, cclegacy, sys, warnID, Mat4, Quat, Vec3, assertIsTrue, murmurhash2_32_gc, errorID, halfToFloat } from '../../core'; import { RenderingSubMesh } from '../../asset/assets'; import { Attribute, Device, Buffer, BufferInfo, AttributeName, BufferUsageBit, Feature, Format, - FormatInfos, FormatType, MemoryUsageBit, PrimitiveMode, getTypedArrayConstructor, DrawInfo, FormatInfo, deviceManager, + FormatInfos, FormatType, MemoryUsageBit, PrimitiveMode, getTypedArrayConstructor, DrawInfo, FormatInfo, deviceManager, FormatFeatureBit, } from '../../gfx'; import { Morph } from './morph'; import { MorphRendering, createMorphRendering } from './morph-rendering'; @@ -409,6 +409,11 @@ export class Mesh extends Asset { if (this.struct.encoded) { // decode mesh data info = decodeMesh(info); } + if (this.struct.quantized + && !(deviceManager.gfxDevice.getFormatFeatures(Format.RGB16F) & FormatFeatureBit.VERTEX_ATTRIBUTE)) { + // dequantize mesh data + info = dequantizeMesh(info); + } this._struct = info.struct; this._data = info.data; @@ -1507,11 +1512,6 @@ export function decodeMesh (mesh: Mesh.ICreateInfo): Mesh.ICreateInfo { return mesh; } - // decode the mesh - if (!MeshoptDecoder.supported) { - return mesh; - } - const res_checker = (res: number): void => { if (res < 0) { errorID(14204, res); @@ -1581,4 +1581,150 @@ export function inflateMesh (mesh: Mesh.ICreateInfo): Mesh.ICreateInfo { return mesh; } +export function dequantizeMesh (mesh: Mesh.ICreateInfo): Mesh.ICreateInfo { + const struct = JSON.parse(JSON.stringify(mesh.struct)) as Mesh.IStruct; + + const bufferBlob = new BufferBlob(); + bufferBlob.setNextAlignment(0); + + function transformVertex ( + reader: ((offset: number) => number), + writer: ((offset: number, value: number) => void), + count: number, + components: number, + componentSize: number, + readerStride: number, + writerStride: number, + ): void { + for (let i = 0; i < count; i++) { + for (let j = 0; j < components; j++) { + const inputOffset = readerStride * i + componentSize * j; + const outputOffset = writerStride * i + componentSize * j; + writer(outputOffset, reader(inputOffset)); + } + } + } + + function dequantizeHalf ( + reader: ((offset: number) => number), + writer: ((offset: number, value: number) => void), + count: number, + components: number, + readerStride: number, + writerStride: number, + ): void { + for (let i = 0; i < count; i++) { + for (let j = 0; j < components; j++) { + const inputOffset = readerStride * i + 2 * j; + const outputOffset = writerStride * i + 4 * j; + const value = halfToFloat(reader(inputOffset)); + writer(outputOffset, value); + } + } + } + + for (let i = 0; i < struct.vertexBundles.length; ++i) { + const bundle = struct.vertexBundles[i]; + const view = bundle.view; + const attributes = bundle.attributes; + const oldAttributes = mesh.struct.vertexBundles[i].attributes; + const strides: number[] = []; + const dequantizes: boolean[] = []; + const readers: ((offset: number) => number)[] = []; + for (let j = 0; j < attributes.length; ++j) { + const attr = attributes[j]; + const inputView = new DataView(mesh.data.buffer, view.offset + getOffset(oldAttributes, j)); + const reader = getReader(inputView, attr.format); + let dequantize = true; + switch (attr.format) { + case Format.R16F: + attr.format = Format.R32F; + break; + case Format.RG16F: + attr.format = Format.RG32F; + break; + case Format.RGB16F: + attr.format = Format.RGB32F; + break; + case Format.RGBA16F: + attr.format = Format.RGBA32F; + break; + default: + dequantize = false; + break; + } + strides.push(FormatInfos[attr.format].size); + dequantizes.push(dequantize); + readers.push(reader!); + } + const netStride = strides.reduce((acc, cur) => acc + cur, 0); + const newBuffer = new Uint8Array(netStride * view.count); + for (let j = 0; j < attributes.length; ++j) { + const attribute = attributes[j]; + const reader = readers[j]; + const outputView = new DataView(newBuffer.buffer, getOffset(attributes, j)); + const writer = getWriter(outputView, attribute.format)!; + const dequantize = dequantizes[j]; + const formatInfo = FormatInfos[attribute.format]; + if (dequantize) { + dequantizeHalf( + reader, + writer, + view.count, + formatInfo.count, + view.stride, + netStride, + ); + } else { + transformVertex( + reader, + writer, + view.count, + formatInfo.count, + formatInfo.size / formatInfo.count, + view.stride, + netStride, + ); + } + } + + bufferBlob.setNextAlignment(netStride); + const newView: Mesh.IBufferView = { + offset: bufferBlob.getLength(), + length: newBuffer.byteLength, + count: view.count, + stride: netStride, + }; + bundle.view = newView; + bufferBlob.addBuffer(newBuffer); + } + + // dump index buffer + for (const primitive of struct.primitives) { + if (primitive.indexView === undefined) { + continue; + } + const view = primitive.indexView; + const buffer = new Uint8Array(mesh.data.buffer, view.offset, view.length); + bufferBlob.setNextAlignment(view.stride); + const newView: Mesh.IBufferView = { + offset: bufferBlob.getLength(), + length: buffer.byteLength, + count: view.count, + stride: view.stride, + }; + primitive.indexView = newView; + bufferBlob.addBuffer(buffer); + } + + const data = new Uint8Array(bufferBlob.getCombined()); + + struct.quantized = false; + + return { + struct, + data, + }; +} + // function get diff --git a/cocos/3d/framework/mesh-renderer.ts b/cocos/3d/framework/mesh-renderer.ts index 9869186e7d1..8c4543f3182 100644 --- a/cocos/3d/framework/mesh-renderer.ts +++ b/cocos/3d/framework/mesh-renderer.ts @@ -899,6 +899,7 @@ export class MeshRenderer extends ModelRenderer { if (this._mesh) { const meshStruct = this._mesh.struct; this._model.createBoundingShape(meshStruct.minPosition, meshStruct.maxPosition); + this._model.updateWorldBound(); } // Initialize lighting map before model initializing // because the lighting map will influence the model's shader diff --git a/cocos/3d/misc/mesh-codec.ts b/cocos/3d/misc/mesh-codec.ts index b6ed3862bc2..f875a7a0571 100644 --- a/cocos/3d/misc/mesh-codec.ts +++ b/cocos/3d/misc/mesh-codec.ts @@ -21,13 +21,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -import meshopt_asm_factory from 'external:emscripten/meshopt/meshopt_decoder.asm.js'; -import meshopt_wasm_factory from 'external:emscripten/meshopt/meshopt_decoder.wasm.js'; -import meshopt_wasm_url from 'external:emscripten/meshopt/meshopt_decoder.wasm.wasm'; - -import { WASM_SUPPORT_MODE } from 'internal:constants'; -import { instantiateWasm } from 'pal/wasm'; +import { CULL_MESHOPT, WASM_SUPPORT_MODE } from 'internal:constants'; +import { ensureWasmModuleReady, instantiateWasm } from 'pal/wasm'; import { sys, logID } from '../../core'; @@ -36,51 +31,65 @@ import { WebAssemblySupportMode } from '../../misc/webassembly-support'; export const MeshoptDecoder = {} as any; -function initDecoderASM (): Promise { - const Module = meshopt_asm_factory; - return Promise.all([Module.ready]).then(() => { - MeshoptDecoder.supported = true; +function initDecoderASM (asm_factory: any): Promise { + return Promise.all([asm_factory.ready]).then(() => { + MeshoptDecoder.supported = asm_factory.supported; MeshoptDecoder.ready = Promise.resolve(); - MeshoptDecoder.decodeVertexBuffer = Module.decodeVertexBuffer; - MeshoptDecoder.decodeIndexBuffer = Module.decodeIndexBuffer; - MeshoptDecoder.decodeIndexSequence = Module.decodeIndexSequence; - MeshoptDecoder.decodeGltfBuffer = Module.decodeGltfBuffer; - MeshoptDecoder.useWorkers = Module.useWorkers; - MeshoptDecoder.decodeGltfBufferAsync = Module.decodeGltfBufferAsync; + MeshoptDecoder.decodeVertexBuffer = asm_factory.decodeVertexBuffer; + MeshoptDecoder.decodeIndexBuffer = asm_factory.decodeIndexBuffer; + MeshoptDecoder.decodeIndexSequence = asm_factory.decodeIndexSequence; + MeshoptDecoder.decodeGltfBuffer = asm_factory.decodeGltfBuffer; + MeshoptDecoder.useWorkers = asm_factory.useWorkers; + MeshoptDecoder.decodeGltfBufferAsync = asm_factory.decodeGltfBufferAsync; logID(14202); }); } -function initDecoderWASM (): Promise { - const Module = meshopt_wasm_factory; +function initDecoderWASM (wasm_factory: any, wasm_url: string): Promise { function instantiate (importObject: WebAssembly.Imports): any { - return instantiateWasm(meshopt_wasm_url, importObject) as any; + return instantiateWasm(wasm_url, importObject) as any; } - return Promise.all([Module.ready(instantiate)]).then(() => { - MeshoptDecoder.supported = true; + return Promise.all([wasm_factory.ready(instantiate)]).then(() => { + MeshoptDecoder.supported = wasm_factory.supported; MeshoptDecoder.ready = Promise.resolve(); - MeshoptDecoder.decodeVertexBuffer = Module.decodeVertexBuffer; - MeshoptDecoder.decodeIndexBuffer = Module.decodeIndexBuffer; - MeshoptDecoder.decodeIndexSequence = Module.decodeIndexSequence; - MeshoptDecoder.decodeGltfBuffer = Module.decodeGltfBuffer; - MeshoptDecoder.useWorkers = Module.useWorkers; - MeshoptDecoder.decodeGltfBufferAsync = Module.decodeGltfBufferAsync; + MeshoptDecoder.decodeVertexBuffer = wasm_factory.decodeVertexBuffer; + MeshoptDecoder.decodeIndexBuffer = wasm_factory.decodeIndexBuffer; + MeshoptDecoder.decodeIndexSequence = wasm_factory.decodeIndexSequence; + MeshoptDecoder.decodeGltfBuffer = wasm_factory.decodeGltfBuffer; + MeshoptDecoder.useWorkers = wasm_factory.useWorkers; + MeshoptDecoder.decodeGltfBufferAsync = wasm_factory.decodeGltfBufferAsync; logID(14203); }); } -export function InitDecoder (): Promise { +function shouldUseWasmModule (): boolean { if (WASM_SUPPORT_MODE === (WebAssemblySupportMode.MAYBE_SUPPORT as number)) { - if (sys.hasFeature(sys.Feature.WASM)) { - return initDecoderWASM(); - } else { - return initDecoderASM(); - } + return sys.hasFeature(sys.Feature.WASM); } else if (WASM_SUPPORT_MODE === (WebAssemblySupportMode.SUPPORT as number)) { - return initDecoderWASM(); + return true; } else { - return initDecoderASM(); + return false; } } -game.onPostInfrastructureInitDelegate.add(InitDecoder); +export function InitDecoder (): Promise { + return ensureWasmModuleReady().then(() => Promise.all([ + import('external:emscripten/meshopt/meshopt_decoder.asm.js'), + import('external:emscripten/meshopt/meshopt_decoder.wasm.js'), + import('external:emscripten/meshopt/meshopt_decoder.wasm.wasm'), + ]).then(([ + { default: meshopt_asm_factory }, + { default: meshopt_wasm_factory }, + { default: meshopt_wasm_url }, + ]) => { + if (shouldUseWasmModule()) { + return initDecoderWASM(meshopt_wasm_factory, meshopt_wasm_url); + } else { + return initDecoderASM(meshopt_asm_factory); + } + })); +} + +if (!CULL_MESHOPT) { + game.onPostInfrastructureInitDelegate.add(InitDecoder); +} diff --git a/cocos/3d/reflection-probe/reflection-probe-component.ts b/cocos/3d/reflection-probe/reflection-probe-component.ts index 3708c0493a3..a4fe36a18c8 100644 --- a/cocos/3d/reflection-probe/reflection-probe-component.ts +++ b/cocos/3d/reflection-probe/reflection-probe-component.ts @@ -192,6 +192,7 @@ export class ReflectionProbe extends Component { * @zh 相机的缓冲清除标志位,指定帧缓冲的哪部分要每帧清除。 */ @type(Enum(ProbeClearFlag)) + @visible(function (this: ReflectionProbe) { return this.probeType === ProbeType.CUBE; }) set clearFlag (value: number) { this._clearFlag = value; this.probe.clearFlag = this._clearFlag; @@ -204,7 +205,7 @@ export class ReflectionProbe extends Component { * @en Clearing color of the camera. * @zh 相机的颜色缓冲默认值。 */ - @visible(function (this: ReflectionProbe) { return this._clearFlag === ProbeClearFlag.SOLID_COLOR; }) + @visible(function (this: ReflectionProbe) { return this._clearFlag === ProbeClearFlag.SOLID_COLOR && this.probeType === ProbeType.CUBE; }) @type(Color) set backgroundColor (val: Color) { this._backgroundColor = val; diff --git a/cocos/asset/assets/material.jsb.ts b/cocos/asset/assets/material.jsb.ts index 5a4c9e89d78..1f18f9811a3 100644 --- a/cocos/asset/assets/material.jsb.ts +++ b/cocos/asset/assets/material.jsb.ts @@ -152,6 +152,8 @@ matProto.setProperty = function (name: string, val: MaterialPropertyFull | Mater wrapSetProperty(this.setPropertyTextureBase, this, name, val, passIdx); } else if (val instanceof Texture) { wrapSetProperty(this.setPropertyGFXTexture, this, name, val, passIdx); + } else if ((val as any) instanceof cclegacy.gfx.Texture) { + wrapSetProperty(this.setPropertyGFXTexture, this, name, val, passIdx); } else if (val === null) { if (passIdx) { this.setPropertyNull(name, passIdx); diff --git a/cocos/core/platform/macro.ts b/cocos/core/platform/macro.ts index c27506d7dd4..612e15e4a0e 100644 --- a/cocos/core/platform/macro.ts +++ b/cocos/core/platform/macro.ts @@ -987,9 +987,9 @@ interface Macro { /** * @en - * Used to set float output, the default value is false. + * Used to set float output render target, more accurate multiple light sources, fog, and translucent effects, custom pipeline only, the default value is false. * @zh - * 用于开启浮点格式的输出, 默认值为 false。 + * 用于开启浮点格式的RT输出, 更精确的多光源、雾化和半透明效果, 仅用于自定义管线, 默认值为 false。 * @default false */ ENABLE_FLOAT_OUTPUT: boolean; diff --git a/cocos/game/game.ts b/cocos/game/game.ts index 14086b18be7..bf8fed9532e 100644 --- a/cocos/game/game.ts +++ b/cocos/game/game.ts @@ -29,7 +29,7 @@ import { findCanvas, loadJsFile } from 'pal/env'; import { Pacer } from 'pal/pacer'; import { ConfigOrientation } from 'pal/screen-adapter'; import assetManager, { IAssetManagerOptions } from '../asset/asset-manager/asset-manager'; -import { EventTarget, AsyncDelegate, sys, macro, VERSION, cclegacy, screen, Settings, settings, assert, garbageCollectionManager, DebugMode, warn, log, _resetDebugSetting } from '../core'; +import { EventTarget, AsyncDelegate, sys, macro, VERSION, cclegacy, screen, Settings, settings, assert, garbageCollectionManager, DebugMode, warn, log, _resetDebugSetting, errorID, logID } from '../core'; import { input } from '../input'; import { deviceManager, LegacyRenderMode } from '../gfx'; import { SplashScreen } from './splash-screen'; @@ -713,6 +713,8 @@ export class Game extends EventTarget { * @param config - Pass configuration object */ public init (config: IGameConfig): Promise { + let time = performance.now() + let startTime = time this._compatibleWithOldParams(config); // DONT change the order unless you know what's you doing return Promise.resolve() @@ -723,7 +725,9 @@ export class Game extends EventTarget { }) .then((): void => { if (DEBUG) { - console.time('Init Base'); + // eslint-disable-next-line no-console + // console.time('Init Base'); + time = performance.now() } const debugMode = config.debugMode || DebugMode.NONE; _resetDebugSetting(debugMode); @@ -735,7 +739,13 @@ export class Game extends EventTarget { .then((): Promise => settings.init(config.settingsPath, config.overrideSettings)) .then((): Promise => { if (DEBUG) { - console.timeEnd('Init Base'); + // eslint-disable-next-line no-console + // console.timeEnd('Init Base'); + + let last = time + time = performance.now() + log(`------ Init Base : ${(time - last) / 1000} s`) + } this.emit(Game.EVENT_POST_BASE_INIT); return this.onPostBaseInitDelegate.dispatch(); @@ -748,7 +758,8 @@ export class Game extends EventTarget { }) .then((): void => { if (DEBUG) { - console.time('Init Infrastructure'); + // eslint-disable-next-line no-console + // console.time('Init Infrastructure'); } macro.init(); this._initXR(); @@ -769,7 +780,12 @@ export class Game extends EventTarget { Layers.init(); this.initPacer(); if (DEBUG) { - console.timeEnd('Init Infrastructure'); + // eslint-disable-next-line no-console + // console.timeEnd('Init Infrastructure'); + + let last = time + time = performance.now() + log(`------ Init Infrastructure : ${(time - last) / 1000} s`) } }) .then((): Promise => { @@ -795,27 +811,40 @@ export class Game extends EventTarget { } const data = effectSettings.data; if (data === null) { - console.error('Effect settings not found, effects will not be imported.'); + errorID(1102); return; } cclegacy.rendering.init(deviceManager.gfxDevice, data); }) + .then((): Promise => { + const scriptPackages = settings.querySettings(Settings.Category.SCRIPTING, 'scriptPackages'); + if (scriptPackages) { + return Promise.all(scriptPackages.map((pack): Promise => import(pack))); + } + return Promise.resolve([]); + }) .then((): Promise => { if (DEBUG) { - console.time('Init SubSystem'); + // eslint-disable-next-line no-console + // console.time('Init SubSystem'); } director.init(); return builtinResMgr.loadBuiltinAssets(); }) .then((): Promise => { if (DEBUG) { - console.timeEnd('Init SubSystem'); + // eslint-disable-next-line no-console + // console.timeEnd('Init SubSystem'); + + let last = time + time = performance.now() + log(`------ Init SubSystem : ${(time - last) / 1000} s`) } this.emit(Game.EVENT_POST_SUBSYSTEM_INIT); return this.onPostSubsystemInitDelegate.dispatch(); }) .then((): void => { - console.log(`Cocos Creator v${VERSION}`); + log(`------ Cocos Creator v${VERSION}`); this.emit(Game.EVENT_ENGINE_INITED); this._engineInited = true; }) @@ -827,7 +856,8 @@ export class Game extends EventTarget { }) .then((): Promise => { if (DEBUG) { - console.time('Init Project'); + // eslint-disable-next-line no-console + // console.time('Init Project'); } const jsList = settings.querySettings(Settings.Category.PLUGINS, 'jsList'); let promise = Promise.resolve(); @@ -838,13 +868,6 @@ export class Game extends EventTarget { } return promise; }) - .then((): Promise => { - const scriptPackages = settings.querySettings(Settings.Category.SCRIPTING, 'scriptPackages'); - if (scriptPackages) { - return Promise.all(scriptPackages.map((pack): Promise => import(pack))); - } - return Promise.resolve([]); - }) .then((): Promise => this._loadProjectBundles()) .then((): Promise => this._loadCCEScripts()) .then((): void | Promise => this._setupRenderPipeline()) @@ -855,7 +878,12 @@ export class Game extends EventTarget { }) .then((): Promise => { if (DEBUG) { - console.timeEnd('Init Project'); + // eslint-disable-next-line no-console + let last = time + time = performance.now() + log(`------ Init Project : ${(time - last) / 1000} s`) + + // console.timeEnd('Init Project'); } this.emit(Game.EVENT_POST_PROJECT_INIT); return this.onPostProjectInitDelegate.dispatch(); @@ -864,6 +892,8 @@ export class Game extends EventTarget { .then((): void => { this._inited = true; this._safeEmit(Game.EVENT_GAME_INITED); + + log(`------ game.init : ${(performance.now() - startTime) / 1000} s`) }); } @@ -1013,11 +1043,11 @@ export class Game extends EventTarget { SplashScreen.instance.update(this._calculateDT(false)); } else if (this._shouldLoadLaunchScene) { this._shouldLoadLaunchScene = false; - const launchScene = settings.querySettings(Settings.Category.LAUNCH, 'launchScene'); + const launchScene = settings.querySettings(Settings.Category.LAUNCH, 'launchScene') as string; if (launchScene) { // load scene director.loadScene(launchScene, (): void => { - console.log(`Success to load scene: ${launchScene}`); + logID(1103, launchScene); this._initTime = performance.now(); director.startAnimation(); this.onStart?.(); @@ -1098,7 +1128,7 @@ export class Game extends EventTarget { } private _setupRenderPipeline (): void | Promise { - const renderPipeline = settings.querySettings(Settings.Category.RENDERING, 'renderPipeline'); + const renderPipeline = settings.querySettings(Settings.Category.RENDERING, 'renderPipeline') as string; if (!renderPipeline) { return this._setRenderPipeline(); } @@ -1124,7 +1154,7 @@ export class Game extends EventTarget { this._safeEmit(Game.EVENT_RENDERER_INITED); } - private _safeEmit (event): void { + private _safeEmit (event: string | number): void { if (EDITOR) { try { this.emit(event); diff --git a/cocos/gfx/base/framebuffer.ts b/cocos/gfx/base/framebuffer.ts index 71c04e1f54b..d609db6bd67 100644 --- a/cocos/gfx/base/framebuffer.ts +++ b/cocos/gfx/base/framebuffer.ts @@ -55,9 +55,19 @@ export abstract class Framebuffer extends GFXObject { return this._depthStencilTexture; } + public get width (): number { + return this._width; + } + + public get height (): number { + return this._height; + } + protected _renderPass: RenderPass | null = null; protected _colorTextures: (Texture | null)[] = []; protected _depthStencilTexture: Texture | null = null; + protected _width: number = 0; + protected _height: number = 0; constructor () { super(ObjectType.FRAMEBUFFER); diff --git a/cocos/gfx/webgl/webgl-framebuffer.ts b/cocos/gfx/webgl/webgl-framebuffer.ts index aeab6338e91..448239c19c6 100644 --- a/cocos/gfx/webgl/webgl-framebuffer.ts +++ b/cocos/gfx/webgl/webgl-framebuffer.ts @@ -96,6 +96,8 @@ export class WebGLFramebuffer extends Framebuffer { }; WebGLCmdFuncCreateFramebuffer(WebGLDeviceManager.instance, this._gpuFramebuffer); + this._width = this._gpuFramebuffer.width; + this._height = this._gpuFramebuffer.height; } public destroy (): void { diff --git a/cocos/gfx/webgl2/states/webgl2-sampler.ts b/cocos/gfx/webgl2/states/webgl2-sampler.ts index f1af1ca9bfc..74b6c51ad3c 100644 --- a/cocos/gfx/webgl2/states/webgl2-sampler.ts +++ b/cocos/gfx/webgl2/states/webgl2-sampler.ts @@ -36,6 +36,8 @@ export class WebGL2Sampler extends Sampler { private _gpuSampler: IWebGL2GPUSampler | null = null; + static MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0 + constructor (info: Readonly, hash: number) { super(info, hash); @@ -48,6 +50,8 @@ export class WebGL2Sampler extends Sampler { addressV: this._info.addressV, addressW: this._info.addressW, + maxAnisotropy: this._info.maxAnisotropy, + glMinFilter: 0, glMagFilter: 0, glWrapS: 0, @@ -68,6 +72,17 @@ export class WebGL2Sampler extends Sampler { gl.samplerParameteri(glSampler, gl.TEXTURE_WRAP_R, this.glWrapR); gl.samplerParameterf(glSampler, gl.TEXTURE_MIN_LOD, minLod); gl.samplerParameterf(glSampler, gl.TEXTURE_MAX_LOD, maxLod); + + if (this.maxAnisotropy > 1) { + let EXT_texture_filter_anisotropic = device.extensions.EXT_texture_filter_anisotropic + if (EXT_texture_filter_anisotropic) { + if (!WebGL2Sampler.MAX_TEXTURE_MAX_ANISOTROPY_EXT) { + WebGL2Sampler.MAX_TEXTURE_MAX_ANISOTROPY_EXT = gl.getParameter(EXT_texture_filter_anisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT) + } + gl.samplerParameterf(glSampler, EXT_texture_filter_anisotropic.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(this.maxAnisotropy, WebGL2Sampler.MAX_TEXTURE_MAX_ANISOTROPY_EXT)); + } + } + } } const sampler = this.glSamplers.get(samplerHash)!; diff --git a/cocos/gfx/webgl2/webgl2-commands.ts b/cocos/gfx/webgl2/webgl2-commands.ts index 80f4caab35c..2d4337c37cf 100644 --- a/cocos/gfx/webgl2/webgl2-commands.ts +++ b/cocos/gfx/webgl2/webgl2-commands.ts @@ -1605,6 +1605,14 @@ export function WebGL2CmdFuncCreateShader (device: WebGL2Device, gpuShader: IWeb gl.shaderSource(gpuStage.glShader, `#version 300 es\n${gpuStage.source}`); gl.compileShader(gpuStage.glShader); + if (glShaderType === gl.FRAGMENT_SHADER) { + if (window.onGLShaderCompiled) { + window.onGLShaderCompiled(gpuShader); + } + device.addCompiledShaderNames(gpuShader.name); + console.log(`Compile Shader ${gpuStage.type}: ${gpuShader.name}`) + } + if (!gl.getShaderParameter(gpuStage.glShader, gl.COMPILE_STATUS)) { error(`${shaderTypeStr} in '${gpuShader.name}' compilation failed.`); error('Shader source dump:', gpuStage.source.replace(/^|\n/g, (): string => `\n${lineNumber++} `)); diff --git a/cocos/gfx/webgl2/webgl2-device.ts b/cocos/gfx/webgl2/webgl2-device.ts index c46c3e65395..fef555d3a3a 100644 --- a/cocos/gfx/webgl2/webgl2-device.ts +++ b/cocos/gfx/webgl2/webgl2-device.ts @@ -56,9 +56,9 @@ import { CommandBufferType, DescriptorSetLayoutInfo, DescriptorSetInfo, PipelineLayoutInfo, BufferViewInfo, CommandBufferInfo, BufferInfo, FramebufferInfo, InputAssemblerInfo, QueueInfo, RenderPassInfo, SamplerInfo, ShaderInfo, TextureInfo, TextureViewInfo, DeviceInfo, GeneralBarrierInfo, TextureBarrierInfo, - BufferBarrierInfo, QueueType, API, Feature, BufferTextureCopy, SwapchainInfo, FormatFeature, Format, FormatFeatureBit, + BufferBarrierInfo, QueueType, API, Feature, BufferTextureCopy, SwapchainInfo, FormatFeature, Format, FormatFeatureBit, TextureBlit, Filter, Rect, } from '../base/define'; -import { WebGL2CmdFuncCopyTextureToBuffers, WebGL2CmdFuncCopyBuffersToTexture, WebGL2CmdFuncCopyTexImagesToTexture } from './webgl2-commands'; +import { WebGL2CmdFuncCopyTextureToBuffers, WebGL2CmdFuncCopyBuffersToTexture, WebGL2CmdFuncCopyTexImagesToTexture, WebGL2CmdFuncBlitTexture, WebGL2CmdFuncBlitFramebuffer } from './webgl2-commands'; import { GeneralBarrier } from '../base/states/general-barrier'; import { TextureBarrier } from '../base/states/texture-barrier'; import { BufferBarrier } from '../base/states/buffer-barrier'; @@ -108,6 +108,14 @@ export class WebGL2Device extends Device { protected _textureExclusive = new Array(Format.COUNT); + compiledShaderNames:string[] = [] + getCompiledShaderNames() { + return this.compiledShaderNames; + } + addCompiledShaderNames(name) { + this.compiledShaderNames.push(name); + } + public initialize (info: Readonly): boolean { WebGL2DeviceManager.setInstance(this); this._gfxAPI = API.WEBGL2; @@ -631,4 +639,36 @@ export class WebGL2Device extends Device { regions, ); } + + public blitTexture ( + srcTex: Readonly, + dstTex: Texture, + regions: Readonly, + filter: Filter + ): void { + WebGL2CmdFuncBlitTexture( + this, + (srcTex as WebGL2Texture).gpuTexture, + (dstTex as WebGL2Texture).gpuTexture, + regions, + filter + ); + } + + public blitFramebuffer ( + srcFramebuffer: Readonly, + dstFramebuffer: Framebuffer, + srcRect: Readonly, + dstRect: Readonly, + filter: Filter + ): void { + WebGL2CmdFuncBlitFramebuffer( + this, + (srcFramebuffer as WebGL2Framebuffer).gpuFramebuffer, + (dstFramebuffer as WebGL2Framebuffer).gpuFramebuffer, + srcRect, + dstRect, + filter + ); + } } diff --git a/cocos/gfx/webgl2/webgl2-framebuffer.ts b/cocos/gfx/webgl2/webgl2-framebuffer.ts index 255c7a9a6b3..539857308ce 100644 --- a/cocos/gfx/webgl2/webgl2-framebuffer.ts +++ b/cocos/gfx/webgl2/webgl2-framebuffer.ts @@ -90,6 +90,8 @@ export class WebGL2Framebuffer extends Framebuffer { }; WebGL2CmdFuncCreateFramebuffer(WebGL2DeviceManager.instance, this._gpuFramebuffer); + this._width = this._gpuFramebuffer.width; + this._height = this._gpuFramebuffer.height; } public destroy (): void { diff --git a/cocos/gfx/webgl2/webgl2-gpu-objects.ts b/cocos/gfx/webgl2/webgl2-gpu-objects.ts index 1cdec040420..81bfa13037c 100644 --- a/cocos/gfx/webgl2/webgl2-gpu-objects.ts +++ b/cocos/gfx/webgl2/webgl2-gpu-objects.ts @@ -136,6 +136,8 @@ export interface IWebGL2GPUTexture { flags: TextureFlags; isPowerOf2: boolean; + anisotropy: number; + glTarget: GLenum; glInternalFmt: GLenum; glFormat: GLenum; @@ -190,6 +192,8 @@ export interface IWebGL2GPUSampler { glWrapT: GLenum; glWrapR: GLenum; + maxAnisotropy: number; + getGLSampler (device: WebGL2Device, minLod: number, maxLod: number): WebGLSampler; } diff --git a/cocos/misc/camera-component.ts b/cocos/misc/camera-component.ts index e4201ecfcbd..2c2067e5d5e 100644 --- a/cocos/misc/camera-component.ts +++ b/cocos/misc/camera-component.ts @@ -313,7 +313,7 @@ export class Camera extends Component { */ @type(FOVAxis) @displayOrder(7) - @visible(function (this: Camera): boolean { + @visible(function visible (this: Camera): boolean { return this._projection === ProjectionType.PERSPECTIVE; }) @tooltip('i18n:camera.fov_axis') @@ -354,10 +354,10 @@ export class Camera extends Component { * @zh 正交模式下的相机视角高度。 */ @displayOrder(9) - @visible(function (this: Camera): boolean { + @visible(function visible (this: Camera): boolean { return this._projection === ProjectionType.ORTHO; }) - @rangeMin(1) + @rangeMin(1e-6) @tooltip('i18n:camera.ortho_height') get orthoHeight (): number { return this._orthoHeight; diff --git a/cocos/physics-2d/box2d-wasm/instantiated.ts b/cocos/physics-2d/box2d-wasm/instantiated.ts index 5156374fd49..023cb80afe1 100644 --- a/cocos/physics-2d/box2d-wasm/instantiated.ts +++ b/cocos/physics-2d/box2d-wasm/instantiated.ts @@ -35,7 +35,8 @@ export const B2 = {} as any; export function getImplPtr (wasmObject: any): number { // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return (wasmObject).$$.ptr; + if (!wasmObject) return 0; + return (wasmObject).$$.ptr as number; } /** diff --git a/cocos/physics-2d/box2d-wasm/joints/joint-2d.ts b/cocos/physics-2d/box2d-wasm/joints/joint-2d.ts index 2f0990e0d6b..0f4c964861b 100644 --- a/cocos/physics-2d/box2d-wasm/joints/joint-2d.ts +++ b/cocos/physics-2d/box2d-wasm/joints/joint-2d.ts @@ -22,7 +22,7 @@ THE SOFTWARE. */ -import { B2, addImplPtrReference, addImplPtrReferenceWASM, getImplPtr } from '../instantiated'; +import { B2, addImplPtrReference, addImplPtrReferenceWASM, getImplPtr, removeImplPtrReference, removeImplPtrReferenceWASM } from '../instantiated'; import { IJoint2D } from '../../spec/i-physics-joint'; import { Joint2D, PhysicsSystem2D, RigidBody2D } from '../../framework'; import { B2PhysicsWorld } from '../physics-world'; @@ -54,7 +54,7 @@ export class B2Joint implements IJoint2D { } onDisable (): void { - PhysicsSystem2D.instance._callAfterStep(this, this._destroy); + PhysicsSystem2D.instance._callAfterStep(this, this.destroy); } // need init after body and connected body init @@ -106,9 +106,11 @@ export class B2Joint implements IJoint2D { this._inited = true; } - _destroy (): void { + destroy (): void { if (!this._inited) return; + removeImplPtrReference(getImplPtr(this._b2joint)); + removeImplPtrReferenceWASM(getImplPtr(this._b2joint)); (PhysicsSystem2D.instance.physicsWorld as B2PhysicsWorld).impl.DestroyJoint(this._b2joint!); this._b2joint = null; diff --git a/cocos/physics-2d/box2d-wasm/joints/mouse-joint.ts b/cocos/physics-2d/box2d-wasm/joints/mouse-joint.ts index f5d359056da..51f73a9cfd2 100644 --- a/cocos/physics-2d/box2d-wasm/joints/mouse-joint.ts +++ b/cocos/physics-2d/box2d-wasm/joints/mouse-joint.ts @@ -118,7 +118,7 @@ export class B2MouseJoint extends B2Joint implements IMouseJoint { } onTouchEnd (event: Touch): void { - this._destroy(); + this.destroy(); this._isTouched = false; } diff --git a/cocos/physics-2d/box2d-wasm/rigid-body.ts b/cocos/physics-2d/box2d-wasm/rigid-body.ts index feb13037e4c..a92e0533863 100644 --- a/cocos/physics-2d/box2d-wasm/rigid-body.ts +++ b/cocos/physics-2d/box2d-wasm/rigid-body.ts @@ -22,7 +22,7 @@ THE SOFTWARE. */ -import { B2 } from './instantiated'; +import { B2, getTSObjectFromWASMObject, getTSObjectFromWASMObjectPtr } from './instantiated'; import { IRigidBody2D } from '../spec/i-rigid-body'; import { RigidBody2D } from '../framework/components/rigid-body-2d'; import { PhysicsSystem2D } from '../framework/physics-system'; @@ -31,8 +31,10 @@ import { Vec2, toRadian, Vec3, Quat, IVec2Like, toDegree, TWO_PI, HALF_PI } from import { PHYSICS_2D_PTM_RATIO, ERigidBody2DType } from '../framework/physics-types'; import { Node } from '../../scene-graph/node'; -import { Collider2D } from '../framework'; +import { Collider2D, Joint2D } from '../framework'; import { NodeEventType } from '../../scene-graph/node-event'; +import { B2Shape2D } from './shapes/shape-2d'; +import { B2Joint } from './joints/joint-2d'; const tempVec3 = new Vec3(); const tempVec2_1 = { x: 0, y: 0 };//new B2.Vec2(0, 0); @@ -114,6 +116,29 @@ export class B2RigidBody2D implements IRigidBody2D { _destroy (): void { if (!this._inited) return; + //collect all fixtures attached to this rigid body and process them + const fixtureList = this.impl?.GetFixtureList(); + if (fixtureList) { + let shapeTSObj = getTSObjectFromWASMObject(fixtureList); + while (shapeTSObj && shapeTSObj.impl) { + shapeTSObj.destroy(); + const nextFixture = fixtureList.GetNext(); + shapeTSObj = getTSObjectFromWASMObject(nextFixture); + } + } + + //collect all joints attached to this rigid body and process them + const jointListPtr = this.impl?.GetJointList(); + if (jointListPtr) { + let jointWASMPtr = B2.JointEdgeGetJoint(jointListPtr) as number; + let jointTSObj = getTSObjectFromWASMObjectPtr(jointWASMPtr); + while (jointTSObj) { + jointTSObj.destroy(); + jointWASMPtr = B2.JointEdgeGetNext(jointListPtr) as number; + jointTSObj = getTSObjectFromWASMObjectPtr(jointWASMPtr); + } + } + (PhysicsSystem2D.instance.physicsWorld as B2PhysicsWorld).removeBody(this); this._inited = false; diff --git a/cocos/physics-2d/box2d-wasm/shapes/shape-2d.ts b/cocos/physics-2d/box2d-wasm/shapes/shape-2d.ts index 5f102e03580..84ab4a5881b 100644 --- a/cocos/physics-2d/box2d-wasm/shapes/shape-2d.ts +++ b/cocos/physics-2d/box2d-wasm/shapes/shape-2d.ts @@ -77,7 +77,7 @@ export class B2Shape2D implements IBaseShape { } onDisable (): void { - PhysicsSystem2D.instance._callAfterStep(this, this._destroy); + PhysicsSystem2D.instance._callAfterStep(this, this.destroy); } start (): void { @@ -92,7 +92,7 @@ export class B2Shape2D implements IBaseShape { } apply (): void { - this._destroy(); + this.destroy(); if (this.collider.enabledInHierarchy) { this._init(); } @@ -200,7 +200,7 @@ export class B2Shape2D implements IBaseShape { this._inited = true; } - _destroy (): void { + destroy (): void { if (!this._inited) return; const fixtures = this._fixtures; diff --git a/cocos/physics/framework/deprecated.ts b/cocos/physics/framework/deprecated.ts index 6a9d9519d11..fdb15eec610 100644 --- a/cocos/physics/framework/deprecated.ts +++ b/cocos/physics/framework/deprecated.ts @@ -148,12 +148,6 @@ removeProperty(RigidBody.prototype, 'RigidBody.prototype', [ }, ]); -removeProperty(EConstraintType, 'EConstraintType.prototype', [ - { - name: 'CONE_TWIST', - }, -]); - /** * Alias of [[RigidBody]] * @deprecated Since v1.2 diff --git a/cocos/physics/framework/physics-enum.ts b/cocos/physics/framework/physics-enum.ts index a84d210aa48..de4bcbc3de8 100644 --- a/cocos/physics/framework/physics-enum.ts +++ b/cocos/physics/framework/physics-enum.ts @@ -270,14 +270,6 @@ export enum EConstraintType { * 铰链约束。 */ HINGE, - /** - * @en - * Cone twist constraint. - * @zh - * 锥形扭转约束。 - * @deprecated coneTwist is deprecated, please use configurable instead - */ - CONE_TWIST, /** * @en * Fixed constraint. diff --git a/cocos/physics/framework/physics-selector.ts b/cocos/physics/framework/physics-selector.ts index 9be81501389..7bb003d67e0 100644 --- a/cocos/physics/framework/physics-selector.ts +++ b/cocos/physics/framework/physics-selector.ts @@ -26,7 +26,7 @@ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable @typescript-eslint/no-unsafe-return */ import { EDITOR, TEST } from 'internal:constants'; -import { IBaseConstraint, IPointToPointConstraint, IHingeConstraint, IConeTwistConstraint, IFixedConstraint, +import { IBaseConstraint, IPointToPointConstraint, IHingeConstraint, IFixedConstraint, IConfigurableConstraint } from '../spec/i-physics-constraint'; import { IBoxShape, ISphereShape, ICapsuleShape, ITrimeshShape, ICylinderShape, @@ -58,10 +58,6 @@ interface IPhysicsWrapperObject { PlaneShape?: Constructor, PointToPointConstraint?: Constructor, HingeConstraint?: Constructor, - /** - * @deprecated cone twist constraint is deprecated, please use configurable instead - */ - ConeTwistConstraint?: Constructor, FixedConstraint?: Constructor, ConfigurableConstraint?: Constructor, } @@ -236,10 +232,6 @@ enum ECheckType { // JOINT // PointToPointConstraint, HingeConstraint, - /** - * @deprecated cone twist constraint is deprecated, please use configurable instead - */ - ConeTwistConstraint, FixedConstraint, ConfigurableConstraint, // CHARACTER CONTROLLER // @@ -422,7 +414,7 @@ function initColliderProxy (): void { const CREATE_CONSTRAINT_PROXY = { INITED: false }; -interface IEntireConstraint extends IPointToPointConstraint, IHingeConstraint, IConeTwistConstraint, IFixedConstraint, IConfigurableConstraint { } +interface IEntireConstraint extends IPointToPointConstraint, IHingeConstraint, IFixedConstraint, IConfigurableConstraint { } const ENTIRE_CONSTRAINT: IEntireConstraint = { impl: null, initialize: FUNC, @@ -488,11 +480,6 @@ function initConstraintProxy (): void { return new selector.wrapper.HingeConstraint!(); }; - CREATE_CONSTRAINT_PROXY[EConstraintType.CONE_TWIST] = function createConeTwistConstraint (): IConeTwistConstraint { - if (check(selector.wrapper.ConeTwistConstraint, ECheckType.ConeTwistConstraint)) { return ENTIRE_CONSTRAINT; } - return new selector.wrapper.ConeTwistConstraint!(); - }; - CREATE_CONSTRAINT_PROXY[EConstraintType.FIXED] = function createFixedConstraint (): IFixedConstraint { if (check(selector.wrapper.FixedConstraint, ECheckType.FixedConstraint)) { return ENTIRE_CONSTRAINT; } return new selector.wrapper.FixedConstraint!(); diff --git a/cocos/physics/spec/i-physics-constraint.ts b/cocos/physics/spec/i-physics-constraint.ts index 91664b25717..ad6692b20e5 100644 --- a/cocos/physics/spec/i-physics-constraint.ts +++ b/cocos/physics/spec/i-physics-constraint.ts @@ -96,8 +96,3 @@ export interface IConfigurableConstraint extends IBaseConstraint { setBreakForce(v: number): void; setBreakTorque(v: number): void; } - -/** - * @deprecated ConeTwistConstraint is deprecated, please use ConfigurableConstraint instead - */ -export type IConeTwistConstraint = IBaseConstraint diff --git a/cocos/render-scene/core/program-lib.ts b/cocos/render-scene/core/program-lib.ts index 9c8095ca7d3..61c30bbe8d1 100644 --- a/cocos/render-scene/core/program-lib.ts +++ b/cocos/render-scene/core/program-lib.ts @@ -535,6 +535,7 @@ export class ProgramLib { } const macroArray = prepareDefines(defines, tmpl.defines); + macroArray.sort((a,b) => a.name.localeCompare(b.name)) const prefix = pipeline.constantMacros + tmpl.constantMacros + macroArray.reduce((acc, cur): string => `${acc}#define ${cur.name} ${cur.value}\n`, ''); diff --git a/cocos/render-scene/core/render-window.ts b/cocos/render-scene/core/render-window.ts index 24f81164daf..2a1b3acf80d 100644 --- a/cocos/render-scene/core/render-window.ts +++ b/cocos/render-scene/core/render-window.ts @@ -29,6 +29,7 @@ import { } from '../../gfx'; import { Root } from '../../root'; import { Camera } from '../scene'; +import { cclegacy } from '../../core'; export interface IRenderWindowInfo { title?: string; @@ -167,6 +168,15 @@ export class RenderWindow { return true; } + setFrameBuffer (fb: Framebuffer) { + this._framebuffer = fb; + this._colorTextures = fb.colorTextures as Texture[]; + this._depthStencilTexture = fb.depthStencilTexture; + this._width = fb.width; + this._height = fb.height; + this._device = cclegacy.director.root.device; + } + public destroy (): void { this.clearCameras(); diff --git a/cocos/render-scene/scene/camera.jsb.ts b/cocos/render-scene/scene/camera.jsb.ts index 15e2da4c92e..dd249ae4b9e 100644 --- a/cocos/render-scene/scene/camera.jsb.ts +++ b/cocos/render-scene/scene/camera.jsb.ts @@ -199,6 +199,28 @@ Object.defineProperty(cameraProto, 'matViewProjInv', { } }); +Object.defineProperty(cameraProto, 'blitTextures', { + configurable: true, + enumerable: true, + get () { + return this.getBlitTextures(); + }, + set (v) { + this.setBlitTextures(v) + } +}); + +Object.defineProperty(cameraProto, 'blitOpaqueSceneColor', { + configurable: true, + enumerable: true, + get () { + return this.getBlitOpaqueSceneColor(); + }, + set (v) { + this.setBlitOpaqueSceneColor(v) + } +}); + const oldInitialize = cameraProto.initialize; cameraProto.initialize = function initialize() { diff --git a/cocos/render-scene/scene/reflection-probe.ts b/cocos/render-scene/scene/reflection-probe.ts index 8b10802b7ca..c10d8548cc5 100644 --- a/cocos/render-scene/scene/reflection-probe.ts +++ b/cocos/render-scene/scene/reflection-probe.ts @@ -412,7 +412,6 @@ export class ReflectionProbe { this.camera.nearClip = camera.nearClip; this.camera.farClip = camera.farClip; this.camera.fov = camera.fov; - this.camera.visibility = camera.visibility; this.camera.clearFlag = camera.clearFlag; this.camera.clearColor = camera.clearColor; this.camera.priority = camera.priority - 1; diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index 2ba97a70061..e855f90ce53 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -584,48 +584,44 @@ class SubmitInfo { class RenderPassLayoutInfo { protected _layoutID = 0; + protected _vertID = -1; protected _stage: RenderStageData | null = null; protected _layout: PipelineLayoutData; protected _inputName: string; protected _descriptorSet: DescriptorSet | null = null; - constructor (layoutId: number, input: [string, ComputeView[]]) { + constructor (layoutId: number, vertId: number, input: [string, ComputeView[]]) { this._inputName = input[0]; this._layoutID = layoutId; + this._vertID = vertId; const lg = context.layoutGraph; this._stage = lg.getRenderStage(layoutId); this._layout = lg.getLayout(layoutId); - const layoutData = this._layout.descriptorSets.get(UpdateFrequency.PER_PASS); - const globalDesc = context.pipeline.descriptorSet; - if (layoutData) { - // find resource - const deviceTex = context.deviceTextures.get(this._inputName); - const gfxTex = deviceTex?.texture; - const layoutDesc = layoutData.descriptorSet!; - if (!gfxTex) { - throw Error(`Could not find texture with resource name ${this._inputName}`); - } - const resId = context.resourceGraph.vertex(this._inputName); - const samplerInfo = context.resourceGraph.getSampler(resId); - // bind descriptors - for (const descriptor of input[1]) { - const descriptorName = descriptor.name; - const descriptorID = lg.attributeIndex.get(descriptorName); - // find descriptor binding - for (const block of layoutData.descriptorSetLayoutData.descriptorBlocks) { - for (let i = 0; i !== block.descriptors.length; ++i) { - // const buffer = layoutDesc.getBuffer(block.offset + i); - // const texture = layoutDesc.getTexture(block.offset + i); - if (descriptorID === block.descriptors[i].descriptorID) { - layoutDesc.bindTexture(block.offset + i, gfxTex); - layoutDesc.bindSampler(block.offset + i, context.device.getSampler(samplerInfo)); - if (!this._descriptorSet) this._descriptorSet = layoutDesc; - continue; - } - // if (!buffer && !texture) { - // layoutDesc.bindBuffer(block.offset + i, globalDesc.getBuffer(block.offset + i)); - // layoutDesc.bindTexture(block.offset + i, globalDesc.getTexture(block.offset + i)); - // layoutDesc.bindSampler(block.offset + i, globalDesc.getSampler(block.offset + i)); - // } + const layoutData = this._layout.descriptorSets.get(UpdateFrequency.PER_PASS); + if (!layoutData) { + return; + } + const layoutDesc = layoutData.descriptorSet!; + // find resource + const deviceTex = context.deviceTextures.get(this._inputName); + const gfxTex = deviceTex?.texture; + if (!gfxTex) { + throw Error(`Could not find texture with resource name ${this._inputName}`); + } + const resId = context.resourceGraph.vertex(this._inputName); + const samplerInfo = context.resourceGraph.getSampler(resId); + // bind descriptors + for (const descriptor of input[1]) { + const descriptorName = descriptor.name; + const descriptorID = lg.attributeIndex.get(descriptorName); + // find descriptor binding + for (const block of layoutData.descriptorSetLayoutData.descriptorBlocks) { + for (let i = 0; i !== block.descriptors.length; ++i) { + if (descriptorID === block.descriptors[i].descriptorID) { + layoutDesc.bindTexture(block.offset + i, gfxTex); + const renderData = context.renderGraph.getData(this._vertID); + layoutDesc.bindSampler(block.offset + i, renderData.samplers.get(descriptorID) || context.device.getSampler(samplerInfo)); + if (!this._descriptorSet) this._descriptorSet = layoutDesc; + continue; } } } @@ -633,6 +629,7 @@ class RenderPassLayoutInfo { } get descriptorSet (): DescriptorSet | null { return this._descriptorSet; } get layoutID (): number { return this._layoutID; } + get vertID (): number { return this._vertID; } get stage (): RenderStageData | null { return this._stage; } get layout (): PipelineLayoutData { return this._layout; } } @@ -842,7 +839,7 @@ class DeviceRenderPass { const layoutGraph = context.layoutGraph; const stageId = layoutGraph.locateChild(layoutGraph.nullVertex(), stageName); if (stageId !== 0xFFFFFFFF) { - this._layout = new RenderPassLayoutInfo(stageId, input); + this._layout = new RenderPassLayoutInfo(stageId, this.rasterPassInfo.id, input); } } } @@ -953,6 +950,25 @@ class DeviceRenderPass { if (this.renderLayout && this.renderLayout.descriptorSet) { this.renderLayout.descriptorSet.update(); } + + const resGraph = context.resourceGraph; + const currentWidth = this._framebuffer ? this._framebuffer.width : 0; + const currentHeight = this._framebuffer ? this._framebuffer.height : 0; + + let width = 0; + let height = 0; + for (const [resName, rasterV] of this._rasterInfo.pass.rasterViews) { + if (rasterV.attachmentType === AttachmentType.SHADING_RATE) { + continue; + } + const resId = resGraph.vertex(resName); + const resDesc = resGraph.getDesc(resId); + width = resDesc.width; + height = resDesc.height; + break; + } + const needRebuild = (width !== currentWidth) || (height !== currentHeight); + for (const [resName, rasterV] of this._rasterInfo.pass.rasterViews) { let deviceTex = context.deviceTextures.get(resName)!; const currTex = deviceTex; @@ -966,8 +982,7 @@ class DeviceRenderPass { const resDesc = resGraph.getDesc(resId); if (deviceTex.framebuffer && resFbo instanceof Framebuffer && deviceTex.framebuffer !== resFbo) { framebuffer = this._framebuffer = deviceTex.framebuffer = resFbo; - } else if (!currTex || (deviceTex.texture - && (deviceTex.texture.width !== resDesc.width || deviceTex.texture.height !== resDesc.height))) { + } else if (!currTex || (deviceTex.texture && needRebuild)) { const gfxTex = deviceTex.texture!; if (currTex) gfxTex.resize(resDesc.width, resDesc.height); switch (rasterV.attachmentType) { diff --git a/cocos/rendering/forward/forward-stage.ts b/cocos/rendering/forward/forward-stage.ts index 3a486735198..9e3a0ccb5f4 100644 --- a/cocos/rendering/forward/forward-stage.ts +++ b/cocos/rendering/forward/forward-stage.ts @@ -184,6 +184,11 @@ export class ForwardStage extends RenderStage { cmdBuff.bindDescriptorSet(SetIndex.GLOBAL, pipeline.descriptorSet); this._renderQueues[0].recordCommandBuffer(device, renderPass, cmdBuff); + let blitOpaqueSceneColor = (camera as any).blitOpaqueSceneColor + if (blitOpaqueSceneColor) { + cmdBuff.blitTexture(blitOpaqueSceneColor.src, blitOpaqueSceneColor.dst, blitOpaqueSceneColor.regions, blitOpaqueSceneColor.filter); + } + for (let i = 0; i < this.additiveInstanceQueues.length; i++) { this.additiveInstanceQueues[i].recordCommandBuffer(device, renderPass, cmdBuff); } @@ -196,6 +201,14 @@ export class ForwardStage extends RenderStage { this._planarQueue.recordCommandBuffer(device, renderPass, cmdBuff); this._renderQueues[1].recordCommandBuffer(device, renderPass, cmdBuff); camera.geometryRenderer?.render(renderPass, cmdBuff, pipeline.pipelineSceneData); + + let blitTextures = (camera as any).blitTextures + if (blitTextures) { + blitTextures.forEach((blit: any) => { + cmdBuff.blitTexture(blit.src, blit.dst, blit.regions, blit.filter); + }) + } + this._uiPhase.render(camera, renderPass); renderProfiler(device, renderPass, cmdBuff, pipeline.profiler, camera); cmdBuff.endRenderPass(); diff --git a/cocos/rendering/pipeline-ubo.ts b/cocos/rendering/pipeline-ubo.ts index 38bfb231123..81c84ebcf3f 100644 --- a/cocos/rendering/pipeline-ubo.ts +++ b/cocos/rendering/pipeline-ubo.ts @@ -36,6 +36,7 @@ import { builtinResMgr } from '../asset/asset-manager/builtin-res-mgr'; import { Texture2D } from '../asset/assets'; import { DebugViewCompositeType } from './debug-view'; import { getDescBindingFromName } from './custom/define'; +import { Root } from '../root'; const _matShadowView = new Mat4(); const _matShadowProj = new Mat4(); @@ -47,7 +48,7 @@ const _tempVec3 = new Vec3(); export class PipelineUBO { public static updateGlobalUBOView (window: RenderWindow, bufferView: Float32Array): void { const director = cclegacy.director; - const root = director.root; + const root = director.root as Root; const fv = bufferView; const shadingWidth = Math.floor(window.width); @@ -75,19 +76,21 @@ export class PipelineUBO { } const debugView = root.debugView; - fv[UBOGlobal.DEBUG_VIEW_MODE_OFFSET] = debugView.singleMode as number; - - for (let i = 1; i <= 3; i++) { + for (let i = 0; i <= 3; i++) { fv[UBOGlobal.DEBUG_VIEW_MODE_OFFSET + i] = 0.0; } - for (let i = DebugViewCompositeType.DIRECT_DIFFUSE as number; i < DebugViewCompositeType.MAX_BIT_COUNT; i++) { - const offset = i >> 3; - const bit = i % 8; - fv[UBOGlobal.DEBUG_VIEW_MODE_OFFSET + 1 + offset] += (debugView.isCompositeModeEnabled(i) ? 1.0 : 0.0) * (10.0 ** bit); - } + if (debugView.isEnabled()) { + fv[UBOGlobal.DEBUG_VIEW_MODE_OFFSET] = debugView.singleMode as number; + + for (let i = DebugViewCompositeType.DIRECT_DIFFUSE as number; i < (DebugViewCompositeType.MAX_BIT_COUNT as unknown as number); i++) { + const offset = i >> 3; + const bit = i % 8; + fv[UBOGlobal.DEBUG_VIEW_MODE_OFFSET + 1 + offset] += (debugView.isCompositeModeEnabled(i) ? 1.0 : 0.0) * (10.0 ** bit); + } - fv[UBOGlobal.DEBUG_VIEW_MODE_OFFSET + 3] += (debugView.lightingWithAlbedo ? 1.0 : 0.0) * (10.0 ** 6.0); - fv[UBOGlobal.DEBUG_VIEW_MODE_OFFSET + 3] += (debugView.csmLayerColoration ? 1.0 : 0.0) * (10.0 ** 7.0); + fv[UBOGlobal.DEBUG_VIEW_MODE_OFFSET + 3] += (debugView.lightingWithAlbedo ? 1.0 : 0.0) * (10.0 ** 6.0); + fv[UBOGlobal.DEBUG_VIEW_MODE_OFFSET + 3] += (debugView.csmLayerColoration ? 1.0 : 0.0) * (10.0 ** 7.0); + } } public static updateCameraUBOView ( @@ -96,7 +99,7 @@ export class PipelineUBO { camera: Camera, ): void { const scene = camera.scene ? camera.scene : cclegacy.director.getScene().renderScene; - const mainLight = scene.mainLight; + const mainLight = scene.mainLight as DirectionalLight; const sceneData = pipeline.pipelineSceneData; const ambient = sceneData.ambient; const skybox = sceneData.skybox; @@ -339,9 +342,9 @@ export class PipelineUBO { if (shadowInfo.type === ShadowType.ShadowMap) { let near = 0.1; let far = 0; - let matShadowView; - let matShadowProj; - let matShadowViewProj; + let matShadowView: Mat4; + let matShadowProj: Mat4; + let matShadowViewProj: Mat4; let levelCount = 0; if (mainLight.shadowFixedArea || mainLight.csmLevel === CSMLevel.LEVEL_1 || !csmSupported) { matShadowView = csmLayers.specialLayer.matShadowView; @@ -403,10 +406,10 @@ export class PipelineUBO { Mat4.perspective( _matShadowProj, - (light as any).angle, + spotLight.angle, 1.0, 0.001, - (light as any).range, + spotLight.range, true, cap.clipSpaceMinZ, cap.clipSpaceSignY, @@ -564,6 +567,6 @@ export class PipelineUBO { } } - public destroy (): void { - } + // eslint-disable-next-line @typescript-eslint/no-empty-function + public destroy (): void {} } diff --git a/cocos/rendering/post-process/components/blit-screen.ts b/cocos/rendering/post-process/components/blit-screen.ts index ebd4a3fc2f7..08eacda5502 100644 --- a/cocos/rendering/post-process/components/blit-screen.ts +++ b/cocos/rendering/post-process/components/blit-screen.ts @@ -1,12 +1,13 @@ import { EDITOR } from 'internal:constants'; import { Material } from '../../../asset/assets'; -import { property } from '../../../core/data/class-decorator'; +import { property, serializable } from '../../../core/data/class-decorator'; import { ccclass, disallowMultiple, executeInEditMode, help, menu } from '../../../core/data/decorators'; import { PostProcessSetting } from './post-process-setting'; @ccclass('cc.BlitScreenMaterial') class BlitScreenMaterial { @property(Material) + @serializable protected _material: Material | undefined; @property(Material) @@ -17,7 +18,9 @@ class BlitScreenMaterial { this._material = v; } - @property + @property({ + serializable: true + }) enable = true; } @@ -28,6 +31,7 @@ class BlitScreenMaterial { @executeInEditMode export class BlitScreen extends PostProcessSetting { @property(Material) + @serializable protected _activeMaterials: Material[] = []; @property({ type: Material, visible: false }) get activeMaterials (): Material[] { @@ -47,6 +51,7 @@ export class BlitScreen extends PostProcessSetting { } @property(BlitScreenMaterial) + @serializable protected _materials: BlitScreenMaterial[] = []; @property(BlitScreenMaterial) diff --git a/cocos/rendering/post-process/components/bloom.ts b/cocos/rendering/post-process/components/bloom.ts index 43fa0451467..5432f2a93bd 100644 --- a/cocos/rendering/post-process/components/bloom.ts +++ b/cocos/rendering/post-process/components/bloom.ts @@ -1,5 +1,8 @@ -import { ccclass, disallowMultiple, executeInEditMode, help, menu, range, rangeMin, serializable, slide, tooltip, type } from '../../../core/data/decorators'; -import { CCFloat, CCInteger } from '../../../core/data/utils/attribute'; +import { cclegacy } from '../../../core'; +import { ccclass, disallowMultiple, executeInEditMode, help, menu, range, rangeMin, + serializable, slide, tooltip, type, visible } from '../../../core/data/decorators'; +import { CCBoolean, CCFloat, CCInteger } from '../../../core/data/utils/attribute'; +import { Root } from '../../../root'; import { PostProcessSetting } from './post-process-setting'; @ccclass('cc.Bloom') @@ -8,6 +11,10 @@ import { PostProcessSetting } from './post-process-setting'; @disallowMultiple @executeInEditMode export class Bloom extends PostProcessSetting { + @serializable + protected _enableAlphaMask = false; + @serializable + protected _useHdrIlluminance: boolean = false; @serializable protected _threshold = 0.8; @serializable @@ -15,6 +22,25 @@ export class Bloom extends PostProcessSetting { @serializable protected _intensity = 2.3; + @tooltip('i18n:bloom.enableAlphaMask') + @type(CCBoolean) + set enableAlphaMask (value: boolean) { + this._enableAlphaMask = value; + } + get enableAlphaMask (): boolean { + return this._enableAlphaMask; + } + + @tooltip('i18n:bloom.useHdrIlluminance') + @visible(() => (cclegacy.director.root as Root).pipeline.getMacroBool('CC_USE_FLOAT_OUTPUT')) + @type(CCBoolean) + set useHdrIlluminance (value: boolean) { + this._useHdrIlluminance = value; + } + get useHdrIlluminance (): boolean { + return this._useHdrIlluminance; + } + @tooltip('i18n:bloom.threshold') @rangeMin(0) @type(CCFloat) diff --git a/cocos/rendering/post-process/components/post-process-setting.ts b/cocos/rendering/post-process/components/post-process-setting.ts index 9f27b5bc50e..90d60b12106 100644 --- a/cocos/rendering/post-process/components/post-process-setting.ts +++ b/cocos/rendering/post-process/components/post-process-setting.ts @@ -6,14 +6,6 @@ import { PostProcess } from './post-process'; @requireComponent(PostProcess) @executeInEditMode export class PostProcessSetting extends Component { - protected static _default: PostProcessSetting | undefined; - static get default (): PostProcessSetting { - if (!this._default) { - this._default = new this(); - } - return this._default; - } - onEnable (): void { const pp = this.getComponent(PostProcess); pp?.addSetting(this); diff --git a/cocos/rendering/post-process/components/post-process.ts b/cocos/rendering/post-process/components/post-process.ts index ef98e92990f..dc284766106 100644 --- a/cocos/rendering/post-process/components/post-process.ts +++ b/cocos/rendering/post-process/components/post-process.ts @@ -1,5 +1,5 @@ import { EDITOR } from 'internal:constants'; -import { property } from '../../../core/data/class-decorator'; +import { property, serializable } from '../../../core/data/class-decorator'; import { ccclass, disallowMultiple, executeInEditMode, help, range, slide, tooltip } from '../../../core/data/decorators'; import { Director, director } from '../../../game'; import { Component } from '../../../scene-graph'; @@ -14,9 +14,10 @@ export class PostProcess extends Component { @tooltip('i18n:postprocess.global') @property + @serializable global = true; - @property + @serializable protected _shadingScale = 1; @tooltip('i18n:postprocess.shadingScale') @slide @@ -36,6 +37,7 @@ export class PostProcess extends Component { @tooltip('i18n:postprocess.enableShadingScaleInEditor') @property + @serializable enableShadingScaleInEditor = false; settings: Map = new Map(); diff --git a/cocos/rendering/post-process/components/taa.ts b/cocos/rendering/post-process/components/taa.ts index 8622b429542..d0a84d199e4 100644 --- a/cocos/rendering/post-process/components/taa.ts +++ b/cocos/rendering/post-process/components/taa.ts @@ -1,4 +1,4 @@ -import { property } from '../../../core/data/class-decorator'; +import { property, serializable } from '../../../core/data/class-decorator'; import { ccclass, disallowMultiple, executeInEditMode, help, menu, range, slide, tooltip } from '../../../core/data/decorators'; import { PostProcessSetting } from './post-process-setting'; @@ -8,7 +8,7 @@ import { PostProcessSetting } from './post-process-setting'; @disallowMultiple @executeInEditMode export class TAA extends PostProcessSetting { - @property + @serializable protected _sampleScale = 1; @tooltip('i18n:taa.sampleScale') @@ -22,7 +22,7 @@ export class TAA extends PostProcessSetting { this._sampleScale = v; } - @property + @serializable protected _feedback = 0.95; @tooltip('i18n:taa.feedback') @slide diff --git a/cocos/rendering/post-process/passes/bloom-pass.ts b/cocos/rendering/post-process/passes/bloom-pass.ts index 85330ea852f..e3895ada6ff 100644 --- a/cocos/rendering/post-process/passes/bloom-pass.ts +++ b/cocos/rendering/post-process/passes/bloom-pass.ts @@ -27,6 +27,11 @@ export class BloomPass extends SettingPass { name = 'BloomPass'; effectName = 'pipeline/post-process/bloom'; outputNames = ['BloomColor']; + private _hdrInputName: string = ''; + + set hdrInputName (name: string) { + this._hdrInputName = name; + } public render (camera: Camera, ppl: Pipeline): void { const cameraID = getCameraUniqueID(camera); @@ -44,11 +49,14 @@ export class BloomPass extends SettingPass { const output = `BLOOM_PREFILTER_COLOR${cameraID}`; // prefilter pass let shadingScale = 1 / 2; - passContext.material.setProperty('texSize', new Vec4(0, 0, setting.threshold, 0), 0); + const enableAlphaMask = setting.enableAlphaMask as unknown as number; + const useHDRIntensity = setting.useHdrIlluminance as unknown as number; + passContext.material.setProperty('texSize', new Vec4(useHDRIntensity, 0, setting.threshold, enableAlphaMask), 0); passContext .updatePassViewPort(shadingScale) .addRenderPass('bloom-prefilter', `bloom-prefilter${cameraID}`) .setPassInput(input, 'outputResultMap') + .setPassInput(this._hdrInputName, 'hdrInputMap') .addRasterView(output, Format.RGBA8) .blitScreen(0) .version(); diff --git a/cocos/rendering/post-process/passes/float-output-process-pass.ts b/cocos/rendering/post-process/passes/float-output-process-pass.ts index 169d26d2afa..d48c97c47e0 100644 --- a/cocos/rendering/post-process/passes/float-output-process-pass.ts +++ b/cocos/rendering/post-process/passes/float-output-process-pass.ts @@ -37,12 +37,15 @@ export class FloatOutputProcessPass extends SettingPass { effectName = 'pipeline/float-output-process'; outputNames = ['FloatOutputProcess']; + hdrInputName: string = ''; + enableInAllEditorCamera = true; enable = true; checkEnable (camera: Camera): boolean { const ppl = (cclegacy.director.root as Root).pipeline; return ppl.getMacroBool('CC_USE_FLOAT_OUTPUT'); } + getHDRInputName (): string { return this.hdrInputName; } onGlobalPipelineStateChanged (): void { passContext.material = this.material; @@ -81,7 +84,7 @@ export class FloatOutputProcessPass extends SettingPass { } passIndx = 1; - const input = this.lastPass!.slotName(camera, 0); + this.hdrInputName = this.lastPass!.slotName(camera, 0); const output = this.slotName(camera, 0); const layoutName = 'tone-mapping'; const passName = `tone-mapping${cameraID}`; @@ -89,7 +92,7 @@ export class FloatOutputProcessPass extends SettingPass { Vec4.set(passContext.clearColor, camera.clearColor.x, camera.clearColor.y, camera.clearColor.z, camera.clearColor.w); passContext.updatePassViewPort() .addRenderPass(layoutName, passName) - .setPassInput(input, 'u_texSampler') + .setPassInput(this.hdrInputName, 'u_texSampler') .setPassInput(copyDS, 'DepthTex') .addRasterView(output, Format.RGBA8) .blitScreen(passIndx) diff --git a/cocos/rendering/post-process/passes/forward-pass.ts b/cocos/rendering/post-process/passes/forward-pass.ts index fb73550de00..4fa9f366640 100644 --- a/cocos/rendering/post-process/passes/forward-pass.ts +++ b/cocos/rendering/post-process/passes/forward-pass.ts @@ -17,10 +17,11 @@ export class ForwardPass extends BasePass { depthBufferShadingScale = 1; calcDepthSlot (camera: Camera): void { - let canUsePrevDepth = !!passContext.depthSlotName; - canUsePrevDepth = !(camera.clearFlag & ClearFlagBit.DEPTH_STENCIL); + const depthSlotName = !!passContext.depthSlotName; + let canUsePrevDepth = !(camera.clearFlag & ClearFlagBit.DEPTH_STENCIL); canUsePrevDepth = canUsePrevDepth && passContext.shadingScale === this.depthBufferShadingScale; if (canUsePrevDepth) { + if (!depthSlotName) passContext.depthSlotName = super.slotName(camera, 1); return; } this.depthBufferShadingScale = passContext.shadingScale; diff --git a/cocos/rendering/post-process/passes/index.ts b/cocos/rendering/post-process/passes/index.ts index 00009f2f35a..c1e94dfb424 100644 --- a/cocos/rendering/post-process/passes/index.ts +++ b/cocos/rendering/post-process/passes/index.ts @@ -13,3 +13,4 @@ export * from './float-output-process-pass'; export * from './forward-transparency-pass'; export * from './forward-transparency-simple-pass'; export * from './skin-pass'; +export * from './post-final-pass'; diff --git a/cocos/rendering/post-process/passes/post-final-pass.ts b/cocos/rendering/post-process/passes/post-final-pass.ts new file mode 100644 index 00000000000..a29b52f4ec4 --- /dev/null +++ b/cocos/rendering/post-process/passes/post-final-pass.ts @@ -0,0 +1,47 @@ +import { Vec4 } from '../../../core'; +import { ClearFlagBit, Format } from '../../../gfx'; +import { Camera } from '../../../render-scene/scene'; +import { getCameraUniqueID } from '../../custom/define'; +import { Pipeline } from '../../custom/pipeline'; +import { passContext } from '../utils/pass-context'; +import { BasePass } from './base-pass'; + +export class PostFinalPass extends BasePass { + name = 'PostFinalPass'; + outputNames = ['PostFinalColor']; + effectName = 'pipeline/post-process/post-final'; + + enableInAllEditorCamera = true; + + public render (camera: Camera, ppl: Pipeline): void { + if (!this.lastPass) { + return; + } + + passContext.clearFlag = camera.clearFlag & ClearFlagBit.COLOR; + Vec4.set(passContext.clearColor, camera.clearColor.x, camera.clearColor.y, camera.clearColor.z, camera.clearColor.w); + + passContext.material = this.material; + + const cameraID = getCameraUniqueID(camera); + + const input0 = this.lastPass.slotName(camera, 0); + const slot0 = this.slotName(camera, 0); + + const isOffScreen = false;//director.root!.mainWindow !== camera.window; + + const fb = camera.window.framebuffer; + const ct = fb && fb.colorTextures[0]; + const format = ct ? ct.format : Format.RGBA8; + + const shadingScale = passContext.shadingScale; + passContext + .updatePassViewPort(1 / shadingScale, 1 / shadingScale) + .addRenderPass('post-final', `${this.name}${cameraID}`) + .setPassInput(input0, 'inputTexture') + .addRasterView(slot0, format, isOffScreen) + .blitScreen(0); + + this.renderProfiler(camera); + } +} diff --git a/cocos/rendering/post-process/passes/setting-pass.ts b/cocos/rendering/post-process/passes/setting-pass.ts index 66dd313f000..4530d5b2131 100644 --- a/cocos/rendering/post-process/passes/setting-pass.ts +++ b/cocos/rendering/post-process/passes/setting-pass.ts @@ -5,11 +5,8 @@ import { BasePass } from './base-pass'; export function getSetting (settingClass: new () => T): T { const cls: typeof PostProcessSetting = settingClass as any; - let setting = passContext.postProcess && passContext.postProcess.getSetting(cls) as T; - if (!setting) { - setting = cls.default as T; - } - return setting; + const setting = passContext.postProcess && passContext.postProcess.getSetting(cls) as T; + return setting!; } export abstract class SettingPass extends BasePass { diff --git a/cocos/rendering/post-process/post-process-builder.ts b/cocos/rendering/post-process/post-process-builder.ts index c9174157a04..eb56eb6baa1 100644 --- a/cocos/rendering/post-process/post-process-builder.ts +++ b/cocos/rendering/post-process/post-process-builder.ts @@ -20,7 +20,7 @@ import { director } from '../../game'; import { Camera as CameraComponent } from '../../misc'; import { BloomPass, ColorGradingPass, FloatOutputProcessPass, ForwardTransparencyPass, - ForwardTransparencySimplePass, FxaaPass, SkinPass } from './passes'; + ForwardTransparencySimplePass, FxaaPass, PostFinalPass, SkinPass } from './passes'; import { PipelineEventType } from '../pipeline-event'; export class PostProcessBuilder implements PipelineBuilder { @@ -79,7 +79,7 @@ export class PostProcessBuilder implements PipelineBuilder { // final output this.addPass(new FSRPass()); // fsr should be final - this.addPass(forwardFinal); + this.addPass(new PostFinalPass()); } getPass (passClass: typeof BasePass, pipelineName = 'forward'): BasePass | undefined { @@ -223,6 +223,8 @@ export class PostProcessBuilder implements PipelineBuilder { taaPass.updateSample(); } + const floatOutputPass = passes.find((p): boolean => p instanceof FloatOutputProcessPass) as FloatOutputProcessPass; + let lastPass: BasePass | undefined; for (let i = 0; i < passes.length; i++) { const pass = passes[i]; @@ -234,6 +236,12 @@ export class PostProcessBuilder implements PipelineBuilder { passContext.isFinalPass = true; } + if (pass.name === 'BloomPass') { + // for override post-process builder + (pass as BloomPass).hdrInputName = (floatOutputPass === undefined || floatOutputPass === null) + ? '' : floatOutputPass.getHDRInputName(); + } + pass.lastPass = lastPass; pass.render(camera, ppl); diff --git a/cocos/rendering/render-additive-light-queue.ts b/cocos/rendering/render-additive-light-queue.ts index ce569f7260e..90d33d989c7 100644 --- a/cocos/rendering/render-additive-light-queue.ts +++ b/cocos/rendering/render-additive-light-queue.ts @@ -246,6 +246,9 @@ export class RenderAdditiveLightQueue { const light = this._instancedLightPassPool.lights[j]; _dynamicOffsets[0] = this._instancedLightPassPool.dynamicOffsets[j]; const descriptorSet = globalDSManager.getOrCreateDescriptorSet(light); + if (!this._instancedQueues[j]) { + continue; + } this._instancedQueues[j].recordCommandBuffer(device, renderPass, cmdBuff, descriptorSet, _dynamicOffsets); } @@ -321,8 +324,8 @@ export class RenderAdditiveLightQueue { const buffer = pass.getInstancedBuffer(l); buffer.merge(subModel, lightPassIdx); buffer.dynamicOffsets[0] = this._lightBufferStride; - if (!this._instancedQueues[l]) { this._instancedQueues[l] = new RenderInstancedQueue(); } - this._instancedQueues[l].queue.add(buffer); + if (!this._instancedQueues[lightIdx]) { this._instancedQueues[lightIdx] = new RenderInstancedQueue(); } + this._instancedQueues[lightIdx].queue.add(buffer); } break; default: lp!.lights.push(light); diff --git a/cocos/rendering/render-pipeline.ts b/cocos/rendering/render-pipeline.ts index bae3fbf16f6..03637a841c8 100644 --- a/cocos/rendering/render-pipeline.ts +++ b/cocos/rendering/render-pipeline.ts @@ -291,14 +291,10 @@ export abstract class RenderPipeline extends Asset implements IPipelineEvent, Pi return true; } - public createRenderPass (clearFlags: ClearFlags, colorFmt: Format, depthFmt: Format): RenderPass { + public createRenderPass (clearFlags: ClearFlags, colorFmt: Format, depthFmt?: Format): RenderPass { const device = this._device; const colorAttachment = new ColorAttachment(); - const depthStencilAttachment = new DepthStencilAttachment(); colorAttachment.format = colorFmt; - depthStencilAttachment.format = depthFmt; - depthStencilAttachment.stencilStoreOp = StoreOp.DISCARD; - depthStencilAttachment.depthStoreOp = StoreOp.DISCARD; if (!(clearFlags & ClearFlagBit.COLOR)) { if (clearFlags & SKYBOX_FLAG) { @@ -312,14 +308,21 @@ export abstract class RenderPipeline extends Asset implements IPipelineEvent, Pi } } - if ((clearFlags & ClearFlagBit.DEPTH_STENCIL) !== ClearFlagBit.DEPTH_STENCIL) { - if (!(clearFlags & ClearFlagBit.DEPTH)) depthStencilAttachment.depthLoadOp = LoadOp.LOAD; - if (!(clearFlags & ClearFlagBit.STENCIL)) depthStencilAttachment.stencilLoadOp = LoadOp.LOAD; + let depthStencilAttachment + if (depthFmt) { + depthStencilAttachment = new DepthStencilAttachment(); + depthStencilAttachment.format = depthFmt; + depthStencilAttachment.stencilStoreOp = StoreOp.DISCARD; + depthStencilAttachment.depthStoreOp = StoreOp.DISCARD; + if ((clearFlags & ClearFlagBit.DEPTH_STENCIL) !== ClearFlagBit.DEPTH_STENCIL) { + if (!(clearFlags & ClearFlagBit.DEPTH)) depthStencilAttachment.depthLoadOp = LoadOp.LOAD; + if (!(clearFlags & ClearFlagBit.STENCIL)) depthStencilAttachment.stencilLoadOp = LoadOp.LOAD; + } + depthStencilAttachment.barrier = device.getGeneralBarrier(new GeneralBarrierInfo( + AccessFlagBit.DEPTH_STENCIL_ATTACHMENT_WRITE, + AccessFlagBit.DEPTH_STENCIL_ATTACHMENT_WRITE, + )); } - depthStencilAttachment.barrier = device.getGeneralBarrier(new GeneralBarrierInfo( - AccessFlagBit.DEPTH_STENCIL_ATTACHMENT_WRITE, - AccessFlagBit.DEPTH_STENCIL_ATTACHMENT_WRITE, - )); const renderPassInfo = new RenderPassInfo([colorAttachment], depthStencilAttachment); @@ -331,7 +334,7 @@ export abstract class RenderPipeline extends Asset implements IPipelineEvent, Pi const hash = murmurhash2_32_gc(`${fbHash}_${clearFlags}`, 666); let renderPass = this._renderPasses.get(hash); if (renderPass) { return renderPass; } - renderPass = this.createRenderPass(clearFlags, fbo.colorTextures[0]!.format, fbo.depthStencilTexture!.format); + renderPass = this.createRenderPass(clearFlags, fbo.colorTextures[0]!.format, fbo.depthStencilTexture ? fbo.depthStencilTexture!.format : undefined); this._renderPasses.set(hash, renderPass); return renderPass; } diff --git a/cocos/rendering/render-reflection-probe-queue.ts b/cocos/rendering/render-reflection-probe-queue.ts index 4f78db4a021..c5c35f91873 100644 --- a/cocos/rendering/render-reflection-probe-queue.ts +++ b/cocos/rendering/render-reflection-probe-queue.ts @@ -34,11 +34,6 @@ import { Camera, SKYBOX_FLAG } from '../render-scene/scene/camera'; import { PipelineRuntime } from './custom/pipeline'; import { RenderInstancedQueue } from './render-instanced-queue'; import { cclegacy, geometry } from '../core'; -import { Layers } from '../scene-graph/layers'; - -// eslint-disable-next-line max-len -const REFLECTION_PROBE_DEFAULT_MASK = Layers.makeMaskExclude([Layers.BitMask.UI_2D, Layers.BitMask.UI_3D, Layers.BitMask.GIZMOS, Layers.BitMask.EDITOR, - Layers.BitMask.SCENE_GIZMO, Layers.BitMask.PROFILER]); const CC_USE_RGBE_OUTPUT = 'CC_USE_RGBE_OUTPUT'; let _phaseID = getPhaseID('default'); @@ -96,25 +91,23 @@ export class RenderReflectionProbeQueue { } const models = scene.models; - const visibility = probe.camera.visibility; + const visibility = probe.visibility; for (let i = 0; i < models.length; i++) { const model = models[i]; - if (scene.isCulledByLod(camera, model)) { + if (!model.node || scene.isCulledByLod(camera, model)) { + continue; + } + if (((visibility & model.node.layer) !== model.node.layer) && (!(visibility & model.visFlags))) { continue; } - // filter model by view visibility - if (model.enabled && model.node && model.worldBounds && model.bakeToReflectionProbe) { + if (model.enabled && model.worldBounds && model.bakeToReflectionProbe) { if (probe.probeType === ProbeType.CUBE) { - if ((((visibility & model.node.layer) === model.node.layer) || (visibility & model.visFlags)) - && geometry.intersect.aabbWithAABB(model.worldBounds, probe.boundingBox!)) { - this.add(model); - } - } else if (((model.node.layer & REFLECTION_PROBE_DEFAULT_MASK) === model.node.layer) - || (REFLECTION_PROBE_DEFAULT_MASK & model.visFlags)) { - if (geometry.intersect.aabbFrustum(model.worldBounds, probe.camera.frustum)) { + if (geometry.intersect.aabbWithAABB(model.worldBounds, probe.boundingBox!)) { this.add(model); } + } else if (geometry.intersect.aabbFrustum(model.worldBounds, probe.camera.frustum)) { + this.add(model); } } } diff --git a/cocos/spine/lib/spine-define.ts b/cocos/spine/lib/spine-define.ts index 28d53f939f2..f267bf1c1fe 100644 --- a/cocos/spine/lib/spine-define.ts +++ b/cocos/spine/lib/spine-define.ts @@ -524,7 +524,6 @@ function overrideProperty_VertexAttachment (): void { proto: prototype, property: 'id', getter: prototype.getId, - setter: prototype.setId, }, { proto: prototype, @@ -727,15 +726,12 @@ function overrideProperty_RegionAttachment (): void { property: 'rendererObject', getter: prototype.getRendererObject, }, - { - proto: prototype, - property: 'offset', - getter: prototype.getOffset, - }, ]; propertyPolyfills.forEach((prop): void => { js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); + + overrideDefineArrayProp(prototype, prototype.getOffset, 'offset'); overrideDefineArrayPropGetSet(prototype, prototype.getUVs, prototype.setUVs, spine.wasmUtil.wasm.VectorFloat, 'uvs'); } @@ -766,6 +762,11 @@ function overrideProperty_SlotData (): void { property: 'index', getter: prototype.getIndex, }, + { + proto: prototype, + property: 'boneData', + getter: prototype.getBoneData, + }, { proto: prototype, property: 'name', @@ -791,8 +792,6 @@ function overrideProperty_SlotData (): void { propertyPolyfills.forEach((prop): void => { js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); - overrideDefineArrayProp(prototype, prototype.getBoneData, 'boneData'); - overrideDefineArrayProp(prototype, prototype.getDeform, 'deform'); } function overrideProperty_IkConstraint (): void { @@ -1226,13 +1225,14 @@ function overrideProperty_Slot (): void { }, { proto: prototype, - property: 'deform', - getter: prototype.getDeform, + property: 'skeleton', + getter: prototype.getSkeleton, }, ]; propertyPolyfills.forEach((prop): void => { js.getset(prop.proto, prop.property, prop.getter); }); + overrideDefineArrayProp(prototype, prototype.getDeform, 'deform'); } function overrideProperty_Skin (): void { diff --git a/cocos/terrain/terrain.ts b/cocos/terrain/terrain.ts index e973a6b2e71..6711c4af64e 100644 --- a/cocos/terrain/terrain.ts +++ b/cocos/terrain/terrain.ts @@ -1997,7 +1997,7 @@ export class Terrain extends Component { if (EDITOR && this._asset) { this._asset.weights[index * 4 + 0] = w.x * 255; this._asset.weights[index * 4 + 1] = w.y * 255; - this._asset.weights[index * 4 + 2] = w.x * 255; + this._asset.weights[index * 4 + 2] = w.z * 255; this._asset.weights[index * 4 + 3] = w.w * 255; } } diff --git a/cocos/ui/editbox/edit-box-impl-base.ts b/cocos/ui/editbox/edit-box-impl-base.ts index 7b742034370..9ce78026dc9 100644 --- a/cocos/ui/editbox/edit-box-impl-base.ts +++ b/cocos/ui/editbox/edit-box-impl-base.ts @@ -37,11 +37,22 @@ export class EditBoxImplBase { */ public _delegate: EditBox | null = null; - public init (delegate: EditBox): void {} + /** + * @engineInternal dirty flag to update the matrix + */ + public _dirtyFlag: boolean | null = false; - public onEnable (): void {} + public init (delegate: EditBox): void { + // To be overrode + } + + public onEnable (): void { + // To be overrode + } - public update (): void { } + public update (): void { + // To be overrode + } public onDisable (): void { if (this._editing) { @@ -53,9 +64,13 @@ export class EditBoxImplBase { this._delegate = null; } - public setTabIndex (index: number): void {} + public setTabIndex (index: number): void { + // To be overrode + } - public setSize (width: number, height: number): void {} + public setSize (width: number, height: number): void { + // To be overrode + } public setFocus (value): void { if (value) { @@ -69,7 +84,11 @@ export class EditBoxImplBase { return this._editing; } - public beginEditing (): void {} + public beginEditing (): void { + // To be overrode + } - public endEditing (): void {} + public endEditing (): void { + // To be overrode + } } diff --git a/cocos/ui/editbox/edit-box-impl.ts b/cocos/ui/editbox/edit-box-impl.ts index 3d86051898e..57361f6b69b 100644 --- a/cocos/ui/editbox/edit-box-impl.ts +++ b/cocos/ui/editbox/edit-box-impl.ts @@ -137,6 +137,7 @@ export class EditBoxImpl extends EditBoxImplBase { } public update (): void { + if (!this._dirtyFlag) return; this._updateMatrix(); } @@ -624,12 +625,12 @@ export class EditBoxImpl extends EditBoxImplBase { this._delegate!._editBoxEditingDidEnded(); }; - elem.addEventListener('compositionstart', cbs.compositionStart); - elem.addEventListener('compositionend', cbs.compositionEnd); - elem.addEventListener('input', cbs.onInput); - elem.addEventListener('keydown', cbs.onKeydown); - elem.addEventListener('blur', cbs.onBlur); - elem.addEventListener('touchstart', cbs.onClick); + elem.addEventListener('compositionstart', cbs.compositionStart as EventListenerOrEventListenerObject); + elem.addEventListener('compositionend', cbs.compositionEnd as EventListenerOrEventListenerObject); + elem.addEventListener('input', cbs.onInput as EventListenerOrEventListenerObject); + elem.addEventListener('keydown', cbs.onKeydown as EventListenerOrEventListenerObject); + elem.addEventListener('blur', cbs.onBlur as EventListenerOrEventListenerObject); + elem.addEventListener('touchstart', cbs.onClick as EventListenerOrEventListenerObject); } private _removeEventListeners (): void { if (!this._edTxt) { @@ -639,12 +640,12 @@ export class EditBoxImpl extends EditBoxImplBase { const elem = this._edTxt; const cbs = this.__eventListeners; - elem.removeEventListener('compositionstart', cbs.compositionStart); - elem.removeEventListener('compositionend', cbs.compositionEnd); - elem.removeEventListener('input', cbs.onInput); - elem.removeEventListener('keydown', cbs.onKeydown); - elem.removeEventListener('blur', cbs.onBlur); - elem.removeEventListener('touchstart', cbs.onClick); + elem.removeEventListener('compositionstart', cbs.compositionStart as EventListenerOrEventListenerObject); + elem.removeEventListener('compositionend', cbs.compositionEnd as EventListenerOrEventListenerObject); + elem.removeEventListener('input', cbs.onInput as EventListenerOrEventListenerObject); + elem.removeEventListener('keydown', cbs.onKeydown as EventListenerOrEventListenerObject); + elem.removeEventListener('blur', cbs.onBlur as EventListenerOrEventListenerObject); + elem.removeEventListener('touchstart', cbs.onClick as EventListenerOrEventListenerObject); cbs.compositionStart = null; cbs.compositionEnd = null; diff --git a/cocos/ui/editbox/edit-box.ts b/cocos/ui/editbox/edit-box.ts index c781ff0bb2c..1b096e5d2fa 100644 --- a/cocos/ui/editbox/edit-box.ts +++ b/cocos/ui/editbox/edit-box.ts @@ -492,6 +492,9 @@ export class EditBox extends Component { public _editBoxEditingDidBegan (): void { ComponentEventHandler.emitEvents(this.editingDidBegan, this); this.node.emit(EventType.EDITING_DID_BEGAN, this); + if (this._impl) { + this._impl._dirtyFlag = true; + } } /** @@ -503,6 +506,9 @@ export class EditBox extends Component { public _editBoxEditingDidEnded (text?: string): void { ComponentEventHandler.emitEvents(this.editingDidEnded, this); this.node.emit(EventType.EDITING_DID_ENDED, this, text); + if (this._impl) { + this._impl._dirtyFlag = false; + } } /** diff --git a/editor/assets/chunks/common/color/tone-mapping.chunk b/editor/assets/chunks/common/color/tone-mapping.chunk index 5f35af77b09..6808b806772 100644 --- a/editor/assets/chunks/common/color/tone-mapping.chunk +++ b/editor/assets/chunks/common/color/tone-mapping.chunk @@ -8,10 +8,12 @@ vec3 HDRToLDR(vec3 color) #if CC_USE_DEBUG_VIEW == CC_SURFACES_DEBUG_VIEW_COMPOSITE_AND_MISC && CC_SURFACES_ENABLE_DEBUG_VIEW if (IS_DEBUG_VIEW_COMPOSITE_ENABLE_TONE_MAPPING) #endif + { // linear exposure has already applied to light intensity #if CC_TONE_MAPPING_TYPE == HDR_TONE_MAPPING_ACES color.rgb = ACESToneMap(color.rgb); #endif + } #endif return color; diff --git a/editor/assets/chunks/shading-entries/data-structures/fs-input.chunk b/editor/assets/chunks/shading-entries/data-structures/fs-input.chunk index bf3553519f8..c038209b091 100644 --- a/editor/assets/chunks/shading-entries/data-structures/fs-input.chunk +++ b/editor/assets/chunks/shading-entries/data-structures/fs-input.chunk @@ -31,7 +31,7 @@ void CCSurfacesGetFragmentInput(out SurfacesStandardFragmentInput fsInput) #define FSInput_worldTangent v_tangent.xyz // unnormalized #define FSInput_mirrorNormal v_tangent.w #else - #define FSInput_worldTangent vec3(0.0, 0.0, 0.0) + #define FSInput_worldTangent vec3(1.0, 1.0, 1.0) // normalize zero vector may crash on webgpu, use 1 instead #define FSInput_mirrorNormal 1.0 #endif diff --git a/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk b/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk index cd1e3391a55..4b19e669c80 100644 --- a/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk +++ b/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk @@ -15,6 +15,14 @@ void main() { vec4 color = SurfacesFragmentModifyBaseColorAndTransparency(); color.a = 1.0; + // HDR Fog + // todo: apply fogColorBrightness to linear fogColor for supporting scatter lighting with HDR + #if CC_USE_FOG != CC_FOG_NONE + float fogFactor = 1.0; + CC_TRANSFER_FOG_BASE(vec4(FSInput_worldPos, 1.0), fogFactor); + CC_APPLY_FOG_BASE(color, fogFactor); + #endif + #if CC_USE_RGBE_OUTPUT color = packRGBE(color.rgb); #else//todo: change to #elif !CC_USE_FLOAT_OUTPUT when sky render queue has been fixed with custom pipeline @@ -22,12 +30,5 @@ void main() { color.rgb = LinearToSRGB(color.rgb); #endif - //todo: LDR fogging in gamma space, HDR fogging should move before tone mapping - #if CC_USE_FOG != CC_FOG_NONE - float fogFactor = 1.0; - CC_TRANSFER_FOG_BASE(vec4(FSInput_worldPos, 1.0), fogFactor); - CC_APPLY_FOG_BASE(color, fogFactor); - #endif - fragColorX = color; } diff --git a/editor/assets/chunks/shading-entries/main-functions/render-to-scene/pipeline/forward-fs.chunk b/editor/assets/chunks/shading-entries/main-functions/render-to-scene/pipeline/forward-fs.chunk index 17565ac6f50..386daaf0908 100644 --- a/editor/assets/chunks/shading-entries/main-functions/render-to-scene/pipeline/forward-fs.chunk +++ b/editor/assets/chunks/shading-entries/main-functions/render-to-scene/pipeline/forward-fs.chunk @@ -128,6 +128,18 @@ void main() { #endif #endif + // Fog, rgbe and gamma output can't apply fog with forward-add pass + // todo: apply fogColorBrightness to linear fogColor for supporting scatter lighting with HDR + #if CC_USE_FOG != CC_FOG_NONE && (!CC_USE_FLOAT_OUTPUT || CC_IS_TRANSPARENCY_PASS) + #if !CC_FORWARD_ADD + #ifdef CC_SURFACES_LIGHTING_MODIFY_FOG + color.rgb = CCSurfacesLightingModifyFog(fogFactor, color.rgb, surfaceData, lightingResult); + #else + CC_APPLY_FOG_BASE(color, fogFactor); + #endif + #endif + #endif + // Color output #if CC_USE_RGBE_OUTPUT color = packRGBE(color.rgb); // for reflection-map @@ -139,16 +151,5 @@ void main() { #endif #endif - // Fog, rgbe and gamma output can't apply fog with forward-add pass - // todo: apply fogColorBrightness to fogColor for supporting scatter lighting with HDR - #if CC_USE_FOG != CC_FOG_NONE && (!CC_USE_FLOAT_OUTPUT || CC_IS_TRANSPARENCY_PASS) - #if !CC_FORWARD_ADD - #ifdef CC_SURFACES_LIGHTING_MODIFY_FOG - color.rgb = CCSurfacesLightingModifyFog(fogFactor, color.rgb, surfaceData, lightingResult); - #else - CC_APPLY_FOG_BASE(color, fogFactor); - #endif - #endif - #endif fragColorX = color; } diff --git a/editor/assets/effects/advanced/fabric.effect.meta b/editor/assets/effects/advanced/fabric.effect.meta index 8a62097c4df..8940a2567de 100644 --- a/editor/assets/effects/advanced/fabric.effect.meta +++ b/editor/assets/effects/advanced/fabric.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "b25c7601-1d07-4a56-86c5-62e83ea7c61e", diff --git a/editor/assets/effects/advanced/leaf.effect b/editor/assets/effects/advanced/leaf.effect index aa690844804..f43c3248f56 100644 --- a/editor/assets/effects/advanced/leaf.effect +++ b/editor/assets/effects/advanced/leaf.effect @@ -113,7 +113,7 @@ CCProgram macro-remapping %{ // ui displayed macros #pragma define-meta HAS_SECOND_UV #pragma define-meta USE_TWOSIDE - //use FSInput_faceSideSign for materials #pragma define-meta USE_TWOSIDE_MATERIAL + //use FSInput_faceSideSign for different textures #pragma define-meta USE_TWOSIDE_MATERIAL #pragma define-meta USE_VERTEX_COLOR #pragma define-meta USE_DITHERED_ALPHA_TEST diff --git a/editor/assets/effects/pipeline/float-output-process.effect b/editor/assets/effects/pipeline/float-output-process.effect index de8f2d61d44..153ce534f7d 100644 --- a/editor/assets/effects/pipeline/float-output-process.effect +++ b/editor/assets/effects/pipeline/float-output-process.effect @@ -42,14 +42,15 @@ CCProgram copy-fs %{ CCProgram tonemap-fs %{ precision highp float; + #define CC_SURFACES_ENABLE_DEBUG_VIEW 1 #include #include - #include - #include + #include #include + #include + #include #include #include - #include in vec2 v_uv; @@ -60,16 +61,7 @@ CCProgram tonemap-fs %{ layout(location = 0) out vec4 fragColor; - vec3 HDR2LDR_PostProcess(vec3 color) { - #if CC_USE_HDR && CC_TONE_MAPPING_TYPE == TONE_MAPPING_ACES - return ACESToneMap(color.rgb); - #else - return color.rgb; - #endif - } - vec4 CCFragOutput_PostProcess(vec4 color) { - // fog related vec4 worldPos = vec4(0.0); #if CC_USE_FOG != CC_FOG_NONE @@ -79,22 +71,23 @@ CCProgram tonemap-fs %{ worldPos = GetWorldPosFromNDCPosRH(posHS, cc_matProj, cc_matViewProjInv); #endif - // todo: apply fogColorBrightness to fogColor for supporting scatter lighting with HDR + // HDR fog + // todo: apply fogColorBrightness to linear fogColor for supporting scatter lighting with HDR + #if CC_USE_FOG != CC_FOG_NONE + float fogFactor = 1.0; + CC_TRANSFER_FOG_BASE(worldPos, fogFactor); + CC_APPLY_FOG_BASE(color, fogFactor); + #endif // tone mapping if (!DebugViewNeedDisplayOriginalData()) { #if CC_USE_FLOAT_OUTPUT - color.rgb = HDR2LDR_PostProcess(color.rgb); + color.rgb = HDRToLDR(color.rgb); color.rgb = LinearToSRGB(color.rgb); #endif } // LDR fog - #if CC_USE_FOG != CC_FOG_NONE - float fogFactor = 1.0; - CC_TRANSFER_FOG_BASE(worldPos, fogFactor); - CC_APPLY_FOG_BASE(color, fogFactor); - #endif return color; } diff --git a/editor/assets/effects/pipeline/post-process/bloom.effect b/editor/assets/effects/pipeline/post-process/bloom.effect index 7a8c4f8d9e0..88537d3c012 100644 --- a/editor/assets/effects/pipeline/post-process/bloom.effect +++ b/editor/assets/effects/pipeline/post-process/bloom.effect @@ -112,14 +112,17 @@ CCProgram prefilter-fs %{ precision highp float; #include #include + #include in vec2 v_uv; uniform BloomUBO { - mediump vec4 texSize; + mediump vec4 texSize;// x: useHDRIlluminance,z: threshold, w: enableAlphaMask }; #pragma rate outputResultMap pass - uniform sampler2D outputResultMap; + uniform sampler2D outputResultMap; // ldr input + #pragma rate hdrInputMap pass + uniform sampler2D hdrInputMap; // hdr input layout(location = 0) out vec4 fragColor; @@ -128,13 +131,23 @@ CCProgram prefilter-fs %{ } void main() { - vec3 color = texture(outputResultMap, v_uv).xyz; - - if (luminance(SRGBToLinear(color)) > texSize.z) { - fragColor = vec4(color, 1.0); - } else { - fragColor = vec4(0.0, 0.0, 0.0, 1.0); - } + vec4 color = vec4(0.0, 0.0, 0.0, 1.0); + #if CC_USE_FLOAT_OUTPUT + if(texSize.x > 0.0) { + color = texture(hdrInputMap, v_uv); + } else { + color = texture(outputResultMap, v_uv); + // color.xyz = SRGBToLinear(color.xyz); + } + #else + color = texture(outputResultMap, v_uv); + // color.xyz = SRGBToLinear(color.xyz); + #endif + + float contribute = step(texSize.z, luminance(color.rgb)); + contribute *= mix(1.0, step(253.0 / 255.0, color.a), texSize.w); + + fragColor = vec4(color.xyz * contribute, 1.0); } }% diff --git a/editor/assets/effects/pipeline/post-process/post-final.effect b/editor/assets/effects/pipeline/post-process/post-final.effect new file mode 100644 index 00000000000..3d8aa313f37 --- /dev/null +++ b/editor/assets/effects/pipeline/post-process/post-final.effect @@ -0,0 +1,40 @@ +// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd. + +CCEffect %{ + techniques: + - passes: + - vert: vs + frag: fs + pass: post-final + rasterizerState: + cullMode: none + depthStencilState: + depthTest: false + depthWrite: false +}% + + +CCProgram vs %{ + #include <./chunks/vs> +}% + + +CCProgram fs %{ + precision highp float; + + in vec2 v_uv; + + uniform UBO { + vec4 inputViewPort; + }; + #pragma rate inputTexture pass + uniform sampler2D inputTexture; + + layout(location = 0) out vec4 fragColor; + + void main () { + fragColor = texture(inputTexture, v_uv); + } + +}% + diff --git a/editor/assets/effects/pipeline/post-process/post-final.effect.meta b/editor/assets/effects/pipeline/post-process/post-final.effect.meta new file mode 100644 index 00000000000..5de7cf6eb07 --- /dev/null +++ b/editor/assets/effects/pipeline/post-process/post-final.effect.meta @@ -0,0 +1,11 @@ +{ + "ver": "1.7.1", + "importer": "effect", + "imported": true, + "uuid": "521c5f6e-1a26-42e2-8108-4400c912d9bf", + "files": [ + ".json" + ], + "subMetas": {}, + "userData": {} +} diff --git a/editor/assets/effects/util/dcc/imported-metallic-roughness.effect b/editor/assets/effects/util/dcc/imported-metallic-roughness.effect index a385d707dde..2ab10f99fb8 100644 --- a/editor/assets/effects/util/dcc/imported-metallic-roughness.effect +++ b/editor/assets/effects/util/dcc/imported-metallic-roughness.effect @@ -25,7 +25,7 @@ CCEffect %{ emissiveMap: { value: grey, editor: { displayName: EmissiveColorMap } } alphaSource: { value: 1.0, editor: { slide: true, range: [0, 1.0], step: 0.001 } } alphaSourceMap: { value: grey, editor: { parent: USE_OPACITY_MAP } } - alphaThreshold: { value: 0.5, target: albedoScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST, slide: true, range: [0, 1.0], step: 0.001 } } + alphaThreshold: { value: 0.5, editor: { parent: USE_ALPHA_TEST, slide: true, range: [0, 1.0], step: 0.001 } } normalStrength: { value: 1.0, editor: { parent: USE_NORMAL_MAP, slide: true, range: [0, 1.0], step: 0.001 } } normalMap: { value: normal } - &forward-add @@ -55,8 +55,8 @@ CCEffect %{ properties: tilingOffset: { value: [1.0, 1.0, 0.0, 0.0] } mainColor: { value: [1.0, 1.0, 1.0, 1.0], target: albedo, editor: { displayName: Albedo, type: color } } - albedoScale: { value: [1.0, 1.0, 1.0], target: albedoScaleAndCutoff.xyz } - alphaThreshold: { value: 0.5, target: albedoScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST } } + albedoScale: { value: 1.0, editor: { displayName: BaseWeight } } + alphaThreshold: { value: 0.5, editor: { parent: USE_ALPHA_TEST } } mainTexture: { value: grey, target: albedoMap, editor: { displayName: AlbedoMap } } alphaSource: { value: 1.0, editor: { slide: true, range: [0, 1.0], step: 0.001 } } alphaSourceMap: { value: grey, editor: { parent: USE_OPACITY_MAP } } @@ -96,7 +96,6 @@ CCProgram shared-ubos %{ uniform Constants { vec4 tilingOffset; vec4 albedo; - vec4 albedoScaleAndCutoff; vec4 emissive; float emissiveScale; float occlusion; @@ -105,6 +104,7 @@ CCProgram shared-ubos %{ float normalStrength; float alphaSource; float albedoScale; + float alphaThreshold; float specularIntensity; }; }% @@ -237,7 +237,7 @@ CCProgram surface-fragment %{ #endif #endif #if USE_ALPHA_TEST - if (baseColor.a < albedoScaleAndCutoff.w) discard; + if (baseColor.a < alphaThreshold) discard; #endif return baseColor; } @@ -265,7 +265,7 @@ CCProgram surface-fragment %{ #endif #endif - if (alpha < albedoScaleAndCutoff.w) discard; + if (alpha < alphaThreshold) discard; #endif } diff --git a/editor/assets/primitives.fbx b/editor/assets/primitives.fbx index f93a097616a..1ddad73bd08 100755 Binary files a/editor/assets/primitives.fbx and b/editor/assets/primitives.fbx differ diff --git a/editor/engine-features/render-config.json b/editor/engine-features/render-config.json index a562f3bd67e..1e1f468623a 100644 --- a/editor/engine-features/render-config.json +++ b/editor/engine-features/render-config.json @@ -6,7 +6,8 @@ "description": "i18n:ENGINE.features.core.description", "required": true, "default": ["base"], - "wechatPlugin": true + "wechatPlugin": true, + "taobaoMinigamePlugin": true }, "graphcis": { "label": "i18n:ENGINE.features.graphics.label", @@ -18,12 +19,14 @@ "required": true, "label": "i18n:ENGINE.features.gfx_webgl.label", "description": "i18n:ENGINE.features.gfx_webgl.description", - "wechatPlugin": true + "wechatPlugin": true, + "taobaoMinigamePlugin": true }, "gfx-webgl2": { "label": "i18n:ENGINE.features.gfx_webgl2.label", "description": "i18n:ENGINE.features.gfx_webgl2.description", - "wechatPlugin": true + "wechatPlugin": true, + "taobaoMinigamePlugin": true } } }, @@ -44,6 +47,7 @@ "label": "i18n:ENGINE.features.base_3d.label", "description": "i18n:ENGINE.features.base_3d.description", "wechatPlugin": true, + "taobaoMinigamePlugin": true, "category": "3d" }, "2d": { @@ -51,27 +55,31 @@ "label": "i18n:ENGINE.features.base_2d.label", "description": "i18n:ENGINE.features.base_2d.description", "category": "2d", - "wechatPlugin": true + "wechatPlugin": true, + "taobaoMinigamePlugin": true }, "xr": { "default": [], "label": "i18n:ENGINE.features.xr.label", "description": "i18n:ENGINE.features.xr.description", - "wechatPlugin": false + "wechatPlugin": false, + "taobaoMinigamePlugin": false }, "ui": { "default": ["ui"], "label": "i18n:ENGINE.features.ui.label", "description": "i18n:ENGINE.features.ui.description", "category": "2d", - "wechatPlugin": true + "wechatPlugin": true, + "taobaoMinigamePlugin": true }, "particle": { "default": ["particle"], "label": "i18n:ENGINE.features.particle.label", "description": "i18n:ENGINE.features.particle.description", "category": "3d", - "wechatPlugin": true + "wechatPlugin": true, + "taobaoMinigamePlugin": true }, "physics": { "label": "i18n:ENGINE.features.physics.label", @@ -119,6 +127,7 @@ "label": "i18n:ENGINE.features.intersection_2d.label", "description": "i18n:ENGINE.features.intersection_2d.description", "wechatPlugin": true, + "taobaoMinigamePlugin": true, "category": "2d" }, "primitive": { @@ -126,13 +135,15 @@ "label": "i18n:ENGINE.features.primitives.label", "description": "i18n:ENGINE.features.primitives.description", "wechatPlugin": true, + "taobaoMinigamePlugin": true, "category": "3d" }, "profiler": { "default": ["profiler"], "label": "i18n:ENGINE.features.profiler.label", "description": "i18n:ENGINE.features.profiler.description", - "wechatPlugin": true + "wechatPlugin": true, + "taobaoMinigamePlugin": true }, "occlusion-query": { "default": [], @@ -140,6 +151,7 @@ "description": "i18n:ENGINE.features.occlusion_query.description", "native": "USE_OCCLUSION_QUERY", "wechatPlugin": false, + "taobaoMinigamePlugin": false, "category": "3d" }, "geometry-renderer": { @@ -148,6 +160,7 @@ "description": "i18n:ENGINE.features.geometry_renderer.description", "native": "USE_GEOMETRY_RENDERER", "wechatPlugin": true, + "taobaoMinigamePlugin": true, "category": "3d" }, "debug-renderer": { @@ -156,6 +169,7 @@ "description": "i18n:ENGINE.features.debug_renderer.description", "native": "USE_DEBUG_RENDERER", "wechatPlugin": false, + "taobaoMinigamePlugin": false, "category": "3d" }, "particle-2d": { @@ -163,6 +177,7 @@ "label": "i18n:ENGINE.features.particle_2d.label", "description": "i18n:ENGINE.features.particle_2d.description", "wechatPlugin": true, + "taobaoMinigamePlugin": true, "category": "2d" }, "audio": { @@ -170,27 +185,31 @@ "label": "i18n:ENGINE.features.audio.label", "description": "i18n:ENGINE.features.audio.description", "native": "USE_AUDIO", - "wechatPlugin": true + "wechatPlugin": true, + "taobaoMinigamePlugin": true }, "video": { "default": ["video"], "label": "i18n:ENGINE.features.video.label", "description": "i18n:ENGINE.features.video.description", "native": "USE_VIDEO", - "wechatPlugin": true + "wechatPlugin": true, + "taobaoMinigamePlugin": true }, "webview": { "default": ["webview"], "label": "i18n:ENGINE.features.webview.label", "description": "i18n:ENGINE.features.webview.description", "native": "USE_WEBVIEW", - "wechatPlugin": true + "wechatPlugin": true, + "taobaoMinigamePlugin": true }, "tween": { "default": ["tween"], "label": "i18n:ENGINE.features.tween.label", "description": "i18n:ENGINE.features.tween.description", - "wechatPlugin": true + "wechatPlugin": true, + "taobaoMinigamePlugin": true }, "websocket": { "default": ["websocket"], @@ -198,6 +217,7 @@ "description": "i18n:ENGINE.features.websocket.description", "native": "USE_SOCKET", "wechatPlugin": false, + "taobaoMinigamePlugin": false, "category": "network" }, "websocket-server": { @@ -206,6 +226,7 @@ "description": "i18n:ENGINE.features.websocket_server.description", "native": "USE_WEBSOCKET_SERVER", "wechatPlugin": false, + "taobaoMinigamePlugin": false, "category": "network" }, "terrain": { @@ -213,6 +234,7 @@ "label": "i18n:ENGINE.features.terrain.label", "description": "i18n:ENGINE.features.terrain.description", "wechatPlugin": true, + "taobaoMinigamePlugin": true, "category": "3d" }, "light-probe": { @@ -220,6 +242,7 @@ "label": "i18n:ENGINE.features.light_probe.label", "description": "i18n:ENGINE.features.light_probe.description", "wechatPlugin": true, + "taobaoMinigamePlugin": true, "category": "3d" }, "tiled-map": { @@ -227,6 +250,7 @@ "label": "i18n:ENGINE.features.tiled_map.label", "description": "i18n:ENGINE.features.tiled_map.description", "wechatPlugin": true, + "taobaoMinigamePlugin": true, "category": "2d" }, "spine": { @@ -234,7 +258,8 @@ "label": "i18n:ENGINE.features.spine.label", "description": "i18n:ENGINE.features.spine.description", "native": "USE_SPINE", - "wechatPlugin": false, + "wechatPlugin": true, + "taobaoMinigamePlugin": false, "category": "2d" }, "dragon-bones": { @@ -243,6 +268,7 @@ "description": "i18n:ENGINE.features.dragon_bones.description", "native": "USE_DRAGONBONES", "wechatPlugin": true, + "taobaoMinigamePlugin": true, "category": "2d" }, "marionette": { @@ -250,6 +276,7 @@ "label": "i18n:ENGINE.features.marionette.label", "description": "i18n:ENGINE.features.marionette.description", "wechatPlugin": false, + "taobaoMinigamePlugin": false, "category": "animation" }, "procedural-animation": { @@ -257,13 +284,15 @@ "label": "i18n:ENGINE.features.procedural_animation.label", "description": "i18n:ENGINE.features.procedural_animation.description", "wechatPlugin": false, + "taobaoMinigamePlugin": false, "category": "animation" }, "custom-pipeline": { "default": [], "label": "i18n:ENGINE.features.custom_pipeline.label", "description": "i18n:ENGINE.features.custom_pipeline.description", - "wechatPlugin": false + "wechatPlugin": false, + "taobaoMinigamePlugin": false } }, "categories": { diff --git a/editor/engine-features/schema.json b/editor/engine-features/schema.json index b6934c7e5dc..dc9bffeac50 100644 --- a/editor/engine-features/schema.json +++ b/editor/engine-features/schema.json @@ -33,6 +33,9 @@ }, "wechatPlugin": { "type": "boolean" + }, + "taobaoMinigamePlugin": { + "type": "boolean" } }, "type": "object" @@ -195,6 +198,9 @@ }, "wechatPlugin": { "type": "boolean" + }, + "taobaoMinigamePlugin": { + "type": "boolean" } }, "type": "object" diff --git a/editor/engine-features/types.ts b/editor/engine-features/types.ts index 9c069d75e6f..90579fe56ec 100644 --- a/editor/engine-features/types.ts +++ b/editor/engine-features/types.ts @@ -66,6 +66,12 @@ export interface FlagBaseItem { wechatPlugin?: boolean; + /** + * Different with wechat plugin, taobao plugin can't read buffer from local wasm. + * So we need another config item for taobao minigame plugin. + */ + taobaoMinigamePlugin?: boolean; + default?: string[]; } @@ -86,6 +92,12 @@ export interface BaseItem { wechatPlugin?: boolean; + /** + * Different with wechat plugin, taobao plugin can't read buffer from local wasm. + * So we need another config item for taobao minigame plugin. + */ + taobaoMinigamePlugin?: boolean; + default?: string[]; category?: string; diff --git a/editor/i18n/en/assets.js b/editor/i18n/en/assets.js index d2393bfd1bc..84943ce0549 100644 --- a/editor/i18n/en/assets.js +++ b/editor/i18n/en/assets.js @@ -93,7 +93,7 @@ module.exports = { propertyTips: { // macros USE_DITHERED_ALPHA_TEST: 'Make transparency using opaque dithered alpha clip with TAA.', - USE_TWOSIDE: 'Two sided material for single-face objects, normal get inverse on back-face. Cull mode should set to None.', + USE_TWOSIDE: 'Two sided lighting for single-face objects, normal get inverse on back-face automatically. Cull mode should set to None.', IS_ANISOTROPY: 'Anisotropic materials, such as hair, disc, metal with micro-wires.', USE_VERTEX_COLOR: 'Use vertex color, will become darker if mesh does not contain vertex color data.', FIX_ANISOTROPIC_ROTATION_MAP: 'Fix the anomalous seam at the black-white joint of the anisotropic rotation map, turn it on if you encounter this problem.', diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index c3b05125f0a..236afc74403 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -1034,6 +1034,10 @@ module.exports = link(mixin({ label: "Box2D Based 2D Physics System", description: "2D Physics system that based on Box2D.", }, + physics_2d_box2d_wasm: { + label: "Box2D-wasm Based 2D Physics System", + description: "2D Physics system that based on Box2D-wasm.", + }, intersection_2d: { label: "2D Intersection Algorithms", description: "Include 2D intersection algorithms.", @@ -1305,6 +1309,8 @@ module.exports = link(mixin({ needBlur: 'Turn on for a softer effect with less noise, but it consumes some performance.', }, bloom: { + enableAlphaMask: 'Transparent channel flag bit, if you turn on this function, please also reduce the object material intrinsic color a channel output, a value of less than 1 object will not have a flood light', + useHdrIlluminance: 'To use scene HDR brightness to filter flooded areas, both HDR mode and the CC_USE_FLOAT_OUTPUT macro must be enabled.', threshold: 'The brightness threshold, brighter area will produce bloom, this value unit is the LDR brightness seen by the human eye, independent of exposure.', iterations: 'The number of blur iterations, the higher the value that results in a larger and softer flare range, but with reduced performance.', intensity: 'Flood intensity, the higher the value, the brighter the halo, please adjust it moderately.', diff --git a/editor/i18n/zh/assets.js b/editor/i18n/zh/assets.js index edf9f8acf94..e02c185354e 100644 --- a/editor/i18n/zh/assets.js +++ b/editor/i18n/zh/assets.js @@ -93,7 +93,7 @@ module.exports = { propertyTips: { // macros USE_DITHERED_ALPHA_TEST: '使用抖动透贴的方式来实现半透明效果,最好同时开启 TAA', - USE_TWOSIDE: '双面材质,通常用于单面物体,正面和背面的法线相反。还需将 Cull Mode 设为 None', + USE_TWOSIDE: '双面材质,仅影响光照,通常用于单面物体,正面和背面的法线会自动取反。还需将 Cull Mode 设为 None', IS_ANISOTROPY: '各向异性材质,通常用于头发、光碟、拉丝金属等', USE_VERTEX_COLOR: '使用顶点色,如果模型本身没有顶点色可能会发黑', FIX_ANISOTROPIC_ROTATION_MAP: '修复各向异性旋转图黑白相接处的异常接缝,遇到此问题再开启', @@ -325,84 +325,65 @@ module.exports = { name: '填充顶点色', title: '如果模型没有顶点颜色属性,添加颜色属性,填充为白色。', }, + meshOptimize: { + name: '网格优化', + title: '是否优化网格数据。', + vertexCache: { + name: '顶点缓存', + title: '优化顶点缓冲区以提高顶点缓存命中率。
建议对顶点数较高的模型启用此选项。', + }, + vertexFetch: { + name: '顶点提取', + title: '优化顶点缓冲区以提高顶点提取效率。
建议对顶点数较高的模型启用此选项。', + }, + overdraw: { + name: '过度绘制', + title: '优化顶点缓冲区以减少过度绘制。
建议对顶点数较高的模型启用此选项。', + }, + }, meshSimplify: { - name: 'Mesh 简化', - title: 'Mesh 简化可以被用来简化导入的模型,可以在需要模型减面时使用。
在一些少数情况下减面后的模型可能会出现显示异常,如发生这种情况请尝试调整参数并重试。', - simplification: { - name: 'Simplification', - title: 'Simplification', - si: { - name: 'Achieve The Ratio R', - title: 'Achieve The Ratio R', - }, - sa: { - name: 'Aggressively Simplify', - title: 'Aggressively Simplify', - }, + name: '网格简化', + title: '是否简化网格数据。', + targetRatio: { + name: '目标比率', + title: '简化网格数据的目标顶点数的比例。
建议将此值设置为 0.5。', }, - scene: { - name: 'Scene', - title: 'Scene', - kn: { - name: 'Keep Nodes Transform', - title: 'Keep Nodes Transform', - }, - ke: { - name: 'Keep Extras Data', - title: 'Keep Extras Data', - }, + autoErrorRate: { + name: '自动误差率', + title: '是否自动计算简化网格数据的误差率。', }, - miscellaneous: { - name: 'Miscellaneous', - title: 'Miscellaneous', - noq: { - name: 'Disable Quantization', - title: 'Disable Quantization', - }, - v: { - name: 'Verbose Output', - title: 'Verbose Output', - }, + errorRate: { + name: '误差率', + title: '简化网格数据的最大误差率。
此值还会影响结果大小。
建议调整直到获得良好的结果。', }, - algorithm: { - name: '减面算法', - simplify: 'simplify', - gltfpack: 'gltfpack (已废弃)', + lockBoundary: { + name: '锁定边界', + title: '是否锁定简化网格数据的边界。', }, - simplify: { - targetRatio: { - name: 'LOD 压缩比例', - title: '减面之后的目标面数比例,0 代表减面至最少,1 代表没有减面的原模型。', - }, - preserveSurfaceCurvature: { - name: '保留表面曲率', - title: 'Preserve Surface Curvature', - }, - preserveBorderEdges: { - name: '保留边界边', - title: 'Preserve Border Edges', - }, - preserveUVSeamEdges: { - name: '保留 UV 缝合边', - title: 'Preserve UV Seam Edges', - }, - preserveUVFoldoverEdges: { - name: '保留 UV 折叠边', - title: 'Preserve UV Foldover Edges', - }, - agressiveness: { - name: '误差距离', - title: '模型减面算法的激进程度。
当设置数值越高时,算法的减面策略会越激进,但是过于激进的策略更有可能导致结果错误。', - }, - maxIterationCount: { - name: '计算迭代次数', - title: '最大重复计数代表减面算法运行的重复次数。
高数值可以使算法运行结果更接近目标,但也会增加运行时间和结果错误的概率。', - }, + }, + meshCluster: { + name: '网格切块', + title: '是否分割网格数据。', + generateBounding: { + name: '生成包围体', + title: '是否为聚类的网格数据生成包围球和法线锥。', + }, + }, + meshCompress:{ + name: '网格压缩', + title: '是否压缩网格数据。', + encode: { + name: '编码', + title: '对网格数据进行编码以减少数据大小。', + }, + compress: { + name: '压缩', + title: '对网格数据进行压缩以减少数据大小。', }, - gltfpack: { - warn: '当前资源使用的减面算法 gltfpack 已被废弃,请选用新的 simplify 减面算法。', + quantize: { + name: '量化', + title: '对网格数据进行量化以减少数据大小。', }, - warn: '警告:优化后,网格资源的数量和名称会发生改变,这将会造成组件引用的资源丢失,请及时手动更新;(另外,对于模型资源中预生成的预制体,资源同步机制会自动更新)', }, animationBakeRate: { name: '动画烘焙速率', diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index cd3a0881867..87c24c16973 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -1008,6 +1008,10 @@ module.exports = link(mixin({ label: "基于 Box2D 的 2D 物理系统", description: "基于 Box2D 的 2D 物理系统支持。", }, + physics_2d_box2d_wasm: { + label: "基于 Box2D-wasm 的 2D 物理系统", + description: "基于 Box2D-wasm 的 2D 物理系统支持。", + }, intersection_2d: { label: "2D 相交检测算法", description: "包含用于二维相交检测的算法。", @@ -1279,6 +1283,8 @@ module.exports = link(mixin({ needBlur: '开启可以获得更柔和的效果,噪点更少,但会耗费一些性能', }, bloom: { + enableAlphaMask: '透明通道标志位,如果开启此功能,请同时降低物体材质的固有色a通道输出,a 值小于 1 的物体将不会有泛光', + useHdrIlluminance: '使用场景 HDR 亮度来筛选泛光区域,必须同时开启 HDR 模式和 CC_USE_FLOAT_OUTPUT 宏', threshold: '光晕的亮度阈值,大于此亮度的区域才会产生泛光,该值单位是人眼所见的 LDR 亮度,和曝光无关', iterations: '模糊迭代次数,该值越大则光晕范围越大、越柔和,但性能也会有所降低', intensity: '泛光强度,该值越大则光晕越亮,请适度调节', diff --git a/editor/inspector/assets/fbx/model.js b/editor/inspector/assets/fbx/model.js index 8c524043019..770af79969d 100644 --- a/editor/inspector/assets/fbx/model.js +++ b/editor/inspector/assets/fbx/model.js @@ -888,7 +888,6 @@ const Elements = { Elements.normals.update.call(panel); Elements.tangents.update.call(panel); Elements.morphNormals.update.call(panel); - Elements.meshOptimizerAlgorithm.update.call(panel); }, }, }; diff --git a/editor/inspector/components.js b/editor/inspector/components.js index 37fd3598924..1dd378709ac 100644 --- a/editor/inspector/components.js +++ b/editor/inspector/components.js @@ -15,8 +15,6 @@ module.exports = { 'cc.SkeletalAnimation': join(__dirname, './components/skeletal-animation.js'), 'cc.SphereLight': join(__dirname, './components/sphere-light.js'), 'cc.SpotLight': join(__dirname, './components/spot-light.js'), - 'cc.PointLight': join(__dirname, './components/point-light.js'), - 'cc.RangedDirectionalLight': join(__dirname, './components/ranged-directional-light.js'), 'cc.Sprite': join(__dirname, './components/sprite.js'), 'cc.Terrain': join(__dirname, './components/terrain.js'), 'cc.VideoPlayer': join(__dirname, './components/video-player.js'), diff --git a/editor/inspector/components/widget.js b/editor/inspector/components/widget.js index a4b52964acd..85e97d536a5 100644 --- a/editor/inspector/components/widget.js +++ b/editor/inspector/components/widget.js @@ -8,6 +8,7 @@ const Vue = require('vue/dist/vue.min.js'); const propUtils = require('../utils/prop'); const cssMediaWidth = 340; +let layout = 'vertical'; exports.template = `