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