public void Render(cudaSurfaceObject_t surface, int cWidth, int cHeight, int iterations, float3 viewDirection, float3 nearFieldLocation, float3 eyeLocation, float3 lightDirection) { int cHalfWidth = cWidth / 2; float pixel = ((float)DEPTH_OF_FIELD) / (((cHeight + cWidth) / 2.0F)); float halfPixel = pixel / 2.0F; float smallStep = 0.01F; float bigStep = 0.02F; for (int y = threadIdx.y + blockIdx.y * blockDim.y; y < cHeight; y += blockDim.y * gridDim.y) { var ny = y - cHeight / 2; float3 tempViewDirectionY = viewDirection; float3 tempViewDirectionX1 = viewDirection; MathFunctions.turnOrthogonal(ref tempViewDirectionY); MathFunctions.crossProduct(ref tempViewDirectionY, viewDirection); tempViewDirectionY = tempViewDirectionY * (ny * pixel); MathFunctions.turnOrthogonal(ref tempViewDirectionX1); for (int x = threadIdx.x + blockDim.x * blockIdx.x; x < cWidth; x += blockDim.x * gridDim.x) { int nx = x - cHalfWidth; float3 pixelLocation = nearFieldLocation; float3 tempViewDirectionX2 = tempViewDirectionX1 * (nx * pixel); pixelLocation = pixelLocation + tempViewDirectionX2 + tempViewDirectionY; float3 rayLocation = pixelLocation; float3 rayDirection = rayLocation - eyeLocation; MathFunctions.normalize(ref rayDirection); var distanceFromCamera = 0.0; var d = Distance(rayLocation, iterations); int i = 0; for (; i < MAX_ITER; i++) { if (d < halfPixel) { break; } //Increase rayLocation with direction and d: rayDirection = rayDirection * d; rayLocation = rayLocation + rayDirection; //And reset ray direction: MathFunctions.normalize(ref rayDirection); //Move the pixel location: distanceFromCamera = MathFunctions.length(nearFieldLocation - rayLocation); if (distanceFromCamera > DEPTH_OF_FIELD) { break; } d = Distance(rayLocation, iterations); } if (distanceFromCamera < DEPTH_OF_FIELD && distanceFromCamera > 0) { rayLocation.x -= smallStep; var locationMinX = Distance(rayLocation, iterations); rayLocation.x += bigStep; var locationPlusX = Distance(rayLocation, iterations); rayLocation.x -= smallStep; rayLocation.y -= smallStep; var locationMinY = Distance(rayLocation, iterations); rayLocation.y += bigStep; var locationPlusY = Distance(rayLocation, iterations); rayLocation.y -= smallStep; rayLocation.z -= smallStep; var locationMinZ = Distance(rayLocation, iterations); rayLocation.z += bigStep; var locationPlusZ = Distance(rayLocation, iterations); rayLocation.z -= smallStep; float3 normal = new float3(); //Calculate the normal: normal.x = (locationMinX - locationPlusX); normal.y = (locationMinY - locationPlusY); normal.z = (locationMinZ - locationPlusZ); MathFunctions.normalize(ref normal); //Calculate the ambient light: var dotNL = MathFunctions.dotProduct(lightDirection, normal); var diff = MathFunctions.saturate(dotNL); //Calculate specular light: float3 halfway = rayDirection + lightDirection; MathFunctions.normalize(ref halfway); var dotNH = MathFunctions.dotProduct(halfway, normal); float s = MathFunctions.saturate(dotNH); float s2 = s * s; float s4 = s2 * s2; float s8 = s4 * s4; float s16 = s8 * s8; float s32 = s16 * s16; float spec = s * s2 * s32; // s^35 var shad = shadow(lightDirection, rayLocation, iterations, 1.0F, DEPTH_OF_FIELD, 16.0F) + 0.25F; var brightness = (10.0F + (200.0F + spec * 45.0F) * shad * diff) / 270.0F; var red = 10 + (380 * brightness); var green = 10 + (280 * brightness); var blue = (180 * brightness); red = MathFunctions.clamp(red, 0, 255.0F); green = MathFunctions.clamp(green, 0, 255.0F); blue = MathFunctions.clamp(blue, 0, 255.0F); uchar4 color = new uchar4(); color.x = (byte)red; color.y = (byte)green; color.z = (byte)blue; TextureHelpers.surf2Dwrite(color, surface, x * sizeof(int), y); } else { uchar4 color = new uchar4(); color.x = (byte)(155.0F + MathFunctions.clamp(i * 1.5F, 0.0F, 100.0F)); color.y = ((byte)(205.0F + MathFunctions.clamp(i * 1.5F, 0.0F, 50.0F))); color.z = 255; TextureHelpers.surf2Dwrite(color, surface, x * sizeof(int), y); } } } }