GLSL: удаление мертвого кода вызывает визуальные ошибки

У меня было много странных проблем, когда я пытался написать raytracer в шейдере opengl. Я пытаюсь определить, является ли источником ошибки я сам, и часто это так, но я пришел к выводу, что некоторые из этих проблем могут быть просто ошибками в моем графическом драйвере (я нахожусь на ATI). В этих случаях я только что реализовал обходные пути.

Но я столкнулся с чем-то, что я не знаю, как обойти (по крайней мере, без действительно странного кода), тот факт, что я не могу переключить некоторые из моих данных с унифицированных массивов на буферы текстуры, потому что в тот момент, когда я удаляю ссылки на единый массив (который больше ничего не делает; я фактически удалил данные), мой шейдер выглядит так:

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

к этому:

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

И обратите внимание, что перемещение камеры также приводит к хаотичным изменениям того, что вы видите.

Вот метод, который я изменяю, чтобы получить эти результаты: (рассматриваемые строки закомментированы, они обращаются к единому массиву 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;

}

Мне кажется, что это просто проблема компилятора, но если это не так, это здорово, потому что это означает, что я могу это исправить.

Кто-нибудь знает, что может быть причиной этого, каковы мои варианты? Я нахожусь под временным ограничением, поэтому я подумываю просто сделать хак, чтобы заставить это работать (т.е. просто оставить строки или что-то подобное)

1 ответ

Боюсь, это очень похоже на ошибку компилятора шейдера. Равномерный массив должен быть оптимизирован из программы шейдера (если на него нет ссылок где-то еще), независимо от того, закомментированы ли эти строки.

Возможно, стоит проверить униформу (используя glGetActiveUniform) для объекта программы с комментариями и без этих строк.

Также - попробуйте запустить его на другом оборудовании.

Другие вопросы по тегам