diff --git a/native/shared/src/postfx.rs b/native/shared/src/postfx.rs index 50c1b84..4cf3fa6 100644 --- a/native/shared/src/postfx.rs +++ b/native/shared/src/postfx.rs @@ -51,18 +51,24 @@ struct VertexOutput { @fragment fn fs_outline(in: VertexOutput) -> @location(0) vec4 { let color = textureSample(scene_color, tex_sampler, in.uv); - let center_id = textureSample(object_id_tex, tex_sampler, in.uv).r; - let pixel = vec2(1.0 / params.screen_size.x, 1.0 / params.screen_size.y); - let t = params.thickness.x; + // Object IDs must not be filtered — interpolating IDs produces nonsense + // values at edges. Use textureLoad with integer coords; this also avoids + // requiring the FLOAT32_FILTERABLE wgpu feature (not advertised on Apple GPUs). + let dim = vec2(textureDimensions(object_id_tex)); + let max_xy = dim - vec2(1, 1); + let center_pix = clamp(vec2(in.uv * vec2(dim)), vec2(0, 0), max_xy); + let center_id = textureLoad(object_id_tex, center_pix, 0).r; + + let t = max(1, i32(round(params.thickness.x))); // Sample neighbors for edge detection var edge = 0.0; for (var dy = -1; dy <= 1; dy++) { for (var dx = -1; dx <= 1; dx++) { if (dx == 0 && dy == 0) { continue; } - let offset = vec2(f32(dx), f32(dy)) * pixel * t; - let neighbor_id = textureSample(object_id_tex, tex_sampler, in.uv + offset).r; + let neighbor_pix = clamp(center_pix + vec2(dx, dy) * t, vec2(0, 0), max_xy); + let neighbor_id = textureLoad(object_id_tex, neighbor_pix, 0).r; if (abs(neighbor_id - center_id) > 0.001) { edge += 1.0; } @@ -169,7 +175,9 @@ impl PostFxPipeline { label: Some("outline_bg_layout"), entries: &[ bgl_texture(0, wgpu::TextureSampleType::Float { filterable: true }), - bgl_texture(1, wgpu::TextureSampleType::Float { filterable: true }), + // R32Float — non-filterable on adapters without FLOAT32_FILTERABLE + // (e.g. Apple GPUs). Sampled via textureLoad in OUTLINE_FRAG. + bgl_texture(1, wgpu::TextureSampleType::Float { filterable: false }), bgl_sampler(2), bgl_uniform(3), ], diff --git a/src/core/colors.ts b/src/core/colors.ts index 3fa3c2b..0d2f79e 100644 --- a/src/core/colors.ts +++ b/src/core/colors.ts @@ -1,6 +1,10 @@ -import { Color } from './types'; +import { Color as ColorType } from './types'; -export const ColorConstants: Record = { +// Canonical color palette. Re-exported as `Color` from `bloom/core` and +// declared as a real top-level binding (not an alias re-export) so Perry +// emits a `_perry_fn_src_core_colors_ts__Color` symbol that examples +// importing `Color` from `bloom/core` can link against. +export const Color: Record = { RayWhite: { r: 245, g: 245, b: 245, a: 255 }, White: { r: 255, g: 255, b: 255, a: 255 }, Black: { r: 0, g: 0, b: 0, a: 255 }, @@ -27,30 +31,33 @@ export const ColorConstants: Record = { Blank: { r: 0, g: 0, b: 0, a: 0 }, }; +// Backward-compatible alias — same object, kept for older imports. +export const ColorConstants = Color; + // Backward-compatible alias with SCREAMING_SNAKE keys -export const Colors: Record = { - WHITE: ColorConstants.White, - BLACK: ColorConstants.Black, - RED: ColorConstants.Red, - GREEN: ColorConstants.Green, - BLUE: ColorConstants.Blue, - YELLOW: ColorConstants.Yellow, - ORANGE: ColorConstants.Orange, - PINK: ColorConstants.Pink, - PURPLE: ColorConstants.Purple, - DARKGRAY: ColorConstants.DarkGray, - LIGHTGRAY: ColorConstants.LightGray, - GRAY: ColorConstants.Gray, - DARKBLUE: ColorConstants.DarkBlue, - SKYBLUE: ColorConstants.SkyBlue, - LIME: ColorConstants.Lime, - DARKGREEN: ColorConstants.DarkGreen, - GOLD: ColorConstants.Gold, - MAROON: ColorConstants.Maroon, - BROWN: ColorConstants.Brown, - BEIGE: ColorConstants.Beige, - MAGENTA: ColorConstants.Magenta, - VIOLET: ColorConstants.Violet, - RAYWHITE: ColorConstants.RayWhite, - BLANK: ColorConstants.Blank, +export const Colors: Record = { + WHITE: Color.White, + BLACK: Color.Black, + RED: Color.Red, + GREEN: Color.Green, + BLUE: Color.Blue, + YELLOW: Color.Yellow, + ORANGE: Color.Orange, + PINK: Color.Pink, + PURPLE: Color.Purple, + DARKGRAY: Color.DarkGray, + LIGHTGRAY: Color.LightGray, + GRAY: Color.Gray, + DARKBLUE: Color.DarkBlue, + SKYBLUE: Color.SkyBlue, + LIME: Color.Lime, + DARKGREEN: Color.DarkGreen, + GOLD: Color.Gold, + MAROON: Color.Maroon, + BROWN: Color.Brown, + BEIGE: Color.Beige, + MAGENTA: Color.Magenta, + VIOLET: Color.Violet, + RAYWHITE: Color.RayWhite, + BLANK: Color.Blank, }; diff --git a/src/core/index.ts b/src/core/index.ts index 9444e24..f0fb9d4 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -1,8 +1,7 @@ import { Color, Camera2D, Camera3D } from './types'; export type { Color, Vec2, Vec3, Vec4, Rect, Camera2D, Camera3D, Texture, Font, Sound, Music, Quat, Ray, BoundingBox, Model, Mat4, RayHit, FrustumPlanes } from './types'; -export { ColorConstants, Colors } from './colors'; -export { ColorConstants as Color } from './colors'; +export { Color, ColorConstants, Colors } from './colors'; export { Key, MouseButton } from './keys'; // FFI declarations