2011-05-04 19 views
13

Estoy trabajando en una aplicación de iPhone que utiliza OpenGL ES 2 para su dibujo. Sé que típicamente las coordenadas de textura están definidas en el rango de 0-1, pero idealmente me gustaría asignarlas de 0 a 1023 (el tamaño de mi TextureAtlas) por motivos de legibilidad. He visto un código de muestra que define las coordenadas de esta manera, pero no he podido averiguar qué llamadas anteriores se hicieron para eso. glMatrixMode(GL_TEXTURE) parece que podría estar involucrado, pero no estoy muy seguro de cómo implementarlo.Coordenadas de textura OpenGL en Pixel Space

Mi objetivo final sería lograr algo como esto, donde la textura que estaría utilizando dentro de los atlas se encuentra en la plaza 48px parte superior izquierda:

GLshort texcoords[]={ 
    48,48, 
    0,48, 
    48,0, 
    0,0, 
}; 
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_SHORT, 0, 0, texcoords); 
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON); 
+2

Una cosa más ... asegúrese de tener 'precision highp float;' en la parte superior del sombreador. Si su textura es más grande que 1024x1024, mediump no le dará la precisión suficiente para muestrear cada píxel de la textura. –

Respuesta

4

Resulta que esto es posible en OpenGL ES 2. Así es como yo lo logró:

Fragmento de Shader:

precision mediump float; 
varying vec2 v_texCoord; 
uniform sampler2D textureSample; 
uniform float texScale; 
void main() 
{ 
    vec2 mult=(2.0*v_texCoord - 1.0)/(2.0*texScale); 
    gl_FragColor = texture2D(textureSample,mult); 
} 

Obj-C:

GLshort texCoords[]={ 
    512,512, 
    0,512, 
    512,0, 
    0,0, 
}; 
GLfloat textureWidth = 512.0; //texture size, assumed square, power of 2 
texCoordLoc = glGetAttribLocation (program, "a_texCoord"); 
GLuint textureScale = glGetUniformLocation (program, "texScale"); 
glUniform1f(textureScale, textureWidth); 
glVertexAttribPointer (texCoordLoc, 2, GL_SHORT, GL_FALSE, 0, texCoords); 

Si Alguien tiene comentarios sobre cómo esto podría funcionar en cuanto a rendimiento, me interesaría.

+2

Bueno, no necesita llamar a glGetAttribLocation/glGetUniformLocation en cada cuadro. Guarda el resultado en una variable. Pero supongo que la diferencia de rendimiento es insignificante. – fabspro

+0

Puede ser una buena idea hacer la división en el lado Obj-C para obtener la menor cantidad posible de operaciones en el sombreador de Fragmentos, es decir, calcular los uniformes ayb para que la línea que define mult se convierta en "vec2 mult = a * v_texCoord + b ; " – tjltjl

+0

@Sam ¿Por qué esto funcionaría, su coord de textura es (2i -1)/2N? – james

36

Esto se ha pedido un par de veces, pero No tengo los enlaces a mano, por lo que una explicación rápida y aproximada. Digamos que la textura es de 8 píxeles de ancho:

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 
^ ^^^^^^^^
0.0 | | | | | | | 1.0 
| | | | | | | | | 
0/8 1/8 2/8 3/8 4/8 5/8 6/8 7/8 8/8 

Los dígitos indican los píxeles de la textura, las barras de los bordes de la textura y en caso de filtración de la cercana frontera entre píxeles. Sin embargo, desea golpear los centros de los píxeles. Así que usted está interesado en las coordenadas de textura

(0/8 + 1/8)/2 = 1/(2 * 8)

(1/8 + 2/8)/2 = 3/(2 * 8)

...

(7/8 + 8/8)/2 = 15/(2 * 8)

o más generalmente por píxel i en una amplia textura N la coordenada de textura adecuada es

(2i + 1)/(2N)

Sin embargo, si desea alinear perfectamente su textura con los píxeles de la pantalla, recuerde que lo que especifique como coordenadas no son los píxeles de un cuadrángulo, sino bordes, que según la proyección pueden alinearse con los bordes de los píxeles de la pantalla, requiere otras coordenadas de textura.

+0

En general, mi pregunta era más acerca de si puedo o no definir las texturas como píxeles, no tengo problemas para alinearlas con una precisión de píxeles perfecta usando flotadores que van de 0 a 1, pero si es posible me gustaría alimentarlos. en valores de píxel reales para que el código sea legible (como el código de ejemplo en mi pregunta original) – Sam

+0

@Sam: existe la extensión GL_ARB_texture_rectangle que también implementa el acceso de textura por píxel, pero quedó obsoleta por la capacidad de un sombreador de fragmentos para acceder a una textura en una base por píxel. – datenwolf

+0

@datenwolf ¿Algún enlace de referencia o código de muestra sobre cómo llevarlo a cabo con un sombreador de fragmentos? – Sam

6

Pierdo 1 hora para encontrar una figura intuitiva, pero sorprendentemente nadie pintó. Así que lo hice.

Dada 4 textura pixel, coordenadas de textura normalizado [0,1], coordenadas de textura no normalizado [0, ancho), gl_FragCoord [0, ancho] son ​​como sigue

enter image description here

Referencia

  1. p270 en https://www.khronos.org/registry/gles/specs/3.1/es_spec_3.1.pdf
  2. https://www.opengl.org/sdk/docs/man/html/gl_FragCoord.xhtml
  3. https://www.opengl.org/wiki/Sampler_(GLSL)
+0

Esto es útil ya que texelFetch es compatible con GLSL 3.0. – zhy