diff --git a/main.c b/main.c index 2d3ecbc..606a0fc 100644 --- a/main.c +++ b/main.c @@ -5,7 +5,17 @@ #define SCENE_MOD 2 -// this is the circle distance function definition + +/* + + Infinite circle scene object + + This circle repeats every SCENE_MOD units in all directions + + It has some basic shading, calculation the hit angle and making shallower impacts darker + +*/ + double circle_dist(Point x, SceneObject *self) { double r = self->args[0]; return pt_dist(pt_mod(x, SCENE_MOD), self->location) - r; @@ -24,7 +34,7 @@ Color circle_color(Point hit, Point direction, SceneObject *self) { return color; } - +// constructs the scene object SceneObject circle_new(Point loc, double radius) { SceneObject so; so.location = loc; @@ -37,16 +47,69 @@ SceneObject circle_new(Point loc, double radius) { } - +/* + + Mandelbulb scene object + + Currently cannot be set at a specific location, always resides at origin (0,0,0) + + Color function is just a flat shader, detail is displayed with ambient occlusion + +*/ +double mandelbulb_dist(Point pt, SceneObject *self) { + int iters = self->args[0]; + double power = self->args[1]; + + Point z = pt; + float dr = 1.0; + float r = 0.0; + for (int i = 0; i < iters ; i++) { + r = pt_length(z); + if (r>2) break; + + // convert to polar coordinates + float theta = acos(z.z/r); + float phi = atan2(z.y,z.x); + dr = pow(r, power-1.0)*power*dr + 1.0; + + // scale and rotate the point + float zr = pow( r,power); + theta = theta*power; + phi = phi*power; + + // convert back to cartesian coordinates + z = pt_mult(pt_new(sin(theta)*cos(phi), sin(phi)*sin(theta), cos(theta)), zr); + pt_add(&z, pt); + } + + return 0.5*log(r)*r/dr; + +} +Color mandelbulb_color(Point hit, Point direction, SceneObject *self) { + return self->color; +} +// constructs the scene object +SceneObject mandelbulb_new(Point location, int iters, double power) { + SceneObject so; + so.location = location; + so.args = malloc(sizeof(double) * 2); + so.args[0] = iters; // iterations + so.args[1] = power; // power + so.distance = mandelbulb_dist; + so.get_color = mandelbulb_color; + so.color = color_new(255,255,255); + return so; +} int main(int argc, char* argv[]) { int threads = 1; Camera cam; cam.fov = 90; - float cam_position = 0; - camera_set_looking_at(&cam, pt_new(cam_position,cam_position,cam_position), pt_new(1,1,1)); + float cam_position = 1.2; + camera_set_looking_at(&cam, pt_new(cam_position,cam_position,cam_position), pt_new(0,0,0)); + // get thread count from command line if (argc > 1) { threads = atoi(argv[1]); } @@ -54,16 +117,14 @@ int main(int argc, char* argv[]) { printf("threads: %d\n", threads); // create basic scene with up to 10 objects - Scene scene = scene_new(1920, 1080, 10); - scene.max_steps = 300; - scene.threshold = 0.02; - - scene_add_obj(&scene, circle_new(pt_new(SCENE_MOD / 2.0, SCENE_MOD/ 2.0, SCENE_MOD / 2.0), .2)); + Scene scene = scene_new(1000, 1000, 10); + scene.max_steps = 1000; + scene.threshold = 0.0001; - //scene_add_obj(&scene, circle_new(pt_new(0,2,0), 0.5)); - //scene_add_obj(&scene, circle_new(pt_new(0,-2,0), 0.5)); - //scene_add_obj(&scene, circle_new(pt_new(0,-4,0), 0.5)); + //scene_add_obj(&scene, circle_new(pt_new(SCENE_MOD / 2.0, SCENE_MOD/ 2.0, SCENE_MOD / 2.0), .2)); + scene_add_obj(&scene, mandelbulb2_new(pt_new(1,1,1), 2000, 3)); + Image *img = render_scene(&scene, &cam, threads); image_save_bmp(*img, "render.bmp"); diff --git a/renders/mandelbulb-100mpx.png b/renders/mandelbulb-100mpx.png new file mode 100644 index 0000000..86f3899 Binary files /dev/null and b/renders/mandelbulb-100mpx.png differ diff --git a/renders/mandelbulb-pow3.png b/renders/mandelbulb-pow3.png new file mode 100644 index 0000000..15a7e21 Binary files /dev/null and b/renders/mandelbulb-pow3.png differ diff --git a/renders/mandelbulb.png b/renders/mandelbulb.png new file mode 100644 index 0000000..ce1d8fd Binary files /dev/null and b/renders/mandelbulb.png differ diff --git a/src/camera.c b/src/camera.c index 3a79f2e..19acfa5 100644 --- a/src/camera.c +++ b/src/camera.c @@ -149,6 +149,12 @@ void camera_iterate_rays_const_dist(Camera camera, int width, int height, int th // only render the lines this thread is responsible for if (y % threads != thread_id) continue; + // display progress in percent + if (y % (height / 100) == 0 && y != 0) { + printf("\r%02i%%", (y * 100) / height); + fflush(stdout); + } + // actually iterate this line curr_pt = starting_point; for (int x = 0; x < width; x++) { diff --git a/src/scene.c b/src/scene.c index 493e440..abe9078 100644 --- a/src/scene.c +++ b/src/scene.c @@ -105,11 +105,19 @@ Color march_ray(Point origin, Point direction, Scene* scene) { // check for a hit if (dist <= threshold) { // a hit! + #ifndef SCENE_NO_AM_OCC + double f = (steps / (double) scene->max_steps); f = f * f * f * f; Color c = closest_obj->get_color(pos, direction, closest_obj); return color_mix(c, color_new(0,0,0), f); + + #else + + return closest_obj->get_color(pos, direction, closest_obj); + + #endif } else { // a miss :(