diff options
| author | Mistivia <i@mistivia.com> | 2025-06-13 21:32:54 +0800 |
|---|---|---|
| committer | Mistivia <i@mistivia.com> | 2025-06-13 21:32:54 +0800 |
| commit | 75fea2a4ba44d0b8dbc28855df743f544049bade (patch) | |
| tree | 224a03aa1627a9588e62925dbd34396e7b2dce1b /src/main.c | |
| parent | 9efe3421b6f5255bf31dbff4016aeed98be99f0d (diff) | |
reflection
Diffstat (limited to 'src/main.c')
| -rw-r--r-- | src/main.c | 44 |
1 files changed, 36 insertions, 8 deletions
@@ -34,6 +34,7 @@ typedef struct { float r; Color color; float specular; + float reflective; } Ball; Ball balls[] = { @@ -41,21 +42,25 @@ Ball balls[] = { .center = {.x = 0, .y = -1, .z = 3}, .r = 1, .specular = 500, + .reflective = 0.2, }, { .center = {.x = 2, .y = 0, .z = 4}, .r = 1, .specular = 500, + .reflective = 0.3, }, { .center = {.x = -2, .y = 0, .z = 4}, .r = 1, .specular = 10, + .reflective = 0.4, }, { .center = {0, -5001, 0}, .r = 5000, .specular = 1000, + .reflective = 0.5, }, }; @@ -84,7 +89,7 @@ void init_color() { balls[1].color = icolor(0xfce38a); balls[2].color = icolor(0xf38181); balls[3].color = icolor(0xeaffd0); - gBackgroupColor = icolor(0xeaeaea); + // gBackgroupColor = icolor(0xeaeaea); } float ball_intersect(Vec3f start, Vec3f ray, Ball *ball) { @@ -124,8 +129,13 @@ bool is_in_shadow(Vec3f pos, Light light) { return false; } +Vec3f reflection(Vec3f rayin, Vec3f norm) { + rayin = vec3f_normalize(vec3f_neg(rayin)); + return vec3f_sub(vec3f_mul(2 * vec3f_dot(norm, rayin), norm), rayin); +} + float specular_coeff(Vec3f l, Vec3f n, Vec3f v, float s) { - Vec3f r = vec3f_sub(vec3f_mul(2 * vec3f_dot(n, l), n), l); + Vec3f r = reflection(vec3f_neg(l), n); v = vec3f_normalize(v); float prod = vec3f_dot(r, vec3f_neg(v)); if (prod < 0) return 0; @@ -166,11 +176,13 @@ Color ball_surface_color(Ball *ball, Vec3f point, Vec3f view) { }; } -Color calc_color(Vec3f v) { - Vec3f start = {.x = 0, .y = 0, .z = 0}; - float tmin = 0.1; - float tmax = FLT_MAX; +#define MAX_TRACE_DEPTH 3 +Vec3f ball_norm(Vec3f center, Vec3f pos) { + return vec3f_normalize(vec3f_sub(pos, center)); +} + +Color calc_color(Vec3f start, Vec3f v, float tmin, float tmax, int trace_depth) { int nearest_idx = -1; float t_nearest = FLT_MAX; for (int i = 0; i < sizeof(balls) / sizeof(Ball); i++) { @@ -181,8 +193,21 @@ Color calc_color(Vec3f v) { } } if (nearest_idx >= 0) { + Ball hit = balls[nearest_idx]; Vec3f intersection = vec3f_add(start, vec3f_mul(t_nearest, v)); - return ball_surface_color(&balls[nearest_idx], intersection, v); + Color local_color = ball_surface_color(&hit, intersection, v); + if (hit.reflective > 0 && trace_depth < MAX_TRACE_DEPTH) { + Vec3f refray = reflection(v, ball_norm(hit.center, intersection)); + Color rcolor = calc_color(intersection, refray, EPSILON, FLT_MAX, trace_depth + 1); + float r = hit.reflective; + return (Color) { + r * rcolor.r + (1-r) * local_color.r, + r * rcolor.g + (1-r) * local_color.g, + r * rcolor.b + (1-r) * local_color.b, + }; + } else { + return local_color; + } } else { return gBackgroupColor; } @@ -194,11 +219,14 @@ int main() { int img_w = 800*2; int img_h = 800*2; Picture pic = new_picture(img_w, img_h); + Vec3f camera_pos = {.x = 0, .y = 0, .z = 0}; + float tmin = 0.1; + float tmax = FLT_MAX; for (int x = 0; x < img_w; x++) { for (int y = 0; y < img_h; y++) { Vec2i screen_pos = {x, y}; Vec3f v = screen_proj(img_w, img_h, screen_pos); - set_pixel(pic, screen_pos, calc_color(v)); + set_pixel(pic, screen_pos, calc_color(camera_pos, v, tmin, tmax, 0)); } } Picture newpic = picture_downscale_2x(pic); |
