Z-борьба по непересекающимся граням треугольника

У меня есть программа OpenGL, которая демонстрирует необычные z-боевые действия, и я не понимаю причины этого. Кажется, большинство боевых действий начинаются по краям треугольников.

Два объекта в упрощенном тестовом примере не пересекаются, как показано ниже. Я убедился, что значения z-near и z-far являются разумными (1 и 100 соответственно). Оба объекта находятся примерно в 2 единицах от начала координат, а камера на показанных изображениях удалена примерно на 10 единиц.

Никаких изменений в настройках глубины OpenGL по умолчанию не было сделано, за исключением того, что было включено тестирование глубины.

Вершинные и фрагментные шейдеры сделаны максимально простыми.

Это использование OpenTK. Я попытался явно создать окно с 32-битным буфером глубины, но это также не дало никакого эффекта.

Я изучил все четыре вопроса, перечисленные в часто задаваемых вопросах по OpenGL. Требования к буферизации глубины.

Отключение проверки глубины устраняет конфликты, оставляя объекты перекрывающимися в порядке отрисовки. В программе не используется отбраковка или трафарет.

Существуют ли какие-либо другие вероятные причины такого рода z-борьбы?

z-fightingНе перекрывается

Матрица вершин создается следующим образом:

Matrix4 transform_matrix;
Matrix4.CreatePerspectiveFieldOfView((float) (45 * Math.PI / 180), aspect_ratio, 1, 100, out transform_matrix);
transform_matrix = Matrix4.Mult(transform_matrix, CameraMatrix);

и CameraMatrix является результатом этого метода:

public void TransformMatrix(out Matrix4 m)
{
    var t = Matrix4.Identity;
    t.Column3 = new Vector4(Offset);

    var rx = Matrix4.Identity;
    var sine_x = (float) Math.Sin(-RotationX * Math.PI / 180);
    var cos_x = (float) Math.Cos(-RotationX * Math.PI / 180);
    rx.Row1 = new Vector4(0, cos_x, -sine_x, 0);
    rx.Row2 = new Vector4(0, sine_x, cos_x, 0);

    var ry = Matrix4.Identity;
    var sine_y = (float) Math.Sin(-RotationY * Math.PI / 180);
    var cos_y = (float) Math.Cos(-RotationY * Math.PI / 180);
    ry.Row0 = new Vector4(cos_y, 0, sine_y, 0);
    ry.Row2 = new Vector4(-sine_y, 0, cos_y, 0);

    var n = Matrix4.Mult(rx, t);
    n = Matrix4.Mult(ry, n);

    m = n;
}

Обновлять

Это происходит только на карте NVIDIA. Протестировал с Интелом, проблем не было.


person metatheorem    schedule 02.03.2014    source источник
comment
Для меня это не похоже на z-файтинг. Попробуйте отладить матрицу проекции.   -  person concept3d    schedule 02.03.2014


Ответы (1)


Это совсем не похоже на z-файтинг. Это дикая догадка, но действительно ли ваша программа использует аппаратное ускорение? Известно, что программный рендерер Microsoft создает подобные повреждения.

Предложения:

  1. Убедитесь, что GL.GetString(StringName.Renderer) не "Microsoft GDI Renderer", так как это указывает на ускорение программного обеспечения.
  2. Попробуйте запросить 24-битный буфер глубины, а не 32-битный, поскольку последний не поддерживается графическими процессорами.
  3. Дважды проверьте биты буфера глубины через Context.GraphicsMode.Depth. По умолчанию 16 бит.

Что происходит, когда вы запрашиваете 32-битную версию, зависит от используемой вами версии OpenTK. OpenTK 1.0 вернется к программному ускорению для неподдерживаемых режимов (например, 32-битных буферов глубины). OpenTK 1.1 приложит все усилия, чтобы дать вам соответствующий GraphicsMode, и вернется к программному ускорению только в крайнем случае.

person The Fiddler    schedule 02.03.2014
comment
32-битные буферы глубины поддерживаются графическими процессорами. Однако многие ICD в Windows не предоставляют формат пикселей для буфера кадра по умолчанию, который имеет 32-битный буфер глубины. Другими словами, вам часто приходится использовать FBO, чтобы получить доступ к 32-битному формату глубины. - person Andon M. Coleman; 02.03.2014
comment
Определенно не первый, так как я тестирую это на Linux. Рендерер GeForce GTX 560/PCIe/SSE2. По умолчанию глубина 24 бита. - person metatheorem; 02.03.2014
comment
Это выглядит очень странно. Можете ли вы загрузить тестовый проект куда-нибудь? - person The Fiddler; 05.03.2014