Jump to content
  • Advertisement
Sign in to follow this  
Deliverance

GPU raytracing with GLSL

This topic is 2867 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've started toying with some (very simple) real time ray tracing on the GPU and i'm having troubles figuring out what space i am in. Let me explain what am i doing.
First there is ray generation: i draw a full screen alligned quad with an ortho projection and generate then ray position in the fragment shader, like so:


vec2 position = position_;

float fov = radians(60.0);
float nearPlane = 1.0;
float nearHeight = nearPlane * tan(fov / 2.0);
float nearWidth = nearHeight * 4.0 / 3.0;

position.x *= nearWidth;
position.y *= nearHeight;

vec3 rayCenter = invModelView[3].xyz;
vec3 rayDirUt = normalize(vec3(position, -nearPlane));
vec3 rayDir = (( invModelView*vec4(rayDirUt, 0.0) ).xyz) * 5000.0;
vec3 rayEnd = rayCenter+rayDir;



Where position_ is the clip space position of the current fragment.
invModelView is the inverse of the current camera, what it does is take a ray in camera space and takes it back to world space(because all the geometry is in world space).

Second there is lighting: i'm using a point light source, and doing the calculations in world space.

The problem is that i have a light which rotates around the origin and illuminates a sphere(centered at the origin) in a wrong way. Here's a picture
that shows the problem, you can clearly see that the light is rotating at the back of the sphere is illuminates as if the light was in front of it:


I'm now listing the full source code of the shader(which is not that much). Hopefully someone will spot the issue :D.

varying vec2 position_;
uniform float time;
uniform mat4 invModelView;

vec3 intersection;
vec3 normal;

float sphereIntersect(vec3 start, vec3 end, vec3 center, float radius)
{
vec3 dir = end - start;
vec3 oc = start - center;
float a = dot(dir, dir);
float b = 2.0 * dot(dir, oc);
float c = dot(start, start) + dot(center, center) - 2.0*dot(start, center) - radius*radius;
float t;

if (c < 0.0)
return 0.0;

float delta = b*b - 4.0*a*c;

if (delta < 0.0)
return 0.0;

float sdelta = sqrt(delta);

t = (-b + sdelta) / (2.0*a);
if (t < 0.0)
t = (-b - sdelta) / (2.0*a);

if (t<0.0 || t>1.0) // The intersection point is not on the line
return 0.0;

intersection = start + dir * t;
normal = vec4(normalize(intersection - center), 0.0).xyz;

return t;
}

float triangleIntersect(vec3 o, vec3 e, vec3 a, vec3 b, vec3 c)
{
vec3 d = e - o;
vec3 e1 = b - a;
vec3 e2 = c - a;
vec3 p = cross(d, e2);
float det = dot(p, e1);
bool isHit = det > 0.00001f;

float invdet = 1.0f / det;

vec3 tvec = o - a;
float u = dot(p, tvec) * invdet;
vec3 q = cross(tvec, e1);
float v = dot(q, d) * invdet;
float t = dot(q, e2) * invdet;
isHit = (u >= 0.0f) && (v >= 0.0f)
&& (u + v <= 1.0f)
&& (t < 1.0)
&& (t > 0.0);

if (!isHit)
return 0.0;

intersection = o+d*t;
normal = normalize(cross(c-a, b-a));

return isHit ? t : 0.0;
}

float sceneIntersect(vec3 rayCenter, vec3 rayEnd)
{
float minT = 10000000.0;
vec3 intersectionFinal;
vec3 normalFinal;
float t;

t = sphereIntersect(rayCenter, rayEnd, (vec4(0.0, 0.0, 0.0, 1.0)).xyz, 3.0);
if (t < minT && t > 0.0)
{
intersectionFinal = intersection;
normalFinal = normal;
minT = t;
}

vec3 tri[50];
float width = 15.0, height = 5.0, depth = 35.0;
tri[0] = vec3(-width, -height, -depth);
tri[1] = vec3(+width, -height, -depth);
tri[2] = vec3(-width, -height, +depth);
tri[3] = vec3(+width, -height, -depth);
tri[4] = vec3(+width, -height, +depth);
tri[5] = vec3(-width, -height, +depth);

tri[8] = vec3(-width, +height, -depth);
tri[7] = vec3(+width, +height, -depth);
tri[6] = vec3(-width, +height, +depth);
tri[11] = vec3(+width, +height, -depth);
tri[10] = vec3(+width, +height, +depth);
tri[9] = vec3(-width, +height, +depth);

tri[14] = vec3(-width, -height, -depth);
tri[13] = vec3(-width, +height, -depth);
tri[12] = vec3(-width, +height, +depth);
tri[17] = vec3(-width, +height, +depth);
tri[16] = vec3(-width, -height, +depth);
tri[15] = vec3(-width, -height, -depth);

tri[18] = vec3(+width, -height, -depth);
tri[19] = vec3(+width, +height, -depth);
tri[20] = vec3(+width, +height, +depth);
tri[21] = vec3(+width, +height, +depth);
tri[22] = vec3(+width, -height, +depth);
tri[23] = vec3(+width, -height, -depth);

tri[26] = vec3(-width, -height, -depth);
tri[25] = vec3(+width, -height, -depth);
tri[24] = vec3(+width, +height, -depth);
tri[29] = vec3(+width, +height, -depth);
tri[28] = vec3(-width, +height, -depth);
tri[27] = vec3(-width, -height, -depth);

tri[30] = vec3(-width, -height, +depth);
tri[31] = vec3(+width, -height, +depth);
tri[32] = vec3(+width, +height, +depth);
tri[33] = vec3(+width, +height, +depth);
tri[34] = vec3(-width, +height, +depth);
tri[35] = vec3(-width, -height, +depth);

int i;
for (i=0; i<12; i++)
{
t = triangleIntersect(rayCenter, rayEnd, tri[i*3+0], tri[i*3+1], tri[i*3+2]);
if (t < minT && t > 0.0)
{
intersectionFinal = intersection;
normalFinal = normal;
minT = t;
}
}
if (minT != 10000000.0)
{
intersection = intersectionFinal;
normal = ( vec4(normalFinal, 0.0)).xyz;

return minT;
}

return 0.0;
}

struct Light
{
int type;
vec3 center;
float radius;
};

Light lights[10];

vec4 shade(int numLights)
{
vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
int i;
for (i=0; i<numLights; i++)
{
if (lights.type == 0)
{
vec3 lightDir = normalize( lights.center - intersection);
float NdotL = max(0.0, dot(lightDir, normal));
color += NdotL;
}
}

return color;
}

void main()
{
vec2 position = position_;

float fov = radians(60.0);
float nearPlane = 1.0;
float nearHeight = nearPlane * tan(fov / 2.0);
float nearWidth = nearHeight * 4.0 / 3.0;

position.x *= nearWidth;
position.y *= nearHeight;

vec3 rayCenter = invModelView[3].xyz;
vec3 rayDirUt = normalize(vec3(position, -nearPlane));
vec3 rayDir = (( invModelView*vec4(rayDirUt, 0.0) ).xyz) * 5000.0;
vec3 rayEnd = rayCenter+rayDir;

int numLights = 1;
lights[0].type = 0;
lights[0].center = vec4(cos(time*5)*5, 0.0, sin(time*5)*5, 0.0);
lights[0].radius = 5.0;

vec4 color = vec4(0.0, 0.0, 0.0, 0.0);

if (sceneIntersect(rayCenter, rayEnd) != 0.0)
{
color += shade(numLights);
}

gl_FragColor = color;
}

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!