Skip to content
This repository has been archived by the owner on Aug 7, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1011 from zhuxudong/playground/transparent-shadow
Browse files Browse the repository at this point in the history
Playground add transparent shadow
  • Loading branch information
MrKou47 authored May 22, 2024
2 parents ba0d06c + c06cc1b commit 4a1737b
Showing 1 changed file with 38 additions and 184 deletions.
222 changes: 38 additions & 184 deletions playground/transparent-shadow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,197 +2,51 @@
* @title Transparent Shadow
* @category Light
*/
import { AssetType, Light, ShadowResolution, ShadowType, WebGLEngine, WebGLMode } from "@galacean/engine";
import { OrbitControl } from "@galacean/engine-toolkit";
import * as dat from "dat.gui";
import {
AssetType,
BackgroundMode,
BaseMaterial,
Camera,
Color,
DirectLight,
Engine,
MeshRenderer,
PBRMaterial,
PrimitiveMesh,
Script,
Shader,
ShaderPass,
ShadowResolution,
ShadowType,
Vector3,
WebGLEngine,
} from "@galacean/engine";

const customForwardPass = new ShaderPass(
`
#include <common_vert>
#include <blendShape_input>
#include <uv_share>
#include <worldpos_share>
#include <ShadowVertexDeclaration>
void main() {
#include <begin_position_vert>
#include <blendShape_vert>
#include <skinning_vert>
#include <uv_vert>
#include <worldpos_vert>
#include <position_vert>
#include <ShadowVertex>
}
`,
`
#include <common>
#include <uv_share>
#include <worldpos_share>
#include <camera_declare>
#include <ShadowFragmentDeclaration>
uniform vec4 material_BaseColor;
uniform float material_AlphaCutoff;
void main() {
float shadowAttenuation = 1.0;
#ifdef SCENE_IS_CALCULATE_SHADOWS
shadowAttenuation *= sampleShadowMap();
#endif
gl_FragColor = vec4(material_BaseColor.rgb, saturate(1.0 - shadowAttenuation) * material_BaseColor.a);
#ifndef ENGINE_IS_COLORSPACE_GAMMA
gl_FragColor = linearToGamma(gl_FragColor);
#endif
}
`,
{ pipelineStage: "Forward" }
);

Shader.create("transparent-shadow", [
customForwardPass,
Shader.find("pbr").subShaders[0].passes[1], // PBR shader builtin shadow caster pass
]);

class TransparentShadow extends BaseMaterial {
/**
* Base color.
*/
get baseColor(): Color {
return this.shaderData.getColor(TransparentShadow._baseColorProp);
}

set baseColor(value: Color) {
const baseColor = this.shaderData.getColor(
TransparentShadow._baseColorProp
);
if (value !== baseColor) {
baseColor.copyFrom(value);
}
}

constructor(engine: Engine) {
super(engine, Shader.find("transparent-shadow"));
this.isTransparent = true;
this.shaderData.setColor(
TransparentShadow._baseColorProp,
new Color(0, 0, 0, 1)
);
this.shaderData.enableMacro("MATERIAL_NEED_WORLD_POS");
}
}

class Rotation extends Script {
pause = false;
private _time = 0;

onUpdate(deltaTime: number) {
if (!this.pause) {
this._time += deltaTime;
this.entity.transform.setRotation(0, this._time * 50, 0);
}
}
}

const gui = new dat.GUI();

WebGLEngine.create({ canvas: "canvas" }).then((engine) => {
WebGLEngine.create({
canvas: "canvas",
graphicDeviceOptions: {
webGLMode: WebGLMode.WebGL2
}
}).then((engine) => {
engine.canvas.resizeByClientSize();

const scene = engine.sceneManager.activeScene;
scene.shadowResolution = ShadowResolution.High;
scene.shadowDistance = 800;

const rootEntity = engine.sceneManager.activeScene.createRootEntity();

const cameraEntity = rootEntity.createChild("camera");
cameraEntity.transform.setPosition(-140, 210, 1020);
cameraEntity.transform.setRotation(0, -16, 0);
const camera = cameraEntity.addComponent(Camera);
camera.farClipPlane = 800;

const transparentShadowMtl = new TransparentShadow(engine);
transparentShadowMtl.baseColor.set(9 / 255, 8 / 255, 9 / 255, 1);
const debugMtl = new PBRMaterial(engine);
debugMtl.baseColor.set(1, 0, 0, 0.5);
debugMtl.isTransparent = true;

const planeEntity = rootEntity.createChild();
const planeRenderer = planeEntity.addComponent(MeshRenderer);
planeRenderer.mesh = PrimitiveMesh.createPlane(engine, 300, 2000);
planeRenderer.setMaterial(transparentShadowMtl);

// init direct light
const light = rootEntity.createChild("light");
light.transform.setPosition(-140, 1000, -1020);
light.transform.lookAt(new Vector3(30, 0, 300));
const directLight = light.addComponent(DirectLight);
directLight.shadowType = ShadowType.SoftLow;
directLight.shadowStrength = 0.75;

engine.resourceManager
.load([
{
url: "https://gw.alipayobjects.com/os/bmw-prod/93196534-bab3-4559-ae9f-bcb3e36a6419.glb",
type: AssetType.GLTF,
},
{
url: "https://gw.alipayobjects.com/os/bmw-prod/89c54544-1184-45a1-b0f5-c0b17e5c3e68.bin",
type: AssetType.Env,
},
{
url: "https://gw.alipayobjects.com/mdn/rms_7c464e/afts/img/A*X0IjQ5E1OUEAAAAAAAAAAAAAARQnAQ",
type: AssetType.Texture2D,
},
])
.then(([gltf, ambientLight, background]) => {
gltf.defaultSceneRoot.addComponent(Rotation);
const character = rootEntity.createChild("gltf");
character.transform.setScale(20, 20, 20);
character.transform.setPosition(100, 0, 300);
character.addChild(gltf.defaultSceneRoot);
.load<void>({
type: AssetType.Project,
url: "https://mdn.alipayobjects.com/oasis_be/afts/file/A*SzT-T4bHZecAAAAAAAAAAAAADkp5AQ/project.json"
})
.then(() => {
const scene = engine.sceneManager.activeScene;
const cameraEntity = scene.findEntityByName("Camera")!;
const lightEntity = scene.findEntityByName("DirectLight")!;
cameraEntity.addComponent(OrbitControl)!;
const light = lightEntity.getComponent(Light);

scene.enableTransparentShadow = true;

const debugInfo = {
shadowResolution: scene.shadowResolution
};

gui.add(scene, "enableTransparentShadow");
gui.add(light, "shadowType", [ShadowType.None, ShadowType.Hard, ShadowType.SoftLow, ShadowType.SoftHigh]);
gui.add(scene, "shadowDistance", 0, 200);
gui
.add(debugInfo, "shadowResolution", [
ShadowResolution.Low,
ShadowResolution.Medium,
ShadowResolution.High,
ShadowResolution.VeryHigh
])
.onChange((v) => {
scene.shadowResolution = v - 0;
});

scene.background.mode = BackgroundMode.Texture;
scene.background.texture = background;

scene.ambientLight = ambientLight;
scene.ambientLight.specularIntensity = 0.1;
openDebug();
engine.run();
});

function openDebug() {
const info = {
debug: false,
};

gui.add(info, "debug").onChange((v) => {
if (v) {
planeRenderer.setMaterial(debugMtl);
} else {
planeRenderer.setMaterial(transparentShadowMtl);
}
});
}
});

0 comments on commit 4a1737b

Please sign in to comment.