// shader.vert
#version 450
layout(location=0) in vec2 src_ul;
layout(location=1) in vec2 src_lr;
layout(location=2) in vec2 dst_ul;
layout(location=3) in vec2 dst_lr;
layout(location=4) in float rotate_theta;
layout(location=5) in vec4 color_factor;
layout(location=0) out vec2 v_tex_coords;
layout(location=1) out vec4 v_color_factor;
layout(set = 1, binding = 0) uniform Uniform {
vec2 u_scale;
};
layout(set = 2, binding = 0) uniform TranslationUniform {
vec2 u_per_batch_scale;
vec2 u_per_batch_translate;
};
const vec2 positions[4] = vec2[4](
vec2(0.0, 0.0),
vec2(1.0, 0.0),
vec2(1.0, 1.0),
vec2(0.0, 1.0)
);
const uint indices[6] = uint[6](
0, 3, 2,
0, 2, 1
);
// matrix to multiply to get wgpu coordinates
const mat3 to_wgpu = mat3(
2.0, 0.0, 0.0,
0.0, -2.0, 0.0,
-1.0, 1.0, 1.0
);
mat3 translation_matrix(vec2 dxdy) {
// NOTE: the first row actually is the first column
return mat3(
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
dxdy, 1.0
);
}
// rotates theta radians clockwise around origin
mat3 rotation_matrix_around_origin(float theta) {
return mat3(
cos(theta), sin(theta), 0.0,
-sin(theta), cos(theta), 0.0,
0.0, 0.0, 1.0
);
}
const mat3 normalized_basis = mat3(
0.0, 0.0, 1.0,
1.0, 1.0, 1.0,
1.0, 0.0, 1.0
);
void main() {
// Just pass color_factor to fragment shader; there isn't any
// processing to be done for it in the vertex shader
v_color_factor = color_factor;
// ---------------
// Define some useful matrices for the
// requested transformation
// ---------------
mat3 src_basis = mat3(
vec3(src_ul, 1.0),
vec3(src_lr, 1.0),
vec3(src_lr[0], src_ul[1], 1.0)
);
mat3 dst_basis = mat3(
vec3(dst_ul, 1.0),
vec3(dst_lr, 1.0),
vec3(dst_lr[0], dst_ul[1], 1.0)
);
// get matrix to turn normalized coordinates to cropped location
// on the texture
mat3 normalized_to_src = src_basis * inverse(normalized_basis);
// matrix that converts cropped source coordinates to destination rect coordinates
mat3 normalized_to_dst = dst_basis * inverse(normalized_basis);
vec2 dst_center = (dst_ul + dst_lr) / 2.0;
mat3 dst_center_to_origin = translation_matrix(-dst_center);
mat3 origin_to_dst_center = translation_matrix(dst_center);
mat3 rotate_around_origin = rotation_matrix_around_origin(rotate_theta);
mat3 rotate_around_dst_center =
origin_to_dst_center *
rotate_around_origin *
dst_center_to_origin;
// ---------------
// now compute actual coordinates
// ---------------
vec2 normalized_pos2 = positions[indices[gl_VertexIndex]];
vec3 normalized_pos3 = vec3(normalized_pos2, 1.0);
vec3 src_pos3 = normalized_to_src * normalized_pos3;
vec3 dst_pos3 = normalized_to_dst * normalized_pos3;
vec3 rot_pos3 = rotate_around_dst_center * dst_pos3;
vec3 translated_pos3 = vec3(
vec2(rot_pos3) * u_per_batch_scale + u_per_batch_translate,
1.0
);
v_tex_coords = vec2(src_pos3);
gl_Position = vec4(
vec2(to_wgpu * (translated_pos3 / vec3(u_scale, 1.0))),
0.0,
1.0
);
}