int MAXBOUNCES = 2; float EPSILON = 0.0001f; float MAXDISTANCE = 9999999; float2 resolution; float valX; float valY; int numSpheres = 6; int numPlanes = 1; int numLights = 1; float sTexW; float sTexH; float lTexW; float lTexH; float pTexW; float pTexH; float3 cameraPosition; float4x4 cameraMatrix; texture sphereTex; texture lightTex; texture planeTex; sampler SphereSampler= sampler_state { Texture = ; }; sampler LightSampler= sampler_state { Texture = ; }; sampler PlaneSampler= sampler_state { Texture = ; }; struct a2v { float4 position : POSITION; float2 texCoord : TEXCOORD0; }; struct v2p { float4 position : POSITION; float2 texCoord : TEXCOORD0; }; struct p2f { float4 color : COLOR0; }; void vs(in a2v IN, out v2p OUT) { OUT.position = IN.position; OUT.texCoord = IN.texCoord; }; float SphereRayIntersectTest(float3 spherePosition, float radius, float3 position, float3 direction) { float intersectionDistance = -1; float diffX = spherePosition.x - position.x; float diffY = spherePosition.y - position.y; float diffZ = spherePosition.z - position.z; float dist = ((diffX * diffX) + (diffY * diffY)) + (diffZ * diffZ); float radSq = radius * radius; if (dist <= radSq) { intersectionDistance = 0; } if(intersectionDistance != 0) { float cross = ((diffX * direction.x) + (diffY * direction.y)) + (diffZ * direction.z); if (cross >= 0) { float num = dist - (cross * cross); if (num <= radSq) { float result = sqrt(radSq - num); intersectionDistance = cross - result; } } } return intersectionDistance; }; float PlaneRayIntersectTest(float3 planeNormal, float distance, float3 rayStart, float3 rayDir) { float result = -1; float num2 = ((planeNormal.x * rayDir.x) + (planeNormal.y * rayDir.y)) + (planeNormal.z * rayDir.z); if (abs(num2) >= 0.00005) { float num3 = ((planeNormal.x * rayStart.x) + (planeNormal.y * rayStart.y)) + (planeNormal.z * rayStart.z); result = (-distance - num3) / num2; if (result < 0) { result = 0; } } return result; }; float3 SphereNormalToPoint(float3 spherePosition, float3 point) { return point - spherePosition; }; float CalculateShade(float3 rayStart, float3 rayDir, float distanceToObject) { float shade = 1; rayStart += (rayDir * EPSILON); for(int s = 0; s < 15; s++) { float4 sPosRad = tex2D(SphereSampler, float2(0,s/sTexH)); float distAway = SphereRayIntersectTest(float3(sPosRad.x, sPosRad.y, sPosRad.z), sPosRad.a, rayStart, rayDir); if(distAway > 0 && distAway < distanceToObject) { shade = 0; } } return shade; }; float2x4 GetNearestSphere(float3 rayStart, float3 rayDir) { float4 nearestPosRad = 0; float nearestDistance = MAXDISTANCE; int nearestObject = -1; for(int i = 0; i < 15; i++) { float4 sPosRad = tex2D(SphereSampler, float2(0,i/sTexH)); float distance = SphereRayIntersectTest(float3(sPosRad.x, sPosRad.y, sPosRad.z), sPosRad.a, rayStart, rayDir); if(distance != -1) { if(distance < nearestDistance) { nearestDistance = distance; nearestObject = i; nearestPosRad = sPosRad; } } } float2x4 data; data[0] = nearestPosRad; data[1] = float4(nearestObject, nearestDistance, 0, 0); return data; }; float2x4 GetNearestPlane(float3 rayStart, float3 rayDir) { float4 nearestData = 0; float nearestDistance = MAXDISTANCE; int nearestObject = -1; for(int i = 0; i < 1; i++) { float4 pData = tex2D(PlaneSampler, float2(0,i/pTexH)); float distance = PlaneRayIntersectTest(float3(pData.x, pData.y, pData.z), pData.a, rayStart, rayDir); if(distance != -1) { if(distance < nearestDistance) { nearestDistance = distance; nearestObject = i; nearestData = pData; } } } float2x4 data; data[0] = nearestData; data[1] = float4(nearestObject, nearestDistance, 0, 0); return data; }; void ps(in v2p IN, out p2f OUT) { float4 outColor = 0; float2 lookUp; lookUp.x = IN.texCoord.x / resolution.x; lookUp.y = IN.texCoord.y / resolution.y; float vpWidth = 0.1; float vpHeight = 0.1 / (resolution.x/resolution.y); float pixelWidth = vpWidth / resolution.x; float pixelHeight = vpHeight / resolution.y; float3 rayDirection = float3(0,0,-1) * 0.1; rayDirection.x -= (IN.texCoord.x - valX) * pixelWidth; rayDirection.y -= (IN.texCoord.y - valY) * pixelHeight; rayDirection = mul(rayDirection, cameraMatrix); rayDirection = normalize(rayDirection); float3 rayPosition = cameraPosition; float2x4 sData = GetNearestSphere(rayPosition, rayDirection); int primType = 0; float4 nearestObjPos = sData[0]; int nearestObject = sData[1][0]; float nearestDistance = sData[1][1]; float2x4 pData = GetNearestPlane(rayPosition, rayDirection); float4 nearestPData = pData[0]; int nearestPlane = pData[1][0]; float nearestPDistance = pData[1][1]; if(nearestPDistance > 0 && nearestPDistance < nearestDistance) //(false) { nearestDistance = nearestPDistance; nearestObjPos = nearestPData; nearestObject = nearestPlane; primType = 1; } if(nearestDistance < MAXDISTANCE) { float4 nearestObjColor = tex2D(SphereSampler, float2(1.0/sTexW, nearestObject/sTexH)); float4 nearestObjMat = tex2D(SphereSampler, float2(2.0/sTexW, nearestObject/sTexH)); if(primType == 0) { nearestObjColor = tex2D(SphereSampler, float2(1.0/sTexW, nearestObject/sTexH)); nearestObjMat = tex2D(SphereSampler, float2(2.0/sTexW, nearestObject/sTexH)); } else { nearestObjColor = tex2D(PlaneSampler, float2(1.0/pTexW, nearestObject/pTexH)); nearestObjMat = tex2D(PlaneSampler, float2(2.0/pTexW, nearestObject/pTexH)); } float3 intersectionPoint = rayPosition + (rayDirection * (nearestDistance * (1-EPSILON))); float shade = 1; for(int l = 0; l < 1; l++) { float4 lPosRad = tex2D(LightSampler, float2(0,l/lTexH)); float3 lightPos = float3(lPosRad.x, lPosRad.y, lPosRad.z); float4 lightInfo = tex2D(LightSampler, float2(1/lTexW,l/lTexH)); float3 lightVector = normalize(lightPos - intersectionPoint); float3 sphereNormal = SphereNormalToPoint(float3(nearestObjPos.x, nearestObjPos.y, nearestObjPos.z), intersectionPoint); float3 planeNormal = float3(nearestObjPos.x, nearestObjPos.y, nearestObjPos.z); float dotProduct = -1; if(primType == 0) dotProduct = dot(normalize(sphereNormal), lightVector); else dotProduct = dot(normalize(planeNormal), lightVector); if(dotProduct > 0) { float shade = CalculateShade(intersectionPoint, lightVector, length(lightPos - intersectionPoint)); outColor += nearestObjColor * dotProduct * nearestObjMat.x * shade * lightInfo.a; } if(nearestObjMat.z > 0) { float shadeSpec = 1; float3 specLight = lightPos - intersectionPoint; float distToIntersection = length(specLight); specLight = normalize(specLight); float3 sphereNormal = intersectionPoint - nearestObjPos; sphereNormal = normalize(sphereNormal); float3 reflected = reflect(specLight, sphereNormal); reflected = normalize(reflected); float specularDP = dot(rayDirection, reflected); if(specularDP > 0) { shadeSpec = CalculateShade(intersectionPoint, specLight, length(lightPos-intersectionPoint)); float specular = pow(specularDP, 40) * nearestObjMat.z * shadeSpec; outColor += specular * float4(lightInfo.x, lightInfo.y, lightInfo.z, 1); } } } } OUT.color = outColor; }; technique Shader360 { pass P0 { VertexShader = compile vs_2_0 vs(); PixelShader = compile ps_3_0 ps(); } }