Смешайте две текстуры с разными координатами и размерами в одном шейдере

У меня есть две текстуры с разными координатами и размеры в моем шейдере фрагмента:

varying highp vec2 v_currentTextureCoords;
varying highp vec2 v_backgroundTextureCoords;
uniform sampler2D u_currentTexture;
uniform sampler2D u_backgroundTexture;

void main()
{
    vec4 currentColor = texture2D(u_currentTexture, v_currentTextureCoords);
    vec4 backgroundColor = texture2D(u_backgroundTexture, v_backgroundTextureCoords);

    gl_FragColor = backgroundColor;
}

Вот соответствующий вершинный шейдер:

attribute vec4 a_position;
attribute vec2 a_currentTextureCoords;
attribute vec2 a_backgroundTextureCoords;
varying vec2 v_currentTextureCoords;
varying vec2 v_backgroundTextureCoords;

void main()
{
    gl_Position = a_position;
    v_currentTextureCoords = a_currentTextureCoords;
    v_backgroundTextureCoords = a_backgroundTextureCoords;
}

Эти шейдеры отвечают за рендеринг u_currentTexture.

EDIT: обновленная запись с моим реальным приложением (Android-приложение) и проблемой.

Как вы можете прочитать выше, две текстуры:

  • u_backgroundTexture: это видеопоток, полный экран, размер 1080x1920.
  • u_currentTexture: это может быть любое изображение размером 469x833 (меньше, но одинаковое соотношение).

Чтобы сделать это простым, на данный момент я не хочу смешивать что-либо, но просто показываю пиксели u_backgroundTexture в шейдерной программе u_currentTexture.

Скриншот приложения - текстура не масштабируется

Как вы можете видеть, отображаемое изображение с шейдерами сверху (верхний левый угол, а не все изображение) совпадает с фоновым изображением, но уменьшено до размера в меньшем прямоугольнике. Это не то, что я хочу.

Я хочу отобразить пиксели, которые находятся "позади" u_currentTexture (те, что у u_backgroundTexture), поэтому в конце никто даже не заметил бы, есть две текстуры.

Но поскольку текстуры имеют разные размеры и координаты, он не дает этого результата вообще (на данный момент это то, что вы видите выше).

Затем в моем шейдере фрагментов мне удалось "масштабировать" текстуру, чтобы изображение в верхнем левом углу имело тот же "зум", что и фоновое изображение:

Скриншот приложения - масштабирование текстуры

Чтобы сделать это, я изменил свой шейдер фрагмента:

varying highp vec2 v_currentTextureCoords;
varying highp vec2 v_backgroundTextureCoords;
uniform sampler2D u_currentTexture;
uniform sampler2D u_backgroundTexture;
uniform vec2 u_scaleRatio; // Notice here

void main()
{
    vec4 currentColor = texture2D(u_currentTexture, v_currentTextureCoords);
    vec4 backgroundColor = texture2D(u_backgroundTexture, v_backgroundTextureCoords * u_scaleRatio); // And here

    gl_FragColor = backgroundColor;
}

Я установил u_scaleRatio в свою программу с помощью glUniform2fv(). Значения в основном (псевдокод):

u_scaleRatio = vec2(currentTextureWidth / backgroundTextureWidth, currentTextureHeight / backgroundTextureHeight);

Как вы можете видеть, он почти работает, но похоже, что на оси X есть offset: рендеринговое изображение в верхнем левом углу - это то, что мы видим в верхнем правом углу... Я не могу найти способ исправить это.

Как я могу изменить свои шейдеры, чтобы исправить это смещение, зная, что текстуры имеют разные размеры и координаты?

ИЗМЕНИТЬ 2:

Чтобы ответить на комментарий ниже, это скриншот с

vec4 backgroundColor = texture2D(u_backgroundTexture, v_currentTextureCoords);

Скриншот приложения

и с:

vec4 backgroundColor = texture2D(u_backgroundTexture, v_currentTextureCoords * u_scaleRatio);

введите описание изображения здесь

EDIT 3:, чтобы ответить на этот ответ, вот скриншот с:

uniform vec2 texelSize; // (1.0/windowResolution.x, 1.0/windowResolution.y)

vec2 uv = gl_FragCoord.xy * texelSize;
vec4 backgroundColor = texture2D(u_backgroundTexture, uv);

Я понимаю, что вы пытаетесь сделать, я думаю, что это сработало бы, если бы координаты точки и текстуры вершин были одинаковыми для обеих текстур, но... они нет. У вас есть идея, как его исправить?

введите описание изображения здесь

Ответ 1

Если я правильно понимаю вашу проблему, вы должны быть в порядке, вычисляя

uniform vec2 texelSize; // (1.0/windowResolution.x, 1.0/windowResolution.y)

vec2 uv = gl_FragCoord.xy * texelSize;
vec4 backgroundColor = texture2D(u_backgroundTexture, uv);

Встроенная переменная gl_FragCoord.xy "содержит значения относительной координаты окна (x, y, z, 1/w) для фрагмента" (https://www.opengl.org/sdk/docs/man/html/gl_FragCoord.xhtml). Поскольку вам в основном нужны координаты текстуры фрагмента, как если бы они были частью полноэкранного квадроцикла, это должно дать ожидаемые результаты. Вы должны только передать относительный размер полноэкранного текселя как единое целое (посмотрите в комментариях для расчета).