GLSL: удаление мертвого кода вызывает визуальные ошибки
У меня было много странных проблем, когда я пытался написать raytracer в шейдере opengl. Я пытаюсь определить, является ли источником ошибки я сам, и часто это так, но я пришел к выводу, что некоторые из этих проблем могут быть просто ошибками в моем графическом драйвере (я нахожусь на ATI). В этих случаях я только что реализовал обходные пути.
Но я столкнулся с чем-то, что я не знаю, как обойти (по крайней мере, без действительно странного кода), тот факт, что я не могу переключить некоторые из моих данных с унифицированных массивов на буферы текстуры, потому что в тот момент, когда я удаляю ссылки на единый массив (который больше ничего не делает; я фактически удалил данные), мой шейдер выглядит так:
к этому:
И обратите внимание, что перемещение камеры также приводит к хаотичным изменениям того, что вы видите.
Вот метод, который я изменяю, чтобы получить эти результаты: (рассматриваемые строки закомментированы, они обращаются к единому массиву 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) для объекта программы с комментариями и без этих строк.
Также - попробуйте запустить его на другом оборудовании.