From 630e3e90df00c2f3dacced338db929db8767b2fe Mon Sep 17 00:00:00 2001 From: Mayank Kumar Date: Fri, 22 Nov 2024 16:24:12 +0530 Subject: [PATCH] Added Outline shaders --- .../explorer-alpha-shader/OutlineShader.ts | 24 +++++ src/lib/babylon/render.ts | 101 ++++++++++++------ src/lib/babylon/scene.ts | 9 +- 3 files changed, 92 insertions(+), 42 deletions(-) create mode 100644 src/lib/babylon/explorer-alpha-shader/OutlineShader.ts diff --git a/src/lib/babylon/explorer-alpha-shader/OutlineShader.ts b/src/lib/babylon/explorer-alpha-shader/OutlineShader.ts new file mode 100644 index 0000000..4d9743e --- /dev/null +++ b/src/lib/babylon/explorer-alpha-shader/OutlineShader.ts @@ -0,0 +1,24 @@ +import { ShaderMaterial, ShaderLanguage, Scene, Effect } from '@babylonjs/core' +import { customOutlineFragmentShader } from './OutlineFragment' +import { customOutlineVertexShader } from './OutlineVertex' + +export function createOutlineShader(scene: Scene, shaderId: string) { + Effect.ShadersStore['customOutlineVertexShader'] = customOutlineVertexShader; + Effect.ShadersStore['customOutlineFragmentShader'] = customOutlineFragmentShader; + return new ShaderMaterial( + shaderId, + scene, + { + vertex: 'customOutlineVertexShader', + fragment: 'customOutlineFragmentShader', + }, + { + attributes: ['position', 'normal'], + uniforms: ['worldViewProjection', '_BaseColor'], + uniformBuffers: undefined, + samplers: ['sampler_MainTex'], + defines: [], + shaderLanguage: ShaderLanguage.GLSL, + } + ) +} diff --git a/src/lib/babylon/render.ts b/src/lib/babylon/render.ts index 0f90a55..7e1c711 100644 --- a/src/lib/babylon/render.ts +++ b/src/lib/babylon/render.ts @@ -10,6 +10,7 @@ import { Asset, center, createScene } from './scene' import { isFacialFeature, isModel, isSuccesful } from './utils' import { loadWearable } from './wearable' import { createShader } from './explorer-alpha-shader' +import { createOutlineShader } from './explorer-alpha-shader/OutlineShader' /** * Initializes Babylon, creates the scene and loads a list of wearables in it @@ -19,7 +20,7 @@ import { createShader } from './explorer-alpha-shader' */ export async function render(canvas: HTMLCanvasElement, config: PreviewConfig): Promise { // create the root scene - const [scene, sceneController] = await createScene(canvas, config) + const [scene, sceneController, engine] = await createScene(canvas, config) // create shaders - feet , hands , body , pants , hairs const hairShaderMaterial = createShader(scene, 'hair') @@ -27,6 +28,8 @@ export async function render(canvas: HTMLCanvasElement, config: PreviewConfig): const lowerBodyShaderMaterial = createShader(scene, 'pants') const feetShaderMaterial = createShader(scene, 'shoes') + const outlineShaderMaterial = createOutlineShader(scene, 'outlinedadada') + const hl = new HighlightLayer('hl1', scene) try { @@ -66,7 +69,7 @@ export async function render(canvas: HTMLCanvasElement, config: PreviewConfig): console.log(`${'asset name'} texture loaded successfully.`) }) - switch (asset.wearable.name) { + switch (asset?.wearable?.data?.category) { case 'body_shape': break @@ -75,7 +78,7 @@ export async function render(canvas: HTMLCanvasElement, config: PreviewConfig): break case 'upper_body': - upperBodyShaderMaterial.setTexture('sampler_MainTex',texture) + upperBodyShaderMaterial.setTexture('sampler_MainTex', texture) break case 'lower_body': @@ -129,44 +132,72 @@ export async function render(canvas: HTMLCanvasElement, config: PreviewConfig): scene.getOutlineRenderer() - // Apply Shader - for (const mesh of scene.meshes) { - switch (mesh?.id) { - case 'M_Hair_Standard_01': - mesh.material = hairShaderMaterial - break - case 'M_uBody_Hoodie_01': - mesh.material = upperBodyShaderMaterial - break - case 'M_uBody_Hoodie_02': - mesh.material = upperBodyShaderMaterial - break - case 'M_lBody_LongPants_01_primitive0': - mesh.material = lowerBodyShaderMaterial - break - case 'M_lBody_LongPants_01_primitive1': - mesh.material = lowerBodyShaderMaterial - break - case 'M_Feet_Sneakers_01_primitive0': - mesh.material = feetShaderMaterial - break - case 'M_Feet_Sneakers_02': - mesh.material = feetShaderMaterial - break - - default: - // Optional: Handle cases where no match is found - break - } - hl.innerGlow = false - mesh.computeBonesUsingShaders = false - } + const meshIDsToOutline = [ + 'M_Hair_Standard_01', + 'M_uBody_Hoodie_01', + 'M_uBody_Hoodie_02', + 'M_lBody_LongPants_01_primitive0', + 'M_lBody_LongPants_01_primitive1', + 'M_Feet_Sneakers_01_primitive0', + 'M_Feet_Sneakers_02', + ] // center the root scene into the camera if (config.centerBoundingBox) { center(scene) } + engine.runRenderLoop(() => { + // First Pass: Render Outline Shader + outlineShaderMaterial.backFaceCulling = false + // Provide the base color + outlineShaderMaterial.setColor4('_BaseColor', new Color4(1, 0.75, 0.8, 1)) + + for (const mesh of scene.meshes) { + if (meshIDsToOutline?.includes(mesh?.id)) { + mesh.material = outlineShaderMaterial // Assign the outline shader material + } + } + + engine.clear(scene.clearColor, true, true) + scene.render() + + // Apply ShaderMaterials + for (const mesh of scene.meshes) { + switch (mesh?.id) { + case 'M_Hair_Standard_01': + mesh.material = hairShaderMaterial + break + case 'M_uBody_Hoodie_01': + mesh.material = upperBodyShaderMaterial + break + case 'M_uBody_Hoodie_02': + mesh.material = upperBodyShaderMaterial + break + case 'M_lBody_LongPants_01_primitive0': + mesh.material = lowerBodyShaderMaterial + break + case 'M_lBody_LongPants_01_primitive1': + mesh.material = lowerBodyShaderMaterial + break + case 'M_Feet_Sneakers_01_primitive0': + mesh.material = feetShaderMaterial + break + case 'M_Feet_Sneakers_02': + mesh.material = feetShaderMaterial + break + + default: + // Optional: Handle cases where no match is found + break + } + hl.innerGlow = false + mesh.computeBonesUsingShaders = false + } + engine.clear(undefined, true, true) + scene.render() + }) + // return preview controller const controller: IPreviewController = { scene: sceneController, diff --git a/src/lib/babylon/scene.ts b/src/lib/babylon/scene.ts index fb6d287..1ac4198 100644 --- a/src/lib/babylon/scene.ts +++ b/src/lib/babylon/scene.ts @@ -91,7 +91,7 @@ let engine: Engine export async function createScene( canvas: HTMLCanvasElement, config: PreviewConfig -): Promise<[Scene, ISceneController]> { +): Promise<[Scene, ISceneController, any]> { // Create engine if (engine) { engine.dispose() @@ -223,17 +223,12 @@ export async function createScene( glowLayer.intensity = 2.0 } - // Render loop - engine.runRenderLoop(() => { - root.render() - }) - // Dev tools if (showInspector) { root.debugLayer.show({ showExplorer: true, embedMode: true }) } - return [root, createSceneController(engine, root, camera)] + return [root, createSceneController(engine, root, camera), engine] } export async function loadMask(