Масштабирование текстуры видео, смешанной с текстурой изображения

Я пробовал искать, и это тривиальная вещь, но я не могу понять это, я просмотрел много ответов, но никогда не отвечал на то, что мне нужно, с полными рабочими примерами.

Я пытаюсь масштабировать текстуру видео во фрагментном шейдере с текстурой изображения на заднем плане. Так что не могу преобразовать вершину. Размер видеотекстуры необходимо изменить до 200 x 200 и расположить в верхнем или нижнем углу.

В конечном итоге он будет использовать MediaStream для веб-камеры с эффектом прозрачного фона. Он работает с bodypix поверх текстуры изображения, используя смешанный шейдер, но необходимо масштабировать видео, чтобы оно не растягивалось до области просмотра.

Если я попробую vec2 из vec2 (200 200), Clamp растянет остальные цвета. Повторите плитку. Ни один из них не является ожидаемым результатом.

Jsfiddle рендеринга видео, но нужно изменить его размер.

https://jsfiddle.net/danrossi303/or3dk2q4/16/

Базовый фрагментный шейдер, с которым я работаю.

  precision mediump float;

 uniform sampler2D background;
 uniform sampler2D frame;

uniform float texWidth;
uniform float texHeight;


void main(void) {
vec2 texCoord = gl_FragCoord.xy / vec2(texWidth,texHeight);

vec4 texel0 = texture2D(background, texCoord);
vec4 texel1 = texture2D(frame, texCoord);
 gl_FragColor = mix(texel0, texel1, 1.);
}

person Dan Rossi    schedule 24.06.2021    source источник


Ответы (1)


Вам нужно масштабировать координаты текстуры для видео:

vec2 frameuv = texCoord * vec2(texWidth, texHeight) / vec2(200.0, 200.0);
vec4 texel1 = texture2D(frame, frameuv);

Отбросить кадр (texel1), если frameuv.x или frameuv.y больше 1,0 (см. step):

float w = step(frameuv.x, 1.0) * step(frameuv.y, 1.0);
gl_FragColor = mix(texel0, texel1, w);

Полный фрагментный шейдер:

precision mediump float;
  
uniform sampler2D background;
uniform sampler2D frame;

uniform float texWidth;
uniform float texHeight;

void main(void) {
    vec2 texCoord = gl_FragCoord.xy / vec2(texWidth,texHeight);
   
    vec4 texel0 = texture2D(background, texCoord);
    vec2 frameuv = texCoord * vec2(texWidth, texHeight) / vec2(200.0, 200.0);
    vec4 texel1 = texture2D(frame, frameuv);
    gl_FragColor = mix(texel0, texel1, step(frameuv.x, 1.0) * step(frameuv.y, 1.0));
}

Кроме того, есть ошибка при загрузке фоновой текстуры. gl.bindTexture привязывает объект текстуры к текущему текстурному блоку. Поэтому блок текстуры должен быть установлен с помощью gl.activeTexture перед вызовом gl.bindTexture:

img.onload = () => {
    gl.activeTexture(gl.TEXTURE0);            // <---
    gl.bindTexture(gl.TEXTURE_2D, texture);
    initBackgroundTexture();
};
img.src = "https://videos.electroteque.org/textures/virtualbg.jpg"; 
person Rabbid76    schedule 24.06.2021