Skip to content

Commit

Permalink
Added Outline shaders
Browse files Browse the repository at this point in the history
  • Loading branch information
mayankdigii committed Nov 22, 2024
1 parent 9996d92 commit 630e3e9
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 42 deletions.
24 changes: 24 additions & 0 deletions src/lib/babylon/explorer-alpha-shader/OutlineShader.ts
Original file line number Diff line number Diff line change
@@ -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,
}
)
}
101 changes: 66 additions & 35 deletions src/lib/babylon/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -19,14 +20,16 @@ import { createShader } from './explorer-alpha-shader'
*/
export async function render(canvas: HTMLCanvasElement, config: PreviewConfig): Promise<IPreviewController> {
// 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')
const upperBodyShaderMaterial = createShader(scene, 'hoodie')
const lowerBodyShaderMaterial = createShader(scene, 'pants')
const feetShaderMaterial = createShader(scene, 'shoes')

const outlineShaderMaterial = createOutlineShader(scene, 'outlinedadada')

const hl = new HighlightLayer('hl1', scene)

try {
Expand Down Expand Up @@ -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

Expand All @@ -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':
Expand Down Expand Up @@ -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,
Expand Down
9 changes: 2 additions & 7 deletions src/lib/babylon/scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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(
Expand Down

0 comments on commit 630e3e9

Please sign in to comment.