#define PI 3.1415926535897932384626433832795 kernel RayTracer < namespace : "Newgrounds"; vendor : "Newgrounds"; version : 1; description : "Pixel Blender Raytracing"; > { output pixel3 dst; parameter float viewPlaneDistance < minValue: 0.1; maxValue: 5.0; defaultValue: 2.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); >; 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); >; parameter float sphere0Radius < minValue: 0.1; maxValue: 8.0; defaultValue: 2.0; >; 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); >; 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]; // 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; i0 that we hit for(int i=0; i0.0) { curT = -B-sqrt(disc); if(curT>0.0 && curT 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. :) sphereColor *= ( mod(floor(uv.x*2000.0)+floor(uv.y*2000.0),2.0)==0.0 )? 0.5 : 1.0; } // 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() { return region(float4(0, 0, RENDER_WIDTH, RENDER_HEIGHT)); } }