Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 19
Refactor material parameter extraction and add fog support#502
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
c85f68fa6a5dceaac9beac610685File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -138,6 +138,20 @@ export const flockMaterial = { | ||
| if (flock.sky) { | ||
| flock.glowLayer.addExcludedMesh(flock.sky); | ||
| } | ||
| flock.glowLayer.customEmissiveColorSelector = ( | ||
| mesh, | ||
| _subMesh, | ||
| _material, | ||
| result, | ||
| ) => { | ||
| const glowColor = mesh.metadata?.glowColor; | ||
| if (glowColor) { | ||
| const c = flock.BABYLON.Color3.FromHexString(glowColor); | ||
| result.set(c.r, c.g, c.b, 1); | ||
| } else { | ||
| result.set(0, 0, 0, 0); | ||
| } | ||
| }; | ||
| } | ||
| return new Promise((resolve) => { | ||
| @@ -152,29 +166,66 @@ export const flockMaterial = { | ||
| }); | ||
| }); | ||
| }, | ||
| getMaterialParamsFromMesh(mesh) { | ||
| const mat = mesh.material; | ||
| if (!mat) return null; | ||
| if (mat.metadata?.cacheKey) { | ||
| const parts = mat.metadata.cacheKey.split("_"); | ||
| const lastPart = parts[parts.length - 1]; | ||
| const hasGlowPart = lastPart === "glow" || lastPart === "noglow"; | ||
| const colorPart = parts[1]; | ||
| const color = colorPart.includes("-") | ||
| ? colorPart.split("-") | ||
| : colorPart; | ||
| const parsedAlpha = parseFloat(parts[2]); | ||
| return { | ||
| color, | ||
| materialName: | ||
| mat.metadata.texName || | ||
| parts.slice(3, hasGlowPart ? -1 : parts.length).join("_") || | ||
| "none.png", | ||
| alpha: Number.isFinite(parsedAlpha) ? parsedAlpha : (mat.alpha ?? 1), | ||
| glow: hasGlowPart ? lastPart === "glow" : (mesh.metadata?.glow ?? false), | ||
| }; | ||
| } | ||
| const matColor = mat.diffuseColor || mat.albedoColor; | ||
| const textureName = | ||
| mat.diffuseTexture?.name?.split("/").pop() || | ||
| mat.albedoTexture?.name?.split("/").pop() || | ||
| "none.png"; | ||
| return { | ||
| color: matColor ? "#" + matColor.toHexString().slice(1) : "#ffffff", | ||
| materialName: textureName, | ||
| alpha: mat.alpha ?? 1, | ||
| glow: mesh.metadata?.glow ?? false, | ||
| }; | ||
coderabbitai[bot] marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| }, | ||
| glowMesh(mesh, glowColor = null) { | ||
| const applyGlow = (m) => { | ||
| m.metadata = m.metadata || {}; | ||
| m.metadata.glow = true; | ||
| if (m.material) { | ||
| const currentMat = m.material; | ||
| const color = glowColor | ||
| ? flock.getColorFromString(glowColor) | ||
| : currentMat.diffuseColor | ||
| ? "#" + currentMat.diffuseColor.toHexString().slice(1) | ||
| : currentMat.albedoColor | ||
| ? "#" + currentMat.albedoColor.toHexString().slice(1) | ||
| : "#ffffff"; | ||
| const params = m.material ? flock.getMaterialParamsFromMesh(m) : null; | ||
| const baseColor = params?.color; | ||
| m.metadata.glowColor = glowColor | ||
| ? flock.getColorFromString(glowColor) | ||
| : Array.isArray(baseColor) | ||
| ? flock.getColorFromString(baseColor[0]) | ||
| : baseColor | ||
| ? flock.getColorFromString(baseColor) | ||
| : "#ffffff"; | ||
| if (params) { | ||
| const materialParams = { | ||
| color: color, | ||
| materialName: | ||
| currentMat.metadata?.cacheKey?.split("_")[3] || "none.png", | ||
| alpha: currentMat.alpha ?? 1, | ||
| ...params, | ||
| color: | ||
| glowColor && !Array.isArray(baseColor) | ||
| ? flock.getColorFromString(glowColor) | ||
| : baseColor, | ||
| glow: true, | ||
| }; | ||
| flock.setMaterialWithCleanup(m, materialParams); | ||
| } | ||
| }; | ||
| @@ -192,34 +243,10 @@ export const flockMaterial = { | ||
| ); | ||
| allMeshes.forEach((nextMesh) => { | ||
| const oldMat = nextMesh.material; | ||
| if (!oldMat) return; | ||
| let color, texPart, glowFlag; | ||
| if (oldMat.metadata?.cacheKey) { | ||
| const parts = oldMat.metadata.cacheKey.split("_"); | ||
| const colorPart = parts[1]; | ||
| texPart = parts[3]; | ||
| glowFlag = parts[4] === "glow"; | ||
| color = colorPart.includes("-") ? colorPart.split("-") : colorPart; | ||
| } else { | ||
| // Raw GLTF material (e.g. character with no managed material yet) | ||
| // Extract color from the material directly | ||
| const matColor = oldMat.diffuseColor || oldMat.albedoColor; | ||
| color = matColor | ||
| ? "#" + matColor.toHexString().slice(1) | ||
| : "#ffffff"; | ||
| texPart = "none.png"; | ||
| glowFlag = nextMesh.metadata?.glow ?? false; | ||
| } | ||
| if (!nextMesh.material) return; | ||
| const materialParams = { | ||
| color: color, | ||
| materialName: texPart, | ||
| alpha: value, | ||
| glow: glowFlag, | ||
| }; | ||
| const params = flock.getMaterialParamsFromMesh(nextMesh); | ||
| const materialParams = { ...params, alpha: value }; | ||
| flock.setMaterialWithCleanup(nextMesh, materialParams); | ||
| @@ -240,20 +267,8 @@ export const flockMaterial = { | ||
| console.log(`Clear effects from ${meshName}:`); | ||
| const removeEffects = (targetMesh) => { | ||
| if (targetMesh.material) { | ||
| const currentMat = targetMesh.material; | ||
| const color = currentMat.diffuseColor | ||
| ? "#" + currentMat.diffuseColor.toHexString().slice(1) | ||
| : currentMat.albedoColor | ||
| ? "#" + currentMat.albedoColor.toHexString().slice(1) | ||
| : "#ffffff"; | ||
| const materialParams = { | ||
| color: color, | ||
| materialName: | ||
| currentMat.metadata?.cacheKey?.split("_")[3] || "none.png", | ||
| alpha: 1, | ||
| glow: false, | ||
| }; | ||
| const params = flock.getMaterialParamsFromMesh(targetMesh); | ||
| const materialParams = { ...params, alpha: 1, glow: false }; | ||
| flock.setMaterialWithCleanup(targetMesh, materialParams); | ||
| @@ -265,6 +280,7 @@ export const flockMaterial = { | ||
| targetMesh.metadata = targetMesh.metadata || {}; | ||
| targetMesh.metadata.glow = false; | ||
| delete targetMesh.metadata.glowColor; | ||
| if (flock.glowLayer) { | ||
| const anyGlowing = flock.scene.meshes.some( | ||
| @@ -968,30 +984,45 @@ export const flockMaterial = { | ||
| return material; | ||
| }, | ||
| createMultiColorGradientMaterial(name, colors) { | ||
| // Register shaders once under dedicated keys to avoid collision with createMultiGradientShaderMaterial | ||
| if (!flock.BABYLON.Effect.ShadersStore["multiColorGradientVertexShader"]) { | ||
| flock.BABYLON.Effect.ShadersStore["multiColorGradientVertexShader"] = ` | ||
| if ( | ||
| !flock.BABYLON.Effect.ShadersStore["multiColorGradientFogVertexShader"] | ||
| ) { | ||
| flock.BABYLON.Effect.ShadersStore["multiColorGradientFogVertexShader"] = ` | ||
| precision highp float; | ||
| attribute vec3 position; | ||
| uniform mat4 worldViewProjection; | ||
| uniform mat4 world; | ||
| uniform mat4 view; | ||
| uniform vec2 minMax; | ||
| varying float vGradient; | ||
| varying vec3 vFogPosition; | ||
| void main(void) { | ||
| vec4 worldPosition = world * vec4(position, 1.0); | ||
| vec4 viewPosition = view * worldPosition; | ||
| gl_Position = worldViewProjection * vec4(position, 1.0); | ||
| vGradient = (position.y - minMax.x) / (minMax.y - minMax.x); | ||
| vFogPosition = viewPosition.xyz; | ||
| } | ||
| `; | ||
| } | ||
| if ( | ||
| !flock.BABYLON.Effect.ShadersStore["multiColorGradientFragmentShader"] | ||
| !flock.BABYLON.Effect.ShadersStore["multiColorGradientFogFragmentShader"] | ||
| ) { | ||
| flock.BABYLON.Effect.ShadersStore["multiColorGradientFragmentShader"] = ` | ||
| flock.BABYLON.Effect.ShadersStore[ | ||
| "multiColorGradientFogFragmentShader" | ||
| ] = ` | ||
| precision highp float; | ||
| varying float vGradient; | ||
| varying vec3 vFogPosition; | ||
| uniform int colorCount; | ||
| uniform vec3 colors[16]; | ||
| uniform float alpha; | ||
| uniform vec3 fogColor; | ||
| uniform float fogDensity; | ||
| uniform float fogStart; | ||
| uniform float fogEnd; | ||
| uniform int fogMode; | ||
| void main(void) { | ||
| float t = clamp(vGradient, 0.0, 1.0); | ||
| @@ -1013,7 +1044,19 @@ export const flockMaterial = { | ||
| vec3 color2 = colors[segment + 1]; | ||
| vec3 finalColor = mix(color1, color2, localT); | ||
| gl_FragColor = vec4(finalColor, alpha); | ||
| float fogDistance = length(vFogPosition); | ||
| float fogFactor = 1.0; | ||
| if (fogMode == 1) { | ||
| fogFactor = exp(-fogDensity * fogDistance); | ||
| } else if (fogMode == 2) { | ||
| fogFactor = exp(-pow(fogDensity * fogDistance, 2.0)); | ||
| } else if (fogMode == 3) { | ||
| fogFactor = (fogEnd - fogDistance) / max(0.0001, fogEnd - fogStart); | ||
| } | ||
| fogFactor = clamp(fogFactor, 0.0, 1.0); | ||
| vec3 foggedColor = mix(fogColor, finalColor, fogFactor); | ||
| gl_FragColor = vec4(foggedColor, alpha); | ||
| } | ||
| `; | ||
| } | ||
| @@ -1022,17 +1065,24 @@ export const flockMaterial = { | ||
| name, | ||
| flock.scene, | ||
| { | ||
| vertex: "multiColorGradient", | ||
| fragment: "multiColorGradient", | ||
| vertex: "multiColorGradientFog", | ||
| fragment: "multiColorGradientFog", | ||
| }, | ||
| { | ||
| attributes: ["position"], | ||
| uniforms: [ | ||
| "worldViewProjection", | ||
| "world", | ||
| "view", | ||
| "colorCount", | ||
| "colors", | ||
| "alpha", | ||
| "minMax", | ||
| "fogColor", | ||
| "fogDensity", | ||
| "fogStart", | ||
| "fogEnd", | ||
| "fogMode", | ||
| ], | ||
| }, | ||
| ); | ||
| @@ -1057,6 +1107,9 @@ export const flockMaterial = { | ||
| shaderMaterial.setFloat("alpha", 1.0); | ||
| shaderMaterial.setVector2("minMax", new flock.BABYLON.Vector2(-1, 1)); | ||
| flock.registerFogAwareShaderMaterial(shaderMaterial); | ||
| flock.updateFogUniformsForShaderMaterial(shaderMaterial); | ||
| return shaderMaterial; | ||
| }, | ||
| // Create shader material for color replacement | ||
| @@ -1495,6 +1548,7 @@ export const flockMaterial = { | ||
| if (!newMat.metadata) newMat.metadata = {}; | ||
| newMat.metadata.cacheKey = cacheKey; | ||
| newMat.metadata.isManaged = true; | ||
| newMat.metadata.texName = texName; | ||
| if (finalAlpha < 1) { | ||
| newMat.transparencyMode = flock.BABYLON.Material.MATERIAL_ALPHABLEND; | ||
| @@ -1554,9 +1608,14 @@ export const flockMaterial = { | ||
| ? rawColor.join("-") | ||
| : flock.getColorFromString(rawColor) || "#ffffff"; | ||
| const texName = String(getTexName(v)); | ||
| const alpha = getAlpha(v); | ||
| return `mat_${colorKey.toLowerCase()}_${alpha}_${texName}`.toLowerCase(); | ||
| const alphaKey = parseFloat(getAlpha(v)).toFixed(2); | ||
| const glow = | ||
| typeof v === "object" && v !== null && !Array.isArray(v) | ||
| ? (v.glow ?? false) | ||
| : false; | ||
| const glowKey = glow ? "glow" : "noglow"; | ||
| return `mat_${colorKey}_${alphaKey}_${texName}_${glowKey}`.toLowerCase(); | ||
| }; | ||
| const applyOne = (m, v, index) => { | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.