aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMistivia <i@mistivia.com>2025-06-13 21:32:54 +0800
committerMistivia <i@mistivia.com>2025-06-13 21:32:54 +0800
commit75fea2a4ba44d0b8dbc28855df743f544049bade (patch)
tree224a03aa1627a9588e62925dbd34396e7b2dce1b /src
parent9efe3421b6f5255bf31dbff4016aeed98be99f0d (diff)
reflection
Diffstat (limited to 'src')
-rw-r--r--src/main.c44
1 files changed, 36 insertions, 8 deletions
diff --git a/src/main.c b/src/main.c
index e21ec2a..1cf1d5f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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);