Skip to content

Commit

Permalink
fix reflection probe
Browse files Browse the repository at this point in the history
  • Loading branch information
star-e committed Aug 28, 2024
1 parent add1948 commit e173277
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 33 deletions.
2 changes: 2 additions & 0 deletions cocos/rendering/custom/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
* ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! =========================
*/
/* eslint-disable max-len */
import type { AABB } from '../../core/geometry/aabb';
import type { Material } from '../../asset/assets';
import type { Camera } from '../../render-scene/scene/camera';
import type { DirectionalLight } from '../../render-scene/scene/directional-light';
Expand Down Expand Up @@ -480,6 +481,7 @@ export interface SceneBuilder extends Setter {
light: Light,
csmLevel?: number,
optCamera?: Camera): void;
setCullingWorldBounds (aabb: AABB): void;
}

/**
Expand Down
10 changes: 9 additions & 1 deletion cocos/rendering/custom/render-graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
*/
/* eslint-disable max-len */
import { AdjI, AdjacencyGraph, BidirectionalGraph, ComponentGraph, ED, InEI, MutableGraph, MutableReferenceGraph, NamedGraph, OutE, OutEI, PolymorphicGraph, PropertyGraph, ReferenceGraph, UuidGraph, VertexListGraph } from './graph';
import type { AABB } from '../../core/geometry/aabb';
import type { Material } from '../../asset/assets';
import type { Camera } from '../../render-scene/scene/camera';
import type { Buffer, Framebuffer, RenderPass, Sampler, SamplerInfo, Swapchain, Texture } from '../../gfx';
Expand Down Expand Up @@ -990,6 +991,7 @@ export const enum CullingFlags {
CAMERA_FRUSTUM = 0x1,
LIGHT_FRUSTUM = 0x2,
LIGHT_BOUNDS = 0x4,
WORLD_BOUNDS = 0x8,
}

export class SceneData {
Expand All @@ -1000,34 +1002,39 @@ export class SceneData {
light: LightInfo = new LightInfo(),
cullingFlags: CullingFlags = CullingFlags.CAMERA_FRUSTUM,
shadingLight: Light | null = null,
worldBounds: AABB | null = null,
) {
this.scene = scene;
this.camera = camera;
this.light = light;
this.flags = flags;
this.cullingFlags = cullingFlags;
this.shadingLight = shadingLight;
this.worldBounds = worldBounds;
}
reset (
scene: RenderScene | null,
camera: Camera | null,
flags: SceneFlags,
cullingFlags: CullingFlags,
shadingLight: Light | null,
worldBounds: AABB | null,
): void {
this.scene = scene;
this.camera = camera;
this.light.reset(null, 0, false, null);
this.flags = flags;
this.cullingFlags = cullingFlags;
this.shadingLight = shadingLight;
this.worldBounds = worldBounds;
}
declare /*pointer*/ scene: RenderScene | null;
declare /*pointer*/ camera: Camera | null;
declare readonly light: LightInfo;
declare flags: SceneFlags;
declare cullingFlags: CullingFlags;
declare /*refcount*/ shadingLight: Light | null;
declare worldBounds: AABB | null;
}

export class Dispatch {
Expand Down Expand Up @@ -1722,9 +1729,10 @@ export class RenderGraphObjectPool {
flags: SceneFlags = SceneFlags.NONE,
cullingFlags: CullingFlags = CullingFlags.CAMERA_FRUSTUM,
shadingLight: Light | null = null,
worldBounds: AABB | null = null,
): SceneData {
const v = this.sd.add(); // SceneData
v.reset(scene, camera, flags, cullingFlags, shadingLight);
v.reset(scene, camera, flags, cullingFlags, shadingLight, worldBounds);
return v;
}
createDispatch (
Expand Down
65 changes: 38 additions & 27 deletions cocos/rendering/custom/scene-culling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { CommandBuffer, Device, Buffer, BufferInfo, BufferViewInfo, MemoryUsageB
import { BatchingSchemes, Pass, RenderScene } from '../../render-scene';
import { CSMLevel, Camera, DirectionalLight, Light, LightType, Model, PointLight, ProbeType,
RangedDirectionalLight,
ReflectionProbe, SKYBOX_FLAG, ShadowType, Shadows, SphereLight, SpotLight } from '../../render-scene/scene';
SKYBOX_FLAG, ShadowType, Shadows, SphereLight, SpotLight } from '../../render-scene/scene';
import { Layers, Node } from '../../scene-graph';
import { PipelineSceneData } from '../pipeline-scene-data';
import { hashCombineStr, getSubpassOrPassID, bool, AlignUp, SetLightUBO } from './define';
Expand Down Expand Up @@ -40,7 +40,8 @@ function computeCullingKey (
const light = sceneData.light.light;
const lightLevel = sceneData.light.level;
const culledByLight = sceneData.light.culledByLight;
const reflectProbe = sceneData.light.probe;
const reflectProbe: boolean = !!(sceneData.flags & SceneFlags.REFLECTION_PROBE);
const worldBounds: boolean = !!(sceneData.cullingFlags & CullingFlags.WORLD_BOUNDS);
const shadeLight = sceneData.shadingLight;
if (camera) {
// camera
Expand Down Expand Up @@ -83,8 +84,9 @@ function computeCullingKey (
hashCode = hashCombineStr(`cast${castShadows}`, hashCode);
hashCode = hashCombineStr(`level${lightLevel}`, hashCode);
if (reflectProbe) {
hashCode = hashCombineStr(`probe${reflectProbe.getProbeId()}`, hashCode);
hashCode = hashCombineStr(`probe${reflectProbe}`, hashCode);
}
hashCode = hashCombineStr(`wb${worldBounds}`, hashCode);
hashCode = hashCombineStr(`refId${refId}`, hashCode);
return hashCode;
}
Expand Down Expand Up @@ -162,7 +164,7 @@ function isReflectProbeMask (model: Model): boolean {
}

const transWorldBounds = new AABB();
function isFrustumVisible (model: Model, frustum: Readonly<Frustum>, castShadow: boolean): boolean {
function isFrustumCulled (model: Model, frustum: Readonly<Frustum>, castShadow: boolean): boolean {
const modelWorldBounds = model.worldBounds;
if (!modelWorldBounds) {
return false;
Expand All @@ -175,7 +177,7 @@ function isFrustumVisible (model: Model, frustum: Readonly<Frustum>, castShadow:
return !intersect.aabbFrustum(transWorldBounds, frustum);
}

function isIntersectAABB (lAABB: AABB, rAABB: AABB): boolean {
function isAABBCulled (lAABB: AABB, rAABB: AABB): boolean {
return !intersect.aabbWithAABB(lAABB, rAABB);
}

Expand All @@ -184,12 +186,13 @@ function sceneCulling (
camera: Camera,
camOrLightFrustum: Readonly<Frustum>,
castShadow: boolean,
probe: ReflectionProbe | null,
probePass: boolean,
models: Array<Model>,
worldBounds: AABB | null,
): void {
const skybox = pSceneData.skybox;
const skyboxModel = skybox.model;
const visibility = camera.visibility;
const visibility = probePass ? REFLECTION_PROBE_DEFAULT_MASK : camera.visibility;
const camSkyboxFlag = camera.clearFlag & SKYBOX_FLAG;
if (!castShadow && skybox && skybox.enabled && skyboxModel && camSkyboxFlag) {
models.push(skyboxModel);
Expand All @@ -203,21 +206,33 @@ function sceneCulling (
if (scene && scene.isCulledByLod(camera, model)) {
continue;
}
if (!probe || (probe && probe.probeType === ProbeType.CUBE)) {
if (isNodeVisible(model.node, visibility)
|| isModelVisible(model, visibility)) {
const wBounds = model.worldBounds;
// frustum culling
if (wBounds && ((!probe && isFrustumVisible(model, camOrLightFrustum, castShadow))
|| (probe && isIntersectAABB(wBounds, probe.boundingBox!)))) {
if (!isNodeVisible(model.node, visibility) && !isModelVisible(model, visibility)) {
continue;
}
const wBounds = model.worldBounds;
if (!wBounds) {
continue;
}
if (probePass) {
if (!model.bakeToReflectionProbe) {
continue;
}
if (worldBounds) {
if (isAABBCulled(wBounds, worldBounds)) {
continue;
}

models.push(model);
} else if (isFrustumCulled(model, camOrLightFrustum, castShadow)) {
continue;
}
} else {
if (isFrustumCulled(model, camOrLightFrustum, castShadow)) {
continue;
}
if (worldBounds && isAABBCulled(wBounds, worldBounds)) {
continue;
}
} else if (isReflectProbeMask(model)) {
models.push(model);
}
models.push(model);
}
}

Expand Down Expand Up @@ -518,28 +533,24 @@ export class SceneCulling {
const light = sceneData.light.light;
const level = sceneData.light.level;
const castShadow = cullingKey.castShadows;
const probe = sceneData.light.probe;
const camera = probe ? probe.camera : sceneData.camera;
const probePass = !!(sceneData.flags & SceneFlags.REFLECTION_PROBE);
const camera = sceneData.camera;
assert(frustomCulledResultID < this.frustumCullingResults.length);
const models = this.frustumCullingResults[frustomCulledResultID];
if (probe) {
sceneCulling(scene, camera, camera.frustum, castShadow, probe, models);
continue;
}
if (light) {
switch (light.type) {
case LightType.SPOT:
sceneCulling(scene, camera, (light as SpotLight).frustum, castShadow, null, models);
sceneCulling(scene, camera, (light as SpotLight).frustum, castShadow, probePass, models, sceneData.worldBounds);
break;
case LightType.DIRECTIONAL: {
const frustum = this.getBuiltinShadowFrustum(pplSceneData, camera, light as DirectionalLight, level);
sceneCulling(scene, camera, frustum, castShadow, null, models);
sceneCulling(scene, camera, frustum, castShadow, probePass, models, sceneData.worldBounds);
}
break;
default:
}
} else {
sceneCulling(scene, camera, camera.frustum, castShadow, null, models);
sceneCulling(scene, camera, camera.frustum, castShadow, probePass, models, sceneData.worldBounds);
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions cocos/rendering/custom/web-pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import { Director } from '../../game';
import { ReflectionProbeManager } from '../../3d';
import { legacyCC } from '../../core/global-exports';
import { WebSetter, setCameraUBOValues, setShadowUBOLightView, setShadowUBOView, setTextureUBOView } from './web-pipeline-types';
import { AABB } from '../../core/geometry/aabb';

const _uboVec = new Vec4();
const _samplerPointInfo = new SamplerInfo(
Expand Down Expand Up @@ -221,6 +222,10 @@ export class WebSceneBuilder extends WebSetter implements SceneBuilder {
const layoutName = this._renderGraph.getLayout(passId);
setShadowUBOLightView(this, this._scene.camera, light, csmLevel, layoutName);
}
setCullingWorldBounds (aabb: AABB): void {
this._scene.cullingFlags |= CullingFlags.WORLD_BOUNDS;
this._scene.worldBounds = aabb;
}
private _renderGraph: RenderGraph;
private _scene: SceneData;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ export class BuiltinPipelineSettings extends Component {
group: { id: 'Bloom', name: 'Bloom (PostProcessing)', style: 'section' },
type: CCFloat,
min: 0,
step: 0.01,
})
set bloomThreshold(value: number) {
this._settings.bloom.threshold = value;
Expand All @@ -332,6 +333,7 @@ export class BuiltinPipelineSettings extends Component {
group: { id: 'Bloom', name: 'Bloom (PostProcessing)', style: 'section' },
type: CCFloat,
min: 0,
visible: false,
})
set bloomIntensity(value: number) {
this._settings.bloom.intensity = value;
Expand Down
10 changes: 7 additions & 3 deletions editor/assets/default_renderpipeline/builtin-pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1440,7 +1440,8 @@ if (rendering) {
colorName: string,
depthStencilName: string,
mainLight: renderer.scene.DirectionalLight | null,
scene: renderer.RenderScene | null = null,
scene: renderer.RenderScene | null,
probe?: renderer.scene.ReflectionProbe,
): void {
// set viewport
const colorStoreOp = this._cameraConfigs.enableMSAA ? StoreOp.DISCARD : StoreOp.STORE;
Expand Down Expand Up @@ -1482,11 +1483,14 @@ if (rendering) {
// TODO(zhouzhenglong): Separate OPAQUE and MASK queue

// add opaque and mask queue
pass.addQueue(QueueHint.NONE, 'reflect-map') // Currently we put OPAQUE and MASK into one queue, so QueueHint is NONE
const builder = pass.addQueue(QueueHint.NONE, 'reflect-map') // Currently we put OPAQUE and MASK into one queue, so QueueHint is NONE
.addScene(camera,
SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.REFLECTION_PROBE,
mainLight || undefined,
scene ? scene : undefined);
if (probe) {
builder.setCullingWorldBounds(probe.boundingBox);
}
}

private _tryAddReflectionProbePasses(ppl: rendering.BasicPipeline, id: number,
Expand Down Expand Up @@ -1542,7 +1546,7 @@ if (rendering) {
const probePass = ppl.addRenderPass(width, height, 'default');
probePass.name = `CubeProbe${probeID}${faceIdx}`;
this._buildReflectionProbePass(probePass, id, probe.camera,
colorName, depthStencilName, mainLight, scene);
colorName, depthStencilName, mainLight, scene, probe);
}
probe.needRender = false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ class NativeSceneBuilder final : public SceneBuilder, public NativeSetter {
}

void useLightFrustum(IntrusivePtr<scene::Light> light, uint32_t csmLevel, const scene::Camera *optCamera) override;
void setCullingWorldBounds(const geometry::AABB &aabb) override;
};

class NativeRenderSubpassBuilderImpl : public NativeSetter {
Expand Down
7 changes: 5 additions & 2 deletions native/cocos/renderer/pipeline/custom/RenderGraphTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,7 @@ enum class CullingFlags : uint32_t {
CAMERA_FRUSTUM = 0x1,
LIGHT_FRUSTUM = 0x2,
LIGHT_BOUNDS = 0x4,
WORLD_BOUNDS = 0x8,
};

constexpr CullingFlags operator|(const CullingFlags lhs, const CullingFlags rhs) noexcept {
Expand Down Expand Up @@ -910,20 +911,22 @@ constexpr bool any(CullingFlags e) noexcept {

struct SceneData {
SceneData() = default;
SceneData(const scene::RenderScene* sceneIn, const scene::Camera* cameraIn, SceneFlags flagsIn, LightInfo lightIn, CullingFlags cullingFlagsIn, IntrusivePtr<scene::Light> shadingLightIn) noexcept
SceneData(const scene::RenderScene* sceneIn, const scene::Camera* cameraIn, SceneFlags flagsIn, LightInfo lightIn, CullingFlags cullingFlagsIn, IntrusivePtr<scene::Light> shadingLightIn, geometry::AABB worldBoundsIn) noexcept

Check failure on line 914 in native/cocos/renderer/pipeline/custom/RenderGraphTypes.h

View workflow job for this annotation

GitHub Actions / ClangTidy Android

the parameter 'worldBoundsIn' is copied for each invocation but only used as a const reference; consider making it a const reference (performance-unnecessary-value-param)
: scene(sceneIn),
camera(cameraIn),
light(std::move(lightIn)),
flags(flagsIn),
cullingFlags(cullingFlagsIn),
shadingLight(std::move(shadingLightIn)) {}
shadingLight(std::move(shadingLightIn)),
worldBounds(worldBoundsIn) {}

const scene::RenderScene* scene{nullptr};
const scene::Camera* camera{nullptr};
LightInfo light;
SceneFlags flags{SceneFlags::NONE};
CullingFlags cullingFlags{CullingFlags::CAMERA_FRUSTUM};
IntrusivePtr<scene::Light> shadingLight;
geometry::AABB worldBounds;
};

struct Dispatch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@ class SceneBuilder : public Setter {
* @param optCamera @en Additional scene culling camera. @zh 额外的场景裁切相机
*/
virtual void useLightFrustum(IntrusivePtr<scene::Light> light, uint32_t csmLevel, const scene::Camera *optCamera) = 0;
virtual void setCullingWorldBounds(const geometry::AABB &aabb) = 0;
void useLightFrustum(IntrusivePtr<scene::Light> light) {
useLightFrustum(std::move(light), 0, nullptr);
}
Expand Down

0 comments on commit e173277

Please sign in to comment.