2011-02-23 34 views
16

he implementado en OpenGL enmascaramiento de acuerdo con el siguiente concepto:OpenGL - máscara con múltiples texturas

  • La máscara está compuesta por los colores blanco y negro.
  • Una textura de primer plano solo debe estar visible en las partes blancas de la máscara.
  • Una textura de fondo solo debe verse en las partes negras de la máscara.

Puedo hacer la parte blanca o de la obra parte negro como supone el uso de glBlendFunc(), pero no los dos al mismo tiempo, debido a que la capa de primer plano no sólo las mezclas sobre la máscara, sino también sobre el fondo capa.

¿Hay alguien que sepa cómo lograr esto de la mejor manera? He estado buscando en la red y he leído algo sobre los sombreadores de fragmentos. ¿Es este el camino a seguir?

+0

Sé que hay una manera de hacer esto, estoy bastante seguro de que es una función simple de 'máscara', pero han pasado * años * desde la última vez que utilicé OpenGL. ¿Has visto: http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=20 – Crisfole

+0

Gracias por la respuesta rápida. Sí, mi implementación se basa en ese tutorial y funciona para una máscara con una textura, pero cuando utilizo dos texturas para una máscara como se describió anteriormente, el resultado no es el esperado: los colores de la imagen de primer plano también se combinan en la capa de fondo de la máscara solo. ¿Debo publicar una captura de pantalla para ilustrar mi problema? – red

+0

Es una tarea muy básica (simple) para un sombreador de fragmentos. Sin embargo, no puedo indicarle una solución de función fija adecuada. – kvark

Respuesta

37

esto debería funcionar:

glEnable(GL_BLEND); 
// Use a simple blendfunc for drawing the background 
glBlendFunc(GL_ONE, GL_ZERO); 
// Draw entire background without masking 
drawQuad(backgroundTexture); 
// Next, we want a blendfunc that doesn't change the color of any pixels, 
// but rather replaces the framebuffer alpha values with values based 
// on the whiteness of the mask. In other words, if a pixel is white in the mask, 
// then the corresponding framebuffer pixel's alpha will be set to 1. 
glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ZERO); 
// Now "draw" the mask (again, this doesn't produce a visible result, it just 
// changes the alpha values in the framebuffer) 
drawQuad(maskTexture); 
// Finally, we want a blendfunc that makes the foreground visible only in 
// areas with high alpha. 
glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA); 
drawQuad(foregroundTexture); 

esto es bastante complicado, así que dime si algo no está claro.

No olvide request an alpha buffer al crear el contexto GL. De lo contrario, es posible obtener un contexto sin un buffer alfa.

Editar: Aquí, hice una ilustración. illustration

Editar: Después de haber escrito esta respuesta, he aprendido que hay mejores maneras de hacer esto:

  • Si usted está limitado a la tubería de función fija de OpenGL, utilice entornos textura
  • Si puede usar sombreadores, use un sombreador de fragmentos.

La forma descrita en esta respuesta funciona y no es particularmente peor en rendimiento que estas 2 mejores opciones, pero es menos elegante y menos flexible.

+0

Gracias Stefan! ¡No podría desear una mejor respuesta! En mi implementación, reemplacé glBlendFunc (GL_SRC_COLOR, GL_ZERO) con glBlendFuncSeparate y ahora funciona. Así que mi error fue que glBlendFunc inmediatamente reemplaza los colores. – red

+0

¿Hay alguna manera de hacerlo sin llamar a glBlendFuncSeparate? Causa segfaults con mi tarjeta gráfica cuando puse esa línea. – Skyler

+0

¿Qué hace drawQuad? – jjxtra

Cuestiones relacionadas