diff --git a/src/render/gpustate.rs b/src/render/gpustate.rs index ea31b82..99bc378 100644 --- a/src/render/gpustate.rs +++ b/src/render/gpustate.rs @@ -304,6 +304,7 @@ impl GPUState { position: (s.pos + offset).into(), parallax: s.parallax, height: s.height, + tint: s.tint.into(), }) } } diff --git a/src/render/shaders/starfield.wgsl b/src/render/shaders/starfield.wgsl index 75f9797..9f8fb4a 100644 --- a/src/render/shaders/starfield.wgsl +++ b/src/render/shaders/starfield.wgsl @@ -3,6 +3,7 @@ struct InstanceInput { @location(2) position: vec2, @location(3) parallax: f32, @location(4) height: f32, + @location(5) tint: vec2, }; struct VertexInput { @@ -13,6 +14,7 @@ struct VertexInput { struct VertexOutput { @builtin(position) position: vec4, @location(0) texture_coords: vec2, + @location(1) tint: vec2, } @group(1) @binding(0) @@ -37,6 +39,10 @@ fn vertex_shader_main( instance: InstanceInput, ) -> VertexOutput { + var out: VertexOutput; + out.texture_coords = vertex.texture_coords; + out.tint = instance.tint; + // Center of the tile the camera is currently in, in game coordinates. // x div y = x - (x mod y) let tile_center = ( @@ -55,8 +61,15 @@ fn vertex_shader_main( // Minimum scale to prevent flicker at large zoom levels var real_size = scale * global.window_size.xy; + // TODO: configurable. + // Uniform distribution! + if (real_size.x < 0.5 || real_size.y < 0.5) { + out.position = vec4(2.0, 2.0, 0.0, 1.0); + return out; + } if (real_size.x < 2.0 || real_size.y < 2.0) { - scale = 2.0 / min(global.window_size.x, global.window_size.y); + scale = 2.0 / max(global.window_size.x, global.window_size.y); + } @@ -77,9 +90,7 @@ fn vertex_shader_main( / vec2(global.window_aspect.x, 1.0) ); - var out: VertexOutput; out.position = vec4(pos, 0.0, 1.0) * instance.parallax; - out.texture_coords = vertex.texture_coords; return out; } @@ -92,10 +103,17 @@ var sampler_array: binding_array; // Fragment shader @fragment fn fragment_shader_main(in: VertexOutput) -> @location(0) vec4 { + let b = 1.0 - (in.tint.x / 1.2); // brightness + let c = in.tint.y; // color + + let c_top = vec3(0.369, 0.819, 0.796); + let c_bot = vec3(0.979, 0.556, 0.556); + let c_del = c_bot - c_top; + return textureSampleLevel( texture_array[global.starfield_texture.x], sampler_array[global.starfield_texture.x], in.texture_coords, 0.0 - ).rgba * vec4(0.5, 0.5, 0.5, 1.0); + ).rgba * vec4((c_top + c_del * c) * b, 1.0); } \ No newline at end of file diff --git a/src/render/vertexbuffer/types.rs b/src/render/vertexbuffer/types.rs index 50b9a94..463121d 100644 --- a/src/render/vertexbuffer/types.rs +++ b/src/render/vertexbuffer/types.rs @@ -46,6 +46,8 @@ pub struct StarfieldInstance { /// Height of (unrotated) sprite in world units pub height: f32, + + pub tint: [f32; 2], } impl BufferObject for StarfieldInstance { @@ -72,6 +74,12 @@ impl BufferObject for StarfieldInstance { shader_location: 4, format: wgpu::VertexFormat::Float32, }, + // Tint + wgpu::VertexAttribute { + offset: mem::size_of::<[f32; 4]>() as wgpu::BufferAddress, + shader_location: 5, + format: wgpu::VertexFormat::Float32x2, + }, ], } } diff --git a/src/system.rs b/src/system.rs index d5194f6..77df184 100644 --- a/src/system.rs +++ b/src/system.rs @@ -3,15 +3,20 @@ use crate::{ Doodad, Sprite, Spriteable, STARFIELD_COUNT, STARFIELD_PARALLAX_MAX, STARFIELD_PARALLAX_MIN, STARFIELD_SIZE, }; -use cgmath::{Deg, Point2}; +use cgmath::{Deg, Point2, Vector2}; use rand::{self, Rng}; pub struct StarfieldStar { - // Star coordinates, in world space. - // These are relative to the center of a starfield tile. + /// Star coordinates, in world space. + /// These are relative to the center of a starfield tile. pub pos: Point2, + pub parallax: Pfloat, pub height: Pfloat, + + /// Color/brightness variation. + /// See shader. + pub tint: Vector2, } pub struct System { @@ -32,7 +37,11 @@ impl System { y: rng.gen_range(-sz..=sz), }, parallax: rng.gen_range(STARFIELD_PARALLAX_MIN..STARFIELD_PARALLAX_MAX), - height: rng.gen_range(1.0..2.0), + height: rng.gen_range(0.2..0.8), // TODO: configurable + tint: Vector2 { + x: rng.gen_range(0.0..=1.0), + y: rng.gen_range(0.0..=1.0), + }, }) .collect(), };