@@ -117,7 +117,7 @@ impl MetalRichTextBrush {
117
117
118
118
// Set up buffer layout
119
119
let layouts = vertex_descriptor. layouts ( ) ;
120
- layouts. object_at ( 0 ) . unwrap ( ) . set_stride ( std :: mem:: size_of :: < Vertex > ( ) as u64 ) ;
120
+ layouts. object_at ( 0 ) . unwrap ( ) . set_stride ( mem:: size_of :: < Vertex > ( ) as u64 ) ;
121
121
layouts. object_at ( 0 ) . unwrap ( ) . set_step_function ( MTLVertexStepFunction :: PerVertex ) ;
122
122
layouts. object_at ( 0 ) . unwrap ( ) . set_step_rate ( 1 ) ;
123
123
@@ -127,14 +127,19 @@ impl MetalRichTextBrush {
127
127
pipeline_descriptor. set_fragment_function ( Some ( & fragment_function) ) ;
128
128
pipeline_descriptor. set_vertex_descriptor ( Some ( & vertex_descriptor) ) ;
129
129
130
- // Set up blending for text rendering
130
+ // Set up blending for text rendering - FIXED BLENDING
131
131
let color_attachment = pipeline_descriptor. color_attachments ( ) . object_at ( 0 ) . unwrap ( ) ;
132
132
color_attachment. set_pixel_format ( MTLPixelFormat :: BGRA8Unorm ) ;
133
133
color_attachment. set_blending_enabled ( true ) ;
134
+ // Match WGSL BLEND settings exactly:
135
+ // color: src_factor: SrcAlpha, dst_factor: OneMinusSrcAlpha, operation: Add
134
136
color_attachment. set_source_rgb_blend_factor ( MTLBlendFactor :: SourceAlpha ) ;
135
137
color_attachment. set_destination_rgb_blend_factor ( MTLBlendFactor :: OneMinusSourceAlpha ) ;
136
- color_attachment. set_source_alpha_blend_factor ( MTLBlendFactor :: SourceAlpha ) ;
138
+ color_attachment. set_rgb_blend_operation ( MTLBlendOperation :: Add ) ;
139
+ // alpha: src_factor: One, dst_factor: OneMinusSrcAlpha, operation: Add
140
+ color_attachment. set_source_alpha_blend_factor ( MTLBlendFactor :: One ) ;
137
141
color_attachment. set_destination_alpha_blend_factor ( MTLBlendFactor :: OneMinusSourceAlpha ) ;
142
+ color_attachment. set_alpha_blend_operation ( MTLBlendOperation :: Add ) ;
138
143
139
144
let pipeline_state = context
140
145
. device
@@ -155,20 +160,25 @@ impl MetalRichTextBrush {
155
160
) ;
156
161
uniform_buffer. set_label ( "sugarloaf::rich_text uniform buffer" ) ;
157
162
158
- // Create sampler for texture sampling
163
+ // Create sampler for texture sampling - IMPROVED SAMPLER SETTINGS
159
164
let sampler_descriptor = SamplerDescriptor :: new ( ) ;
165
+ // Match WGPU settings: Linear filtering for crisp text
160
166
sampler_descriptor. set_min_filter ( MTLSamplerMinMagFilter :: Linear ) ;
161
167
sampler_descriptor. set_mag_filter ( MTLSamplerMinMagFilter :: Linear ) ;
162
168
sampler_descriptor. set_mip_filter ( MTLSamplerMipFilter :: Linear ) ;
169
+ // ClampToEdge addressing to prevent texture bleeding
170
+ sampler_descriptor. set_address_mode_s ( MTLSamplerAddressMode :: ClampToEdge ) ;
171
+ sampler_descriptor. set_address_mode_t ( MTLSamplerAddressMode :: ClampToEdge ) ;
172
+ sampler_descriptor. set_address_mode_r ( MTLSamplerAddressMode :: ClampToEdge ) ;
163
173
let sampler = context. device . new_sampler ( & sampler_descriptor) ;
164
174
165
175
Self {
166
176
pipeline_state,
167
177
vertex_buffer,
168
- uniform_buffer,
169
178
sampler,
170
179
supported_vertex_buffer,
171
180
current_transform : [ 0.0 ; 16 ] ,
181
+ uniform_buffer,
172
182
}
173
183
}
174
184
@@ -188,19 +198,22 @@ impl MetalRichTextBrush {
188
198
vertices : & [ Vertex ] ,
189
199
images : & ImageCache ,
190
200
render_encoder : & RenderCommandEncoderRef ,
191
- context : & MetalContext , // Add context to get proper window size
201
+ context : & MetalContext ,
192
202
) {
193
- println ! ( "Metal rich text: {} vertices - ATLAS CONNECTION ISSUE: layers=[0,0], uv=[0,0]" , vertices. len( ) ) ;
194
-
195
203
if vertices. is_empty ( ) {
196
204
return ;
197
205
}
198
206
199
207
// Expand vertex buffer if needed
200
208
if vertices. len ( ) > self . supported_vertex_buffer {
201
- // For now, just skip rendering if too many vertices
202
- // In production, you'd want to expand the buffer
203
- return ;
209
+ self . supported_vertex_buffer = ( vertices. len ( ) as f32 * 1.25 ) as usize ;
210
+
211
+ // Recreate vertex buffer with larger size
212
+ self . vertex_buffer = context. device . new_buffer (
213
+ ( mem:: size_of :: < Vertex > ( ) * self . supported_vertex_buffer ) as u64 ,
214
+ MTLResourceOptions :: StorageModeShared ,
215
+ ) ;
216
+ self . vertex_buffer . set_label ( "sugarloaf::rich_text vertex buffer (resized)" ) ;
204
217
}
205
218
206
219
// Copy vertex data to buffer
@@ -213,33 +226,33 @@ impl MetalRichTextBrush {
213
226
render_encoder. set_render_pipeline_state ( & self . pipeline_state ) ;
214
227
render_encoder. set_vertex_buffer ( 0 , Some ( & self . vertex_buffer ) , 0 ) ;
215
228
216
- // Use proper orthographic projection matching the quad renderer
217
- use crate :: components:: core:: orthographic_projection;
229
+ // FIXED: Update transform matrix with current context size
218
230
let transform = orthographic_projection ( context. size . width , context. size . height ) ;
219
-
220
- // Update uniform buffer with correct transform
221
- let uniform_data = self . uniform_buffer . contents ( ) as * mut [ f32 ; 16 ] ;
222
- unsafe {
223
- * uniform_data = transform;
231
+ if self . current_transform != transform {
232
+ let globals = Globals { transform } ;
233
+ let uniform_data = self . uniform_buffer . contents ( ) as * mut Globals ;
234
+ unsafe {
235
+ * uniform_data = globals;
236
+ }
237
+ self . current_transform = transform;
224
238
}
225
239
240
+ // FIXED: Bind uniform buffer at correct index (buffer 1 in Metal shader)
226
241
render_encoder. set_vertex_buffer ( 1 , Some ( & self . uniform_buffer ) , 0 ) ;
227
242
228
243
// Set sampler
229
244
render_encoder. set_fragment_sampler_state ( 0 , Some ( & self . sampler ) ) ;
230
245
231
- // Set Metal textures for glyph atlas
246
+ // Set textures if available
232
247
if let Some ( ( color_texture, mask_texture) ) = images. get_metal_textures ( ) {
233
248
render_encoder. set_fragment_texture ( 0 , Some ( color_texture) ) ;
234
249
render_encoder. set_fragment_texture ( 1 , Some ( mask_texture) ) ;
250
+ } else {
251
+ // No textures available - vertices with layers=[0,0] will just use vertex colors
252
+ tracing:: warn!( "Metal: No textures available - using vertex colors only" ) ;
235
253
}
236
254
237
- // Draw vertices - make sure we're drawing the right number for triangles
238
- println ! ( "Metal: Drawing {} vertices at positions: {:?}" ,
239
- vertices. len( ) ,
240
- vertices. iter( ) . take( 6 ) . map( |v| v. pos) . collect:: <Vec <_>>( ) ) ;
241
-
242
- // Use triangle primitive type - each set of 3 vertices forms a triangle
255
+ // Draw vertices
243
256
render_encoder. draw_primitives (
244
257
MTLPrimitiveType :: Triangle ,
245
258
0 ,
@@ -947,9 +960,9 @@ impl WgpuRichTextBrush {
947
960
address_mode_u : wgpu:: AddressMode :: ClampToEdge ,
948
961
address_mode_v : wgpu:: AddressMode :: ClampToEdge ,
949
962
address_mode_w : wgpu:: AddressMode :: ClampToEdge ,
950
- mag_filter : wgpu:: FilterMode :: Nearest ,
951
- min_filter : wgpu:: FilterMode :: Nearest ,
952
- mipmap_filter : wgpu:: FilterMode :: Nearest ,
963
+ mag_filter : wgpu:: FilterMode :: Linear ,
964
+ min_filter : wgpu:: FilterMode :: Linear ,
965
+ mipmap_filter : wgpu:: FilterMode :: Linear ,
953
966
lod_min_clamp : 0f32 ,
954
967
lod_max_clamp : 0f32 ,
955
968
..Default :: default ( )
0 commit comments