2008-10-15 13 views
8

Tengo datos de imagen y quiero obtener una imagen secundaria de eso para usar como una textura opengl.OpenGL SubTexturing

glGenTextures(1, &m_name); 
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldName); 
glBindTexture(GL_TEXTURE_2D, m_name); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_data); 

¿Cómo puedo obtener una imagen secundaria de esa imagen cargada como una textura. Creo que tiene algo que ver con el uso de glTexSubImage2D, pero no tengo ni idea de cómo usarlo para crear una nueva textura que pueda cargar. Llamando:

glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, xWidth, yHeight, GL_RGBA, GL_UNSIGNED_BYTE, m_data); 

DOE nada de lo que puedo ver, y llamando glCopyTexSubImage2D sólo toma parte de mi uso de este dispositivo. Gracias

Respuesta

27

Editar: Utilice glPixelStorei. Lo usa para establecer GL_UNPACK_ROW_LENGTH en el ancho (en píxeles) de toda la imagen. Luego llama a glTexImage2D (o lo que sea), pasándole un puntero al primer píxel de la subimagen y al ancho y alto de la subimagen.

No olvide restaurar GL_UNPACK_ROW_LENGTH a 0 cuando haya terminado con él.

Es decir:

glPixelStorei(GL_UNPACK_ROW_LENGTH, img_width); 
char *subimg = (char*)m_data + (sub_x + sub_y*img_width)*4; 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, subimg); 
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 

O, si usted es alérgico a puntero matemáticas:

glPixelStorei(GL_UNPACK_ROW_LENGTH, img_width); 
glPixelStorei(GL_UNPACK_SKIP_PIXELS, sub_x); 
glPixelStorei(GL_UNPACK_SKIP_ROWS, sub_y); 

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_data); 

glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); 
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); 

Edit2: En aras de la exhaustividad, debo señalar que si estás usando OpenGL-ES entonces no obtienes GL_UNPACK_ROW_LENGTH. En cuyo caso, usted podría (a) extraer la sub-imagen en un nuevo buffer usted mismo, o (b) ...

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTES, NULL); 

for(int y = 0; y < sub_height; y++) 
{ 
    char *row = m_data + ((y + sub_y)*img_width + sub_x) * 4; 
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, sub_width, 1, GL_RGBA, GL_UNSIGNED_BYTE, row); 
} 
+0

Básicamente tengo una imagen (como datos en bruto), y quiero usar parte de esa imagen como una textura. Sé cómo cargar toda la imagen como una textura, pero no sé cómo usar solo un poco. – DavidG

+0

El póster respondió esto. Si tienes una imagen en la memoria, se almacena de alguna manera. Si usó glTexImage2D (... GL_RGBA, GL_UNSIGNED_BYTE) para cargar, entonces hay un byte para R, G, B y valor alfa. Las imágenes se almacenan con el píxel (0, 0) comienza en la posición 0. Pixel x en la fila y comienza en la imagen [ancho * y + x] [0] – mstrobl

+0

ya que estoy usando OpenGL ES, terminé haciendo la primera opción que has dado, que es extraer la subimagen en un nuevo buffer. lamentablemente en el dispositivo ya no funciona, entonces voy a volver a trabajar la textura para que no tenga que resolver el problema. – DavidG

1

Para aquellos pegado con OpenGL ES 1.1/2.0 en 2018 y más tarde, Hice algunas pruebas con diferentes métodos de cómo actualizar parte de la textura de los datos de imagen (la imagen es del mismo tamaño que la textura).

Método 1: Copia toda imagen con glTexImage2D:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_Pixels); 

Método 2: toda Copiar imagen con glTexSubImage2D:

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, m_Pixels); 

Método 3: Copia parte de la imagen, línea por línea en un bucle:

auto *ptr = m_Pixels + (x + y * mWidth) * 4; 
for(int i = 0; i < h; i++, ptr += mWidth * 4) { 
    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y+i, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, ptr); 
} 

Método 4: Copia toda la anchura de la imagen, pero verticalmente copia única parte que ha cambiado:

auto *ptr = m_Pixels + (y * mWidth) * 4; 
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, mWidth, h, GL_RGBA, GL_UNSIGNED_BYTE, ptr); 

Y aquí están los resultados de la prueba realizada en el PC, por 100000 tiempos de actualización diferentes partes de la textura que tenían aproximadamente 1/5 del tamaño de la textura completa.

  • Método 1-38,17 sec
  • Método 2-26.09 seg
  • Método 3 - 54.83 seg - más lento
  • Método 4 - 5,93 seg - ganador

Como era de esperar, el método 4 es más rápido, ya que las copias sólo una parte de la imagen, y lo hace con una sola llamada a la función glTex ...().