3

I've been having a lot of strange problem's while trying to write a raytracer in an opengl shader. I try to determine if the source of the error is myself, and often this is the case, but I've come to the conclusion that some of these problems may just be bugs in my graphics driver (I'm on ATI). In these cases, I've just implemented workarounds.

But I just ran into something I'm not sure how to work around (At least without really weird code), the fact that I can't switch over some of my data from uniform arrays to texture buffers, because the moment I delete the references to the uniform array (which doesn't do anything anymore; I've removed any actual usage of the data), my shader goes from looking like this:

https://dl.dropboxusercontent.com/u/39921754/bug_pic_0.png

to this:

https://dl.dropboxusercontent.com/u/39921754/bug_pic_1.png

And note that moving the camera causes what you see to change erratically as well.

Here is the method I'm changing to get these results: (the lines in question are commented out, they access the uniform array quad_vertex_indices)

bool Collide_KDTree(Ray ray, out Surface surface)
{
float t_entry, t_exit;

if(!RayBox(ray.tail, ray.head, scene_bounds.position, scene_bounds.extent, t_entry, t_exit))
    return false;

uint node_indices[TREE_DEPTH];
float node_exits[TREE_DEPTH];

uint top= 0;

node_indices[top]= kd_nodes.length()- 1;
node_exits[top++]= t_exit;

while(top> 0)
{
    uint node_index_foo= node_indices[top- 1];
    KDNode node= kd_nodes[node_indices[top- 1]];
    t_exit= node_exits[top- 1];
    top--;

    if(node.node_type== NodeType_Parent)
    {
        uint near_index, far_index;

        if(ray.tail[node.split_axis] < node.split)
        {
            near_index=  node.left_index_or_offset+ 1;
            far_index= node.right_index_or_count+ 1;
        }
        else
        {
            near_index=  node.right_index_or_count+ 1;
            far_index= node.left_index_or_offset+ 1;
        }

        float t_intersection;

        RayAxisAlignedPlane(ray.tail, ray.head, node.split_axis, node.split, t_intersection);

        if(t_intersection> t_exit)
        {
            node_indices[top]= near_index;
            node_exits[top++]= t_exit;
        }
        else if(t_intersection< t_entry)
        {
            if(t_intersection< 0)
            {
                node_indices[top]= near_index;
                node_exits[top++]= t_exit;
            }
            else
            {
                node_indices[top]= far_index;
                node_exits[top++]= t_exit;
            }
        }
        else if(t_intersection> t_entry && t_intersection< t_exit)
        {
            if(t_intersection< 0)
            {
                node_indices[top]= near_index;
                node_exits[top++]= t_exit;
            }
            else
            {
                node_indices[top]= far_index;
                node_exits[top++]= t_exit;

                node_indices[top]= near_index;
                node_exits[top++]= t_intersection;
            }
        }
    }
    else
    {
        float shortest_distance= INFINITY;
        bool collision_detected= false;

        uint primitive_offset= node.left_index_or_offset;
        uint primitive_count= node.right_index_or_count;

        for(uint i= primitive_offset; i< (primitive_offset+ primitive_count); i++)
        {
            uint primitive_index= primitive_indices[i];

            if(primitive_index< QUAD_COUNT)
            {
                uint quad_index= primitive_index;

                vec3 intersection;

                //uint foo0= quad_vertex_indices[quad_index* 4+ 0];
                //uint foo1= quad_vertex_indices[quad_index* 4+ 1];
                //uint foo2= quad_vertex_indices[quad_index* 4+ 2];
                //uint foo3= quad_vertex_indices[quad_index* 4+ 3];

                vec3 vertex0= vertices[texelFetch(test_texture_buffer, int(quad_index* 4+ 0)).r];
                vec3 vertex1= vertices[texelFetch(test_texture_buffer, int(quad_index* 4+ 1)).r];
                vec3 vertex2= vertices[texelFetch(test_texture_buffer, int(quad_index* 4+ 2)).r];
                vec3 vertex3= vertices[texelFetch(test_texture_buffer, int(quad_index* 4+ 3)).r];

                if(RayQuad(ray.tail, ray.head, vertex0, vertex1, vertex2, vertex3, quad_normals[quad_index], intersection))
                {
                    float this_distance= distance(ray.tail, intersection);

                    if(this_distance< shortest_distance)
                    {
                        surface.position= intersection;
                        surface.normal= quad_normals[quad_index];
                        surface.material= materials[quad_material_indices[quad_index]];

                        shortest_distance= this_distance;
                        collision_detected= true;
                    }
                }
            }
            else
            {
                uint sphere_index= primitive_index- QUAD_COUNT;

                vec3 intersection;

                if(RaySphere(ray.tail, ray.head, spheres[sphere_index].position, spheres[sphere_index].radius, intersection))
                {
                    float this_distance= distance(ray.tail, intersection);

                    if(this_distance< shortest_distance)
                    {
                        surface.position= intersection;
                        surface.normal= normalize(intersection- spheres[sphere_index].position);
                        surface.material= materials[sphere_material_indices[sphere_index]];

                        shortest_distance= this_distance;
                        collision_detected= true;
                    }
                }
            }
        }

        if(collision_detected && (shortest_distance/ length(ray.head))< t_exit)
            return true;

        t_entry= t_exit;
    }
}

return false;

}

It seems to the me that this is simply a compiler issue, but if it isn't, that's great, because it means I can fix it.

Does anyone know what could be causing this, what my options are? I'm under time constraints so I'm considering just doing a hack to get this to work (i.e. just leave the lines in, or something similar)

datenwolf
  • 159,371
  • 13
  • 185
  • 298
user2345397
  • 301
  • 1
  • 11
  • make sure you initialize variables to some default values. In NVidia drivers I had my shader going mad printing to pixels weird stuff because I had some variables not initialized.Maybe your case suffers from the same issue. – Michael IV May 03 '13 at 18:10

1 Answers1

2

I'm afraid it does look very much like a shader compiler error. The uniform array should be optimized out of the shader program (unless it is referenced somewhere else) whether or not those lines are commented out.

It might be worth checking the uniforms (using glGetActiveUniform) for the program object with and without those lines commented.

Also - try running it on different hardware.

GuyRT
  • 2,919
  • 13
  • 8
  • 1
    I didn't know about glGetActiveUniform, thanks. I had some others run it and it appears that my uniform array sizes were way too large. (Although that IS why I'm trying to switch over to different memory). This was easy to determine because these other compilers were spitting out useful information, including line numbers, and the actual words "arrays are too large", not to mention refusing to compile the shader (nvidia cards it appears). I'm now fairly certain my problems were related to having huge uniform arrays and a compiler that was accepting it and then going beserk during execution. – user2345397 May 07 '13 at 03:13
  • @user2345397 you should create an answer to your own question now that you found the solution to your problem – Jules G.M. Aug 05 '13 at 18:15
  • Unfortunately I can not meaningfully explain the connection between my errors and the problems observed so I don't think I can call what I did to fix (or rather what I did that happened to fix) the problems observed could be called a legitimate answer. – user2345397 Aug 11 '13 at 00:43