168 {
169 mxvk::Mat4D object_rotation;
170 object_rotation.
BuildXYZ(instance.rotation.x, instance.rotation.y, instance.rotation.z);
171
172 std::vector<mxvk::vec4D> camera_vertices(instance.mesh.vertices.size());
173 std::vector<mxvk::vec4D> projected_vertices(instance.mesh.vertices.size());
174 for (std::size_t index = 0; index < instance.mesh.vertices.size(); ++index) {
175 const mxvk::vec4D &vertex = instance.mesh.vertices[index];
176 mxvk::vec4D transformed(
177 vertex.
x * instance.scale.x,
178 vertex.
y * instance.scale.y,
179 vertex.
z * instance.scale.z,
180 1.0f);
181 transformed = object_rotation.
MulVec(transformed);
182 transformed += instance.position;
183 transformed = camera_rotation.MulVec(transformed);
185 camera_vertices[index] = transformed;
186 projected_vertices[index] = project(transformed);
187 }
188
189 const mxvk::vec4D light_direction = normalized({-0.35f, -0.65f, -1.0f, 0.0f});
190 for (const Triangle &triangle : instance.mesh.triangles) {
191 const mxvk::vec4D &a = camera_vertices[triangle.indices[0]];
192 const mxvk::vec4D &b = camera_vertices[triangle.indices[1]];
193 const mxvk::vec4D &c = camera_vertices[triangle.indices[2]];
194 mxvk::vec4D normal = mxvk::vec4D().Build(a, b).CrossProduct(mxvk::vec4D().Build(a, c));
196
197 const mxvk::vec4D center = (a + b + c) * (1.0f / 3.0f);
198 const mxvk::vec4D view_direction(-center.
x, -center.
y, -center.
z, 0.0f);
199 if (normal.
DotProduct(view_direction) <= 0.0f) {
200 if (!instance.mesh.two_sided) {
201 continue;
202 }
203 normal = normal * -1.0f;
204 }
205
206 const float diffuse = std::max(0.0f, normal.
DotProduct(light_direction));
207 const float intensity = std::clamp(0.32f + diffuse * 0.68f, 0.0f, 1.0f);
208 rasterize_triangle(
209 projected_vertices[triangle.indices[0]],
210 projected_vertices[triangle.indices[1]],
211 projected_vertices[triangle.indices[2]],
213 }
214 }
void BuildXYZ(float theta_x, float theta_y, float theta_z)
Build an XYZ Euler rotation matrix from angles in degrees.
vec4D MulVec(const vec4D &in) const
Transform a homogeneous 4D vector by this matrix.
void Normalize()
Normalize the 3D components in place and reset W to 1.
constexpr float DotProduct(const vec4D &v) const
Compute the 3D dot product, ignoring the W component.
constexpr float CAMERA_DISTANCE
MXCOLOR shade_color(MXCOLOR color, float intensity)
Scale the RGB channels of a color while preserving alpha.