2017-01-02 82 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

有沒有任何指導去做這件事? –