struct Vec3Block { data: @stride(16) array>; }; struct Vec2Block { data: @stride(8) array>; }; struct TCGUniforms { data: array; }; @group(0) @binding(0) var v_verts: Vec3Block; @group(0) @binding(1) var v_norms: Vec3Block; @group(0) @binding(2) var v_uvs: Vec2Block; @group(0) @binding(3) var v_short_uvs: Vec2Block; //@group(0) @binding(4) //var v_tcg: TCGUniforms; fn calculate_tcg( traits: PassTrait, obj_pos: ptr>, obj_norm: ptr>, model_matrix: ptr>, mv_inv: ptr>, uv_0_4_idx: vec4, uv_4_7_idx: vec4, ) -> vec2 { if (traits.uv_source == -1) { return vec2(0.0); } if (traits.tcg_mtx_idx >= 0) { var src: vec4; switch (traits.uv_source) { case 0: { src = vec4((*obj_pos).xyz, 1.0); } case 1: { src = vec4((*obj_norm).xyz, 1.0); } case 2: { if (c_traits.shader.short_uvs == 1u) { src = vec4(v_short_uvs.data[uv_0_4_idx.x], 0.0, 1.0); } else { src = vec4(v_uvs.data[uv_0_4_idx.x], 0.0, 1.0); } } case 3: { src = vec4(v_uvs.data[uv_0_4_idx.y], 0.0, 1.0); } case 4: { src = vec4(v_uvs.data[uv_0_4_idx.z], 0.0, 1.0); } case 5: { src = vec4(v_uvs.data[uv_0_4_idx.w], 0.0, 1.0); } case 6: { src = vec4(v_uvs.data[uv_4_7_idx.x], 0.0, 1.0); } case 7: { src = vec4(v_uvs.data[uv_4_7_idx.y], 0.0, 1.0); } case 8: { src = vec4(v_uvs.data[uv_4_7_idx.z], 0.0, 1.0); } default: {} } let tcgm = process_uv_anim(model_matrix, mv_inv, traits); var tmp = (tcgm.mtx * src).xyz; if (traits.normalize == 1u) { tmp = normalize(tmp); } let tmp_proj = tcgm.post_mtx * vec4(tmp, 1.0); return (tmp_proj / tmp_proj.w).xy; } else { switch (traits.uv_source) { case 0: { return (*obj_pos).xy; } case 1: { return (*obj_norm).xy; } case 2: { if (c_traits.shader.short_uvs == 1u) { return v_short_uvs.data[uv_0_4_idx.x]; } else { return v_uvs.data[uv_0_4_idx.x]; } } case 3: { return v_uvs.data[uv_0_4_idx.y]; } case 4: { return v_uvs.data[uv_0_4_idx.z]; } case 5: { return v_uvs.data[uv_0_4_idx.w]; } case 6: { return v_uvs.data[uv_4_7_idx.x]; } case 7: { return v_uvs.data[uv_4_7_idx.y]; } case 8: { return v_uvs.data[uv_4_7_idx.z]; } default: {} } } return vec2(0.0); } @stage(vertex) fn vs_main( @location(0) pos_norm_idx: vec2, @location(1) uv_0_4_idx: vec4, @location(2) uv_4_7_idx: vec4, ) -> VertexOutput { var out: VertexOutput; var obj_pos = vec4(v_verts.data[pos_norm_idx.x], 1.0); var obj_norm = vec4(v_norms.data[pos_norm_idx.y], 0.0); var model_matrix_no_trans = make_rotate(radians(u_model.orientation)) * make_scale(u_model.scale); var model_matrix = make_translate(u_model.position) * model_matrix_no_trans; var mv = u_global.view * model_matrix; var mv_inv = transpose(u_global.view * model_matrix_no_trans); var mv_pos = mv * obj_pos; var mv_norm = mv_inv * obj_norm; out.position = u_global.proj * mv_pos; out.uv_lightmap = calculate_tcg(c_traits.lightmap, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx); out.uv_diffuse = calculate_tcg(c_traits.diffuse, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx); out.uv_diffuse_mod = calculate_tcg(c_traits.diffuse_mod, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx); out.uv_emissive = calculate_tcg(c_traits.emissive, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx); out.uv_specular = calculate_tcg(c_traits.specular, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx); out.uv_extended_specular = calculate_tcg(c_traits.extended_specular, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx); out.uv_reflection = calculate_tcg(c_traits.reflection, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx); out.uv_alpha = calculate_tcg(c_traits.alpha, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx); out.uv_alpha_mod = calculate_tcg(c_traits.alpha_mod, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx); if (c_traits.shader.samus_reflection == 1u) { // TODO dyn reflection } if (u_traits.post_type > 0u && u_traits.post_type < 5u) { out.lighting = vec3(1.0); } else { var lighting = u_global.ambient.xyz + u_model.ambient_color.xyz; for (var i = 0; i < 8; i = i + 1) { var light = u_model.lights[i]; var delta = mv_pos.xyz - light.pos; var dist = length(delta); var delta_norm = delta / dist; var ang_dot = max(dot(delta_norm, light.dir), 0.0); var lin_att = light.lin_att; var att = 1.0 / (lin_att.z * dist * dist * lin_att.y * dist + lin_att.x); var ang_att = light.ang_att; var ang_att_d = ang_att.z * ang_dot * ang_dot * ang_att.y * ang_dot + ang_att.x; var this_color = light.color.xyz * ang_att_d * att * max(dot(-delta_norm, mv_norm.xyz), 0.0); if (i == 0 && c_traits.shader.world_shadow == 1u) { // TODO ExtTex0 sample } lighting = lighting + this_color; } out.lighting = clamp(lighting, vec3(0.0), vec3(1.0)); } // TODO dyn reflection sample return out; }