Tuesday, April 2, 2013

Thursday, March 21, 2013

Molecule Visualizer presented at nVidia's GTC 2013, San Jose, CA. Wicked!

3D vision live session!



Looking forward to running the visualizer on Kayla board!
NVIDIA GTC 2013 - San Jose - Silicon Valley - CA

Monday, February 25, 2013

Complex Geometry and Interactive Raytracing




A few screenshots and a video of the interactive CUDA raytracer with added support for OBJ files.






It took me a while to complete the algorithm that extrapolates normals in a triangle. The trick is to compute the area of each triangle defines by the intersection point and the three vertices. Once you get that, just find the weighted mean, and you're done. Here is the code:

float4 v0 = triangle.p0 - intersection;
float4 v1 = triangle.p1 - intersection;
float4 v2 = triangle.p2 - intersection;
float a0 = 0.5f*vectorLength(crossProduct( v1,v2 ));
float a1 = 0.5f*vectorLength(crossProduct( v0,v2 ));
float a2 = 0.5f*vectorLength(crossProduct( v0,v1 ));
normal = (triangle.n0*a0 + triangle.n1*a1 + triangle.n2*a2)/(a0+a1+a2);

As simple as that :-)





Monday, February 4, 2013

Mandelbrot Set as a texture

GPUs are amazing, I tried to use the Mandelbrot set as a texture, because it's amazingly beautiful and easy to implement. The algorithm I used is the following:
__device__ void mandelbrotSet( const SceneInfo& sceneInfo, const float x, const float y, float4& color )
{
   float W = (float)gTextureWidth;
   float H = (float)gTextureHeight;

   float  MinRe               = -2.f;
   float  MaxRe               =       1.f;
   float  MinIm               = -1.2f;
   float  MaxIm               =       MinIm + (MaxRe - MinRe) * H/W;
   float  Re_factor    =       (MaxRe - MinRe) / (W - 1.f);
   double Im_factor    =       (MaxIm - MinIm) / (H - 1.f);
   float  MaxIterations = 20.f+sceneInfo.pathTracingIteration.x;

   float c_im = MaxIm - y*Im_factor;
   float c_re = MinRe + x*Re_factor;
   float Z_re = c_re;
   float Z_im = c_im;
   bool isInside = true;
   unsigned n;
   for( n = 0; isInside && n < MaxIterations; ++n )
   {
      float Z_re2 = Z_re*Z_re;
      float Z_im2 = Z_im*Z_im;
      if ( Z_re2+Z_im2>4.f )
      {
         isInside = false;
      }
      Z_im = 2.f*Z_re*Z_im+c_im;
      Z_re = Z_re2 - Z_im2+c_re;
   }

   color.x += Z_re/64.f;
   color.y += Z_im/64.f;
   color *= (n/MaxIterations);
}

GPUs amaze me for making it possible to enjoy real-time computation of ray-traced images, with the Mandelbrot set... as a texture.













Sunday, February 3, 2013

3D Parametric Curves are cool


3D Parametric Curves are cool because they make it easy to construct beautiful shapes out of simple mathematical formulas. Since I am lazy and not good at modeling 3D scenes, I thought that using these equations was probably the best way to get nice images.

The following curves are made of cylinders, following the paths defined by the parametric curves.














Here are the functions I used to generated the shapes:

void trefoilKnot(float R, float t, float4& p)
{
   p.x = R*(sin(t)+2.f*sin(2.f*t));
   p.y = R*(cos(t)-2.f*cos(2.f*t));
   p.z = R*(-sin(3.f*t));
}

void torus(float R, float t, float4& p )
{
   p.x = R*(3.f*cos(t)+cos(10.f*t)*cos(t));
   p.y = R*(3.f*sin(t)+cos(10.f*t)*sin(t));
   p.z = R*sin(10.f*t);
}

void star(float R, float t, float4& p )
{
   p.x = R*(2.f*sin(3.f*t)*cos(t));
   p.y = R*(2.f*sin(3.f*t)*sin(t));
   p.z = R*sin(3.f*t);
}

void spring(float R, float t, float4& p)
{
   p.x = R*cos(t);
   p.y = R*sin(t);
   p.z = R*cos(t);
}

void heart(float R, float u, float v, float4& p)
{
   p.x = R*4.f*pow(sin(u),3.f);
   p.y = R*0.25f*(13*cos(u)-5*cos(2.f*u)-2.f*cos(3.f*u)-cos(4.f*u));
   p.z = 0.f;
}

void thing(float R, float t, float4 a, float4& p)
{
   p.x = R*(sin(t)+a.x*sin(a.y*t));
   p.y = R*(cos(t)-a.x*cos(a.y*t));
   p.z = R*(-sin(a.z*t));
}

void moebius(float R, float u, float v, float s, float du, float dv, float4& p )
{
   p.x = 2.f*R*(cos(u)+v*cos(u/2)*cos(u));
   p.y = 2.f*R*(sin(u)+v*cos(u/2)*sin(u));
   p.z = 2.f*R*(v*sin(u/2));
}

Sunday, January 13, 2013

Raytracing on the web

I had this in mind for quite a while but never got the chance to implement it. But there it is: A ray-traced molecule visualizer available on the web. The following syntax enables access to a remote HTTP service using the GPU to generate the JPEG image.


http://localhost/get?molecule=XXXX[&scheme=0|1|2][&structure=0|1|2|3][&rotation=<float>,<float>,<float>][&quality=<integer>]

Parameters:
  • molecule=XXXX
    • 4 capital letters identifiying the molecule. The list bellow is  the only one you can use for now).
  • scheme=[0|1|2]
    • 0: Standard
    • 1: Chain
    • 2: Residue
    • example: scheme=2
  • structure=[0|1|2|3]
    • 0: Real size atoms
    • 1: Fixed size atoms
    • 2: Sticks
    • 3: Sticks and atoms 
    • 4: Backbone
    • example: structure=1
  • rotation=[x,y,z] Rotates the molecule according to x,y and z. Note that x,y,and z are real numbers specifying degrees of rotation for each axe.
    • example: rotation=45,0,0
  • quality=[1-100]
    • Identifies the number of iterations to process. The higher the better, and slower... 
  • bkcolor=[r,g,b] Specifies the red, green and blue values for background color.
    • example: bkcolor=255,0,127
  • postprocessing=[0|1|2]
    • 0: None
    • 1: Depth of field
    • 2: Ambient occlusion
  • size=[0|1|2|3|4]
    • 0: 512x512
    • 1: 768x768
    • 2: 1024x1024
    • 3: 1600x1600
    • 4: 2048x2048

Sunday, December 30, 2012

Ellipsoids finally added to the ray-tracing engine

It took me a little while to correctly implement the ray-ellipsoid intersection function but there it is :-)



float4 O_C = ray.origin-ellipsoid.center;
float4 dir = ray.direction;
normalizeVector( dir );

float a =
        ((dir.x*dir.x)/(ellipsoid.size.x*ellipsoid.size.x))
      + ((dir.y*dir.y)/(ellipsoid.size.y*ellipsoid.size.y))
      + ((dir.z*dir.z)/(ellipsoid.size.z*ellipsoid.size.z));
float b =
        ((2.f*O_C.x*dir.x)/(ellipsoid.size.x*ellipsoid.size.x))
      + ((2.f*O_C.y*dir.y)/(ellipsoid.size.y*ellipsoid.size.y))
      + ((2.f*O_C.z*dir.z)/(ellipsoid.size.z*ellipsoid.size.z));
float c =
        ((O_C.x*O_C.x)/(ellipsoid.size.x*ellipsoid.size.x))
      + ((O_C.y*O_C.y)/(ellipsoid.size.y*ellipsoid.size.y))
      + ((O_C.z*O_C.z)/(ellipsoid.size.z*ellipsoid.size.z))
      - 1.f;

float d = ((b*b)-(4.f*a*c));
if ( d<0.f || a==0.f || b==0.f || c==0.f )
   return false;

d = sqrt(d);

float t1 = (-b+d)/(2.f*a);
float t2 = (-b-d)/(2.f*a);

if( t1<=EPSILON && t2<=EPSILON ) return false; // both intersections are behind the ray origin
back = (t1<=EPSILON || t2<=EPSILON); // If only one intersection (t>0) then we are inside the ellipsoid and the intersection is at the back of the ellipsoid
float t=0.f;
if( t1<=EPSILON )
   t = t2;
else
   if( t2<=EPSILON )
      t = t1;
   else
      t=(t1<t2) ? t1 : t2;

if( t<EPSILON ) return false; // Too close to intersection

intersection = ray.origin + t*dir;
normal = intersection-ellipsoid.center;
normal.x = 2.f*normal.x/(ellipsoid.size.x*ellipsoid.size.x);
normal.y = 2.f*normal.y/(ellipsoid.size.y*ellipsoid.size.y);
normal.z = 2.f*normal.z/(ellipsoid.size.z*ellipsoid.size.z);

normal.w = 0.f;
normal *= (back) ? -1.f : 1.f;
normalizeVector(normal);
return true;

Sunday, December 2, 2012

Meet Taro, Ken and Ai, my new friends ;)

It's snowing outside, and it's freezing cold, so I decided to use my GPU to warm me up. Taro, Ken and Ai came out from this sunday of december.

Download the Windows Theme!!

Monday, November 19, 2012

RayCharts

Excited to announce that I will soon be releasing a ray-traced chart component. Here are a few screenshots of the pre-beta release.

Friday, November 16, 2012

Using textures to control refraction

Textures, just like in bump mapping, can be used to alterate the normal to a surface. If you combine it with refraction, ray-tracing can generate some cheap and pretty cool effects.