Hello there.
I am programming a raymarcher in C++. It is still 100% CPU but planning to move to OpenGL as soon as I can.
So far I tried rendering a mandelbulb (variation) using Quilez formula (
http://www.iquilezles.org/www/articles/mandelbulb/mandelbulb.htm - the non-optimized one) but can't figure out where to look exactly to solve this problem.
Here is a small render of it - please note the red color is the background/sky color.
It looks like some kind of shiva/elephant to me - using a power = 4 (code below). The only problem being, most of the fractal surface isn't displayed at all but gets overshooten. I guess it should look something like :
with the area approximately inside the green bound fully drawn. Worth mentioning too : the white pixels are actually shaded using the raymarching steps ambiant occlusion method. They "appear" white because for some reason, all the "white" pixels are intersected at either step 1 or 2. Any step more and I get geometry overshoot and no intersection at all.
So I dumped the raymarch steps of a random "red" pixel and I get :
#STEP 0# x=0 y=1 z=-15
#DISTANCE# 17.8838
#STEP 1# x=-0.107225 y=-2.16106 z=2.60185
#DISTANCE# 3.00974
#STEP 2# x=-0.12527 y=-2.69305 z=5.56415
#DISTANCE# 9.87785
#STEP 3# x=-0.184495 y=-4.43902 z=15.2863
#DISTANCE# 24.4502
#STEP 4# x=-0.33109 y=-8.76075 z=39.3511
#DISTANCE# 74.5188
#STEP 5# x=-0.777879 y=-21.9324 z=112.695
#DISTANCE# 272.294
#EXIT#
The weird thing is at Step 0 the distance is already 17.8 when the point of view is only at z=-15 so it looks to me the fractal geometry got overshot. I get the same kind of results with a "real" power 8 mandelbulb formula.
Is my DE function not correct ?
long double DistanceEstimators::CPPDE (D3Vec w) {
D3Vec z = w;
float r = z.getLength();
float dr = 1.0;
int escape = 20;
int Power = 4;
double Scale = 1;
// Iterate
for (int i = 0; i != 10 && r < escape * Scale; i++) {
// extract polar coordinates
float wr = std::sqrt(w * w);
float wo = std::acos(w.y / wr);
float wi = std::atan2(w.x, w.z);
// scale and rotate the point
wr = std::pow(wr, Power);
wo = wo * Power;
wi = wi * Power;
// convert back to cartesian coordinates
w.x = std::sin(wo) * std::sin(wi);
w.y = std::cos(wo);
w.z = std::sin(wo) * std::cos(wi);
z = z + w;
r = Scale * z.getLength();
}
// Back
return 0.5 * std::log(r) * r / dr;
}
Thanks for any hint!
-Lapinot