1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
#version 460
struct Transformation {
vec4 rotation;
vec3 translation;
};
layout(binding = 0) uniform UniformBlock {
vec3 scale;
Transformation model;
Transformation view;
mat4 projection;
} uniform_block;
layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 0) out vec3 vertexColor;
// /////////////////
// // Quaternions //
// /////////////////
//
// To mathematicians, the components of a quaternion are traditionally
// multiplied by 1, i, j, and k, where 1 is a real number and i, j, and k are
// unit values along the three imaginary axes. GLSL doesn't give us component
// names that map cleanly onto these, and xyzw are confusing in this context
// because it's unclear whether x or w is the real-valued component, so we
// reference the components by numeric index. Yes, that sucks, but everything
// else sucks worse.
//
// That is: 0 is the real value and 1, 2, and 3 are the i, j, and k values.
//
// When reading code samples elsewhere, keep in mind that this is not the
// only possible choice. Checking how components are labeled should be the
// very first thing you do in understanding any quaternion arithmetic,
// anywhere. Also keep in mind that there are many equivalent ways to write
// any algebraic expression, and check carefully whether things are identical
// in meaning.
//
// This same challenge arises with matrices, it's just that the designers
// of GLSL have chosen to encapsulate that complexity inside the language.
// This is kept carefully the same as quaternion_conjugate() in
// linear_algebra.rs.
vec4 quaternion_conjugate(vec4 a) {
return vec4(a[0], -a[1], -a[2], -a[3]);
}
// This is kept carefully the same as quaternion_product() in
// linear_algebra.rs.
vec4 quaternion_product(vec4 a, vec4 b) {
return vec4((a[0] * b[0]) - (a[1] * b[1]) - (a[2] * b[2]) - (a[3] * b[3]),
(a[0] * b[1]) + (a[1] * b[0]) + (a[2] * b[3]) - (a[3] * b[2]),
(a[0] * b[2]) - (a[1] * b[3]) + (a[2] * b[0]) + (a[3] * b[1]),
(a[0] * b[3]) + (a[1] * b[2]) - (a[2] * b[1]) + (a[3] * b[0]));
}
vec3 quaternion_rotate(vec3 position, vec4 rotation) {
vec4 result = quaternion_product(quaternion_product(rotation,
vec4(0.0, position)),
quaternion_conjugate(rotation));
return vec3(result[1], result[2], result[3]);
}
vec3 transform(vec3 a, Transformation transformation) {
vec3 rotated = quaternion_rotate(a, transformation.rotation);
vec3 translated = rotated + transformation.translation;
return translated;
}
vec4 apply_all_transforms(vec3 position) {
vec3 scaled = vec3(position.x * uniform_block.scale.x,
position.y * uniform_block.scale.y,
position.z * uniform_block.scale.z);
vec3 model = transform(scaled, uniform_block.model);
vec3 view = transform(model, uniform_block.view);
vec4 projected = vec4(view, 1.0) * uniform_block.projection;
return projected;
}
void main() {
gl_Position = apply_all_transforms(vec3(inPosition, 0.0));
vertexColor = inColor;
}
|