#define PI 3.1415926535897932384626433832795 kernel SmartRayTracer < namespace : "smart-page.net"; vendor : "smart-page.net (original by Newgrounds)"; version : 1; description : "Pixel Blender Raytracing"; > /* Original shader by the genious Mike Welsh: http://mike.newgrounds.com/news/post/156863 Modified by www.smart-page.net - added viewport controls and anti aliasing */ { output pixel4 dst; parameter int A_widthAndHeight < minValue: int(0.0); maxValue: int(1600.0); defaultValue: int(500.0); >; parameter bool A_antiAntialias < defaultValue: false; >; parameter bool A_showCheckboard < defaultValue: false; >; parameter bool A_computeShadows < defaultValue: true; >; parameter float B_viewPlaneDistance < minValue: 0.1; maxValue: 5.0; defaultValue: 2.0; >; parameter float B_viewCameraY < minValue : 0.0; maxValue : 360.0; defaultValue : 0.0; >; parameter float B_viewCameraX < minValue : 0.0; maxValue : 90.0; defaultValue : 20.0; >; parameter float3 C_lightPos < minValue: float3(-6.0, -6.0, -25.0); maxValue: float3(6.0, 6.0, 0.0); defaultValue: float3(0.0, 2.0, 0.0); >; parameter float D_sphereSpacing < minValue: float(0.0); maxValue: float(20.0); defaultValue: float(0.6); >; parameter float E_sphere_0_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_1_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_2_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_3_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_4_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_5_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_6_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_7_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_8_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_9_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_10_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_11_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_12_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_13_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_14_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; parameter float E_sphere_15_Y < minValue: float(0.0); maxValue: float(5.0); defaultValue: float(0.0); >; const float RENDER_WIDTH = 720.0; const float RENDER_HEIGHT = 720.0; const float SPECULAR_EXPONENT = 50.0; const int MAX_RAY_SHOTS = 8; const int NUM_SPHERES = 18; const int SPHERE_PARAMETER_COUNT = 11; const float3 LOOKAT = float3(0.0, 0.0, 0.0); 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[11] = 0.0; sphereArray[12] = -1000.2; sphereArray[13] = -8.0; sphereArray[14] = 1000.0; sphereArray[15] = 0.7; sphereArray[16] = 0.7; sphereArray[17] = 0.7; sphereArray[18] = 0.3; sphereArray[19] = 0.8; sphereArray[20] = 0.5; sphereArray[21] = 0.5; float angle = PI/float(8.0); 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 ) { shootRay(org, 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 = C_lightPos - hitPoint; // hit point to light lightVectorLen = length(lightVector); l = lightVector / lightVectorLen; // SHADOW TEST // fire a ray from our hit position towards the light if(A_computeShadows){ 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; }else{ shadowTest = 1; } 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 && A_showCheckboard) { 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)); col = 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; } //Anti Alias ? if(!A_antiAntialias){ outcol=col; break; } outcol+=0.25*col; } } dst=pixel4(outcol.x,outcol.y,outcol.z,1.0); } region generated() { return region(float4(0, 0, A_widthAndHeight, A_widthAndHeight)); } }