2017-01-02 46 views
-1

我正试图将一个钟面的方形图像映射到我创建的圆GL_POLYGON上。我目前使用下面的代码:纹理将一个正方形图像映射到一个圆上OpenGl

 float angle, radian, x, y, xcos, ysin, tx, ty;  

     glEnable(GL_TEXTURE_2D); 
     glBindTexture(GL_TEXTURE_2D, an_face_texture1); 

     glBegin(GL_POLYGON); 

     for (angle=0.0; angle<360.0; angle+=2.0) 
     { 
      radian = angle * (pi/180.0f); 

      xcos = (float)cos(radian); 
      ysin = (float)sin(radian); 
      x = xcos * radius; 
      y = ysin * radius; 
      tx = (x/radius + 1)*0.5; 
      ty = (y/radius + 1)*0.5; 

      glTexCoord2f(tx, ty); 
      glVertex2f(x, y);   
     } 

     glEnd(); 
     glDisable(GL_TEXTURE_2D); 

然而,当我这样做时,我结束了一个奇怪的重叠图像效果。如下所示:enter image description here原始纹理图像是enter image description here但是切出的角落是png格式。生成的纹理这种方式协调并从以前的答案了:HERE

下面是用来加载图像的代码:

#ifndef PNGLOAD_H 

#include <png.h> 
#include <stdlib.h> 

int png_load(const char* file_name, 
      int* width, 
      int* height, 
      char** image_data_ptr) 
{ 
png_byte header[8]; 

FILE* fp = fopen(file_name, "rb"); 
if (fp == 0) 
{ 
    fprintf(stderr, "erro: could not open PNG file %s\n", file_name); 
    perror(file_name); 
    return 0; 
} 

// read the header 
fread(header, 1, 8, fp); 

if (png_sig_cmp(header, 0, 8)) 
{ 
    fprintf(stderr, "error: %s is not a PNG.\n", file_name); 
    fclose(fp); 
    return 0; 
} 

png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 
if (!png_ptr) 
{ 
    fprintf(stderr, "error: png_create_read_struct returned 0.\n"); 
    fclose(fp); 
    return 0; 
} 

// create png info struct 
png_infop info_ptr = png_create_info_struct(png_ptr); 
if (!info_ptr) 
{ 
    fprintf(stderr, "error: png_create_info_struct returned 0.\n"); 
    png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); 
    fclose(fp); 
    return 0; 
} 

// create png info struct 
png_infop end_info = png_create_info_struct(png_ptr); 
if (!end_info) 
{ 
    fprintf(stderr, "error: png_create_info_struct returned 0.\n"); 
    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); 
    fclose(fp); 
    return 0; 
} 

// the code in this if statement gets called if libpng encounters an error 
if (setjmp(png_jmpbuf(png_ptr))) { 
    fprintf(stderr, "error from libpng\n"); 
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); 
    fclose(fp); 
    return 0; 
} 

// init png reading 
png_init_io(png_ptr, fp); 

// let libpng know you already read the first 8 bytes 
png_set_sig_bytes(png_ptr, 8); 

// read all the info up to the image data 
png_read_info(png_ptr, info_ptr); 

// variables to pass to get info 
int bit_depth, color_type; 
png_uint_32 temp_width, temp_height; 

// get info about png 
png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type, 
    NULL, NULL, NULL); 

if (width) { *width = temp_width; } 
if (height){ *height = temp_height; } 

// Update the png info struct. 
png_read_update_info(png_ptr, info_ptr); 

// Row size in bytes. 
int rowbytes = png_get_rowbytes(png_ptr, info_ptr); 

// glTexImage2d requires rows to be 4-byte aligned 
rowbytes += 3 - ((rowbytes-1) % 4); 

// Allocate the image_data as a big block, to be given to opengl 
png_byte* image_data; 
image_data = (png_byte*)malloc(rowbytes * temp_height * sizeof(png_byte)+15); 
if (image_data == NULL) 
{ 
    fprintf(stderr, "error: could not allocate memory for PNG image data\n"); 
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); 
    fclose(fp); 
    return 0; 
} 

// row_pointers is for pointing to image_data for reading the png with libpng 
png_bytep* row_pointers = (png_bytep*)malloc(temp_height * sizeof(png_bytep)); 
if (row_pointers == NULL) 
{ 
    fprintf(stderr, "error: could not allocate memory for PNG row pointers\n"); 
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); 
    free(image_data); 
    fclose(fp); 
    return 0; 
} 

// set the individual row_pointers to point at the correct offsets of image_data 
int i; 
for (i = 0; i < temp_height; i++) 
{ 
    row_pointers[temp_height - 1 - i] = image_data + i * rowbytes; 
} 

// read the png into image_data through row_pointers 
png_read_image(png_ptr, row_pointers); 

// clean up 
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); 

//free(image_data); 
*image_data_ptr = (char*)image_data; // return data pointer 

free(row_pointers); 
fclose(fp); 

fprintf(stderr, "\t texture image size is %d x %d\n", *width, *height); 

return 1; 
} 

#endif 

和:

unsigned int load_and_bind_texture(const char* filename) 
{ 
char* image_buffer = NULL; // the image data 
int width = 0; 
int height = 0; 

// read in the PNG image data into image_buffer 
if (png_load(filename, &width, &height, &image_buffer)==0) 
{ 
    fprintf(stderr, "Failed to read image texture from %s\n", filename); 
    exit(1); 
} 

unsigned int tex_handle = 0; 

// request one texture handle 
glGenTextures(1, &tex_handle); 

// create a new texture object and bind it to tex_handle 
glBindTexture(GL_TEXTURE_2D, tex_handle); 

glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 

glTexImage2D(GL_TEXTURE_2D, 0, 
      GL_RGB, width, height, 0, 
      GL_RGB, GL_UNSIGNED_BYTE, image_buffer); 


free(image_buffer); // free the image buffer memory 

return tex_handle; 
} 

这些话叫从init()方法:

background_texture = load_and_bind_texture("images/office-wall.png"); 
an_face_texture1 = load_and_bind_texture("images/clock.png"); 
+0

你几乎肯定是不正确加载纹理。由于您没有向我们展示您的加载代码,因此我们无法帮助您解决问题。 –

+0

@NicolBolas图像以加载背景的相同方式加载。这两张图片都是png。无论如何,我已编辑过这个问题以反映您的疑虑。只是说它有任何用处。 –

回答

1

图像以加载背景的相同方式加载。

是的,那几乎肯定是问题。虽然这两个图像都是PNG,但它们几乎可以肯定地不一样格式

让我们实际调试您在加载纹理中看到的内容。你看到2与10重叠。3与9重叠。8与4重叠。所有彼此交错。这个模式重复3次。

这就好像你把原始图像垂直折叠,然后重复它。 3次。

重复“3”,强烈暗示libPNG实际读取的内容与您告诉OpenGL纹理数据的实际内容不匹配。你告诉OpenGL纹理是RGB格式,每个像素3个字节。

但不是每个PNG都是格式化那样。一些PNG是灰度;每像素一个字节。因为你使用了低级别的libpng的阅读界面,你看从PNG的像素数据的准确格式。是的,它解压缩它。但是你正在阅读PNG概念上存储的内容。

因此,如果PNG是灰度PNG,则您拨打png_read_image可以读取不是每像素3字节的数据。但是你告诉OpenGL数据是每个像素3个字节。因此,如果libPNG每个像素写入1个字节,则会给OpenGL提供错误的纹理数据。

这是不好的。

如果您打算使用libPNG的低级读取例程,那么您必须必须实际检查正在读取的PNG格式并调整您的OpenGL代码以匹配。

使用更高级别的读取例程并明确告诉它将灰度转换为RGB会容易得多。

+0

从来没有想过这个!然而,我不知道该怎么做。有什么可以将我当前的png转换为正确的格式? –

+0

@KieranLavelle:如果你的加载代码更加健壮,那么它可以适应PNG的格式。 –

+0

有没有任何指导去做这件事? –