2016-12-09 4 views
12

J'ai deux textures avec différentes coordonnéesettailles dans mon shader fragment:Mélanger deux textures avec des coordonnées différentes et tailles dans le même shaders

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

Voici le vertex shader correspondant :

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

Ces shaders sont responsables de la rendu g u_currentTexture.

EDIT: mise à jour post avec ma vraie application (application Android) et le problème.

Comme vous pouvez le lire ci-dessus, les deux textures sont:

  • u_backgroundTexture: il est un flux vidéo, plein écran, la taille est 1080x1920
  • u_currentTexture: il peut être une image, la taille est 469x833 (plus petit mais même ratio).

Pour faire simple, pour l'instant, Je ne veux pas mélanger quoi que ce soit, mais afficher seulement les pixels de u_backgroundTexturedans le programme de shaders de u_currentTexture.

Application Screenshot - Texture not scaled

Comme vous pouvez le voir, l'image rendue avec les shaders ci-dessus (en haut à gauche, et non pas l'image entière), est le même que l'image d'arrière-plan, mais mis à l'échelle pour tenir dans un petit rectangle. Ce n'est pas ce que je veux.

Je veux affichage des pixels qui sont « derrière » u_currentTexture (ceux de u_backgroundTexture), alors à la fin, on ne remarquerez même pas il y a deux textures.

Mais puisque les textures ont différentes tailles et coordonne, il ne donne pas ce résultat du tout (pour l'instant, c'est ce que vous voyez ci-dessus).

Puis, dans mon fragment shader, j'ai réussi à "échelle" la texture que l'image dans le coin supérieur gauche a le même "zoom" que l'image de fond:

Application Screenshot - Texture scaled

Pour faire cela, je modifié mon fragment shader:

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

Je mis u_scaleRatio dans mon programme avec glUniform2fv().Les valeurs sont essentiellement (pseudo-code):

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

Comme vous pouvez le voir, il est presque travail, mais il semble qu'il y ait un décalage sur l'axe X: l'image rendue dans la partie supérieure gauche coin est en fait ce que nous voyons dans le haut droite coin ... Je ne peux pas trouver un moyen de le corriger.

Comment puis-je modifier mes shaders pour pouvoir corriger ce décalage, sachant que les textures ont des tailles et des coordonnées différentes?

EDIT 2:

Pour répondre à un commentaire ci-dessous, ceci est une capture d'écran avec

vec4 backgroundColor = texture2D(u_backgroundTexture, v_currentTextureCoords); 

Application screenshot

et avec:

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

enter image description here

EDIT 3: de répondre à this answer, voici une capture d'écran avec:

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

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

Je comprends ce que vous essayez de faire, je pense qu'il aurait travaillé si les coordonnées de position de sommet et la texture étaient la même chose pour les deux textures mais ... elles ne le sont pas. Avez-vous une idée de comment le réparer?

enter image description here

+1

Vous pouvez publier votre résultat avec des textures de tailles différentes. – eldo

+1

Je ne pense pas que votre fragment shader vous donne des couleurs correctes. Le résultat de la multiplication de la couleur rouge et bleue est la couleur noire. 'vec4 (1, 0, 0, 1) * vec4 (0, 0, 1, 1) = vec4 (0, 0, 0, 1)' Vous devriez utiliser une autre méthode de mélange comme la fonction 'mix'. – MarGenDo

+0

@eldo J'ai ajouté plus d'explications et une capture d'écran dans mon post original. – GuiTeK

Répondre

0

Si je comprends bien votre problème, vous devriez être bien en calculant

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

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

La variable intégrée gl_FragCoord.xy« contient la fenêtre de coordonnées relatives (x, y, z, 1/w) les valeurs pour le fragment " (https://www.opengl.org/sdk/docs/man/html/gl_FragCoord.xhtml). Puisque vous avez besoin des coordonnées de texture du fragment comme si elles faisaient partie d'un quad complet, cela devrait vous donner les résultats attendus. Il suffit de passer la taille relative d'un texel en plein écran (regardez dans la partie commentée pour le calcul).

+0

Je comprends ce que vous essayez de faire, je pense que cela aurait fonctionné si la position du vertex et les coordonnées de texture étaient les mêmes pour les deux textures mais ... elles ne le sont pas. Avez-vous une idée de comment le réparer? PS: J'ai mis à jour mon post original avec capture d'écran. – GuiTeK

+0

Pouvez-vous poster du code comment exactement vous avez mis en œuvre ma suggestion? –

+0

C'est exactement le même code que j'ai posté dans mon article original sauf que j'ai ajouté 'uniform vec2 texelSize;', 'vec2 uv = gl_FragCoord.xy * texelSize;' et remplacé la ligne 'vec4 backgroundColor = ...' par le vôtre. Bien sûr, j'ai défini 'texelSize' avec' GLES20.glUniform2fv (mTexelSizeUniformLocation, 1, mTexelSize, 0); ',' mTexelSize' étant un tableau 'float' de 2 éléments. – GuiTeK