Skip to content

Commit

Permalink
[Complete] multi-light source adjustment logic (#179)
Browse files Browse the repository at this point in the history
* Complete multi-light source adjustment logic

* Spotlight logic adjustment correct effect
  • Loading branch information
GengineJS authored Oct 13, 2023
1 parent 57f2f8d commit 9dca300
Show file tree
Hide file tree
Showing 13 changed files with 1,110 additions and 309 deletions.
4 changes: 3 additions & 1 deletion cocos/asset/assets/effect-asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,9 @@ export class EffectAsset extends Asset {
public onLoaded (): void {
if (cclegacy.rendering && cclegacy.rendering.enableEffectImport) {
addEffectDefaultProperties(this);
(cclegacy.rendering.programLib as ProgramLibrary).addEffect(this);
const programLib = cclegacy.rendering.programLib;
programLib.addEffect(this);
programLib.init(deviceManager.gfxDevice);
} else {
programLib.register(this);
}
Expand Down
4 changes: 4 additions & 0 deletions cocos/gfx/base/shader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ export abstract class Shader extends GFXObject {
return this._samplers;
}

get stages (): ShaderStage[] {
return this._stages;
}

protected _name = '';
protected _stages: ShaderStage[] = [];
protected _attributes: Attribute[] = [];
Expand Down
7 changes: 5 additions & 2 deletions cocos/gfx/webgl/webgl-command-buffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -405,10 +405,13 @@ export class WebGLCommandBuffer extends CommandBuffer {
}
}

public pipelineBarrier (GeneralBarrier: Readonly<GeneralBarrier>, bufferBarriers?: Readonly<BufferBarrier[]>,
public pipelineBarrier (
GeneralBarrier: Readonly<GeneralBarrier>,
bufferBarriers?: Readonly<BufferBarrier[]>,
buffers?: Readonly<Buffer[]>,
textureBarriers?: Readonly<TextureBarrier[]>,
textures?: Readonly<Texture[]>): void {}
textures?: Readonly<Texture[]>,
): void {}

Check failure on line 414 in cocos/gfx/webgl/webgl-command-buffer.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

Unexpected empty method 'pipelineBarrier'

protected bindStates (): void {
const bindStatesCmd = this._cmdAllocator.bindStatesCmdPool.alloc(WebGLCmdBindStates);
Expand Down
153 changes: 145 additions & 8 deletions cocos/rendering/custom/define.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@

import { EDITOR } from 'internal:constants';
import { BufferInfo, Buffer, BufferUsageBit, ClearFlagBit, Color, DescriptorSet, LoadOp,
Format, Rect, Sampler, StoreOp, Texture, Viewport, MemoryUsageBit, Filter, Address } from '../../gfx';
Format, Rect, Sampler, StoreOp, Texture, Viewport, MemoryUsageBit, Filter, Address, DescriptorSetLayoutInfo, DescriptorSetLayoutBinding } from '../../gfx';

Check warning on line 27 in cocos/rendering/custom/define.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

This line has a length of 159. Maximum allowed is 150
import { ProbeType, ReflectionProbe } from '../../render-scene/scene/reflection-probe';
import { Camera, SKYBOX_FLAG } from '../../render-scene/scene/camera';
import { CSMLevel, ShadowType } from '../../render-scene/scene/shadows';
import { CSMLevel, ShadowType, Shadows } from '../../render-scene/scene/shadows';
import { Light, LightType } from '../../render-scene/scene/light';
import { DirectionalLight } from '../../render-scene/scene/directional-light';
import { RangedDirectionalLight } from '../../render-scene/scene/ranged-directional-light';
import { PointLight } from '../../render-scene/scene/point-light';
import { SphereLight } from '../../render-scene/scene/sphere-light';
import { SpotLight } from '../../render-scene/scene/spot-light';
import { supportsR32FloatTexture, supportsRGBA16HalfFloatTexture } from '../define';
import { UBOForwardLight, supportsR32FloatTexture, supportsRGBA16HalfFloatTexture } from '../define';
import { BasicPipeline, Pipeline } from './pipeline';
import {
AccessType, AttachmentType, CopyPair, LightInfo,
Expand All @@ -46,7 +46,7 @@ import { getProfilerCamera, SRGBToLinear } from '../pipeline-funcs';
import { RenderWindow } from '../../render-scene/core/render-window';
import { RenderData, RenderGraph } from './render-graph';
import { WebComputePassBuilder, WebPipeline } from './web-pipeline';
import { DescriptorSetData, LayoutGraph, LayoutGraphData } from './layout-graph';
import { DescriptorSetData, DescriptorSetLayoutData, LayoutGraph, LayoutGraphData } from './layout-graph';
import { AABB } from '../../core/geometry';
import { DebugViewCompositeType, DebugViewSingleType } from '../debug-view';
import { ReflectionProbeManager } from '../../3d/reflection-probe/reflection-probe-manager';
Expand Down Expand Up @@ -2474,6 +2474,140 @@ export function bool (val): boolean {
return !!val;
}

export function AlignUp (value: number, alignment: number): number {
return (value + (alignment - 1)) & ~(alignment - 1);
}
const kLightMeterScale = 10000;
export function SetLightUBO (
light: Light | null,
bHDR: boolean,
exposure: number,
shadowInfo: Shadows | null,
buffer: Float32Array,
offset: number,
elemSize: number,
): void {
const vec4Array = new Float32Array(4);
let size = 0.0;
let range = 0.0;
let luminanceHDR = 0.0;
let luminanceLDR = 0.0;

if (light && light.type === LightType.SPHERE) {
const sphereLight = light as SphereLight;
vec4Array[0] = sphereLight.position.x;
vec4Array[1] = sphereLight.position.y;
vec4Array[2] = sphereLight.position.z;
vec4Array[3] = LightType.SPHERE;
size = sphereLight.size;
range = sphereLight.range;
luminanceHDR = sphereLight.luminanceHDR;
luminanceLDR = sphereLight.luminanceLDR;
} else if (light && light.type === LightType.SPOT) {
const spotLight = light as SpotLight;
vec4Array[0] = spotLight.position.x;
vec4Array[1] = spotLight.position.y;
vec4Array[2] = spotLight.position.z;
vec4Array[3] = LightType.SPOT;
size = spotLight.size;
range = spotLight.range;
luminanceHDR = spotLight.luminanceHDR;
luminanceLDR = spotLight.luminanceLDR;
} else if (light && light.type === LightType.POINT) {
const pointLight = light as PointLight;
vec4Array[0] = pointLight.position.x;
vec4Array[1] = pointLight.position.y;
vec4Array[2] = pointLight.position.z;
vec4Array[3] = LightType.POINT;
size = 0.0;
range = pointLight.range;
luminanceHDR = pointLight.luminanceHDR;
luminanceLDR = pointLight.luminanceLDR;
} else if (light && light.type === LightType.RANGED_DIRECTIONAL) {
const rangedDirLight = light as RangedDirectionalLight;
vec4Array[0] = rangedDirLight.position.x;
vec4Array[1] = rangedDirLight.position.y;
vec4Array[2] = rangedDirLight.position.z;
vec4Array[3] = LightType.RANGED_DIRECTIONAL;
size = 0.0;
range = 0.0;
luminanceHDR = rangedDirLight.illuminanceHDR;
luminanceLDR = rangedDirLight.illuminanceLDR;
}

let index = offset + UBOForwardLight.LIGHT_POS_OFFSET;
buffer.set(vec4Array, index);

index = offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET;
vec4Array.set([size, range, 0, 0]);
buffer.set(vec4Array, index);

index = offset + UBOForwardLight.LIGHT_COLOR_OFFSET;
const color = light ? light.color : new Color();
if (light && light.useColorTemperature) {
const tempRGB = light.colorTemperatureRGB;
buffer[index++] = color.x * tempRGB.x;
buffer[index++] = color.y * tempRGB.y;
buffer[index++] = color.z * tempRGB.z;
} else {
buffer[index++] = color.x;
buffer[index++] = color.y;
buffer[index++] = color.z;
}

if (bHDR) {
buffer[index] = luminanceHDR * exposure * kLightMeterScale;
} else {
buffer[index] = luminanceLDR;
}

switch (light ? light.type : LightType.UNKNOWN) {
case LightType.SPHERE:
buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 2] = 0;
buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 3] = 0;
break;
case LightType.SPOT: {
const spotLight = light as SpotLight;
buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 2] = spotLight.spotAngle;
buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 3] = (shadowInfo && shadowInfo.enabled
&& spotLight.shadowEnabled
&& shadowInfo.type === ShadowType.ShadowMap) ? 1.0 : 0.0;

index = offset + UBOForwardLight.LIGHT_DIR_OFFSET;
const direction = spotLight.direction;
buffer[index++] = direction.x;
buffer[index++] = direction.y;
buffer[index] = direction.z;
} break;
case LightType.POINT:
buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 2] = 0;
buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 3] = 0;
break;
case LightType.RANGED_DIRECTIONAL: {
const rangedDirLight = light as RangedDirectionalLight;
const right = rangedDirLight.right;
buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 0] = right.x;
buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 1] = right.y;
buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 2] = right.z;
buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 3] = 0;

const direction = rangedDirLight.direction;
buffer[offset + UBOForwardLight.LIGHT_DIR_OFFSET + 0] = direction.x;
buffer[offset + UBOForwardLight.LIGHT_DIR_OFFSET + 1] = direction.y;
buffer[offset + UBOForwardLight.LIGHT_DIR_OFFSET + 2] = direction.z;
buffer[offset + UBOForwardLight.LIGHT_DIR_OFFSET + 3] = 0;

const scale = rangedDirLight.scale;
buffer[offset + UBOForwardLight.LIGHT_BOUNDING_SIZE_VS_OFFSET + 0] = scale.x * 0.5;
buffer[offset + UBOForwardLight.LIGHT_BOUNDING_SIZE_VS_OFFSET + 1] = scale.y * 0.5;
buffer[offset + UBOForwardLight.LIGHT_BOUNDING_SIZE_VS_OFFSET + 2] = scale.z * 0.5;
buffer[offset + UBOForwardLight.LIGHT_BOUNDING_SIZE_VS_OFFSET + 3] = 0;
} break;
default:
break;
}
}

export function getSubpassOrPassID (sceneId: number, rg: RenderGraph, lg: LayoutGraphData): number {
const queueId = rg.getParent(sceneId);
assert(queueId !== 0xFFFFFFFF);
Expand All @@ -2493,10 +2627,13 @@ export function getSubpassOrPassID (sceneId: number, rg: RenderGraph, lg: Layout
assert(passLayoutId !== lg.nullVertex());

const subpassLayoutName: string = rg.getLayout(subpassOrPassID);
assert(!!subpassLayoutName);
const subpassLayoutId = lg.locateChild(passLayoutId, subpassLayoutName);
assert(subpassLayoutId !== lg.nullVertex());
layoutId = subpassLayoutId;
if (subpassLayoutName.length === 0) {
layoutId = passLayoutId;
} else {
const subpassLayoutId = lg.locateChild(passLayoutId, subpassLayoutName);
assert(subpassLayoutId !== lg.nullVertex());
layoutId = subpassLayoutId;
}
}
assert(layoutId !== lg.nullVertex());
return layoutId;
Expand Down
62 changes: 17 additions & 45 deletions cocos/rendering/custom/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,9 @@ import {
validPunctualLightsCulling,
} from './define';
import { RenderReflectionProbeQueue } from '../render-reflection-probe-queue';
import { SceneCulling } from './scene-culling';
import { LightResource, SceneCulling } from './scene-culling';
import { Pass } from '../../render-scene';
import { WebProgramLibrary } from './web-program-library';

class ResourceVisitor implements ResourceGraphVisitor {
name: string;
Expand Down Expand Up @@ -1280,23 +1281,15 @@ class DeviceSceneTransversal extends WebSceneTransversal {
}
get graphScene (): GraphScene { return this._graphScene; }
public preRenderPass (visitor: WebSceneVisitor): DevicePreSceneTask {
if (!this._preSceneTask) {
this._preSceneTask = new DevicePreSceneTask(this._currentQueue, this._graphScene, visitor);
}
this._preSceneTask.apply(this._currentQueue, this.graphScene);
this._preSceneTask = new DevicePreSceneTask(this._currentQueue, this._graphScene, visitor);
return this._preSceneTask;
}
public transverse (visitor: WebSceneVisitor): DeviceSceneTask {
if (!this._sceneTask) {
this._sceneTask = new DeviceSceneTask(this._currentQueue, this._graphScene, visitor);
}
this._sceneTask.apply(this._currentQueue, this.graphScene);
this._sceneTask = new DeviceSceneTask(this._currentQueue, this._graphScene, visitor);
return this._sceneTask;
}
public postRenderPass (visitor: WebSceneVisitor): DevicePostSceneTask {
if (!this._postSceneTask) {
this._postSceneTask = new DevicePostSceneTask(this._sceneData, context.ubo, this._camera, visitor);
}
this._postSceneTask = new DevicePostSceneTask(this._sceneData, context.ubo, this._camera, visitor);
return this._postSceneTask;
}
}
Expand Down Expand Up @@ -1372,17 +1365,9 @@ class DevicePreSceneTask extends WebSceneTask {
public start (): void {
if (this.graphScene.blit) {
this._currentQueue.createBlitDesc(this.graphScene.blit);
return;
}
if (!this.camera) {
return;
}
const sceneFlag = this._graphScene.scene!.flags;
if (sceneFlag & SceneFlags.DEFAULT_LIGHTING) {
this._sceneCulling();
validPunctualLightsCulling(context.pipeline, this.camera);
context.additiveLight.gatherLightPasses(this.camera, this._cmdBuff, this._currentQueue.devicePass.layoutName);
}
context.lightResource.buildLightBuffer(context.commandBuffer);
context.lightResource.tryUpdateRenderSceneLocalDescriptorSet(context.culling);
}

public submit (): void {
Expand Down Expand Up @@ -1562,14 +1547,6 @@ class DeviceSceneTask extends WebSceneTask {
}
}

private _recordAdditiveLights (): void {
context.additiveLight?.recordCommandBuffer(
context.device,
this._renderPass,
context.commandBuffer,
);
}

public submit (): void {
const devicePass = this._currentQueue.devicePass;
const sceneCulling = context.culling;
Expand All @@ -1580,21 +1557,10 @@ class DeviceSceneTask extends WebSceneTask {
this._recordBlit();
return;
}
const renderQueueDesc = sceneCulling.sceneQueryIndex.get(this.graphScene.sceneID)!;
const renderQueueDesc = sceneCulling.renderQueueIndex.get(this.graphScene.sceneID)!;
const renderQueue = sceneCulling.renderQueues[renderQueueDesc.renderQueueTarget];
const graphSceneData = this.graphScene.scene!;
renderQueue.opaqueQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer);
renderQueue.opaqueInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer);
if (graphSceneData.flags & SceneFlags.DEFAULT_LIGHTING) {
this._recordAdditiveLights();
this.visitor.bindDescriptorSet(
SetIndex.GLOBAL,
context.descriptorSet!,
);
}

renderQueue.transparentInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer);
renderQueue.transparentQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer);
renderQueue.recordCommands(context.commandBuffer, this._renderPass);
if (bool(graphSceneData.flags & SceneFlags.REFLECTION_PROBE)) renderQueue.probeQueue.removeMacro();
if (graphSceneData.flags & SceneFlags.GEOMETRY) {
this.camera!.geometryRenderer?.render(
Expand Down Expand Up @@ -1877,6 +1843,7 @@ class ExecutorContext {
for (const infoMap of this.submitMap) {
for (const info of infoMap[1]) info[1].reset();
}
this.lightResource.clear();
}
resize (width: number, height: number): void {
this.width = width;
Expand All @@ -1899,6 +1866,7 @@ class ExecutorContext {
readonly pools: ExecutorPools;
readonly blit: BlitInfo;
readonly culling: SceneCulling;
lightResource: LightResource = new LightResource();
renderGraph: RenderGraph;
width: number;
height: number;
Expand Down Expand Up @@ -1926,6 +1894,8 @@ export class Executor {
width,
height,
);
const programLib: WebProgramLibrary = cclegacy.rendering.programLib;
context.lightResource.init(programLib, device, 16);
}

resize (width: number, height: number): void {
Expand Down Expand Up @@ -1979,8 +1949,10 @@ export class Executor {
context.renderGraph = rg;
context.reset();
const cmdBuff = context.commandBuffer;
context.culling.buildRenderQueues(rg, context.layoutGraph, context.pipelineSceneData);
context.culling.uploadInstancing(cmdBuff);
const culling = context.culling;
culling.buildRenderQueues(rg, context.layoutGraph, context.pipelineSceneData);
context.lightResource.buildLights(culling, context.pipelineSceneData.isHDR, context.pipelineSceneData.shadows);
culling.uploadInstancing(cmdBuff);
this._removeDeviceResource();
cmdBuff.begin();
if (!this._visitor) this._visitor = new RenderVisitor();
Expand Down
Loading

0 comments on commit 9dca300

Please sign in to comment.