Skip to content

Commit

Permalink
feat(GUI): shadows of GUI (#182)
Browse files Browse the repository at this point in the history
New feature: You can set shadows to GUI
rename class
  • Loading branch information
hellmor committed May 30, 2023
1 parent 328bf72 commit 7797b86
Show file tree
Hide file tree
Showing 19 changed files with 537 additions and 121 deletions.
8 changes: 5 additions & 3 deletions samples/gui/Sample_UIChangeParent.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GUIHelp } from "@orillusion/debug/GUIHelp";
import { createExampleScene } from "@samples/utils/ExampleScene";
import { Engine3D, Object3DUtil, Object3D, ViewPanel, UIImage, ImageType, UIPanel, makeAloneSprite, Color, Time, UITransform } from "@orillusion/core";
import { Engine3D, Object3DUtil, Object3D, ViewPanel, UIImage, ImageType, UIPanel, makeAloneSprite, Color, Time, UITransform, BitmapTexture2D } from "@orillusion/core";

export class Sample_UIChangeParent {
async run() {
Expand Down Expand Up @@ -35,8 +35,10 @@ export class Sample_UIChangeParent {
panelRoot.addChild(logoObject);

let image1: UIImage = logoObject.addComponent(UIImage);
let logoTexture = await Engine3D.res.loadTexture('png/logo.png');
image1.sprite = makeAloneSprite('logo', logoTexture);
let bitmapTexture2D = new BitmapTexture2D();
bitmapTexture2D.flipY = true;
await bitmapTexture2D.load('png/logo.png');
image1.sprite = makeAloneSprite('logo', bitmapTexture2D);
image1.uiTransform.resize(100, 100);
}

Expand Down
83 changes: 83 additions & 0 deletions samples/gui/Sample_UIImageGroup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { BitmapTexture2D, Engine3D, Object3D, Scene3D, Texture, UIImageGroup, UIShadow, ViewPanel, makeAloneSprite } from "@orillusion/core";
import { GUIHelp } from "@orillusion/debug/GUIHelp";
import { createExampleScene } from "@samples/utils/ExampleScene";
import { Stats } from "@orillusion/stats";
import { GUIUtil } from "@samples/utils/GUIUtil";

export class Sample_UIImageGroup {
scene: Scene3D;
imageGroup: UIImageGroup;

async run() {
Engine3D.setting.shadow.autoUpdate = true;
Engine3D.setting.shadow.shadowBias = 0.002;

GUIHelp.init();

await Engine3D.init();
let exampleScene = createExampleScene();
this.scene = exampleScene.scene;
this.scene.addComponent(Stats);
Engine3D.startRenderView(exampleScene.view);


GUIHelp.open();
GUIHelp.endFolder();

await this.createImageGroup();
}

async createImageGroup() {
// enable ui canvas i
let canvas = this.scene.view.enableUICanvas(0);
//create UI root
let panelRoot: Object3D = new Object3D();
//create panel
let panel = panelRoot.addComponent(ViewPanel, { billboard: true });
canvas.addChild(panel.object3D);

let bitmapTexture2D = new BitmapTexture2D();
bitmapTexture2D.flipY = true;
await bitmapTexture2D.load('png/logo.png');

let uiNode = new Object3D();
panelRoot.addChild(uiNode);
//create sprite sheet list
this.imageGroup = this.createSpriteSheets(uiNode, bitmapTexture2D);
let shadow = this.imageGroup.object3D.addComponent(UIShadow);

GUIUtil.renderUIShadow(shadow, false);

this.createGUI();
}

private halfSize = 0;
createGUI() {
GUIHelp.addFolder('Position');
let xy = this.imageGroup.getXY(1);
let pos = { x: 0, y: xy.y };
let action = () => this.imageGroup.setXY(1, pos.x, pos.y);
GUIHelp.add(pos, 'x', - Engine3D.width * 0.5, Engine3D.width * 0.5, 1).onChange(action);
GUIHelp.add(pos, 'y', - Engine3D.height * 0.5, Engine3D.height * 0.5, 1).onChange(action);
GUIHelp.open();
GUIHelp.endFolder();
}

private createSpriteSheets(root: Object3D, texture: Texture): UIImageGroup {
let sprite = makeAloneSprite('KB3D_NTT_Ads_basecolor', texture);
let imgGroup = root.addComponent(UIImageGroup, { count: 2 });
let size = 256;
this.halfSize = size * 0.5;
for (let i = 0; i < 2; i++) {
imgGroup.setSprite(i, sprite);
imgGroup.setSize(i, size, size);
if (i == 1) {
imgGroup.setXY(1, - this.halfSize, 128 - this.halfSize)
} else {
imgGroup.setXY(0, - this.halfSize, - this.halfSize)
}
}
return imgGroup;

}
}
52 changes: 52 additions & 0 deletions samples/gui/Sample_UIImageShadow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { GUIHelp } from "@orillusion/debug/GUIHelp";
import { createExampleScene } from "@samples/utils/ExampleScene";
import { Engine3D, Object3DUtil, Object3D, BitmapTexture2D, UIImage, makeAloneSprite, WorldPanel, UIShadow } from "@orillusion/core";
import { GUIUtil } from "@samples/utils/GUIUtil";

export class Sample_UIImageShadow {
private img: UIImage;

async run() {
Engine3D.setting.shadow.autoUpdate = true;
Engine3D.setting.shadow.shadowBias = 0.002;

GUIHelp.init();

await Engine3D.init();
let exampleScene = createExampleScene();
Engine3D.startRenderView(exampleScene.view);

// create floor
let floor = Object3DUtil.GetSingleCube(100, 2, 50, 0.5, 0.5, 0.5);
exampleScene.scene.addChild(floor);

//create UI root
let panelRoot: Object3D = new Object3D();
panelRoot.scaleX = panelRoot.scaleY = panelRoot.scaleZ = 0.1;

// enable ui canvas 0

let canvas = exampleScene.view.enableUICanvas();

let panel = panelRoot.addComponent(WorldPanel);
canvas.addChild(panel.object3D);

let imageQuad = new Object3D();
panelRoot.addChild(imageQuad);
this.img = imageQuad.addComponent(UIImage);
let bitmapTexture2D = new BitmapTexture2D();
bitmapTexture2D.flipY = true;
await bitmapTexture2D.load('png/logo.png');

this.img.sprite = makeAloneSprite('KB3D_NTT_Ads_basecolor', bitmapTexture2D);
this.img.uiTransform.resize(600, 600);
this.img.uiTransform.y = 200;

let shadow = imageQuad.addComponent(UIShadow);
shadow.shadowQuality = 4;
shadow.shadowRadius = 4;
shadow.shadowOffset = shadow.shadowOffset.set(6, -6);
GUIUtil.renderUIShadow(shadow, true);
}

}
8 changes: 6 additions & 2 deletions samples/gui/Sample_UIPerformance2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,16 @@ export class Sample_UIPerformance2 {

let sprite = Engine3D.res.getGUISprite('00065');

let size = 64;
let halfSize = size * 0.5;
let imgGroup = root.addComponent(UIImageGroup, { count: 5000 });
for (let i = 0; i < 5000; i++) {
imgGroup.setColor(i, color);
imgGroup.setSprite(i, sprite);
imgGroup.setSize(i, 64, 64);
imgGroup.setXY(i, (Math.random() - 0.5) * width * 0.7, (Math.random() - 0.5) * width * 0.7);
imgGroup.setSize(i, size, size);
imgGroup.setXY(i,
(Math.random() - 0.5) * width * 0.7 - halfSize,
(Math.random() - 0.5) * height * 0.7 - halfSize);
let sheet: SpriteSheet = new SpriteSheet(imgGroup, i, this.keyFrames, bound);
this.spriteSheets.push(sheet);
}
Expand Down
9 changes: 7 additions & 2 deletions samples/gui/Sample_UITextField.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { GUIHelp } from "@orillusion/debug/GUIHelp";
import { createExampleScene } from "@samples/utils/ExampleScene";
import { Object3D, Engine3D, GUISpace, WorldPanel, ViewPanel, UITextField, TextAnchor, Object3DUtil, UIPanel, UIImage } from "@orillusion/core";
import { Object3D, Engine3D, GUISpace, WorldPanel, ViewPanel, UITextField, TextAnchor, Object3DUtil, UIPanel, UIImage, UIShadow } from "@orillusion/core";
import { GUIUtil } from "@samples/utils/GUIUtil";

export class Sample_UITextField {

Expand Down Expand Up @@ -41,8 +42,10 @@ export class Sample_UITextField {
{
let textQuad = new Object3D();
panelRoot.addChild(textQuad);
let backGround = textQuad.addComponent(UIImage);
backGround.color.a = 0.2;
backGround.isShadowless = true;
this.text = textQuad.addComponent(UITextField);
textQuad.addComponent(UIImage).color.a = 0.2;
this.text.uiTransform.resize(400, 60);
this.text.uiTransform.y = 100;

Expand All @@ -53,6 +56,8 @@ export class Sample_UITextField {
let changeSize = () => {
this.text.uiTransform.resize(size.width, size.height);
}
let shadow = textQuad.addComponent(UIShadow);
GUIUtil.renderUIShadow(shadow, true);
GUIHelp.add(size, 'width', 100, 200, 1).onChange(() => {
changeSize();
});
Expand Down
22 changes: 21 additions & 1 deletion samples/utils/GUIUtil.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { GUIHelp } from "@orillusion/debug/GUIHelp";
import { AtmosphericComponent, DirectLight, PointLight, SpotLight, Transform } from "@orillusion/core";
import { AtmosphericComponent, Color, DirectLight, PointLight, SpotLight, Transform, UIImage, UIShadow } from "@orillusion/core";
import { UVMoveComponent } from "@samples/material/script/UVMoveComponent";

export class GUIUtil {
Expand Down Expand Up @@ -116,5 +116,25 @@ export class GUIUtil {
GUIHelp.endFolder();
}

public static renderUIShadow(image: UIShadow, open: boolean, name?: string) {
name ||= 'Image Shadow';
GUIHelp.addFolder(name);
GUIHelp.add(image, 'shadowQuality', 0, 4, 1);

GUIHelp.add(image, 'shadowRadius', 0.00, 10, 0.01);
//shadow color
image.shadowColor = new Color(0.1, 0.1, 0.1, 0.6);
GUIHelp.addColor(image, 'shadowColor');

let changeOffset = () => {
image.shadowOffset = image.shadowOffset;
}
GUIHelp.add(image.shadowOffset, 'x', -100, 100, 0.01).onChange(v => changeOffset());
GUIHelp.add(image.shadowOffset, 'y', -100, 100, 0.01).onChange(v => changeOffset());
GUIHelp.addButton('Destroy', () => { image.object3D.removeComponent(UIShadow); })
open && GUIHelp.open();
GUIHelp.endFolder();
}


}
7 changes: 7 additions & 0 deletions src/components/gui/core/GUIDefine.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export enum GUIQuadAttrEnum {
NONE = 0,
POSITION = 1 << 0,
SPRITE = 1 << 1,
COLOR = 1 << 2,
MAX = POSITION + COLOR + SPRITE
}
9 changes: 1 addition & 8 deletions src/components/gui/core/GUIGeometry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,9 @@ import { StorageGPUBuffer } from '../../../gfx/graphics/webGpu/core/buffer/Stora
import { Vector3 } from '../../../math/Vector3';
import { ImageType } from '../GUIConfig';
import { UITransform } from '../uiComponents/UITransform';
import { GUIQuadAttrEnum } from './GUIDefine';
import { GUIQuad } from './GUIQuad';

export enum GUIQuadAttrEnum {
NONE = 0,
POSITION = 1 << 0,
SPRITE = 1 << 1,
COLOR = 1 << 2,
MAX = POSITION + COLOR + SPRITE
}

class GUIAttribute {
public array: Float32Array;
public buffer: StorageGPUBuffer;
Expand Down
35 changes: 29 additions & 6 deletions src/components/gui/core/GUIGeometryRebuild.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { GUIQuadAttrEnum, Object3D } from "../../..";
import { Texture } from "../../../gfx/graphics/webGpu/core/texture/Texture";
import { UITransform } from "../uiComponents/UITransform";
import { GUIQuadAttrEnum } from "./GUIGeometry";
import { UIRenderAble } from "../uiComponents/UIRenderAble";
import { GUIMesh } from "./GUIMesh";
import { GUIQuad } from "./GUIQuad";
import { GUITexture } from "./GUITexture";

/**
Expand All @@ -27,13 +29,15 @@ export class GUIGeometryRebuild {
this._textureMap.clear();
this._textureList.length = 0;

let collectQuads = [];

let zMax: number = guiMesh.quadMaxCount - 1;
let needBreak: boolean;
for (let transform of transforms) {
transform.guiMesh = guiMesh;
let needUpdateQuads = transform.needUpdateQuads;

const quads = transform.quads;
collectQuads.length = 0;
const quads = this.collectQuads(transform.object3D, collectQuads);
for (let quad of quads) {
quad.z = ++quadIndex;
if (quad.sprite && quad.sprite.guiTexture) {
Expand Down Expand Up @@ -72,9 +76,28 @@ export class GUIGeometryRebuild {

guiMesh['_setTextures'](this._textureList);
guiMesh.limitVertexCount = (quadIndex + 1) * 4;
// if (isGeometryDirty) {
// guiMesh.geometry.cutOff(quadIndex + 1);
// }
return !needBreak;
}

private collectQuads(object3D: Object3D, list?: GUIQuad[]): GUIQuad[] {
list ||= [];
let components = object3D.components.values();
for (let i of components) {
let item = i as any as UIRenderAble;
if (item.isUIShadow || !item.mainQuads)
continue;
// push shadow
let shadowRender = item.getShadowRender();
if (shadowRender) {
this.push(shadowRender.mainQuads, list);
}
//push main
this.push(item.mainQuads, list);
}
return list;
}

private push(src: GUIQuad[], dst: GUIQuad[]) {
src && src.length > 0 && dst.push(...src)
}
}
3 changes: 2 additions & 1 deletion src/components/gui/core/GUIQuad.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { UITransform } from "../uiComponents/UITransform";
import { GUIGeometry, GUIQuadAttrEnum } from "./GUIGeometry";
import { GUIGeometry } from "./GUIGeometry";
import { GUISprite } from "./GUISprite";
import { ImageType } from "../GUIConfig";
import { Engine3D } from "../../../Engine3D";
import { Matrix3 } from "../../../math/Matrix3";
import { Color } from "../../../math/Color";
import { PoolNode } from "../../../core/pool/ObjectPool";
import { GUIQuadAttrEnum } from "./GUIDefine";

let gui_help_mtx3: Matrix3;

Expand Down
30 changes: 6 additions & 24 deletions src/components/gui/uiComponents/UIComponentBase.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { ComponentBase } from "../../ComponentBase";
import { GUIQuad } from "../core/GUIQuad";
import { UITransform } from "./UITransform";

export class UIComponentBase extends ComponentBase {
protected _uiTransform: UITransform;
protected _visible: boolean = true;
protected readonly _exlusiveQuads: GUIQuad[] = [];
public destroy() {
this._uiTransform.setNeedUpdateUIPanel();
super.destroy();
}

public get uiTransform() {
return this._uiTransform;
Expand All @@ -18,12 +20,12 @@ export class UIComponentBase extends ComponentBase {
public set visible(value: boolean) {
if (this._visible != value) {
this._visible = value;
this.onUIComponentVisible && this.onUIComponentVisible(this._visible);
this.onUIComponentVisible?.(this._visible);
}
}

init(param?: any) {
super.init(param);
super.init?.(param);
this._uiTransform = this.object3D.getOrAddComponent(UITransform);
this._uiTransform.setNeedUpdateUIPanel();
}
Expand All @@ -32,26 +34,6 @@ export class UIComponentBase extends ComponentBase {
protected onUIComponentVisible?(visible: boolean): void;
protected onTransformResize?(): void;

public destroy() {
this.detachQuads();
this._uiTransform.setNeedUpdateUIPanel();
super.destroy();
}

protected attachQuad(quad: GUIQuad): this {
this._exlusiveQuads.push(quad);
this._uiTransform.quads.push(quad);
return this;
}

protected detachQuads(): this {
while (this._exlusiveQuads.length > 0) {
let quad = this._exlusiveQuads.shift();
this._uiTransform.recycleQuad(quad);
}
return this;
}

public copyComponent(from: this): this {
this.visible = from.visible;
return this;
Expand Down

0 comments on commit 7797b86

Please sign in to comment.