www.pudn.com > gpurt.zip > RayTracer.cg


struct appin { 
	float4 position : POSITION; 
	float4 color0   : COLOR0; 
	float4 rayPos : TEXCOORD0; 
	float4 rayDir : TEXCOORD1; 
}; 
 
struct vertout { 
	float4 position : POSITION; 
	float4 color0   : COLOR0; 
	 
	float4 rayPos : TEXCOORD0; 
	float4 rayDir : TEXCOORD1; 
	float2 coords : WPOS; 
}; 
 
vertout rayVert(appin IN,	uniform float4x4 Projection : state.matrix.projection, 
							uniform float4x4 MVP : state.matrix.mvp, 
							uniform float4x4 ModelView : state.matrix.modelview,  
							uniform float4x4 ModelViewIT ) { 
	vertout OUT; 
 
	OUT.position=mul(Projection, IN.position); 
 
	OUT.rayPos=mul(ModelView, IN.rayPos); 
	OUT.rayDir=mul(ModelViewIT, IN.rayDir); 
	 
 
	return OUT; 
} 
 
// implementation of refract function from Cg stdlib 
float3 refraction(float3 i, float3 n, float eta) 
{ 
    float cosi = dot(-i, n); 
    float cost2 = 1.0 - eta * eta * (1.0 - cosi*cosi); 
    float3 t = eta*i + ((eta*cosi - sqrt(abs(cost2))) * n); 
    return t * float3(cost2 > 0.0); 
} 
 
// fresnel approximation 
float fast_fresnel(float3 I, float3 N, float3 fresnelValues) 
{ 
    float power = fresnelValues.x; 
    float scale = fresnelValues.y; 
    float bias = fresnelValues.z; 
 
    return bias + pow(1.0 - dot(I, N), power) * scale; 
} 
 
bool hitSphere(float3 rayStart, float3 rayDir, float3 spherePos, float sphereRadius, inout float t)  
{ 
   // intersection rayon/sphere  
   float3 dist = spherePos - rayStart;  
   float B = dot(rayDir, dist); //rayDir * dist; 
   float D = B*B - dot(dist, dist) + sphereRadius * sphereRadius;  
     
   bool retvalue = false; 
     
   if (D >= 0.0f){ 
     //else:return false;  
 
   float t0 = B - sqrt(D);  
   float t1 = B + sqrt(D); 
 
     
   if ((t0 > 0.0001f) && (t0 < t))  
   { 
     t = t0; 
     retvalue = true;  
   }  
   if ((t1 > 0.0001f) && (t1 < t))  
   { 
     t = t1;  
     retvalue = true;  
   } 
    
  } 
  return retvalue;  
} 
 
float4 lighting(float3 pos, float3 normal, float4 color, float3 lightPos, float3 viewPos){ 
	 
	 
	// store normalized light vector 
	float3 lightVec = normalize(lightPos-pos); 
	// calculate half angle vector 
	float3 eyeVec = float3(viewPos-pos); 
	float3 halfVec = normalize(lightVec + eyeVec); 
	 
	// calculate diffuse component 
	float diffuse = dot(normal, lightVec); 
	// calculate specular component 
	float specular = dot(normal, halfVec); 
	// Use the lit function to compute lighting vector from 
	// diffuse and specular values 
	float4 lighting = lit(diffuse, specular, 32); 
	 
	// blue diffuse material 
	float3 diffuseMaterial = float3(0.0, 0.0, 1.0); 
	// white specular material 
	float3 specularMaterial = float3(1.0, 1.0, 1.0); 
	 
	// combine diffuse and specular contributions and 
	// output final vertex color 
	float4 res; 
	res.rgb = lighting.y * color.rgb + lighting.z * specularMaterial; 
	res.a = 1.0; 
 
	return res; 
} 
 
bool rayCast(float3 rayStart, float3 rayDir, uniform samplerRECT scene, out float4 hitColorOut, out float3 hitPosOut, out float3 hitNormalOut){ 
	float t=99999.0; 
	 
	float4 sphere; 
	float2 index=float2(0,0); 
	 
	sphere = texRECT(scene,index); 
 
	float3 hitPos; 
	float3 hitNormal; 
	float4 hitColor; 
	 
	float interT=0; 
	float4 interSphere; 
	float2 interMatIndex; 
 
	while(sphere.a>0){ 
	//for(int i=0; i<5; i++){ 
		if(hitSphere(rayStart, rayDir, sphere.rgb, sphere.a, t)){ 
			interT=t; 
			interSphere=sphere; 
			interMatIndex=index+float2(1,0); 
		} 
 
		index.x+=2; 
		sphere = texRECT(scene,index); 
	} 
	float4 res; 
	 
	if(interT>0){ 
		hitPos=rayStart+rayDir*interT; 
		hitNormal=normalize(hitPos-interSphere.rgb); 
		hitColor=texRECT(scene,interMatIndex); 
			 
		res=lighting(hitPos, hitNormal, hitColor, float3(1,1,-1), rayStart); 
		 
		hitPosOut=hitPos; 
		hitNormalOut=hitNormal; 
		 
		hitColorOut=res; 
		 
		return true; 
		//res=res+rayCast(hitPos,  reflect(rayDir, hitNormal) , scene); 
	}else{ 
		hitColorOut=float4(0,0,0,0); 
		 
		return false; 
	} 
	 
	//hitColorOut=res; 
	//return res; 
} 
 
void rayFrag(vertout IN,  
	out   float4 color : COLOR, 
	uniform float3 lightVec, 
	uniform samplerRECT scene) 
{ 
	float3 hitPos; 
	float3 hitNormal; 
	float4 hitColor; 
	 
	float3 rayStart=IN.rayPos.xyz; 
	float3 rayDir=IN.rayDir.xyz; 
	 
 
	bool res=false; 
	 
	int i=0;  
	 
	do{ 
		res=rayCast(rayStart, rayDir, scene, hitColor, hitPos, hitNormal); 
		color=color+hitColor; 
		 
		rayStart=hitPos; 
		rayDir=reflect(IN.rayDir.xyz, hitNormal); 
		 
		i++; 
	}while(res && i<3); 
 
		 
 }