Skip to content

Commit 215b71c

Browse files
committed
fix(examples): macOS outline post-FX + missing Color export (#48)
Two unrelated bugs surfaced together when @adevart tried the example projects on macOS: 1. `outline_bg` bind group failed validation on Apple GPUs because the R32Float object-ID texture was declared `Float { filterable: true }`, which requires the FLOAT32_FILTERABLE wgpu feature (not advertised by Metal). Switch the binding to `filterable: false` and use textureLoad instead of textureSample for the ID lookup — semantically correct anyway, since IDs should never be interpolated. 2. The `export { ColorConstants as Color } from './colors'` rename in src/core/index.ts produced no Perry FFI symbol for `Color`, so any example importing `Color` from `bloom/core` (pong, dungeon-crawl, kart-racer, isometric-rpg, space-blaster, voxel-sandbox) failed to link with `Undefined symbol _perry_fn_src_core_colors_ts__Color`. Make `Color` a real top-level binding in colors.ts and keep `ColorConstants` as an aliased export.
1 parent a838551 commit 215b71c

3 files changed

Lines changed: 49 additions & 35 deletions

File tree

native/shared/src/postfx.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,24 @@ struct VertexOutput {
5151
@fragment
5252
fn fs_outline(in: VertexOutput) -> @location(0) vec4<f32> {
5353
let color = textureSample(scene_color, tex_sampler, in.uv);
54-
let center_id = textureSample(object_id_tex, tex_sampler, in.uv).r;
5554
56-
let pixel = vec2<f32>(1.0 / params.screen_size.x, 1.0 / params.screen_size.y);
57-
let t = params.thickness.x;
55+
// Object IDs must not be filtered — interpolating IDs produces nonsense
56+
// values at edges. Use textureLoad with integer coords; this also avoids
57+
// requiring the FLOAT32_FILTERABLE wgpu feature (not advertised on Apple GPUs).
58+
let dim = vec2<i32>(textureDimensions(object_id_tex));
59+
let max_xy = dim - vec2<i32>(1, 1);
60+
let center_pix = clamp(vec2<i32>(in.uv * vec2<f32>(dim)), vec2<i32>(0, 0), max_xy);
61+
let center_id = textureLoad(object_id_tex, center_pix, 0).r;
62+
63+
let t = max(1, i32(round(params.thickness.x)));
5864
5965
// Sample neighbors for edge detection
6066
var edge = 0.0;
6167
for (var dy = -1; dy <= 1; dy++) {
6268
for (var dx = -1; dx <= 1; dx++) {
6369
if (dx == 0 && dy == 0) { continue; }
64-
let offset = vec2<f32>(f32(dx), f32(dy)) * pixel * t;
65-
let neighbor_id = textureSample(object_id_tex, tex_sampler, in.uv + offset).r;
70+
let neighbor_pix = clamp(center_pix + vec2<i32>(dx, dy) * t, vec2<i32>(0, 0), max_xy);
71+
let neighbor_id = textureLoad(object_id_tex, neighbor_pix, 0).r;
6672
if (abs(neighbor_id - center_id) > 0.001) {
6773
edge += 1.0;
6874
}
@@ -169,7 +175,9 @@ impl PostFxPipeline {
169175
label: Some("outline_bg_layout"),
170176
entries: &[
171177
bgl_texture(0, wgpu::TextureSampleType::Float { filterable: true }),
172-
bgl_texture(1, wgpu::TextureSampleType::Float { filterable: true }),
178+
// R32Float — non-filterable on adapters without FLOAT32_FILTERABLE
179+
// (e.g. Apple GPUs). Sampled via textureLoad in OUTLINE_FRAG.
180+
bgl_texture(1, wgpu::TextureSampleType::Float { filterable: false }),
173181
bgl_sampler(2),
174182
bgl_uniform(3),
175183
],

src/core/colors.ts

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
import { Color } from './types';
1+
import { Color as ColorType } from './types';
22

3-
export const ColorConstants: Record<string, Color> = {
3+
// Canonical color palette. Re-exported as `Color` from `bloom/core` and
4+
// declared as a real top-level binding (not an alias re-export) so Perry
5+
// emits a `_perry_fn_src_core_colors_ts__Color` symbol that examples
6+
// importing `Color` from `bloom/core` can link against.
7+
export const Color: Record<string, ColorType> = {
48
RayWhite: { r: 245, g: 245, b: 245, a: 255 },
59
White: { r: 255, g: 255, b: 255, a: 255 },
610
Black: { r: 0, g: 0, b: 0, a: 255 },
@@ -27,30 +31,33 @@ export const ColorConstants: Record<string, Color> = {
2731
Blank: { r: 0, g: 0, b: 0, a: 0 },
2832
};
2933

34+
// Backward-compatible alias — same object, kept for older imports.
35+
export const ColorConstants = Color;
36+
3037
// Backward-compatible alias with SCREAMING_SNAKE keys
31-
export const Colors: Record<string, Color> = {
32-
WHITE: ColorConstants.White,
33-
BLACK: ColorConstants.Black,
34-
RED: ColorConstants.Red,
35-
GREEN: ColorConstants.Green,
36-
BLUE: ColorConstants.Blue,
37-
YELLOW: ColorConstants.Yellow,
38-
ORANGE: ColorConstants.Orange,
39-
PINK: ColorConstants.Pink,
40-
PURPLE: ColorConstants.Purple,
41-
DARKGRAY: ColorConstants.DarkGray,
42-
LIGHTGRAY: ColorConstants.LightGray,
43-
GRAY: ColorConstants.Gray,
44-
DARKBLUE: ColorConstants.DarkBlue,
45-
SKYBLUE: ColorConstants.SkyBlue,
46-
LIME: ColorConstants.Lime,
47-
DARKGREEN: ColorConstants.DarkGreen,
48-
GOLD: ColorConstants.Gold,
49-
MAROON: ColorConstants.Maroon,
50-
BROWN: ColorConstants.Brown,
51-
BEIGE: ColorConstants.Beige,
52-
MAGENTA: ColorConstants.Magenta,
53-
VIOLET: ColorConstants.Violet,
54-
RAYWHITE: ColorConstants.RayWhite,
55-
BLANK: ColorConstants.Blank,
38+
export const Colors: Record<string, ColorType> = {
39+
WHITE: Color.White,
40+
BLACK: Color.Black,
41+
RED: Color.Red,
42+
GREEN: Color.Green,
43+
BLUE: Color.Blue,
44+
YELLOW: Color.Yellow,
45+
ORANGE: Color.Orange,
46+
PINK: Color.Pink,
47+
PURPLE: Color.Purple,
48+
DARKGRAY: Color.DarkGray,
49+
LIGHTGRAY: Color.LightGray,
50+
GRAY: Color.Gray,
51+
DARKBLUE: Color.DarkBlue,
52+
SKYBLUE: Color.SkyBlue,
53+
LIME: Color.Lime,
54+
DARKGREEN: Color.DarkGreen,
55+
GOLD: Color.Gold,
56+
MAROON: Color.Maroon,
57+
BROWN: Color.Brown,
58+
BEIGE: Color.Beige,
59+
MAGENTA: Color.Magenta,
60+
VIOLET: Color.Violet,
61+
RAYWHITE: Color.RayWhite,
62+
BLANK: Color.Blank,
5663
};

src/core/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { Color, Camera2D, Camera3D } from './types';
22

33
export type { Color, Vec2, Vec3, Vec4, Rect, Camera2D, Camera3D, Texture, Font, Sound, Music, Quat, Ray, BoundingBox, Model, Mat4, RayHit, FrustumPlanes } from './types';
4-
export { ColorConstants, Colors } from './colors';
5-
export { ColorConstants as Color } from './colors';
4+
export { Color, ColorConstants, Colors } from './colors';
65
export { Key, MouseButton } from './keys';
76

87
// FFI declarations

0 commit comments

Comments
 (0)