go to: [home]


Implementing Ray Tracing on GPU
Part 5


Shader in Shader

This title isn't a typo: the ray tracer requires a shader for light calculation and this is implemented in a GPU shader program. In the shader, a lighting equation is used (for example Phong lighting model) to shade ray-object intersection points. In the shader rays are also reflected and can be used in another "instance" of the ray tracer. Material information is stored in a texture, but for simplification and sake of clarity it is implemented as a list of "if" statements here.

pixel3 ray_shade( PixelShaderInput IN )
{
pixel3 OUT;
   vec4 raydir = tex2D(tex0,IN.texCoord);
   vec4 raypos = tex2D(tex1,IN.texCoord);
   vec4 uvt    = tex2D(tex4,IN.texCoord);
   vec4 colorbuf = tex2D(tex5,IN.texCoord);
   float r=0.0;
   
   float shininess = 20;

   vec3 diffuse = vec3(1,1,1);
   vec3 specular = vec3(1,1,1);
   vec3 ambient = vec3(0.1,0.1,0.2);
      
   vec2 EDcoord = Coord2D(4*TRIANGLE_ELEMENTS*uvt.w, EDsize);
   //vec4 Vertex1 = tex2D(ED, EDcoord);
   float material = tex2D(ED, EDcoord).w;
   vec3 Normal1 = tex2D(ED, vec2(EDcoord.x+1.0/EDsize,EDcoord.y));
   //vec3 Vertex2 = tex2D(ED, vec2(EDcoord.x+2.0/EDsize,EDcoord.y));
   vec3 Normal2 = tex2D(ED, vec2(EDcoord.x+3.0/EDsize,EDcoord.y));
   //vec3 Vertex3 = tex2D(ED, vec2(EDcoord.x+4.0/EDsize,EDcoord.y));
   vec3 Normal3 = tex2D(ED, vec2(EDcoord.x+5.0/EDsize,EDcoord.y));
if (material == 0.0) { diffuse = vec3(1,1,1); r=0.5;} if (material == 1.0) { diffuse = vec3(0.5,0.5,0.5); r=0;} if (material == 2.0) { diffuse = vec3(1,0,0); r=0.05;} if (material == 3.0) { diffuse = vec3(0,1,0); r=0.05;} if (material == 4.0) { diffuse = vec3(1,1,0); r=0.05;} if (material == 5.0) { diffuse = vec3(0,0.5,0.5); r=0.1; shininess = 100; } if (material == 6.0) { diffuse = vec3(0.5,0.5,0.0); r=0.1; shininess = 120;} if (material == 7.0) { diffuse = vec3(0.5,0.5,0.5); r=0.5; shininess = 30;} // Phong Lighting Model with 1 Light vec3 hitpoint = raypos.xyz + (raydir.xyz * uvt.z); vec3 light0 = camera_pos; vec3 L = normalize(light0 - hitpoint); vec3 nU = Normal2 - Normal1; vec3 nV = Normal3 - Normal1; vec3 N = normalize(Normal1 + nU*uvt.x + nV*uvt.y); float lambert = max(dot(N,L),0.0); vec3 E = normalize(camera_pos - hitpoint); vec3 R = -normalize(reflect(L,N)); float phong = pow(max(dot(R,E),0.0), shininess); vec3 Itot = saturate(ambient + diffuse*lambert + specular*phong); Itot = colorbuf.xyz + Itot * colorbuf.w; colorbuf.w *= r; Itot = Itot - Itot * colorbuf.w; colorbuf.xyz = Itot; if (raydir.w == 10.5) discard; // AABB isn't hit if (uvt.w < 0) discard; // Reflektor: OUT.color1.xyz = reflect(normalize(raydir.xyz),N); OUT.color1.w = raydir.w; OUT.color2.xyz = hitpoint; OUT.color2.w = raypos.w; OUT.color0 = colorbuf; return OUT; }

Result


Output of a scene calculated on the GPU


Triangle based spheres



Reflecting room, calculated with shadows


go to: [home]