Public feed #528524

Raytracing Effect

public text v1 · immutable
Raw Edit
·published 2007-06-01 16:18 UTC
rendered paste body
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 = <sphereTex>;
};

sampler LightSampler=
sampler_state
{
    Texture = <lightTex>;
};

sampler PlaneSampler=
sampler_state
{
    Texture = <planeTex>;
};

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)
	{
		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();          
    }
}