11#include <glm/gtc/matrix_transform.hpp>
40 Vec3 normal = glm::cross(edge1, edge2);
41 float len = glm::length(normal);
43 return Vec3(0.0f, 0.0f, 1.0f);
76 return m *
Vec4(p, 1.0f);
106 if (std::abs(clip.w) < 1e-12f)
107 return Vec3(clip.x, clip.y, clip.z);
108 return Vec3(clip.x / clip.w, clip.y / clip.w, clip.z / clip.w);
126 float &screen_x,
float &screen_y,
float &depth) {
127 screen_x = (ndc.x + 1.0f) * 0.5f *
static_cast<float>(width);
128 screen_y = (1.0f - ndc.y) * 0.5f *
static_cast<float>(height);
162 float &u,
float &v,
float &w) {
163 float det = (y2 - y0) * (x1 - x0) - (x2 - x0) * (y1 - y0);
164 if (std::abs(det) < 1e-12f) {
168 float inv_det = 1.0f / det;
169 u = ((y1 - y2) * (px - x2) + (x2 - x1) * (py - y2)) * inv_det;
170 v = ((y2 - y0) * (px - x2) - (x2 - x0) * (py - y2)) * inv_det;
192 const Vec3 &light_direction,
193 const Color &specular_color =
Color(0, 0, 0, 0),
194 float shininess = 0.0f) {
195 Vec3 n = glm::length(normal) > 1e-12f ? glm::normalize(normal) :
Vec3(0.0f, 0.0f, 1.0f);
196 Vec3 l = glm::normalize(light_direction);
197 float ndotl = std::max(0.0f, glm::dot(n, l));
198 float ambient = 0.3f;
199 float diffuse_term = (1.0f - ambient) * ndotl;
200 float intensity = ambient + diffuse_term;
202 float spec_r = 0.0f, spec_g = 0.0f, spec_b = 0.0f;
203 if (shininess > 0.0f && ndotl > 0.0f) {
204 float spec = std::pow(ndotl, shininess);
205 spec_r = specular_color.r * spec;
206 spec_g = specular_color.g * spec;
207 spec_b = specular_color.b * spec;
210 return Color(base_color.
r * intensity + spec_r,
211 base_color.
g * intensity + spec_g,
212 base_color.
b * intensity + spec_b,
232 const std::vector<Light> &lights,
234 const Color &specular_color =
Color(0, 0, 0, 0),
235 float shininess = 0.0f) {
236 Vec3 n = glm::length(normal) > 1e-12f ? glm::normalize(normal) :
Vec3(0.0f, 0.0f, 1.0f);
238 float total_r = base_color.
r * ambient;
239 float total_g = base_color.
g * ambient;
240 float total_b = base_color.
b * ambient;
242 int nlights =
static_cast<int>(lights.size());
243 if (nlights == 0)
return Color(total_r, total_g, total_b, base_color.
a);
245 for (
int i = 0; i < nlights; i++) {
246 const Light &light = lights[i];
248 float ndotl = std::max(0.0f, glm::dot(n, light_dir));
249 float li = light.
intensity /
static_cast<float>(nlights);
250 float diff = (1.0f - ambient) * ndotl * li;
251 total_r += base_color.
r * diff * light.
color.
r;
252 total_g += base_color.
g * diff * light.
color.
g;
253 total_b += base_color.
b * diff * light.
color.
b;
255 if (shininess > 0.0f && ndotl > 0.0f) {
256 float spec = std::pow(ndotl, shininess) * li;
257 total_r += specular_color.r * spec * light.
color.
r;
258 total_g += specular_color.g * spec * light.
color.
g;
259 total_b += specular_color.b * spec * light.
color.
b;
263 return Color(std::min(total_r, 1.0f), std::min(total_g, 1.0f),
264 std::min(total_b, 1.0f), base_color.
a);
void compute_barycentric(float px, float py, float x0, float y0, float x1, float y1, float x2, float y2, float &u, float &v, float &w)
Compute barycentric coordinates (u, v, w) of a point in a triangle.
void ndc_to_screen(const Vec3 &ndc, int width, int height, float &screen_x, float &screen_y, float &depth)
Convert from normalized device coordinates (NDC) to screen (pixel) coordinates.
glm::mat4 Mat4
4×4 floating-point matrix.
glm::vec3 Vec3
3-component floating-point vector (xyz).
Vec3 transform_direction(const Mat4 &m, const Vec3 &d)
Transform a direction vector by a 4×4 matrix (with implicit w=0).
Vec3 compute_face_normal(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2)
Compute the unit-length normal vector of a triangle face.
Color shade_pixel(const Color &base_color, const Vec3 &normal, const Vec3 &light_direction, const Color &specular_color=Color(0, 0, 0, 0), float shininess=0.0f)
Compute the shaded color of a pixel with a single directional light.
Color shade_pixel_multi(const Color &base_color, const Vec3 &normal, const std::vector< Light > &lights, float ambient, const Color &specular_color=Color(0, 0, 0, 0), float shininess=0.0f)
Compute the shaded color with multiple light sources.
Vec3 transform_point(const Mat4 &m, const Vec3 &p)
Transform a point by a 4×4 matrix (with implicit w=1).
Vec3 perspective_divide(const Vec4 &clip)
Perform perspective division: divide xyz by w.
Vec4 transform_point_homogeneous(const Mat4 &m, const Vec3 &p)
Transform a point by a 4×4 matrix, returning the full Vec4 result.
glm::vec4 Vec4
4-component floating-point vector (xyzw).
An RGBA color with floating-point components.
float g
Green channel, [0, 1].
float r
Red channel, [0, 1].
float b
Blue channel, [0, 1].
float a
Alpha (opacity) channel, [0, 1]. 1.0 = fully opaque.
A light source for the Blinn-Phong shading model.
Color color
Color of the light (default: white).
Vec3 position
Position of the light.
float intensity
Brightness multiplier (default: 1.0).
Fundamental types used throughout the scimesh rendering engine.