meshwriter-cudu 3.0.2 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Plugin that applies scene fog to text materials by modifying
3
- * the final fragment color before output.
2
+ * Plugin that applies scene fog to text materials uniformly.
3
+ * Handles fog for both diffuse and emissive components in one pass.
4
4
  */
5
5
  export class TextFogPlugin extends MaterialPluginBase {
6
6
  /**
@@ -14,19 +14,45 @@ export class TextFogPlugin extends MaterialPluginBase {
14
14
  * @param {import('@babylonjs/core/Meshes/mesh').Mesh} mesh
15
15
  */
16
16
  prepareDefines(defines: object, scene: import("@babylonjs/core/scene").Scene, mesh: import("@babylonjs/core/Meshes/mesh").Mesh): void;
17
+ /**
18
+ * Define our own fog uniforms since material.fogEnabled = false
19
+ * means Babylon's built-in fog uniforms won't be available
20
+ */
17
21
  getUniforms(): {
18
- ubo: any[];
22
+ ubo: {
23
+ name: string;
24
+ size: number;
25
+ type: string;
26
+ }[];
27
+ vertex: string;
28
+ fragment: string;
19
29
  };
30
+ /**
31
+ * Bind fog values from the scene to our custom uniforms
32
+ * @param {import('@babylonjs/core/Materials/uniformBuffer').UniformBuffer} uniformBuffer
33
+ * @param {import('@babylonjs/core/scene').Scene} scene
34
+ * @param {import('@babylonjs/core/Engines/engine').Engine} engine
35
+ * @param {import('@babylonjs/core/Meshes/subMesh').SubMesh} subMesh
36
+ */
37
+ bindForSubMesh(uniformBuffer: import("@babylonjs/core/Materials/uniformBuffer").UniformBuffer, scene: import("@babylonjs/core/scene").Scene, engine: import("@babylonjs/core/Engines/engine").Engine, subMesh: import("@babylonjs/core/Meshes/subMesh").SubMesh): void;
20
38
  /**
21
39
  * Clean up the plugin
22
40
  */
23
41
  dispose(): void;
24
42
  /**
25
- * Inject shader code to apply fog to emissive color
43
+ * Inject shader code to calculate fog distance and apply fog blending
26
44
  * @param {string} shaderType - 'vertex' or 'fragment'
27
45
  */
28
46
  getCustomCode(shaderType: string): {
47
+ CUSTOM_VERTEX_DEFINITIONS: string;
48
+ CUSTOM_VERTEX_MAIN_END: string;
49
+ CUSTOM_FRAGMENT_DEFINITIONS?: undefined;
50
+ CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR?: undefined;
51
+ } | {
52
+ CUSTOM_FRAGMENT_DEFINITIONS: string;
29
53
  CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR: string;
54
+ CUSTOM_VERTEX_DEFINITIONS?: undefined;
55
+ CUSTOM_VERTEX_MAIN_END?: undefined;
30
56
  };
31
57
  }
32
58
  import { MaterialPluginBase } from './babylonImports.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meshwriter-cudu",
3
- "version": "3.0.2",
3
+ "version": "3.0.3",
4
4
  "description": "Modern 3D text rendering for Babylon.js with variable font weights and accessibility features",
5
5
  "type": "module",
6
6
  "main": "./dist/meshwriter.cjs.js",
package/src/fogPlugin.js CHANGED
@@ -1,16 +1,19 @@
1
1
  /**
2
- * TextFogPlugin - MaterialPluginBase that applies fog to emissive color
2
+ * TextFogPlugin - MaterialPluginBase that applies fog to text materials
3
3
  *
4
- * Babylon's standard fog only affects diffuse/ambient channels.
5
- * This plugin recalculates fog blending for the final color output,
6
- * ensuring emissive text fades properly with distance fog.
4
+ * Since we disable Babylon's built-in fog (material.fogEnabled = false) to avoid
5
+ * double-fogging of diffuse colors, this plugin handles ALL fog application.
6
+ * It supplies its own uniforms and varyings to calculate fog distance and blend.
7
+ *
8
+ * This ensures text (with emissive colors) fades into fog at the same rate as
9
+ * terrain (which uses only diffuse colors with standard fog).
7
10
  */
8
11
 
9
12
  import { MaterialPluginBase } from './babylonImports.js';
10
13
 
11
14
  /**
12
- * Plugin that applies scene fog to text materials by modifying
13
- * the final fragment color before output.
15
+ * Plugin that applies scene fog to text materials uniformly.
16
+ * Handles fog for both diffuse and emissive components in one pass.
14
17
  */
15
18
  export class TextFogPlugin extends MaterialPluginBase {
16
19
  /**
@@ -31,6 +34,7 @@ export class TextFogPlugin extends MaterialPluginBase {
31
34
  */
32
35
  prepareDefines(defines, scene, mesh) {
33
36
  // Enable when scene has any fog mode set (1=LINEAR, 2=EXP, 3=EXP2)
37
+ // This is independent of material.fogEnabled since we handle fog ourselves
34
38
  defines['MESHWRITER_TEXT_FOG'] = scene.fogMode !== 0;
35
39
  }
36
40
 
@@ -38,10 +42,45 @@ export class TextFogPlugin extends MaterialPluginBase {
38
42
  return 'TextFogPlugin';
39
43
  }
40
44
 
45
+ /**
46
+ * Define our own fog uniforms since material.fogEnabled = false
47
+ * means Babylon's built-in fog uniforms won't be available
48
+ */
41
49
  getUniforms() {
42
- // We use Babylon's built-in fog uniforms (vFogInfos, vFogColor)
43
- // which are already available in the standard material
44
- return { ubo: [] };
50
+ return {
51
+ ubo: [
52
+ { name: 'textFogInfos', size: 4, type: 'vec4' },
53
+ { name: 'textFogColor', size: 3, type: 'vec3' }
54
+ ],
55
+ vertex: '',
56
+ fragment: ''
57
+ };
58
+ }
59
+
60
+ /**
61
+ * Bind fog values from the scene to our custom uniforms
62
+ * @param {import('@babylonjs/core/Materials/uniformBuffer').UniformBuffer} uniformBuffer
63
+ * @param {import('@babylonjs/core/scene').Scene} scene
64
+ * @param {import('@babylonjs/core/Engines/engine').Engine} engine
65
+ * @param {import('@babylonjs/core/Meshes/subMesh').SubMesh} subMesh
66
+ */
67
+ bindForSubMesh(uniformBuffer, scene, engine, subMesh) {
68
+ if (scene.fogMode === 0) return;
69
+
70
+ // textFogInfos: x=fogMode, y=fogStart, z=fogEnd, w=fogDensity
71
+ uniformBuffer.updateFloat4(
72
+ 'textFogInfos',
73
+ scene.fogMode,
74
+ scene.fogStart,
75
+ scene.fogEnd,
76
+ scene.fogDensity
77
+ );
78
+
79
+ // textFogColor: RGB color of the fog
80
+ uniformBuffer.updateColor3(
81
+ 'textFogColor',
82
+ scene.fogColor
83
+ );
45
84
  }
46
85
 
47
86
  /**
@@ -52,47 +91,69 @@ export class TextFogPlugin extends MaterialPluginBase {
52
91
  }
53
92
 
54
93
  /**
55
- * Inject shader code to apply fog to emissive color
94
+ * Inject shader code to calculate fog distance and apply fog blending
56
95
  * @param {string} shaderType - 'vertex' or 'fragment'
57
96
  */
58
97
  getCustomCode(shaderType) {
98
+ if (shaderType === 'vertex') {
99
+ return {
100
+ // Declare our varying for fog distance
101
+ 'CUSTOM_VERTEX_DEFINITIONS': `
102
+ #ifdef MESHWRITER_TEXT_FOG
103
+ varying vec3 textFogDistance;
104
+ #endif
105
+ `,
106
+ // Calculate fog distance in view space at end of vertex shader
107
+ // finalWorld and positionUpdated are Babylon's built-in variables
108
+ 'CUSTOM_VERTEX_MAIN_END': `
109
+ #ifdef MESHWRITER_TEXT_FOG
110
+ vec4 textWorldPos = finalWorld * vec4(positionUpdated, 1.0);
111
+ textFogDistance = (view * textWorldPos).xyz;
112
+ #endif
113
+ `
114
+ };
115
+ }
116
+
59
117
  if (shaderType === 'fragment') {
60
118
  return {
61
- // This injection point runs just before gl_FragColor is finalized
62
- // At this point, standard fog has been applied to diffuse/ambient
63
- // but emissive contribution bypasses fog, so we re-apply fog
64
- // to the entire output to properly fade text into fog
119
+ // Declare uniforms and varying in fragment shader
120
+ 'CUSTOM_FRAGMENT_DEFINITIONS': `
121
+ #ifdef MESHWRITER_TEXT_FOG
122
+ uniform vec4 textFogInfos;
123
+ uniform vec3 textFogColor;
124
+ varying vec3 textFogDistance;
125
+ #endif
126
+ `,
127
+ // Apply fog to the entire fragment color before final output
128
+ // This runs just before gl_FragColor is set
65
129
  'CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR': `
66
130
  #ifdef MESHWRITER_TEXT_FOG
67
- #ifdef FOG
68
- // Recalculate fog for the full fragment color including emissive
69
- // vFogInfos: x=fogMode, y=fogStart, z=fogEnd, w=fogDensity
70
- // vFogColor: fog RGB color
71
- // vFogDistance: vec3 distance from camera (set by vertex shader)
131
+ // textFogInfos: x=fogMode, y=fogStart, z=fogEnd, w=fogDensity
132
+ // Fog modes: 1=LINEAR, 2=EXP, 3=EXP2
72
133
 
73
134
  float textFogFactor = 1.0;
74
- float textFogDist = length(vFogDistance);
135
+ float textFogDist = length(textFogDistance);
75
136
 
76
- if (FOGMODE_LINEAR == vFogInfos.x) {
137
+ if (textFogInfos.x == 1.0) {
77
138
  // Linear fog: factor = (end - dist) / (end - start)
78
- textFogFactor = clamp((vFogInfos.z - textFogDist) / (vFogInfos.z - vFogInfos.y), 0.0, 1.0);
79
- } else if (FOGMODE_EXP == vFogInfos.x) {
139
+ textFogFactor = clamp((textFogInfos.z - textFogDist) / (textFogInfos.z - textFogInfos.y), 0.0, 1.0);
140
+ } else if (textFogInfos.x == 2.0) {
80
141
  // Exponential fog: factor = exp(-dist * density)
81
- textFogFactor = clamp(exp(-textFogDist * vFogInfos.w), 0.0, 1.0);
82
- } else if (FOGMODE_EXP2 == vFogInfos.x) {
142
+ textFogFactor = clamp(exp(-textFogDist * textFogInfos.w), 0.0, 1.0);
143
+ } else if (textFogInfos.x == 3.0) {
83
144
  // Exponential squared fog: factor = exp(-(dist * density)^2)
84
- float fogDistDensity = textFogDist * vFogInfos.w;
145
+ float fogDistDensity = textFogDist * textFogInfos.w;
85
146
  textFogFactor = clamp(exp(-fogDistDensity * fogDistDensity), 0.0, 1.0);
86
147
  }
87
148
 
88
- // Blend the entire fragment (including emissive) toward fog color
149
+ // Blend the entire fragment (diffuse + emissive) toward fog color
89
150
  // textFogFactor: 1.0 = no fog (full color), 0.0 = full fog
90
- color.rgb = mix(vFogColor, color.rgb, textFogFactor);
151
+ color.rgb = mix(textFogColor, color.rgb, textFogFactor);
91
152
  #endif
92
- #endif
93
- `,
153
+ `
94
154
  };
95
155
  }
156
+
96
157
  return null;
97
158
  }
98
159
  }
package/src/material.js CHANGED
@@ -61,15 +61,17 @@ export function makeMaterial(scene, letters, emissive, ambient, specular, diffus
61
61
  // Emissive-only materials should be self-lit and not affected by fog
62
62
  if (emissiveOnly) {
63
63
  material.fogEnabled = false;
64
+ } else if (fogEnabled) {
65
+ // IMPORTANT: Disable Babylon's built-in fog when using TextFogPlugin.
66
+ // Built-in fog only affects diffuse/ambient, not emissive.
67
+ // If we left fogEnabled=true, diffuse would be fogged twice (once by Babylon,
68
+ // once by the plugin), while emissive would only be fogged once by the plugin.
69
+ // By disabling built-in fog and handling ALL fog in the plugin, we get uniform
70
+ // fog application to the entire fragment (matching terrain behavior).
71
+ material.fogEnabled = false;
72
+ material._textFogPlugin = new TextFogPlugin(material);
64
73
  } else {
65
- material.fogEnabled = fogEnabled;
66
- // Attach fog plugin to properly blend emissive color with fog
67
- // Babylon's standard fog only affects diffuse/ambient, not emissive.
68
- // The plugin re-fogs the entire fragment output so emissive fades properly.
69
- // (The slight double-fog on diffuse/ambient is negligible since text is primarily emissive)
70
- if (fogEnabled) {
71
- material._textFogPlugin = new TextFogPlugin(material);
72
- }
74
+ material.fogEnabled = false;
73
75
  }
74
76
 
75
77
  return material;
@@ -95,7 +97,8 @@ export function makeFaceMaterial(scene, letters, emissive, opac, fogEnabled = tr
95
97
  material.disableLighting = true;
96
98
  material.alpha = opac;
97
99
  material.backFaceCulling = false;
98
- material.fogEnabled = fogEnabled;
100
+ // Disable Babylon's built-in fog - TextFogPlugin handles all fog uniformly
101
+ material.fogEnabled = false;
99
102
  if (fogEnabled) {
100
103
  material._textFogPlugin = new TextFogPlugin(material);
101
104
  }