2010-04-06 14 views
20

Estoy haciendo fundido de rayos en el sombreador de fragmentos. Puedo pensar en un par de formas de dibujar un quad de pantalla completa para este propósito. Dibuje un cuadrante en el espacio del clip con la matriz de proyección establecida en la matriz de identidad, o use el sombreador de geometría para convertir un punto en una franja triangular. El primero usa el modo inmediato, obsoleto en OpenGL 3.2. Lo último lo utilizo por novedad, pero todavía usa el modo inmediato para dibujar un punto.¿Cuál es la mejor manera de dibujar un quad de pantalla completa en OpenGL 3.2?

+3

La geometría shader para generar un quad desde unos sonidos puntuales como overkill si solo necesitas un solo quad. Solo dibuja dos triángulos o una franja triangular. Esos cuatro vértices no te harán daño, al menos no tan duro como un sombreador de geometría especial para algo tan simple. –

Respuesta

16

Puede enviar dos triángulos creando un quad, con sus atributos de vértice establecidos en -1/1 respectivamente.

No necesita multiplicarlos con ninguna matriz en el sombreado de vértices/fragmentos.

Éstos son algunos ejemplos de código, simple como es :)

Vertex Shader:

const vec2 madd=vec2(0.5,0.5); 
attribute vec2 vertexIn; 
varying vec2 textureCoord; 
void main() { 
    textureCoord = vertexIn.xy*madd+madd; // scale vertex attribute to [0-1] range 
    gl_Position = vec4(vertexIn.xy,0.0,1.0); 
} 

Fragmento de Shader:

varying vec2 textureCoord; 
void main() { 
    vec4 color1 = texture2D(t,textureCoord); 
    gl_FragColor = color1; 
} 
+3

Por cierto, esto sigue su idea anterior, pero definitivamente no está en desuso en OpenGL 3.2.Aún puede enviar atributos de vértice a través de una matriz/búfer de vértices, etc. OpenGL sigue siendo una API de renderizado de modo inmediato. – AdilYalcin

2

La siguiente proviene de la función draw de la clase que dibuja texturas fbo en un cuadrante alineado con la pantalla.

Gl.glUseProgram(shad);  

Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, vbo);   
Gl.glEnableVertexAttribArray(0); 
Gl.glEnableVertexAttribArray(1); 
Gl.glVertexAttribPointer(0, 3, Gl.GL_FLOAT, Gl.GL_FALSE, 0, voff); 
Gl.glVertexAttribPointer(1, 2, Gl.GL_FLOAT, Gl.GL_FALSE, 0, coff); 

Gl.glActiveTexture(Gl.GL_TEXTURE0); 
Gl.glBindTexture(Gl.GL_TEXTURE_2D, fboc); 
Gl.glUniform1i(tileLoc, 0); 

Gl.glDrawArrays(Gl.GL_QUADS, 0, 4); 

Gl.glBindTexture(Gl.GL_TEXTURE_2D, 0); 
Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, 0); 

Gl.glUseProgram(0); 

El sí y las coordenadas de cuatro reales se obtuvo a partir de:

private float[] v=new float[]{ -1.0f, -1.0f, 0.0f, 
           1.0f, -1.0f, 0.0f, 
           1.0f, 1.0f, 0.0f, 
           -1.0f, 1.0f, 0.0f, 

           0.0f, 0.0f, 
           1.0f, 0.0f, 
           1.0f, 1.0f, 
           0.0f, 1.0f 
}; 

La unión y montaje de la década de VBO lo dejo a ti.

El shader de vértice:

#version 330 

layout(location = 0) in vec3 pos; 
layout(location = 1) in vec2 coord; 

out vec2 coords; 

void main() { 
    coords=coord.st; 
    gl_Position=vec4(pos, 1.0); 
} 

Debido a que la posición es en bruto, es decir, no multiplicado por cualquier matriz la -1, -1 :: 1, 1 de la quad encajan en la ventana gráfica. Busque el tutorial de Alfonse vinculado a cualquiera de sus publicaciones en openGL.org.

+0

que idioma es ese? ¿Java? ¿pitón? –

+2

D lenguaje de programación. ¡Excelente! True punteros con sintaxis Java/C# – ste3e

5

Una indirecta por Chistophe Riccio:

Un triángulo grande es más eficiente para la razón por la que he ilustrado en vídeos:

http://www.youtube.com/watch?v=WFx6StqpRdY

http://www.youtube.com/watch?v=WnUS8kzA3dI&feature=related

+1

¿Por qué es mejor representar un triángulo? ¿Alguien puede explicar en palabras simples? ¿Hay algún ejemplo de código fuente en ese lugar? – fen

+4

Chrostophe podría explicar mejor, pero mi entendimiento es que el borde diagonal en el caso de un quad hace que las ejecuciones de PS sean incoherentes, lo que al menos daña un poco el rendimiento. – kvark

+1

Lo que haya en esos videos no explica nada. – Robinson

11

Para dar salida a una pantalla completa shader de geometría cuádruple se puede utilizar:

#version 330 core 

layout(points) in; 
layout(triangle_strip, max_vertices = 4) out; 

out vec2 texcoord; 

void main() 
{ 
    gl_Position = vec4(1.0, 1.0, 0.5, 1.0); 
    texcoord = vec2(1.0, 1.0); 
    EmitVertex(); 

    gl_Position = vec4(-1.0, 1.0, 0.5, 1.0); 
    texcoord = vec2(0.0, 1.0); 
    EmitVertex(); 

    gl_Position = vec4(1.0,-1.0, 0.5, 1.0); 
    texcoord = vec2(1.0, 0.0); 
    EmitVertex(); 

    gl_Position = vec4(-1.0,-1.0, 0.5, 1.0); 
    texcoord = vec2(0.0, 0.0); 
    EmitVertex(); 

    EndPrimitive(); 
} 

Vertex shader es simplemente vacío:

#version 330 core 

void main() 
{ 
} 

Para utilizar este shader puede utilizar el comando ficticia empate con vacío VBO:

glDrawArrays(GL_POINTS, 0, 1); 
+1

¿Por qué el espacio de recorte Z 0.5 en lugar de 0.0? ¿Y por qué usar esto cuando se dibuja un cuadrángulo real (o como han señalado otros, un triángulo grande) es mucho más fácil y menos costoso? –

+0

La coordenada Z puede ser 0.0, tienes razón. En cuanto a la segunda pregunta, es realmente menos costosa para la CPU, y es más flexible, ya que uno puede cambiar el sombreador sin reconstrucción del programa. –

+0

¿Cuánto cuesta menos? ¿Es algo que realmente sería notable y mensurable? –

Cuestiones relacionadas