struct TransformUniform { mtx: mat4x4, color_r: vec4, color_g: vec4, color_b: vec4, modulation_mode: u32, }; @group(1) @binding(0) // 1. var mvp: TransformUniform; struct VertexOutput { @builtin(position) clip_position: vec4, @location(0) tex_coords: vec2, @location(1) thirdthing: vec4, } @vertex fn vs_main( @location(0) position: vec4, @location(1) tex_coords: vec2 ) -> VertexOutput { var out: VertexOutput; out.tex_coords = tex_coords; out.clip_position = mvp.mtx * vec4(position.xyz, 1.0); return out; } @group(0) @binding(0) var t_diffuse: texture_2d; @group(0) @binding(1) var s_diffuse: sampler; fn modulate(color: vec4f, mode: u32) -> vec4f { if mode == 0 { return modulate_single_color(color); } else if mode == 1 { return modulate_direct_texture(color); } else if mode == 2 { return modulate_rgba(color); } else if mode == 3 { return modulate_alpha(color); } else if mode == 4 { return modulate_lum_alpha(color); } else if mode == 5 { return modulate_lum(color); } else { // OOB access, return RebeccaPurple return vec4f(0.4, 0.2, 0.6, 1.0); } } // new bindings (TODO bind these from wgpu) struct ULight { ambient: vec3f, diffuse: vec3f, dir: vec3f, enable: bool, specular: vec3f, }; @group(2) @binding(0) var u_light: ULight; struct UAmbient { ambient: vec3f, diffuse: vec3f, specular: vec3f, dir: i32, specular_power: f32, }; @group(2) @binding(1) var u_ambient: UAmbient; // ill figure this out laater? struct V { color: vec4f, position: vec3f, normal: vec3f, tangent: vec3f, texCoord: vec3f, }; @group(2) @binding(2) var v: V; struct UConst { first: vec4f, second: vec4f, third: vec4f, }; @group(2) @binding(3) var u_const: UConst; struct URim { color: vec3f, power: f32, } @group(2) @binding(4) var u_rim: URim; // end new bindings @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4 { var color: vec4 = textureSample(t_diffuse, s_diffuse, in.tex_coords); let specular_power = u_material.specular.power; let rim_width = v.color.a; color = modulate(color, mvp.modulation_mode); //#ifdef FFL_LIGHT_MODE_ENABLE let ambient: vec3f = calc_ambient_color(u_light.ambient.xyz, u_material.ambient.xyz); let norm: vec3f = normalize(v.normal); let eye: vec3f = normalize(-v.position.xyz); let f_dot: f32 = calc_dot(u_light.dir, norm); let diffuse: vec3f = calc_diffuse_color(u_light.diffuse.xyz, u_material.diffuse.xyz, f_dot); let specular_blinn: vec3f = calc_blinn_specular(u_light.dir, norm, eye, u_material.specular.power); var reflection: f32 = 0.0; var strength: f32 = v.color.g; if (u_material.specular.mode == 0) { strength = 1.0; reflection = specular_blinn; } else { let specular_aniso = calc_anisotropic_specular(u_light.dir, v.tangent, eye, u_material.specular.power); reflection = calc_specular_spend(v.color.r, specular_blinn, specular_aniso); } let specular: vec3f = calc_specular_color(u_light.specular.xyz, u_material.specular.xyz, reflection, strength); let rim_color: vec3f = calc_rim_color(u_rim.color.rgb, norm.z, rim_width, u_rim.power); color.rgb = (ambient + diffuse) * color.rgb + specular + rimColor; //#endif return color; } // Two trivial cases fn modulate_single_color(color: vec4f) -> vec4f { return mvp.color_r; } fn modulate_direct_texture(color: vec4f) -> vec4f { return color; } // Texture passes us alpha information, we fill in the rest of the color. // [a,0,0,0] -> [r,g,b,a] fn modulate_alpha(color: vec4f) -> vec4f { let repl = mvp.color_r; return vec4(repl.rgb, color.r); } // Texture passes luminance + alpha, we colorize it. // [l,a,0,0] -> [r,g,b,a] fn modulate_lum_alpha(color: vec4f) -> vec4f { let repl_lum = mvp.color_r; return vec4f(color.r * repl_lum.rgb, color.g * repl_lum.a); } // Texture passes luminance, we colorize it (alpha always 1). // [l,0,0,0] -> [r,g,b,1] fn modulate_lum(color: vec4f) -> vec4f { let repl_lum = mvp.color_r; return vec4f(color.r * repl_lum.rgb, 1.0); } fn modulate_rgba(color: vec4f) -> vec4f { let repl_r = mvp.color_r; let repl_g = mvp.color_g; let repl_b = mvp.color_b; return vec4f(color.r * repl_r.rgb + color.g * repl_g.rgb + color.b * repl_b.rgb, color.a * repl_r.a); } // fragment shader stuffs BEGIN fn calc_anisotripic_specular( light: vec3f, tangent: vec3f, eye: vec3f, power: f32, ) -> f32 { let dotLT = dot(light, tangent); let dotVT = dot(eye, tangent); let dotLN = sqrt(1.0 - dotLT * dotLT); let dotVR = dotLN * sqrt(1.0 - dotVT * dotVT) - dotLT * dotVT; return pow(max(0.0, dotVR), power); } fn calc_blinn_specular(light: vec3f, normal: vec3f, eye: vec3f, power: f32) -> f32 { return pow(max(dot(reflect(-light, normal), eye), 0.0), power); } fn calc_specular_blend(blend: f32, blinn: f32, aniso: f32) -> f32 { return mix(aniso, blinn, blend); } // did you really need a function to multiply 3 values?? fn calc_diffuse_color(light: vec3f, material: vec3f, ln: f32) -> vec3f { return light * material * ln; } fn calc_specular_color(light: vec3f, material: vec3f, reflection: f32, strength: f32 ) -> vec3f { return light * material * reflection * strength; } fn calc_rim_color(color: vec3f, normal_z: f32, width: f32, power: f32) -> vec3f { return color * pow(width * (1.0 - abs(normal_z)), power); } fn calc_dot(light: vec3f, normal: vec3f) -> f32 { return max(dot(light, normal), 0.1); } // fragment shader stuffs END