[opengtl-commits] [428] add the raytracer example

[ Thread Index | Date Index | More lists.tuxfamily.org/opengtl-commits Archives ]


Revision: 428
Author:   cyrille
Date:     2008-10-06 14:52:52 +0200 (Mon, 06 Oct 2008)

Log Message:
-----------
add the raytracer example

Added Paths:
-----------
    trunk/OpenGTL/OpenShiva/tests/imagegenerators/raytracer.shiva


Added: trunk/OpenGTL/OpenShiva/tests/imagegenerators/raytracer.shiva
===================================================================
--- trunk/OpenGTL/OpenShiva/tests/imagegenerators/raytracer.shiva	                        (rev 0)
+++ trunk/OpenGTL/OpenShiva/tests/imagegenerators/raytracer.shiva	2008-10-06 12:52:52 UTC (rev 428)
@@ -0,0 +1,357 @@
+/**
+ * Inspired from http://mike.newgrounds.com/news/post/156863 .
+ */
+
+// <languageVersion : 1.0;>
+
+// #define PI 3.1415926535897932384626433832795
+
+kernel RayTracer
+// <   namespace : "Newgrounds";
+//     vendor : "Newgrounds";
+//     version : 1;
+//     description : "Pixel Blender Raytracing";
+// >
+{
+    const float viewPlaneDistance = 2.0;
+//     parameter float  viewPlaneDistance
+//     <
+//         minValue:       0.1;
+//         maxValue:       5.0;
+//         defaultValue:   2.0;
+//     >;
+    
+    const float3 lightPos = { 0.0, 2.0, -4.0 };
+//     parameter float3 lightPos
+//     <
+//         minValue:       float3(-6.0, -6.0, -25.0);
+//         maxValue:       float3(6.0, 6.0, 0.0);
+//         defaultValue:   float3(0.0, 2.0, -4.0);
+//     >;
+    
+    const float3 sphere0Position = { 0.0, 2.0, -10.0 };
+//     parameter float3 sphere0Position
+//     <
+//         minValue:       float3(-6.0, -6.0, -25.0);
+//         maxValue:       float3(6.0, 6.0, -2.0);
+//         defaultValue:   float3(0.0, 2.0, -10.0);
+//     >;
+    
+    const float sphere0Radius = 2.0;
+//     parameter float sphere0Radius
+//     <
+//         minValue:       0.1;
+//         maxValue:       8.0;
+//         defaultValue:   2.0;
+//     >;
+    
+    const float3 sphere0Color = { 0.8, 0.8, 0.8 };
+//     parameter float3 sphere0Color
+//     <
+//         minValue:       float3(0.0, 0.0, 0.0);
+//         maxValue:       float3(1.0, 1.0, 1.0);
+//         defaultValue:   float3(0.8, 0.8, 0.8);
+//     >;
+    
+    const float4 sphere0Material = {0.05, 0.1, 1.0, 1.0};
+//     parameter float4 sphere0Material
+//     <
+//         minValue:       float4(0.0, 0.0, 0.0, 0.0);
+//         maxValue:       float4(1.0, 1.0, 1.0, 1.0);
+//         defaultValue:   float4(0.05, 0.1, 1.0, 1.0);
+//     >;
+    
+    const float RENDER_WIDTH            = 512.0;
+    const float RENDER_HEIGHT           = 512.0;
+    const float SPECULAR_EXPONENT       = 50.0;
+    
+    const int   MAX_RAY_SHOTS           = 4;
+    const int   NUM_SPHERES             = 35;
+    const int   SPHERE_PARAMETER_COUNT  = 11;
+    
+    dependent float sphereArray[NUM_SPHERES*SPHERE_PARAMETER_COUNT];
+
+    
+    
+    const float PI = 3.14;
+    float sin(float v)
+    {
+      return v;
+    }
+    float cos(float v)
+    {
+      return v;
+    }
+    float acos(float v)
+    {
+      return v;
+    }
+    float sqrt(float v)
+    {
+      return v;
+    }
+    float pow(float v, float v2)
+    {
+      return v;
+    }
+    float max(float v, float v2)
+    {
+      return v;
+    }
+    float dot(float3 v, float3 v2)
+    {
+      return 0.0;
+    }
+    float3 normalize( float3 v)
+    {
+      return v;
+    }
+    float length( float3 v)
+    {
+      return v;
+    }
+    float mod( float v, float v2)
+    {
+      return v;
+    }
+    float floor( float v)
+    {
+      return v;
+    }
+    
+    
+    
+    
+    
+    
+    // initialize our sphere parameters
+    void evaluateDependents()
+    {
+        // SPHERE PARAMETRS
+        // (x, y, z, radius, r, g, b, ambient, diffuse, specular, reflectivity)
+        
+        sphereArray[0] = sphere0Position.x;
+        sphereArray[1] = sphere0Position.y;
+        sphereArray[2] = sphere0Position.z;
+        sphereArray[3] = sphere0Radius;
+        sphereArray[4] = sphere0Color.x;
+        sphereArray[5] = sphere0Color.y;
+        sphereArray[6] = sphere0Color.z;
+        sphereArray[7] = sphere0Material.x;
+        sphereArray[8] = sphere0Material.y;
+        sphereArray[9] = sphere0Material.z;
+        sphereArray[10] = sphere0Material.w;
+               
+        sphereArray[11] = 0.0;
+        sphereArray[12] = -1003.0;
+        sphereArray[13] = -8.0;
+        sphereArray[14] = 1000.0;
+        sphereArray[15] = 0.6;
+        sphereArray[16] = 0.6;
+        sphereArray[17] = 0.6;
+        sphereArray[18] = 0.1;
+        sphereArray[19] = 0.8;
+        sphereArray[20] = 0.5;
+        sphereArray[21] = 0.5;
+        
+        // let's make a bunch of fakely random spheres
+        for(int i=SPHERE_PARAMETER_COUNT*2; i<NUM_SPHERES*SPHERE_PARAMETER_COUNT; i+=SPHERE_PARAMETER_COUNT)
+        {
+            float ifloat = float(i);
+            sphereArray[i] = sin(ifloat/5.0)*6.0;
+            sphereArray[i+1] = sin(ifloat/4.1)*2.5;
+            sphereArray[i+2] = -18.0 - sin(ifloat/3.1+1.2)*10.0;
+            sphereArray[i+3] = pow(sin(ifloat/1.34+65.3)*0.5+0.5, 3.0)*1.0 + 0.2;
+            sphereArray[i+4] = cos(ifloat/2.1+1.3)*0.5+0.5;
+            sphereArray[i+5] = cos(ifloat/0.1+1.3)*0.5+0.5;
+            sphereArray[i+6] = cos(ifloat/5.1+6.3)*0.5+0.5;
+            sphereArray[i+7] = 0.1;
+            sphereArray[i+8] = 0.7;
+            sphereArray[i+9] = 1.0;
+            sphereArray[i+10] = pow( sin(ifloat/2.1 + 1.243)*0.5 + 0.5, 5.0);
+            
+        }
+    }
+    
+    // shootRay():  fires a ray from origin, toward dir
+    //              returns first intersection
+    void shootRay(
+        in  float3  origin,
+        in  float3  dir,
+        out int     hit,
+        out float3  pos,
+        out float   t,
+        out int     sphereNum
+    )
+    {
+        float curT;
+        float B;
+        float C;
+        float disc;
+        float3 spherePos;
+        float3 sphereToOrigin;
+        float sphereRadius;
+        
+        hit = 0;
+        t = 99999.0;
+        
+        // cycle through all spheres and find the smallest t>0 that we hit
+        for(int i=0; i<NUM_SPHERES*SPHERE_PARAMETER_COUNT; i+=SPHERE_PARAMETER_COUNT)
+        {
+            spherePos = float3( sphereArray[i], sphereArray[i+1], sphereArray[i+2] );
+            sphereRadius = sphereArray[i+3];
+
+            sphereToOrigin = origin - spherePos;
+            B = dot(sphereToOrigin, dir);
+            C = dot(sphereToOrigin, sphereToOrigin) - sphereRadius*sphereRadius;
+            
+            disc = B*B-C;
+            if(disc>0.0)
+            {
+                curT = -B-sqrt(disc);
+                if(curT>0.0 && curT<t)
+                {
+                    sphereNum = i;
+                    t = curT;
+                    hit = 1;
+                }
+            }
+        }
+        
+        pos = origin + dir*t;
+    }
+    
+    void evaluatePixel(output pixel3 dst)
+    {
+        dst = float3(0,0,0);
+        
+        float3 origin = float3(0, 0, 0);
+        
+        // calculate direction vector for this pixel
+        float3 dir = float3(
+            2.0 * dst.coord.x/RENDER_WIDTH   - 1.0,
+            -2.0 * dst.coord.y/RENDER_HEIGHT + 1.0,
+            -viewPlaneDistance
+        );
+                    
+        // sphere parameters
+        int     sphereNum;
+        float3  spherePos;
+        float   sphereRadius;
+        float3  sphereColor;
+        float4  sphereMaterial;              
+                
+        float3 hitPoint;
+        float t;
+        int hit;
+        
+        float3 sphereHit;   // hit point relative to sphere
+        float3 n;           // surface normal
+        float3 lightVector; // surface to light
+        float  lightVectorLen;
+        float3 l;           // normalized light vector
+        float3 lReflect;    // reflected off surface
+        float3 dirReflect;
+        
+        int shadowTest;
+        float3 temp;
+        int temp2;
+        
+        int rayShots = MAX_RAY_SHOTS;
+        float3 colorScale = float3(1.0, 1.0, 1.0);
+        
+        // lighting
+        float specular;
+        float diffuse;
+        float lightVal;
+        
+        // texturing
+        float phi;
+        float2 uv;
+        
+        while( rayShots > 0 )
+        {
+            // let's make sure dir is properly normalized
+            dir = normalize(dir);
+            
+            // INTERSECTION TEST
+            // find the first sphere we intersect with
+            shootRay(origin, dir, hit, hitPoint, t, sphereNum);
+                        
+            if(hit != 0)
+            {                
+                // grab the parameters for the sphere we hit
+                spherePos       = float3( sphereArray[sphereNum], sphereArray[sphereNum+1], sphereArray[sphereNum+2] );
+                sphereRadius     = sphereArray[sphereNum+3];
+                sphereColor     = float3( sphereArray[sphereNum+4], sphereArray[sphereNum+5], sphereArray[sphereNum+6] );
+                sphereMaterial  = float4( sphereArray[sphereNum+7], sphereArray[sphereNum+8], sphereArray[sphereNum+9], sphereArray[sphereNum+10] );
+                
+                sphereHit = hitPoint - spherePos;
+                n = sphereHit / sphereRadius;                      // normal at the point we hit
+                lightVector = lightPos - hitPoint;                 // hit point to light
+                lightVectorLen = length(lightVector);
+                l = lightVector / lightVectorLen;
+                
+                // SHADOW TEST
+                // fire a ray from our hit position towards the light
+                shootRay(hitPoint, l, shadowTest, temp, t, temp2);
+                
+                if(shadowTest == 0)                 // if we didn't hit anything, we can see the light
+                    shadowTest = 1;
+                else if(t < lightVectorLen)         // if we hit something before the light, we are in shadow
+                    shadowTest = 0;
+                
+                diffuse = dot(l, n);
+               
+                lReflect = l - 2.0*diffuse*n;      // reflect the light vector                
+                specular = dot(dir, lReflect);
+                
+                diffuse = max( diffuse, 0.0 );
+                specular = pow( max(specular, 0.0), SPECULAR_EXPONENT );
+                
+                // ground checkboard texture
+                if(sphereNum == 11)
+                {
+                    phi = acos( -dot(float3(1.0, 0.0, 0.0), n) );
+                    uv = float2(
+                        acos( dot( float3(0.0, 0.0, 1.0), n) /sin(phi) )/(2.0*PI),
+                        phi/PI
+                    );
+                 
+                    // we could do sampleLinear here to do some actual texturing. :)
+                    if( mod(floor(uv.x*2000.0)+floor(uv.y*2000.0),2.0)==0.0 )
+                    {
+                      sphereColor *= 0.5;
+                    }
+                }
+                
+                // finally, blend our color into this pixel
+
+                lightVal = (sphereMaterial.x + float(shadowTest)*(diffuse*sphereMaterial.y + specular*sphereMaterial.z));
+                dst += colorScale*lightVal*sphereColor;
+                
+                // reflection
+                if(sphereMaterial.w > 0.0)
+                {
+                    dirReflect = dir - 2.0*dot(dir, n)*n; // reflect our view vector
+                    dirReflect = normalize(dirReflect);
+                    // originate at our hit position, fire at reflected angle
+                    origin = hitPoint;
+                    dir = dirReflect;
+                    --rayShots;
+                    
+                    // blend according to reflectivity
+                    colorScale *= sphereMaterial.w*sphereColor;
+                }
+                else rayShots = 0;
+            }
+            else rayShots = 0;
+        }
+    }
+    
+    region generated()
+    {
+        region reg = { 0, 0, RENDER_WIDTH, RENDER_HEIGHT };
+        return reg;
+    }
+}


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/