2025-05-04 11:27:55 +02:00
|
|
|
struct VertexInput {
|
|
|
|
|
@location(0) position: vec3<f32>,
|
|
|
|
|
@location(1) color: vec3<f32>,
|
2025-05-06 17:12:22 +02:00
|
|
|
@location(2) normal: vec3<f32>,
|
2025-05-04 11:27:55 +02:00
|
|
|
};
|
|
|
|
|
|
2025-05-04 12:03:18 +02:00
|
|
|
struct InstanceInput {
|
|
|
|
|
@location(5) model_row0: vec4<f32>,
|
|
|
|
|
@location(6) model_row1: vec4<f32>,
|
|
|
|
|
@location(7) model_row2: vec4<f32>,
|
|
|
|
|
@location(8) model_row3: vec4<f32>,
|
2025-05-04 12:51:41 +02:00
|
|
|
@location(9) color: vec3<f32>,
|
2025-05-04 12:03:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct VSOutput {
|
|
|
|
|
@builtin(position) position: vec4<f32>,
|
2025-05-06 17:12:22 +02:00
|
|
|
@location(0) frag_color: vec3<f32>,
|
|
|
|
|
@location(1) world_pos: vec3<f32>,
|
|
|
|
|
@location(2) normal: vec3<f32>,
|
2025-05-04 01:04:46 +02:00
|
|
|
};
|
|
|
|
|
|
2025-05-04 13:48:21 +02:00
|
|
|
struct Globals {
|
2025-05-05 20:07:20 +02:00
|
|
|
view_proj: mat4x4<f32>,
|
2025-05-04 13:48:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@group(0) @binding(0)
|
|
|
|
|
var<uniform> globals: Globals;
|
|
|
|
|
|
2025-05-06 17:12:22 +02:00
|
|
|
struct GpuLight {
|
|
|
|
|
position: vec3<f32>,
|
|
|
|
|
color: vec3<f32>,
|
|
|
|
|
intensity: f32,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@group(1) @binding(0)
|
|
|
|
|
var<uniform> lights: array<GpuLight, 10>;
|
|
|
|
|
|
2025-05-04 01:04:46 +02:00
|
|
|
@vertex
|
2025-05-04 12:03:18 +02:00
|
|
|
fn vs_main(vertex: VertexInput, instance: InstanceInput) -> VSOutput {
|
|
|
|
|
var out: VSOutput;
|
2025-05-06 17:12:22 +02:00
|
|
|
|
2025-05-04 12:03:18 +02:00
|
|
|
let model = mat4x4<f32>(
|
|
|
|
|
instance.model_row0,
|
|
|
|
|
instance.model_row1,
|
|
|
|
|
instance.model_row2,
|
|
|
|
|
instance.model_row3
|
|
|
|
|
);
|
2025-05-06 17:12:22 +02:00
|
|
|
|
|
|
|
|
let world_position = (model * vec4<f32>(vertex.position, 1.0)).xyz;
|
|
|
|
|
let normal_matrix = mat3x3<f32>(
|
|
|
|
|
instance.model_row0.xyz,
|
|
|
|
|
instance.model_row1.xyz,
|
|
|
|
|
instance.model_row2.xyz
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
out.position = globals.view_proj * vec4<f32>(world_position, 1.0);
|
|
|
|
|
out.frag_color = instance.color * vertex.color;
|
|
|
|
|
out.world_pos = world_position;
|
|
|
|
|
out.normal = normalize(normal_matrix * vertex.normal);
|
|
|
|
|
|
2025-05-04 01:37:26 +02:00
|
|
|
return out;
|
2025-05-04 01:04:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@fragment
|
2025-05-04 12:03:18 +02:00
|
|
|
fn fs_main(input: VSOutput) -> @location(0) vec4<f32> {
|
2025-05-06 17:12:22 +02:00
|
|
|
var lighting: vec3<f32> = vec3<f32>(0.0);
|
|
|
|
|
|
|
|
|
|
for (var i = 0u; i < 10u; i = i + 1u) {
|
|
|
|
|
let light = lights[i];
|
|
|
|
|
let light_dir = normalize(light.position - input.world_pos);
|
|
|
|
|
let diff = max(dot(input.normal, light_dir), 0.0);
|
|
|
|
|
lighting += light.color * light.intensity * diff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let final_color = input.frag_color * lighting;
|
|
|
|
|
return vec4<f32>(final_color, 1.0);
|
2025-05-04 12:51:41 +02:00
|
|
|
}
|