2016-12-09 6 views
12

У меня есть две текстуры с различными координатамииразмеры в моем пиксельный шейдер:Смешать две текстуры с различными координатами и размерами в одном шейдере

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; 
} 

Эти шейдеры несут ответственность за renderin g u_currentTexture.

EDIT: обновленный пост с моим настоящим приложением (приложение для Android) и проблема.

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

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

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

Application Screenshot - Texture not scaled

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

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

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

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

Application Screenshot - Texture scaled

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

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: тонированное изображение в верхнем покинул угол на самом деле то, что мы видим в верхней части right corner ... Я не могу найти способ исправить его.

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

EDIT 2:

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

vec4 backgroundColor = texture2D(u_backgroundTexture, v_currentTextureCoords); 

Application screenshot

и с:

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

enter image description here

EDIT 3: ответить на this answer, вот скриншот с:

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

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

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

enter image description here

+1

Вы можете опубликовать свой результат с помощью различных текстур. – eldo

+1

Я не думаю, что ваш фрагментарный шейдер дает вам правильные цвета. Результатом умножения красного и синего цвета является черный цвет. 'vec4 (1, 0, 0, 1) * vec4 (0, 0, 1, 1) = vec4 (0, 0, 0, 1)' Вам следует использовать другой метод смешивания, такой как 'mix'. – MarGenDo

+0

@eldo Я добавил больше объяснений и скриншотов в своем оригинальном посте. – GuiTeK

ответ

0

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

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«содержит окно относительные координаты (х, у, г, 1/w) для фрагмента « (https://www.opengl.org/sdk/docs/man/html/gl_FragCoord.xhtml). Поскольку вам в основном нужны координаты текстуры фрагмента, как если бы они были частью полноэкранного квадроцикла, это должно дать ожидаемые результаты. Вы должны только передать относительный размер полноэкранного текселя как единое целое (посмотрите в комментариях для расчета).

+0

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

+0

Можете ли вы опубликовать некоторый код, как именно вы внедрили мое предложение? –

+0

Это тот же самый код, который я опубликовал в своем исходном сообщении, но я добавил 'равномерное vec2 texelSize;', 'vec2 uv = gl_FragCoord.xy * texelSize;' и заменил строку 'vec4 backgroundColor = ...' вашей. Конечно, я установил 'texelSize' с' GLES20.glUniform2fv (mTexelSizeUniformLocation, 1, mTexelSize, 0); ',' mTexelSize' является массивом 'float' из 2 элементов. – GuiTeK