blob: 807f620b03cdebb66b189455346073e2c3596a0b [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
uniform FrameInfo {
mat4 mvp;
float enable_skinning;
float joint_texture_size;
}
frame_info;
uniform sampler2D joints_texture;
// This attribute layout is expected to be identical to `SkinnedVertex` within
// `impeller/scene/importer/scene.fbs`.
in vec3 position;
in vec3 normal;
in vec4 tangent;
in vec2 texture_coords;
in vec4 color;
in vec4 joints;
in vec4 weights;
out vec3 v_position;
out mat3 v_tangent_space;
out vec2 v_texture_coords;
out vec4 v_color;
const int kMatrixTexelStride = 4;
mat4 GetJoint(float joint_index) {
// The size of one texel in UV space. The joint texture should always be
// square, so the answer is the same in both dimensions.
float texel_size_uv = 1 / frame_info.joint_texture_size;
// Each joint matrix takes up 4 pixels (16 floats), so we jump 4 pixels per
// joint matrix.
float matrix_start = joint_index * kMatrixTexelStride;
// The texture space coordinates at the start of the matrix.
float x = mod(matrix_start, frame_info.joint_texture_size);
float y = floor(matrix_start / frame_info.joint_texture_size);
// Nearest sample the middle of each the texel by adding `0.5 * texel_size_uv`
// to both dimensions.
y = (y + 0.5) * texel_size_uv;
mat4 joint =
mat4(texture(joints_texture, vec2((x + 0.5) * texel_size_uv, y)),
texture(joints_texture, vec2((x + 1.5) * texel_size_uv, y)),
texture(joints_texture, vec2((x + 2.5) * texel_size_uv, y)),
texture(joints_texture, vec2((x + 3.5) * texel_size_uv, y)));
return joint;
}
void main() {
mat4 skin_matrix;
if (frame_info.enable_skinning == 1) {
skin_matrix =
GetJoint(joints.x) * weights.x + GetJoint(joints.y) * weights.y +
GetJoint(joints.z) * weights.z + GetJoint(joints.w) * weights.w;
} else {
skin_matrix = mat4(1); // Identity matrix.
}
gl_Position = frame_info.mvp * skin_matrix * vec4(position, 1.0);
v_position = gl_Position.xyz;
vec3 lh_tangent = (skin_matrix * vec4(tangent.xyz * tangent.w, 0.0)).xyz;
vec3 out_normal = (skin_matrix * vec4(normal, 0.0)).xyz;
v_tangent_space = mat3(frame_info.mvp) *
mat3(lh_tangent, cross(out_normal, lh_tangent), out_normal);
v_texture_coords = texture_coords;
v_color = color;
}