summary refs log tree commit diff
path: root/shaders/shader.vert
diff options
context:
space:
mode:
Diffstat (limited to 'shaders/shader.vert')
-rw-r--r--shaders/shader.vert86
1 files changed, 85 insertions, 1 deletions
diff --git a/shaders/shader.vert b/shaders/shader.vert
index d53ef0a..ff1698d 100644
--- a/shaders/shader.vert
+++ b/shaders/shader.vert
@@ -1,7 +1,22 @@
 #version 460
 
+struct Transformation {
+  vec4 rotation;
+  vec3 translation;
+};
+
+// layout(binding = 0) uniform vec3 only_transform;
+
+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;
 
 vec2 triangle[3] = vec2[](
@@ -16,8 +31,77 @@ vec3 colors[3] = vec3[](
   vec3(0.0, 0.0, 1.0)
 );
 
+
+// /////////////////
+// // 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);
+  //return vec4(scaled, 1.0);
+  vec3 model = transform(scaled, uniform_block.model);
+  vec3 view = transform(model, uniform_block.view);
+  //vec4 projected = vec4(view, 1.0) * uniform_block.projection;
+  vec4 projected = vec4(view, 1.0) * uniform_block.projection;
+  //return vec4(view, 1.000);
+  return projected;
+  //return vec4(position, 1.0);
+}
+
+
 void main() {
-  gl_Position = vec4(inPosition, 0.0, 1.0);
+  gl_Position = apply_all_transforms(vec3(inPosition, 0.0));
   vertexColor = inColor;
 }