MandelBox Volumetric Shader

Hello!

MandelBox Fractal adapted to Blender OSL ( i tried my best!):

shader MBox(
    float ITER = 2,
    float SCALE = -2.25, // -2.25
    float Fact = 2.0,
    output closure color CL = holdout()
){
    // globals
    float mld;
    float ABSCL;
    float mr=0.25, mxr=1.2;
    //
    float mandBox(point P){
    	vector z = P,p0=z;
    	z =clamp(z, -1.0, 1.0) *2.0-z;
    	z*=SCALE/clamp(dot(z,z),mr,mxr);
    	for(int i = 0; i < ITER ; i+=1){
           z=clamp(z, -1.0, 1.0) *2.0-z;
           z*=SCALE/clamp(dot(z,z),mr,mxr);
    	   z+=p0;
    	}
        float dL=(length(z-P)-3.5)/1.0; // w = 1.0
    	mld=min(mld,dL);
    	float dS=min(dL,(length(z)-ABSCL)/1.0); // w = 1.0
    	return dS;
    }    
    // Output
    CL =  henyey_greenstein(length(normalize(I)))*pow(mandBox(P*Fact),20)*25+emission()*pow(mandBox(P*Fact),2)*(1.2*length(I))*
            pow(color(noise("uperlin",0.5,0.1),noise("uperlin",0.1,0.01),noise("uperlin",0.4,0.6)),-2.0*dot(P*sign(P),sqrt(I)))*(0.5/length(I*sign(P)))*2;
    return;
}

And one of the possible results:


Have fun!

Thank you, very interesting :slight_smile:

Cu Torolf

Very nice…I am looking forward to playing with this…well done

Hi tree3d,
awesome shader, thanks man.






Thank you guys! It’s such a blessing to see other results and points of view about this (and the other) codes! It makes me want to keep doing it!

:open_mouth: das sexuh

Hi tree3d,

maybe you are still reading in here.
Done a 3d fractal in the bge using your OSL script and a Volume Ray Casting by martinsh.
Visualize Fractals in Blender

Greetings

Hi tree3d,

is it possible for you to implement another fractal code to OSL, maybe the buddha fractal or any other, cause I love playing with your adapted OSL code and my coding skills are not that great?

example C code of the buddha fractal(original author Paul Bourke):

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/*
   Crude, but functional, little program to calculate the
   So called "budda mandelbrot" or "buddhabrot"
   Please note that this is not supposed to be the most efficient
   implementation, it is only intended to be a simple example with
   plenty of scope for improvement by the reader.
*/

#define TRUE  1
#define FALSE 0
#define MAX(x,y) (x > y ? x : y)
#define MIN(x,y) (x < y ? x : y)

// Image dimensions
#define NX 1000
#define NY 1000

// Length of sequece to test escape status
// Also known as bailout
#define NMAX 200

// Number of iterations, multiples of 1 million
#define TMAX (1000L)

typedef struct {
   double x,y;
} XY;

// Prototypes
void WriteImage(char *,unsigned int *,int,int);
int Iterate(double,double,int *,XY *);

int main(int argc,char **argv) 
{
   int i,n,ix,iy;
   long t,tt;
   double x,y;
   XY *xyseq = NULL;

   // The density plot
   unsigned int *image = NULL;

   // Malloc space for the image and clear to black
   if ((image = (unsigned int *)malloc(NX*NY*sizeof(unsigned int))) == NULL) {
      fprintf(stderr,"Failed to malloc memory for the image
");
      exit(-1);
   }
   for (i=0;i<NX*NY;i++) 
      image[i] = 0;

   // Malloc space for the sequence
   xyseq = (XY *)malloc(NMAX*sizeof(XY));

   // Iterate
    for (tt=0;tt<1000000;tt++) {
       for (t=0;t<TMAX;t++) {

          // Choose a random point in same range 
          x = 6 * drand48() - 3;
          y = 6 * drand48() - 3;

          // Determine state of this point, draw if it escapes 
          if (Iterate(x,y,&n,xyseq)) {
             for (i=0;i<n;i++) {
                ix = 0.3 * NX * (xyseq[i].x + 0.5) + NX/2;
                iy = 0.3 * NY * xyseq[i].y + NY/2;
                if (ix >= 0 && iy >= 0 && ix < NX && iy < NY)
                   image[iy*NX+ix]++;
                }
         }
      } / t
   } // tt

   // Save the result 
   WriteImage("buddha_single.tga",image,NX,NY);

   exit(0);
}

/*
   Write the buddha image to a minimal TGA file.
   Can be opened with gimp, PhotoShop, etc.
*/
void WriteImage(char *fname,unsigned int *image,int width,int height)
{
   int i;
   float ramp,biggest=0,smallest;
   FILE *fptr;

   // Find the largest density value
   for (i=0;i<width*height;i++)
      biggest = MAX(biggest,image[i]);
   smallest = biggest;
   for (i=0;i<width*height;i++)
      smallest = MIN(smallest,image[i]);
   fprintf(stderr,"Density value range: %g to %g
",smallest,biggest);

   // Write the image
   fprintf(stderr,"Writing \"%s\"
",fname);
   if ((fptr = fopen(fname,"wb")) == NULL) {
      fprintf(stderr,"Failed to open output file
");
      exit(0);
   }
   
   // TGA header, endian independent
   putc(0,fptr);  /* Length of ID */
   putc(0,fptr);  /* No colour map */
   putc(2,fptr); /* uncompressed RGB  */
   putc(0,fptr); /* Index of colour map entry */
   putc(0,fptr);
   putc(0,fptr); /* Colour map length */
   putc(0,fptr);
   putc(0,fptr); /* Colour map size */
   putc(0,fptr); /* X origin */
   putc(0,fptr);
   putc(0,fptr); /* Y origin */
   putc(0,fptr);
   putc((width & 0x00ff),fptr); /* X width */
   putc((width & 0xff00) / 256,fptr);
   putc((height & 0x00ff),fptr); /* Y width */
   putc((height & 0xff00) / 256,fptr);
   putc(24,fptr);                      /* 24 bit bitmap     */
   putc(0x00,fptr);

   // Raw uncompressed bytes
   for (i=0;i<width*height;i++) {
      ramp = 2*(image[i] - smallest) / (biggest - smallest);
      if (ramp > 1)
         ramp = 1;
      ramp = pow(ramp,0.5);
      fputc((int)(ramp*255),fptr);
      fputc((int)(ramp*255),fptr);
      fputc((int)(ramp*255),fptr);
   }
   fclose(fptr);
}

/*
   Iterate the Mandelbrot and return TRUE if the point escapes
*/
int Iterate(double x0,double y0,int *n,XY *seq)
{
   int i;
   double x=0,y=0,xnew,ynew;

   *n = 0;
   for (i=0;i<NMAX;i++) {
      xnew = x * x - y * y + x0;
      ynew = 2 * x * y + y0;
      seq[i].x = xnew;
      seq[i].y = ynew;
      if (xnew*xnew + ynew*ynew > 10) {
         *n = i;
         return(TRUE);   
      }
      x = xnew;
      y = ynew;
   }

   return(FALSE);
}

I don’t know if you are still reading this thread, but have you found a way to make it work in blender 2.8? Sadly the osl does not compile due to an error in 2.8

Just change

for(int i = 0; i < ITER ; i+=1){

for

for(int i = 0; i> ITER ; i+=1){

It still works today! Some encoding must went wrong with time:

Its not:


for(int i = 0; i> ITER ; i+=1){

But rather:


for(int i = 0; i < ITER ; i+=1){

This will set the boundary for the “fractal” calculation, so we don’t want to invert it :wink:

Cheers guys!

Thank you very much!