OpenGl将方形图像纹理映射到圆形

OpenGl将方形图像纹理映射到圆形,opengl,texture-mapping,Opengl,Texture Mapping,我正在尝试将一个时钟面的正方形图像映射到我创建的圆形GL_多边形上。我目前正在使用以下代码: 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

我正在尝试将一个时钟面的正方形图像映射到我创建的圆形GL_多边形上。我目前正在使用以下代码:

        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);
然后从init()方法调用这些函数:

加载图像的方式与加载背景的方式相同

是的,这几乎肯定是问题所在。虽然两幅图像都是PNG,但几乎可以肯定它们的格式不同

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

就好像你拿了原始图像,垂直折叠,然后重复。三次

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

但并不是每个PNG都是这样格式化的。一些PNG是灰度的;每像素一字节。因为使用了低级libPNG读取接口,所以可以从PNG读取像素数据的精确格式。是的,它会解压。但是你读的正是PNG在概念上存储的内容

因此,如果PNG是灰度PNG,那么调用
PNG\u read\u image
可以读取不是每像素3字节的数据。但是你告诉OpenGL数据是每像素3字节。因此,如果libPNG每像素写入1字节,那么您将为OpenGL提供错误的texel数据

那太糟糕了

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


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

几乎可以肯定,您加载的纹理不正确。由于您没有向我们显示加载代码,我们无法帮助您解决此问题。@NicolBolas图像加载方式与背景加载方式相同。这两幅图像都是png。我对问题进行了编辑,以反映您的担忧。只是以防万一,别想了!!但是我不知道该怎么做。有没有办法将当前的png格式转换成正确的格式?@KieranLavelle:如果你能让加载的代码更加健壮,这样它就能适应png的格式,那就更好了。有没有相关的指南?
#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;
}
background_texture = load_and_bind_texture("images/office-wall.png");
an_face_texture1 = load_and_bind_texture("images/clock.png");