Skip to content

Commit

Permalink
feat(outline): add outlineManager (Orillusion#97)
Browse files Browse the repository at this point in the history
add outline manager to support control of outline effects
The outline effect cannot display properly and has been fixed.
  • Loading branch information
hellmor authored May 6, 2023
1 parent 148bf1f commit 0fd810d
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 85 deletions.
93 changes: 8 additions & 85 deletions src/gfx/renderJob/post/OutlinePost.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import { VirtualTexture } from '../../../textures/VirtualTexture';
import { StorageGPUBuffer } from '../../graphics/webGpu/core/buffer/StorageGPUBuffer';
import { UniformGPUBuffer } from '../../graphics/webGpu/core/buffer/UniformGPUBuffer';
Expand All @@ -11,7 +10,6 @@ import { RendererPassState } from '../passRenderer/state/RendererPassState';
import { PostBase } from './PostBase';
import { Engine3D } from '../../../Engine3D';
import { clamp } from '../../../math/MathUtil';
import { Color } from '../../../math/Color';
import { Vector2 } from '../../../math/Vector2';
import { RTDescriptor } from '../../graphics/webGpu/descriptor/RTDescriptor';
import { GBufferFrame } from '../frame/GBufferFrame';
Expand All @@ -20,69 +18,8 @@ import { View3D } from '../../../core/View3D';
import { OutlineCalcOutline_cs } from '../../../assets/shader/compute/OutlineCalcOutline_cs';
import { Outline_cs } from '../../../assets/shader/compute/Outline_cs';
import { OutLineBlendColor_cs } from '../../../assets/shader/compute/OutLineBlendColor_cs';
import { OutlinePostSlot, outlinePostData } from '../../../io/OutlinePostData';

export class OutlinePostSlot {
public indexList: Float32Array;
public color: Color;
public count: number;
}

export class OutlinePostData {
//max to 8 groups of different colors can be selected
public readonly SlotCount: number = 8;
public readonly MaxEntities: number = 16;
public readonly defaultColor: Color = new Color(0.2, 1, 1, 1);
private readonly slots: OutlinePostSlot[] = [];

private dataDirty: boolean = true;

constructor() {
let groupCount = Engine3D.setting.render.postProcessing.outline.groupCount;
this.SlotCount = Math.max(1, Math.min(groupCount, this.SlotCount));
for (let i = 0; i < this.SlotCount; i++) {
let slot: OutlinePostSlot = (this.slots[i] = new OutlinePostSlot());
slot.indexList = new Float32Array(this.MaxEntities);
slot.color = this.defaultColor.clone();
slot.count = 0;
}
}

public clear(): void {
for (let i = 0; i < this.SlotCount; i++) {
this.clearAt(i);
}
}

public clearAt(slotIndex: number): this {
this.dataDirty = true;
let slot: OutlinePostSlot = this.slots[slotIndex];
slot.color.copyForm(this.defaultColor);
slot.indexList.fill(-1);
slot.count = 0;
return this;
}

public fillDataAt(slot: number, indexList: number[], color: Color): this {
this.dataDirty = true;
let data = this.slots[slot];
if (data) {
data.indexList.fill(-1);
for (let i = 0, c = indexList.length; i < c; i++) {
data.indexList[i] = indexList[i];
}
data.count = indexList.length;
data.color.copyForm(color);
}
return this;
}

public fetchData(target: { dirty: boolean; slots: OutlinePostSlot[] }): this {
target.dirty = this.dataDirty;
target.slots = this.slots;
this.dataDirty = false;
return this;
}
}

/**
* post effect out line
Expand Down Expand Up @@ -138,11 +75,8 @@ export class OutlinePost extends PostBase {
oldOutlineColor: StorageGPUBuffer;
rtFrame: RTFrame;

outlineData: OutlinePostData;

constructor() {
super();
this.outlineData = new OutlinePostData();
}

/**
Expand Down Expand Up @@ -208,7 +142,7 @@ export class OutlinePost extends PostBase {

private createCompute() {
let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer");
let visibleMap = rtFrame.getPositionMap();// RTResourceMap.getTexture(RTResourceConfig.zBufferTexture_NAME);
let visibleMap = rtFrame.getPositionMap();

this.calcWeightCompute = new ComputeShader(OutlineCalcOutline_cs);
this.calcWeightCompute.setStorageBuffer('outlineSetting', this.outlineSetting);
Expand Down Expand Up @@ -263,29 +197,18 @@ export class OutlinePost extends PostBase {
outDec.clearValue = [0, 0, 0, 1];
outDec.loadOp = `clear`;

this.rtFrame = new RTFrame([
this.outlineTex
], [
outDec
]);

let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer");

// RTResourceMap.createRTTextures(
// [RTResourceConfig.colorBufferTex_NAME, RTResourceConfig.positionBufferTex_NAME, RTResourceConfig.normalBufferTex_NAME, RTResourceConfig.materialBufferTex_NAME],
// [GPUTextureFormat.rgba16float, GPUTextureFormat.rgba16float, GPUTextureFormat.rgba8unorm, GPUTextureFormat.rgba8unorm],
// );
this.rtFrame = new RTFrame([this.outlineTex], [outDec]);

this.outlineSetting = new UniformGPUBuffer(8);
this.weightBuffer = new StorageGPUBuffer(this.lowTexSize.x * this.lowTexSize.y * 4, GPUBufferUsage.COPY_SRC);
this.oldOutlineColor = new StorageGPUBuffer(this.lowTexSize.x * this.lowTexSize.y * 4, GPUBufferUsage.COPY_SRC);

this.slotsArray = new Float32Array(this.outlineData.SlotCount * 4);
this.slotsArray = new Float32Array(outlinePostData.SlotCount * 4);
this.slotsBuffer = new StorageGPUBuffer(this.slotsArray.length);
this.slotsBuffer.setFloat32Array('slotsArray', this.slotsArray);
this.slotsBuffer.apply();

this.entitiesArray = new Float32Array(this.outlineData.SlotCount * this.outlineData.MaxEntities);
this.entitiesArray = new Float32Array(outlinePostData.SlotCount * outlinePostData.MaxEntities);
this.entitiesBuffer = new StorageGPUBuffer(this.entitiesArray.length);
this.entitiesBuffer.setFloat32Array('entitiesArray', this.entitiesArray);
this.slotsBuffer.apply();
Expand All @@ -296,10 +219,10 @@ export class OutlinePost extends PostBase {
private fetchData: { dirty: boolean; slots: OutlinePostSlot[] };

private fetchOutlineData(): void {
this.outlineData.fetchData(this.fetchData);
outlinePostData.fetchData(this.fetchData);
if (this.fetchData.dirty) {
let slotCount = this.outlineData.SlotCount;
let maxEntities = this.outlineData.MaxEntities;
let slotCount = outlinePostData.SlotCount;
let maxEntities = outlinePostData.MaxEntities;
for (let i = 0; i < slotCount; i++) {
let offset = 4 * i;
let slot = this.fetchData.slots[i];
Expand Down
68 changes: 68 additions & 0 deletions src/io/OutlineManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { Object3D, Color, MeshRenderer, outlinePostData } from "@orillusion/core";

/**
* manager of outline effect
* @group IO
*/
export class OutlinePostManager {

private _tempIndexArray: number[] = [];

/**
* config outline manager.
* Specify specific 3D objects to use the specified color for display outline
* @param objectList A set of 3D objects
* @param color Specified color for outline
*/
public setOutline(objectList: Object3D[], color?: Color) {
this.setOutlineList([objectList], color ? [color] : null);
}

/**
* config outline manager.
* The first set of objects uses the first color to display outline, and so on
* @param groupList A group of 3D objects set
* @param colorList Specified color list for outline
*/
public setOutlineList(groupList: Object3D[][], colorList?: Color[]) {
groupList ||= [];
let defaultColor = outlinePostData.defaultColor;
let maxGroup = outlinePostData.SlotCount;
for (let i = 0; i < maxGroup; i++) {
this._tempIndexArray.length = 0;
let group = groupList[i];
let color = (colorList ? colorList[i] : null) || defaultColor;
if (group) {
for (const item of group) {
this.getEntityIdList(item, this._tempIndexArray);
}
}
outlinePostData.fillDataAt(i, this._tempIndexArray, color);
}
}

/**
* clear outline effect
*/
public clearOutline(): this {
outlinePostData.clear();
return this;
}

private _rendererList: MeshRenderer[] = [];

private getEntityIdList(item: Object3D, target: number[]): void {
this._rendererList.length = 0;
let renderers = item.getComponents(MeshRenderer, this._rendererList);
for (const render of renderers) {
target.push(render.object3D.transform._worldMatrix.index);
}
}


}

/**
* @internal
*/
export let outlinePostManager: OutlinePostManager = new OutlinePostManager();
67 changes: 67 additions & 0 deletions src/io/OutlinePostData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Engine3D } from "../Engine3D";
import { Color } from "../math/Color";

export class OutlinePostSlot {
public indexList: Float32Array;
public color: Color;
public count: number;
}

export class OutlinePostData {
//Supports up to 8 sets of colors
public readonly SlotCount: number = 8;
public readonly MaxEntities: number = 16;
public readonly defaultColor: Color = new Color(0.2, 1, 1, 1);
private readonly slots: OutlinePostSlot[] = [];

private dataDirty: boolean = true;

constructor() {
let groupCount = Engine3D.setting.render.postProcessing.outline.groupCount;
this.SlotCount = Math.max(1, Math.min(groupCount, this.SlotCount));
for (let i = 0; i < this.SlotCount; i++) {
let slot: OutlinePostSlot = (this.slots[i] = new OutlinePostSlot());
slot.indexList = new Float32Array(this.MaxEntities);
slot.color = this.defaultColor.clone();
slot.count = 0;
}
}

public clear(): void {
for (let i = 0; i < this.SlotCount; i++) {
this.clearAt(i);
}
}

public clearAt(slotIndex: number): this {
this.dataDirty = true;
let slot: OutlinePostSlot = this.slots[slotIndex];
slot.color.copyForm(this.defaultColor);
slot.indexList.fill(-1);
slot.count = 0;
return this;
}

public fillDataAt(slot: number, indexList: number[], color: Color): this {
this.dataDirty = true;
let data = this.slots[slot];
if (data) {
data.indexList.fill(-1);
for (let i = 0, c = indexList.length; i < c; i++) {
data.indexList[i] = indexList[i];
}
data.count = indexList.length;
data.color.copyForm(color);
}
return this;
}

public fetchData(target: { dirty: boolean; slots: OutlinePostSlot[] }): this {
target.dirty = this.dataDirty;
target.slots = this.slots;
this.dataDirty = false;
return this;
}
}

export let outlinePostData: OutlinePostData = new OutlinePostData();

0 comments on commit 0fd810d

Please sign in to comment.