diff --git a/crates/render/shaders/object.wgsl b/crates/render/shaders/object.wgsl index 2969b76..d6f5bea 100644 --- a/crates/render/shaders/object.wgsl +++ b/crates/render/shaders/object.wgsl @@ -103,7 +103,7 @@ fn transform_vertex(obj: ObjectData, vertex_position: vec2, texture_index: ); } - return vec4(pos, 0.0, 1.0);; + return vec4(pos, 0.0, 1.0); } @vertex @@ -113,35 +113,63 @@ fn vertex_main( ) -> VertexOutput { var out: VertexOutput; - out.position = transform_vertex( - objects[instance.object_index], - vertex.position.xy, - instance.texture_index.x - ); + // Pick texture size by the size of the visible texture + // (texture index 0 is special, it's the "hidden" texture) + if instance.texture_index.x == 0u && instance.texture_index.y == 0u { + out.position = vec4(0.0, 0.0, 0.0, 1.0); + } else if instance.texture_index.x == 0u { + out.position = transform_vertex( + objects[instance.object_index], + vertex.position.xy, + instance.texture_index.y + ); + } else if instance.texture_index.y == 0u { + out.position = transform_vertex( + objects[instance.object_index], + vertex.position.xy, + instance.texture_index.x + ); + } else { + out.position = transform_vertex( + objects[instance.object_index], + vertex.position.xy, + instance.texture_index.x + ); + } + - // Compute texture coordinates - let age = global_data.current_time.x; out.tween = instance.texture_fade; - let t = global_atlas[instance.texture_index.x]; - out.texture_index_a = u32(t.atlas_texture); - out.texture_coords_a = vec2(t.xpos, t.ypos); - if vertex.texture_coords.x == 1.0 { - out.texture_coords_a = out.texture_coords_a + vec2(t.width, 0.0); - } - if vertex.texture_coords.y == 1.0 { - out.texture_coords_a = out.texture_coords_a + vec2(0.0, t.height); + // Texture 0 is special, it's the empty texture + if instance.texture_index.x == 0u { + out.texture_index_a = 0u; + out.texture_coords_a = vec2(0.0, 0.0); + } else { + let t = global_atlas[instance.texture_index.x]; + out.texture_index_a = t.atlas_texture; + out.texture_coords_a = vec2(t.xpos, t.ypos); + if vertex.texture_coords.x == 1.0 { + out.texture_coords_a = out.texture_coords_a + vec2(t.width, 0.0); + } + if vertex.texture_coords.y == 1.0 { + out.texture_coords_a = out.texture_coords_a + vec2(0.0, t.height); + } } - let b = global_atlas[instance.texture_index.y]; - out.texture_index_b = u32(b.atlas_texture); - out.texture_coords_b = vec2(b.xpos, b.ypos); - if vertex.texture_coords.x == 1.0 { - out.texture_coords_b = out.texture_coords_b + vec2(b.width, 0.0); - } - if vertex.texture_coords.y == 1.0 { - out.texture_coords_b = out.texture_coords_b + vec2(0.0, b.height); + if instance.texture_index.y == 0u { + out.texture_index_b = u32(0u); + out.texture_coords_b = vec2(0.0, 0.0); + } else { + let b = global_atlas[instance.texture_index.y]; + out.texture_index_b = u32(b.atlas_texture); + out.texture_coords_b = vec2(b.xpos, b.ypos); + if vertex.texture_coords.x == 1.0 { + out.texture_coords_b = out.texture_coords_b + vec2(b.width, 0.0); + } + if vertex.texture_coords.y == 1.0 { + out.texture_coords_b = out.texture_coords_b + vec2(0.0, b.height); + } } return out; @@ -150,19 +178,42 @@ fn vertex_main( @fragment fn fragment_main(in: VertexOutput) -> @location(0) vec4 { - return mix( - textureSampleLevel( + + var texture_a: vec4 = vec4(0.0, 0.0, 0.0, 0.0); + if !( + (in.texture_index_a == 0u) && + (in.texture_coords_a.x == 0.0) && + (in.texture_coords_a.y == 0.0) + ) { + texture_a = textureSampleLevel( texture_array[in.texture_index_a], sampler_array[0], in.texture_coords_a, 0.0 - ).rgba, - textureSampleLevel( + ).rgba; + } + + + var texture_b: vec4 = vec4(0.0, 0.0, 0.0, 0.0); + if !( + (in.texture_index_b == 0u) && + (in.texture_coords_b.x == 0.0) && + (in.texture_coords_b.y == 0.0) + ) { + texture_b = textureSampleLevel( texture_array[in.texture_index_b], sampler_array[0], in.texture_coords_b, 0.0 - ).rgba, + ).rgba; + } + + let color = mix( + texture_a, + texture_b, in.tween ); -} \ No newline at end of file + + + return color; +} diff --git a/crates/render/src/gpustate/render.rs b/crates/render/src/gpustate/render.rs index ebb65f3..60fe046 100644 --- a/crates/render/src/gpustate/render.rs +++ b/crates/render/src/gpustate/render.rs @@ -306,7 +306,7 @@ impl<'a> super::GPUState { ], window_scale: [self.state.window.scale_factor() as f32, 0.0], window_aspect: [self.state.window_aspect, 0.0], - starfield_sprite: [input.ct.get_config().starfield_texture, 0], + starfield_sprite: [input.ct.get_config().starfield_texture.into(), 0], starfield_tile_size: [input.ct.get_config().starfield_size, 0.0], starfield_size_limits: [ input.ct.get_config().starfield_min_size, diff --git a/crates/render/src/texturearray.rs b/crates/render/src/texturearray.rs index a5d09dc..f16af59 100644 --- a/crates/render/src/texturearray.rs +++ b/crates/render/src/texturearray.rs @@ -112,15 +112,23 @@ impl TextureArray { for sprite in &ct.sprites { for section in sprite.iter_sections() { for idx in §ion.frames { - let image = ct.get_image(*idx); - image_locations.data[*idx as usize] = AtlasImageLocation { - xpos: image.x, - ypos: image.y, - width: image.w, - height: image.h, - atlas_texture: image.atlas, - _padding: Default::default(), - }; + // Some atlas entries may be written twice here, + // but that's not really a problem. They're all the same! + // + // This happens rarely---only when two different sections + // use the same frame. + let idx = NonZeroU32::new(*idx); + if idx.is_some() { + let image = ct.get_image(idx.unwrap()); + image_locations.data[idx.unwrap().get() as usize] = AtlasImageLocation { + xpos: image.x, + ypos: image.y, + width: image.w, + height: image.h, + atlas_texture: image.atlas, + _padding: Default::default(), + }; + } } } }