Jump to content
  • Advertisement
Sign in to follow this  
Ben Danger

OpenGL Glsl ray tracing

This topic is 525 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'm trying to make a ray tracer in OpenGL compute shaders. I have just made it so the rays can collide with spheres with no secondary rays or lighting effects but it runs really slow with even just a few spheres at around 50ms per frame. I changed it so the compute shader didn't try anything which made it quite a bit faster. Can anyone see what could be slowing it down?. Each ray loops through every shape and tries to intersect it

 

here is the compute shader

 

 

#version 430 core
layout (local_size_x = 1, local_size_y = 1) in;
layout(rgba32f, binding = 0) uniform image2D img_output;

uniform vec3 playerView;
uniform mat4 viewMatrix;
 
vec3 spherePositions[3] = {vec3(0.0f,0.0f, 3.0f),vec3(-1.0f,0.0f, 2.0f),vec3(3.0f,-50.0f,100.0f)};
float sphereRadii[3] = {1.0f, 0.3f,50.0f};
vec4 computeSphereIntercept(vec3 ray,float closestRayHit,vec3 position,float radius,vec3 colour);

void main() {
    //vec4 pixel = vec4(1.0f,1.0f,1.0f, 1.0);
    ivec2 pixelCoords = ivec2(gl_GlobalInvocationID.xy);
    vec4 collision = vec4(1.0f,1.0f,1.0f,100.0f);

    vec3 ray = normalize(vec3(mix(-1.33,1.33,(pixelCoords.x/800.0)),mix(1,-1,(pixelCoords.y/600.0)),1));
    //float nearestRayHit = 100.0f;
    for(int i = 0;i < 3;i++){
        if(length(cross(ray,spherePositions))-length(spherePositions) <= sphereRadii){
            collision = computeSphereIntercept(ray,collision.w,spherePositions,sphereRadii,collision.xyz);

        }

        //nearestRayHit = collision.w;
        //pixel = vec4(collision.xyz,1.0f);
 

    }
 
 
    // output to a specific pixel in the image
    imageStore(img_output, pixelCoords, vec4(collision.xyz,1.0f));
}

vec4 computeSphereIntercept(vec3 ray,float closestRayHit,vec3 position,float radius,vec3 colour){
    vec3 spherePos = (viewMatrix * vec4(position,1.0f)).xyz;

    float distRaySphereCollision = dot(ray,spherePos);
    vec3 raySphereCollision = ray*distRaySphereCollision;
    //float centerToRaySphereCollision = length(raySphereCollision-spherePos);
    float centerToRaySphereCollision = pow(raySphereCollision.x-spherePos.x,2)+pow(raySphereCollision.y-spherePos.y,2)+pow(raySphereCollision.z-spherePos.z,2);
    float interceptEdgeFromRaySphereCollision = sqrt(pow(radius,2)-centerToRaySphereCollision);
    if(closestRayHit > distRaySphereCollision-interceptEdgeFromRaySphereCollision && distRaySphereCollision > 0 && centerToRaySphereCollision <= radius*radius && pow(spherePos.x,2)+pow(spherePos.y,2)+pow(spherePos.z,2) >= radius*radius){
        closestRayHit = distRaySphereCollision-interceptEdgeFromRaySphereCollision;
        colour = vec3(1.0f,0.0f,0.0f);
    }
    else if(closestRayHit > distRaySphereCollision+interceptEdgeFromRaySphereCollision && pow(spherePos.x,2)+pow(spherePos.y,2)+pow(spherePos.z,2) < radius*radius){
        closestRayHit = distRaySphereCollision-interceptEdgeFromRaySphereCollision;
        colour = vec3(1.0f,0.0f,0.0f);
    }

    return vec4(colour.xyz,closestRayHit);
}

 

 

how it determines collision with a sphere is it finds the distance to the point where it makes a 90 degrees angle from that point to the sphere and that point to the camera, if the distance from  that point to the sphere is bigger than its radius no collision, if the distance is less than it finds the exact spot where it hits with one square root I think.

 


 

Edited by Ben Danger

Share this post


Link to post
Share on other sites
Advertisement

Each ray loops through every shape
 

This could be the cause.

Normally one's trying to implement some kind of partitioning. kD-trees layed up linearly in memory, bounding hierarchies, etc.

I didn't trace rays myself though, but quite good results was achieved in the era before computing shaders.

Share this post


Link to post
Share on other sites

Each ray loops through every shape

 
This could be the cause.
Normally one's trying to implement some kind of partitioning. kD-trees layed up linearly in memory, bounding hierarchies, etc.
I didn't trace rays myself though, but quite good results was achieved in the era before computing shaders.

I was planning on using octrees for storing voxels. Are you familiar with voxel quest? I'm pretty sure it uses ray tracing, how could it be possible to have such high res graphics like it? Although I'm not expecting to have anything that good it just bugs me that it's possible and I can't figure out how

Share this post


Link to post
Share on other sites

layout (local_size_x = 1, local_size_y = 1) in;

 

This means only one thread out of 32 on NV or 64 on AMD does any work, all other threads are idle.

 

Change to local size of 8 each, so one thread group opereates on 8x8 pixels.

Each thread needs to pick the proper pixel to construct it's ray, the rest of the code probably don't needs much changes.

Share this post


Link to post
Share on other sites
I canged the local size to 8 x 8 and if anything hte performance is worse, is this correct for local size of 8 x 8?
glDispatchCompute((GLuint)SCREENWIDTH, (GLuint)SCREENHEIGHT, 1);

I tested it it with a global size of SCREENWIDTH/8 and SCREENHEIGHT/8 and it runs much faster. It seems that originally I was having 63 inactive shader threads then when I changed the local size to 8x8 i was accidentally drawing 64x the pixels than the screen had.

Share this post


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

  • Advertisement
×

Important Information

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

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!