ОРИГИНАЛ:
Я спрашивал об этом раньше, но мой первоначальный пример был немного неполным, и я думаю, что теперь могу более конкретно рассказать о своей проблеме.
Для контекста я использую openGL 3.3 на старом компьютере Apple Mac и пытаюсь визуализировать перекрывающиеся слои четырехугольников. Каждый четырехугольник отображается на кусок текстуры png 4096 x 4096, который имеет области полной прозрачности.
Я хочу использовать альфа-смешивание, чтобы прозрачные части слоя N открывали непрозрачные части слоя N-1 (позади него). Поскольку мне не нужна полупрозрачность, я хотел бы знать - есть ли способ настроить glBlendFuncSeparate
так, чтобы цвет фрагмента был просто самым непрозрачным текселем на переднем плане - дополнительное умножение не требуется?
Я пробовал что-то вроде этого:
glBlendFuncSeparate(GL_SRC_COLOR, GL_DST_COLOR, GL_ONE, GL_ZERO);
но я думаю, что совершенно неправильно понимаю значение параметров. Я думал, они имели в виду: сохранить исходный цвет и установить его в качестве цвета назначения ... применить исходный альфа-канал. (Я знаю, что это абсолютно неправильно).
Первоначально я думал, что это вопрос xyz, и искал другие причины, по которым я замечаю проблемы с производительностью, но даже несмотря на то, что приведенный выше вызов функции приводит к совершенно неправильным цветам, моя анимация работает плавно даже в привет-треугольнике + sin (время ) перевод дела.
Я бы опубликовал часть своего кода, но он в основном состоит из настройки буферов вершин и объявлений больших статических массивов для тестирования. Мои шейдеры в основном сквозные: (например, основная функция в моем фрагментном шейдере :)
void main(void)
{
vec4 texel = texture(tex0, v_uv);
color = vec4(texel.rgb, texel.a);
}
и текстуры загружаются правильно. Я настроил рендеринг сзади наперед.
Как мне настроить такой рендеринг?
Заранее спасибо.
ОБНОВЛЕНИЕ:
Я пытался:
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ONE);
glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);
но появляется только передний слой с непрозрачным белым для его прозрачности. Я проверил значения RGBA, и похоже, что прозрачные секции имеют размер [1.0, 1.0, 1.0, 0.0], поэтому похоже, что мне нужно игнорировать цвет, когда альфа равен 0.0, даже если цвет не [0.0, 0.0, 0.0, а]. Чтобы смоделировать это, я добавил оператор if (alpha is 0.0), then discard;
, но затем задержка вернулась.
Значит, функции не совсем правильные, или что-то еще не так.
Для получения дополнительной информации о моей настройке:
(Свою большую текстуру выложил внизу)
Данные вершин и индексов для каждого слоя были бы слишком длинными для публикации, но на каждый из пяти слоев приходится по три квадрата (я передаю положение камеры шейдеру и использую значение положения по оси Z для смещений). Это может быть отдельным источником неэффективности.
Полный фрагментный и вершинный шейдеры:
// вершина
#version 330 core
precision highp float;
layout (location = 0) in vec3 a_position;
layout (location = 1) in vec2 a_uv;
out vec2 v_uv;
uniform mat4 u_matrix;
uniform float u_aspect;
uniform vec3 u_position_cam;
uniform int u_count_layers;
void main(void)
{
// scroll speed depends on the inverse of the z position
float speed_factor = (1.0 / pow(2.0, u_count_layers - a_position.z));
// x offset
float X = -u_position_cam.x * speed_factor;
// make sure the bg quad jumps back to the correct position
X = mod(X, (u_aspect) * 2.0);
X += a_position.x;
// y offset
float Y = -clamp(u_position_cam.y, 0.0, 2.0) * speed_factor;
Y += a_position.y;
gl_Position = u_matrix * vec4(X, Y, a_position.z, 1.0);
v_uv = a_uv;
}
// фрагмент
#version 330 core
precision highp float;
in vec2 v_uv;
uniform sampler2D tex0;
out vec4 color;
void main(void)
{
vec4 texel = texture(tex0, v_uv);
color = vec4(texel);
}
В этом в основном нерешенном вопросе о переполнении стека обсуждается проблема. Я испытываю ... короче говоря, многие перекрывающиеся прозрачные формы вызывают задержку, но если одни и те же формы не перекрываются, тогда все в порядке. Конечно, альтернативного алгоритма смешивания пока не найдено.
Подумайте о цифрах - каждая секция текстуры покрывает 1280 x 720 пикселей. Всего 5 слоев по 3 четверки в каждом. Для каждого пикселя я проделываю одну и ту же работу N слоев раз, так что 4 608 000? Думаю, это может быть слишком дорого. Я также делаю странные арифметические операции по модулю и смещения. Если способ, которым я пытаюсь добиться прокрутки с параллаксом, слишком неуклюж, то как это можно сделать эффективно? Я готов изменить свой алгоритм / настройку, если определенно есть лучший способ сделать это. Мне любопытно, как правильно настроить текстуры и прозрачные слои, чтобы избежать проблем, с которыми я сталкиваюсь.
Мысль: а что если рендерить спереди назад? Как бы изменились функции наложения? (Я знаю, что вы обычно визуализируете прозрачные объекты сзади наперед, но здесь мне просто нужно перестать проверять слои, как только я выберу один с альфа == 1.0).