got mandelbulbs working

rework
Anton Lydike 5 years ago
parent 89fa8d2349
commit d72321b14a

@ -5,7 +5,17 @@
#define SCENE_MOD 2 #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 circle_dist(Point x, SceneObject *self) {
double r = self->args[0]; double r = self->args[0];
return pt_dist(pt_mod(x, SCENE_MOD), self->location) - r; 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; return color;
} }
// constructs the scene object
SceneObject circle_new(Point loc, double radius) { SceneObject circle_new(Point loc, double radius) {
SceneObject so; SceneObject so;
so.location = loc; 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 main(int argc, char* argv[]) {
int threads = 1; int threads = 1;
Camera cam; Camera cam;
cam.fov = 90; cam.fov = 90;
float cam_position = 0; float cam_position = 1.2;
camera_set_looking_at(&cam, pt_new(cam_position,cam_position,cam_position), pt_new(1,1,1)); 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) { if (argc > 1) {
threads = atoi(argv[1]); threads = atoi(argv[1]);
} }
@ -54,16 +117,14 @@ int main(int argc, char* argv[]) {
printf("threads: %d\n", threads); printf("threads: %d\n", threads);
// create basic scene with up to 10 objects // create basic scene with up to 10 objects
Scene scene = scene_new(1920, 1080, 10); Scene scene = scene_new(1000, 1000, 10);
scene.max_steps = 300; scene.max_steps = 1000;
scene.threshold = 0.02; scene.threshold = 0.0001;
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, circle_new(pt_new(0,2,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, 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, mandelbulb2_new(pt_new(1,1,1), 2000, 3));
Image *img = render_scene(&scene, &cam, threads); Image *img = render_scene(&scene, &cam, threads);
image_save_bmp(*img, "render.bmp"); image_save_bmp(*img, "render.bmp");

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

@ -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 // only render the lines this thread is responsible for
if (y % threads != thread_id) continue; 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 // actually iterate this line
curr_pt = starting_point; curr_pt = starting_point;
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {

@ -105,11 +105,19 @@ Color march_ray(Point origin, Point direction, Scene* scene) {
// check for a hit // check for a hit
if (dist <= threshold) { if (dist <= threshold) {
// a hit! // a hit!
#ifndef SCENE_NO_AM_OCC
double f = (steps / (double) scene->max_steps); double f = (steps / (double) scene->max_steps);
f = f * f * f * f; f = f * f * f * f;
Color c = closest_obj->get_color(pos, direction, closest_obj); Color c = closest_obj->get_color(pos, direction, closest_obj);
return color_mix(c, color_new(0,0,0), f); return color_mix(c, color_new(0,0,0), f);
#else
return closest_obj->get_color(pos, direction, closest_obj);
#endif
} else { } else {
// a miss :( // a miss :(

Loading…
Cancel
Save