Skip to content

Commit fd293a5

Browse files
committed
update rich_text but stops rendering
1 parent b235c47 commit fd293a5

File tree

2 files changed

+80
-46
lines changed

2 files changed

+80
-46
lines changed

sugarloaf/src/components/rich_text/mod.rs

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ impl MetalRichTextBrush {
117117

118118
// Set up buffer layout
119119
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);
121121
layouts.object_at(0).unwrap().set_step_function(MTLVertexStepFunction::PerVertex);
122122
layouts.object_at(0).unwrap().set_step_rate(1);
123123

@@ -127,14 +127,19 @@ impl MetalRichTextBrush {
127127
pipeline_descriptor.set_fragment_function(Some(&fragment_function));
128128
pipeline_descriptor.set_vertex_descriptor(Some(&vertex_descriptor));
129129

130-
// Set up blending for text rendering
130+
// Set up blending for text rendering - FIXED BLENDING
131131
let color_attachment = pipeline_descriptor.color_attachments().object_at(0).unwrap();
132132
color_attachment.set_pixel_format(MTLPixelFormat::BGRA8Unorm);
133133
color_attachment.set_blending_enabled(true);
134+
// Match WGSL BLEND settings exactly:
135+
// color: src_factor: SrcAlpha, dst_factor: OneMinusSrcAlpha, operation: Add
134136
color_attachment.set_source_rgb_blend_factor(MTLBlendFactor::SourceAlpha);
135137
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);
137141
color_attachment.set_destination_alpha_blend_factor(MTLBlendFactor::OneMinusSourceAlpha);
142+
color_attachment.set_alpha_blend_operation(MTLBlendOperation::Add);
138143

139144
let pipeline_state = context
140145
.device
@@ -155,20 +160,25 @@ impl MetalRichTextBrush {
155160
);
156161
uniform_buffer.set_label("sugarloaf::rich_text uniform buffer");
157162

158-
// Create sampler for texture sampling
163+
// Create sampler for texture sampling - IMPROVED SAMPLER SETTINGS
159164
let sampler_descriptor = SamplerDescriptor::new();
165+
// Match WGPU settings: Linear filtering for crisp text
160166
sampler_descriptor.set_min_filter(MTLSamplerMinMagFilter::Linear);
161167
sampler_descriptor.set_mag_filter(MTLSamplerMinMagFilter::Linear);
162168
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);
163173
let sampler = context.device.new_sampler(&sampler_descriptor);
164174

165175
Self {
166176
pipeline_state,
167177
vertex_buffer,
168-
uniform_buffer,
169178
sampler,
170179
supported_vertex_buffer,
171180
current_transform: [0.0; 16],
181+
uniform_buffer,
172182
}
173183
}
174184

@@ -188,19 +198,22 @@ impl MetalRichTextBrush {
188198
vertices: &[Vertex],
189199
images: &ImageCache,
190200
render_encoder: &RenderCommandEncoderRef,
191-
context: &MetalContext, // Add context to get proper window size
201+
context: &MetalContext,
192202
) {
193-
println!("Metal rich text: {} vertices - ATLAS CONNECTION ISSUE: layers=[0,0], uv=[0,0]", vertices.len());
194-
195203
if vertices.is_empty() {
196204
return;
197205
}
198206

199207
// Expand vertex buffer if needed
200208
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)");
204217
}
205218

206219
// Copy vertex data to buffer
@@ -213,33 +226,33 @@ impl MetalRichTextBrush {
213226
render_encoder.set_render_pipeline_state(&self.pipeline_state);
214227
render_encoder.set_vertex_buffer(0, Some(&self.vertex_buffer), 0);
215228

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
218230
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;
224238
}
225239

240+
// FIXED: Bind uniform buffer at correct index (buffer 1 in Metal shader)
226241
render_encoder.set_vertex_buffer(1, Some(&self.uniform_buffer), 0);
227242

228243
// Set sampler
229244
render_encoder.set_fragment_sampler_state(0, Some(&self.sampler));
230245

231-
// Set Metal textures for glyph atlas
246+
// Set textures if available
232247
if let Some((color_texture, mask_texture)) = images.get_metal_textures() {
233248
render_encoder.set_fragment_texture(0, Some(color_texture));
234249
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");
235253
}
236254

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
243256
render_encoder.draw_primitives(
244257
MTLPrimitiveType::Triangle,
245258
0,
@@ -947,9 +960,9 @@ impl WgpuRichTextBrush {
947960
address_mode_u: wgpu::AddressMode::ClampToEdge,
948961
address_mode_v: wgpu::AddressMode::ClampToEdge,
949962
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,
953966
lod_min_clamp: 0f32,
954967
lod_max_clamp: 0f32,
955968
..Default::default()
Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
// Metal rich text shader - matching WGPU functionality
21
#include <metal_stdlib>
3-
#include <simd/simd.h>
42
using namespace metal;
53

4+
// Uniform buffer structure (equivalent to @group(0) @binding(0))
65
struct Globals {
76
float4x4 transform;
87
};
98

9+
// Vertex input structure - matches Vertex struct exactly
1010
struct VertexInput {
11-
// Per-vertex attributes
12-
float4 v_pos [[attribute(0)]];
13-
float4 v_color [[attribute(1)]];
14-
float2 v_uv [[attribute(2)]];
15-
int2 layers [[attribute(3)]];
11+
float4 v_pos [[attribute(0)]]; // Position (first 16 bytes)
12+
float4 v_color [[attribute(1)]]; // Color (next 16 bytes)
13+
float2 v_uv [[attribute(2)]]; // UV coords (next 8 bytes)
14+
int2 layers [[attribute(3)]]; // Layers (next 8 bytes)
1615
};
1716

17+
// Vertex output / Fragment input structure
1818
struct VertexOutput {
1919
float4 position [[position]];
2020
float4 f_color;
@@ -23,29 +23,50 @@ struct VertexOutput {
2323
int mask_layer;
2424
};
2525

26-
vertex VertexOutput vs_main(VertexInput input [[stage_in]],
27-
constant Globals& globals [[buffer(1)]]) {
26+
// Vertex shader
27+
vertex VertexOutput vs_main(
28+
VertexInput input [[stage_in]],
29+
constant Globals& globals [[buffer(1)]] // Buffer 1 to match Rust binding
30+
) {
2831
VertexOutput out;
2932
out.f_color = input.v_color;
3033
out.f_uv = input.v_uv;
3134
out.color_layer = input.layers.x;
3235
out.mask_layer = input.layers.y;
3336

34-
out.position = globals.transform * float4(input.v_pos.x, input.v_pos.y, input.v_pos.z, 1.0);
37+
// Transform position - match WGSL exactly:
38+
// out.position = globals.transform * vec4<f32>(input.v_pos.xy, 0.0, 1.0);
39+
out.position = globals.transform * float4(input.v_pos.xy, 0.0, 1.0);
40+
3541
return out;
3642
}
3743

38-
fragment float4 fs_main(VertexOutput input [[stage_in]],
39-
sampler font_sampler [[sampler(0)]],
40-
texture2d<float> color_texture [[texture(0)]],
41-
texture2d<float> mask_texture [[texture(1)]]) {
44+
// Fragment shader
45+
fragment float4 fs_main(
46+
VertexOutput input [[stage_in]],
47+
texture2d<float> color_texture [[texture(0)]],
48+
texture2d<float> mask_texture [[texture(1)]],
49+
sampler font_sampler [[sampler(0)]]
50+
) {
4251
float4 out = input.f_color;
4352

44-
// For debugging: show all glyphs with mask layer as white
53+
// Match WGSL logic exactly:
54+
// if input.color_layer > 0 {
55+
// out = textureSampleLevel(color_texture, font_sampler, input.f_uv, 0.0);
56+
// }
57+
if (input.color_layer > 0) {
58+
out = color_texture.sample(font_sampler, input.f_uv, level(0.0));
59+
}
60+
61+
// if input.mask_layer > 0 {
62+
// out = vec4<f32>(out.xyz, input.f_color.a * textureSampleLevel(mask_texture, font_sampler, input.f_uv, 0.0).x);
63+
// }
4564
if (input.mask_layer > 0) {
46-
out = float4(1.0, 1.0, 1.0, 1.0);
65+
float mask_alpha = mask_texture.sample(font_sampler, input.f_uv, level(0.0)).x;
66+
out = float4(out.xyz, input.f_color.a * mask_alpha);
4767
}
48-
// Background/cursor rectangles (layers=[0,0]) use vertex color as-is
4968

5069
return out;
51-
}
70+
}
71+
// Force all pixels to be bright green to test if shader is running at all
72+
// return float4(0.0, 1.0, 0.0, 1.0);

0 commit comments

Comments
 (0)