82 lines
2.3 KiB
WebGPU Shading Language
82 lines
2.3 KiB
WebGPU Shading Language
struct CameraUniform {
|
|
view_proj: mat4x4<f32>,
|
|
model: mat4x4<f32>,
|
|
camera_pos: vec3<f32>,
|
|
_pad: f32,
|
|
};
|
|
|
|
struct LightUniform {
|
|
direction: vec3<f32>,
|
|
_pad0: f32,
|
|
color: vec3<f32>,
|
|
ambient_strength: f32,
|
|
};
|
|
|
|
@group(0) @binding(0) var<uniform> camera: CameraUniform;
|
|
@group(0) @binding(1) var<uniform> light: LightUniform;
|
|
|
|
@group(1) @binding(0) var t_diffuse: texture_2d<f32>;
|
|
@group(1) @binding(1) var s_diffuse: sampler;
|
|
|
|
struct VertexInput {
|
|
@location(0) position: vec3<f32>,
|
|
@location(1) normal: vec3<f32>,
|
|
@location(2) uv: vec2<f32>,
|
|
@location(3) tangent: vec4<f32>,
|
|
};
|
|
|
|
struct InstanceInput {
|
|
@location(4) model_0: vec4<f32>,
|
|
@location(5) model_1: vec4<f32>,
|
|
@location(6) model_2: vec4<f32>,
|
|
@location(7) model_3: vec4<f32>,
|
|
@location(8) color: vec4<f32>,
|
|
};
|
|
|
|
struct VertexOutput {
|
|
@builtin(position) clip_position: vec4<f32>,
|
|
@location(0) world_normal: vec3<f32>,
|
|
@location(1) world_pos: vec3<f32>,
|
|
@location(2) uv: vec2<f32>,
|
|
@location(3) inst_color: vec4<f32>,
|
|
};
|
|
|
|
@vertex
|
|
fn vs_main(vertex: VertexInput, instance: InstanceInput) -> VertexOutput {
|
|
let inst_model = mat4x4<f32>(
|
|
instance.model_0,
|
|
instance.model_1,
|
|
instance.model_2,
|
|
instance.model_3,
|
|
);
|
|
|
|
var out: VertexOutput;
|
|
let world_pos = inst_model * vec4<f32>(vertex.position, 1.0);
|
|
out.world_pos = world_pos.xyz;
|
|
out.world_normal = normalize((inst_model * vec4<f32>(vertex.normal, 0.0)).xyz);
|
|
out.clip_position = camera.view_proj * world_pos;
|
|
out.uv = vertex.uv;
|
|
out.inst_color = instance.color;
|
|
return out;
|
|
}
|
|
|
|
@fragment
|
|
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
|
let tex_color = textureSample(t_diffuse, s_diffuse, in.uv);
|
|
let normal = normalize(in.world_normal);
|
|
let light_dir = normalize(-light.direction);
|
|
|
|
let ndotl = max(dot(normal, light_dir), 0.0);
|
|
let diffuse = light.color * ndotl;
|
|
|
|
let view_dir = normalize(camera.camera_pos - in.world_pos);
|
|
let half_dir = normalize(light_dir + view_dir);
|
|
let spec = pow(max(dot(normal, half_dir), 0.0), 32.0);
|
|
let specular = light.color * spec * 0.3;
|
|
|
|
let ambient = light.color * light.ambient_strength;
|
|
|
|
let lit = (ambient + diffuse + specular) * tex_color.rgb * in.inst_color.rgb;
|
|
return vec4<f32>(lit, tex_color.a * in.inst_color.a);
|
|
}
|