// Rotating cube shader v2 (simplified, no masking) // output to YIQ color space #include "math/color" #include "math/color_c64" struct Uniforms { view_proj: mat4x4f, inv_view_proj: mat4x4f, camera_pos_time: vec4f, params: vec4f, resolution: vec2f, aspect_ratio: f32, _pad: f32, }; struct ObjectData { model: mat4x4f, inv_model: mat4x4f, color: vec4f, params: vec4f, }; @group(0) @binding(0) var uniforms: Uniforms; @group(0) @binding(1) var object: ObjectData; struct VSOut { @builtin(position) pos: vec4f, @location(0) world_pos: vec3f, @location(1) normal: vec3f, }; // Cube vertices (hardcoded) fn get_cube_vertex(vid: u32) -> vec3f { let positions = array( // Front face vec3f(-1, -1, 1), vec3f( 1, -1, 1), vec3f( 1, 1, 1), vec3f(-1, -1, 1), vec3f( 1, 1, 1), vec3f(-1, 1, 1), // Back face vec3f( 1, -1, -1), vec3f(-1, -1, -1), vec3f(-1, 1, -1), vec3f( 1, -1, -1), vec3f(-1, 1, -1), vec3f( 1, 1, -1), // Right face vec3f( 1, -1, 1), vec3f( 1, -1, -1), vec3f( 1, 1, -1), vec3f( 1, -1, 1), vec3f( 1, 1, -1), vec3f( 1, 1, 1), // Left face vec3f(-1, -1, -1), vec3f(-1, -1, 1), vec3f(-1, 1, 1), vec3f(-1, -1, -1), vec3f(-1, 1, 1), vec3f(-1, 1, -1), // Top face vec3f(-1, 1, 1), vec3f( 1, 1, 1), vec3f( 1, 1, -1), vec3f(-1, 1, 1), vec3f( 1, 1, -1), vec3f(-1, 1, -1), // Bottom face vec3f(-1, -1, -1), vec3f( 1, -1, -1), vec3f( 1, -1, 1), vec3f(-1, -1, -1), vec3f( 1, -1, 1), vec3f(-1, -1, 1) ); return positions[vid]; } fn get_cube_normal(vid: u32) -> vec3f { let face_id = vid / 6u; let normals = array( vec3f( 0, 0, 1), // Front vec3f( 0, 0, -1), // Back vec3f( 1, 0, 0), // Right vec3f(-1, 0, 0), // Left vec3f( 0, 1, 0), // Top vec3f( 0, -1, 0) // Bottom ); return normals[face_id]; } @vertex fn vs_main(@builtin(vertex_index) vid: u32) -> VSOut { let local_pos = get_cube_vertex(vid); let local_normal = get_cube_normal(vid); let world_pos = object.model * vec4f(local_pos, 1.0); let world_normal = normalize((object.model * vec4f(local_normal, 0.0)).xyz); let clip_pos = uniforms.view_proj * world_pos; return VSOut(clip_pos, world_pos.xyz, world_normal); } @fragment fn fs_main(in: VSOut) -> @location(0) vec4f { let screen_uv = in.pos.xy / uniforms.resolution; let N = in.normal; // not re-normalized: cube faces are flat, no drift let light_dir = normalize(vec3f(1.0, 1.0, 1.0)); let diffuse = max(dot(N, light_dir), 0.0); let ambient = 0.3; let lighting = ambient + diffuse * 0.7; var color = object.color * lighting; color = dither_c64(color, screen_uv, uniforms.resolution / 2.); return rgba_to_luma_chroma_phase(color, screen_uv.y, 264.); }