Невозможно применить смешивание к кубу, расположенному за полупрозрачной текстурированной поверхностью

#c #opengl #shader #textures #blending

#c #opengl #шейдер #Текстуры #смешивание

Вопрос:

Следуя руководству из learnopengl.com о рендеринге полупрозрачных стекол Windows с помощью наложения я попытался применить этот принцип к моей простой сцене (где мы можем перемещаться по сцене с помощью мыши), содержащей:

  • Куб: 6 граней, каждая из которых имеет 2 треугольника, построенных с использованием двух атрибутов (положение и цвет), определенных в связанном с ним вершинном шейдере и переданных его фрагментному шейдеру.
  • Grass: 2D-поверхность (два треугольника), к которой была применена текстура png с использованием sampler2D uniform (фон изображения png прозрачный).
  • Окно: полупрозрачная 2D-поверхность, основанная на тех же шейдерах (вершина и фрагмент), что и трава выше. Обе текстуры были загружены с learnopengl.com

Проблема, с которой я сталкиваюсь, заключается в том, что когда дело доходит до травы, я вижу ее через окно, но не куб!

скриншот

Мой код структурирован следующим образом (я специально оставил рендеринг окна до самого последнего):

 // enable depth test amp; blending
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA);

while (true):
  glClearColor(background.r, background.g, background.b, background.a);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  cube.draw();
  grass.draw();
  window.draw();
 

Редактировать: я поделюсь ниже шейдерами вершин и фрагментов, используемыми для рисования двух текстурированных поверхностей (трава и окно):

 #version 130

in vec2 position;
in vec2 texture_coord;
// opengl tranformation matrices
uniform mat4 model;      // object coord -> world coord
uniform mat4 view;       // world coord  -> camera coord
uniform mat4 projection; // camera coord -> ndc coord
out vec2 texture_coord_vert;

void main() {
  gl_Position = projection * view * model * vec4(position, 0.0, 1.0);
  texture_coord_vert = texture_coord;
}

 
 #version 130
in vec2 texture_coord_vert;
uniform sampler2D texture2d;
out vec4 color_out;

void main() {
  vec4 color = texture(texture2d, texture_coord_vert);
  // manage transparency
  if (color.a == 0.0)
    discard;
  color_out = color;
}
 

И те, которые использовались для рендеринга цветного куба:

 #version 130

in vec3 position;
in vec3 color;
// opengl tranformation matrices
uniform mat4 model;      // object coord -> world coord
uniform mat4 view;       // world coord  -> camera coord
uniform mat4 projection; // camera coord -> ndc coord
out vec3 color_vert;

void main() {
  gl_Position = projection * view * model * vec4(position, 1.0);
  color_vert = color;
}
 
 #version 130

in vec3 color_vert;
out vec4 color_out;

void main() {
  color_out = vec4(color_vert, 1.0);
}
 

P.S: В моих шейдерных программах используется GLSL версии v1.30, потому что мой внутренний графический процессор, похоже, не поддерживает более поздние версии.

Что касается фрагмента кода, который выполняет фактический чертеж, у меня в основном есть один экземпляр Renderer класса для каждого типа геометрии (один общий для обеих текстурированных поверхностей и один для куба). Этот класс управляет созданием / привязкой / удалением VAO и привязкой / удалением VBO (создание VBO, созданных вне класса, чтобы я мог делиться вершинами с похожими формами). Его конструктор принимает в качестве аргумента программу шейдеров и атрибуты вершин. Я постараюсь показать соответствующий фрагмент кода ниже

 Renderer::Renderer(Program program, vector attributes) {
  vao.bind();
  vbo.bind();

  define_attributes(attributes);

  vao.unbind();
  vbo.unbind();
}

Renderer::draw(Uniforms uniforms) {
  vao.bind();
  program.use();

  set_uniforms(unfiorms);
  glDrawArrays(GL_TRIANGLES, 0, n_vertexes);

  vao.unbind();
  program.unuse();
}
 

Комментарии:

1. Нет, трава видна через окно, это куб, который не виден через окно. Пожалуйста, взгляните на мое редактирование, я добавил свои программы для шейдеров и более подробно о том, как выполняется рендеринг @Rabbid76

Ответ №1:

Ваша функция функции смешивания зависит от целевого альфа-канала ( GL_ONE_MINUS_DST_ALPHA ):

 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA);
 
 dest = src * src_alpha   dest * (1-dest_alpha) 
 

Если альфа-канал куба равен 0.0, цвет куба не смешивается с цветом окна.

Традиционная функция альфа-смешивания зависит только от исходного альфа-канала:

 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
 dest = src * src_alpha   dest * (1-src_alpha) 
 

См. Также glBlendFunc и Смешивание

Комментарии:

1. Большое спасибо, я был недостаточно осторожен. На самом деле это объясняет, почему в середине grass поверхности у меня была область с тем же цветом, window что и, из-за того, что эти пиксели были полностью непрозрачными в текстурном изображении назначения.