[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;
+ }
+}