Почему все отображается, когда для функции трафарета установлено значение GL_NEVER? [закрыто]C#

Место общения программистов C#
Ответить
Anonymous
 Почему все отображается, когда для функции трафарета установлено значение GL_NEVER? [закрыто]

Сообщение Anonymous »

Информация о версии и оборудовании:
  • Средство рендеринга: ANGLE (Intel, Intel(R) Iris(R) Xe Graphics (0x00009A49) Direct3D11 vs_5_0 ps_5_0, D3D11-31.0.101.5333)
  • Версия: OpenGL ES 3.0.0 (ANGLE 2.1.25606 git hash: cb8b4e1307a9)"
Моя цель — реализовать следующий алгоритм (из этого поста Reddit) на C# с помощью Avalonia Framework OpenGlControlBase: Исходный код. Идея состоит в том, чтобы разместить 3D-объект в левой половине экрана, который я могу вращать и панорамировать. Существует также ползунок, который управляет разрезающей плоскостью. Поперечное сечение объекта, определенное этой плоскостью, должно отображаться с правой стороны, причем область сечения каким-то образом окрашена, а окружающие биты должны быть черными. Результат должен выглядеть примерно так: Результат Видео
Итак, вот моя проблема: левая сторона отображается нормально, но правая сторона представляет для меня проблему. Она не только отображает замаскированное сечение, но и отображает всю область сплошным цветом:
Изображение

Я предполагаю, что буфера трафарета нет, потому что я пишу в него, но при попытке чтения из него я получаю только нули или когда говорю рендереру использовать GL_NEVER в качестве функции трафарета. он по-прежнему отображает все, как будто никакого трафарета не было...
Вот мой код:

Код: Выделить всё

        public override unsafe void OnOpenGlRender(GlInterface GL,
int fb,
PixelSize size,
Vector3 cameraPos,
Quaternion quaternion,
Vector3 pan,
Vector3 cameraUpVector,
float scale
)
{
//int rboId;
//GL.GenRenderbuffers(1, &rboId);
//GL.BindRenderbuffer(GL_RENDERBUFFER, rboId);
//GL.RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, 100, 100);
//GL.BindRenderbuffer(GL_RENDERBUFFER, 0);

//int fboId;
//GL.GenFramebuffers(1, &fboId);
//GL.BindFramebuffer(GL_FRAMEBUFFER, fboId);

//GL.FramebufferRenderbuffer(GL_FRAMEBUFFER,
//                           GL_DEPTH_STENCIL,
//                           GL_RENDERBUFFER,
//                           rboId);

//int status = GL.CheckFramebufferStatus(GL_FRAMEBUFFER);
//bool fboUsed;
//if (status != GL_FRAMEBUFFER_COMPLETE)
//    fboUsed = false;

GL.UseProgram(_shaderProgram);
GL.Viewport(0, 0, size.Width, size.Height);
glUnsafeHelper.StencilMask(0xFFFFFFFF);
GL.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
DrawRegular(GL, size, cameraPos, quaternion, pan, cameraUpVector, scale);
DrawCrossSection(GL, size);

CheckError(GL);
}

private unsafe void DrawRegular(GlInterface GL,
PixelSize size,
Vector3 cameraPos,
Quaternion quaternion,
Vector3 pan,
Vector3 cameraUpVector,
float scale)
{
GL.Enable(GL_DEPTH_TEST);
GL.Enable(GL_BLEND);
glUnsafeHelper.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

GL.Enable(GL_STENCIL_TEST);
glUnsafeHelper.StencilFunc(GL_NEVER, 0, 0);

GL.Viewport(0, 0, size.Width / 2, size.Height);
var projection = Matrix4x4.CreateOrthographic(size.Width * 0.5f, size.Height, 0.01f, 1000);
var projectionLoc = GL.GetUniformLocationString(_shaderProgram, "uProjection");
GL.UniformMatrix4fv(projectionLoc, 1, false, &projection);

var model = Matrix4x4.CreateFromQuaternion(quaternion);
model *= Matrix4x4.CreateTranslation(pan);
model *= Matrix4x4.CreateScale(scale);
var modelLoc = GL.GetUniformLocationString(_shaderProgram, "uModel");
GL.UniformMatrix4fv(modelLoc, 1, false, &model);

var view = Matrix4x4.CreateLookAt(cameraPos, new Vector3(), cameraUpVector);
var viewLoc = GL.GetUniformLocationString(_shaderProgram, "uView");
GL.UniformMatrix4fv(viewLoc, 1, false, &view);

GL.BindVertexArray(_vertexArrayObject);
GL.BindBuffer(GL_ARRAY_BUFFER, _vertexBufferObject);
GL.BindBuffer(GL_ARRAY_BUFFER, _colorBufferObject);
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBufferObject);

GL.DrawElements(GL_TRIANGLES, _indices.Length, GL_UNSIGNED_INT, nint.Zero);

GL.Disable(GL_DEPTH_TEST);
GL.Disable(GL_BLEND);
}

private unsafe void DrawCrossSection(GlInterface GL, PixelSize size)
{
GL.Enable(GL_CULL_FACE);

GL.Viewport(size.Width / 2, 0, size.Width / 2, size.Height);
var projection = Matrix4x4.CreateOrthographic(size.Width * 0.5f, size.Height, 0.01f, 1000);
var projectionLoc = GL.GetUniformLocationString(_shaderProgram, "uProjection");
GL.UniformMatrix4fv(projectionLoc, 1, false, &projection);

var model = Matrix4x4.Identity;
model *= Matrix4x4.CreateScale(10);
var modelLoc = GL.GetUniformLocationString(_shaderProgram, "uModel");
GL.UniformMatrix4fv(modelLoc, 1, false, &model);

var view = Matrix4x4.Identity;
var viewLoc = GL.GetUniformLocationString(_shaderProgram, "uView");
GL.UniformMatrix4fv(viewLoc, 1, false, &view);

GL.Enable(GL_STENCIL_TEST);
glUnsafeHelper.StencilFunc(GL_LEQUAL, 0,  0);

var clipPlaneLoc = GL.GetUniformLocationString(_shaderProgram, "uClipPlane");
glUnsafeHelper.Uniform4f(clipPlaneLoc, clipPlane);

glUnsafeHelper.ColorMask(false, false, false, true);

glUnsafeHelper.StencilOp(GL_INCR, GL_INCR, GL_INCR);
glUnsafeHelper.CullFace(GL_FRONT);
GL.DrawElements(GL_TRIANGLES, _indices.Length, GL_UNSIGNED_INT, nint.Zero);

glUnsafeHelper.StencilOp(GL_DECR, GL_DECR, GL_DECR);
glUnsafeHelper.CullFace(GL_BACK);
GL.DrawElements(GL_TRIANGLES, _indices.Length, GL_UNSIGNED_INT, nint.Zero);

glUnsafeHelper.ColorMask(true, true, true, true);
glUnsafeHelper.StencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glUnsafeHelper.StencilFunc(GL_LEQUAL, 1, 0xFFFFFFFF);

model = Matrix4x4.Identity;
model *= Matrix4x4.CreateScale(10);
GL.UniformMatrix4fv(modelLoc, 1, false, &model);

view = Matrix4x4.Identity;
GL.UniformMatrix4fv(viewLoc, 1, false, &view);

projection = Matrix4x4.Identity;
projectionLoc = GL.GetUniformLocationString(_shaderProgram, "uProjection");
GL.UniformMatrix4fv(projectionLoc, 1, false, &projection);

glUnsafeHelper.Uniform4f(clipPlaneLoc, new Vector4(0, 0, -1, 1000));

GL.BindBuffer(GL_ARRAY_BUFFER, 0);
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
GL.BindVertexArray(0);

var drawModelLoc = GL.GetUniformLocationString(_shaderProgram, "uDrawModel");
GL.Uniform1f(drawModelLoc, 0.0f);

GL.BindVertexArray(_quadVertexArrayObject);
GL.BindBuffer(GL_ARRAY_BUFFER, _quadVertexBufferObject);
GL.BindBuffer(GL_ARRAY_BUFFER, _quadColorBufferObject);
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _quadIndexBufferObject);

GL.DrawElements(GL_TRIANGLES, quadIndices.Length, GL_UNSIGNED_INT, nint.Zero);

GL.Disable(GL_STENCIL_TEST);
GL.Disable(GL_CULL_FACE);
}
Теперь я не понимаю, почему буфер трафарета не применяется и все нормально отображается с правой стороны. Как видите, как только я ожидал, что это будет какая-то проблема с трафаретным буфером, я добавил эти две строки в метод DrawRegular:

Код: Выделить всё

GL.Enable(GL_STENCIL_TEST);
glUnsafeHelper.StencilFunc(GL_NEVER, 0, 0);
Насколько я понимаю, это должно привести к тому, что последующие вызовы элемента рисования ничего не отрисуют и что экран должен быть просто черным/пустым с правой стороны. Поскольку я думаю, что буфер трафарета либо не существует, либо он каким-то образом деактивирован, я провел небольшое исследование, как активировать/добавить его снова. Именно там я наткнулся на этот сайт о FBO: Учебное пособие по объектам фреймбуфера. Я не до конца это понял, но все равно попробовал реализовать. Вот что представляют собой закомментированные строки в методе OnOpenGlRender. Сначала я попытался поместить строки в метод Init, но это тоже не сработало. Когда они в текущем состоянии раскомментированы, экран становится только серым. Я чувствую, что подход с ПФ – это правильный путь для дальнейшего развития, но я действительно не понимаю, что там на самом деле должно произойти. Я думаю, что мне нужно определить новый FBO, который включает трафаретный буфер, в который я могу писать, затем привязаться к этому новому FBO и использовать этот новый кадровый буфер вместо кадрового буфера, предоставляемого системой. Есть какие-нибудь подсказки, почему это не работает?

Подробнее здесь: https://stackoverflow.com/questions/798 ... o-gl-never
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»