#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
что и, из-за того, что эти пиксели были полностью непрозрачными в текстурном изображении назначения.