我无法弄清楚为什么我的PNG图像在尝试使用NDK& OpenGL的。 PNG位于我的资源文件夹中,它们具有alpha图层。以下是我从资源文件夹中获取它们的方法:
void loadNativePNG(texture_t* tmpTex)
{
png_structp png_ptr;
png_infop info_ptr;
unsigned int width;
unsigned int height;
int i;
int bit_depth;
int color_type ;
png_size_t rowbytes;
png_bytep *row_pointers;
png_byte header[8];
char realPath[1024];
memset(realPath, 0, 1024);
strcat(realPath, FS_Gamedir());
if (tmpTex->path[0] != '/')
strcat(realPath, "/");
strcat(realPath, tmpTex->path);
tmpTex->format = TEXTURE_TYPE_UNKNOWN ;
file = zip_fopen(APKArchive, realPath, 0);
//LOGI("[Android Main] Opening %s", realPath);
if ( !file )
abort_textureLoading_("Could not open file '%s'\n",tmpTex->path);
zip_fread(file, header, 8);
if (png_sig_cmp(header, 0, 8) != 0 )
abort_textureLoading_("[read_png_file] File is not recognized as a PNG file.\n", tmpTex->path);
// initialize
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL)
abort_textureLoading_("[read_png_file] png_create_read_struct failed");
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL)
abort_textureLoading_("[read_png_file] png_create_info_struct failed");
if (setjmp(png_jmpbuf(png_ptr)))
abort_textureLoading_("[read_png_file] Error during init_io");
png_set_read_fn(png_ptr, NULL, png_zip_read);
png_set_sig_bytes(png_ptr, 8);
png_read_info(png_ptr, info_ptr);
//Retrieve metadata and transfer to structure bean tmpTex
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
tmpTex->width = width;
tmpTex->height = height;
// Set up some transforms.
if (color_type & PNG_COLOR_MASK_ALPHA) {
png_set_strip_alpha(png_ptr);
}
if (bit_depth > 8) {
png_set_strip_16(png_ptr);
}
if (color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
png_set_gray_to_rgb(png_ptr);
}
if (color_type == PNG_COLOR_TYPE_PALETTE) {
png_set_palette_to_rgb(png_ptr);
}
// Update the png info struct.
png_read_update_info(png_ptr, info_ptr);
// Rowsize in bytes.
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
tmpTex->bpp = rowbytes / width;
if (tmpTex->bpp == 4)
tmpTex->format = TEXTURE_GL_RGBA;
else
tmpTex->format = TEXTURE_GL_RGB;
//Since PNG can only store one image there is only one mipmap, allocated an array of one
tmpTex->numMipmaps = 1;
tmpTex->data = malloc(sizeof(uchar*));
if ((tmpTex->data[0] = (uchar*)malloc(rowbytes * height))==NULL)
{
//Oops texture won't be able to hold the result :(, cleanup LIBPNG internal state and return;
free(tmpTex->data);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return;
}
//Next we need to send to libpng an array of pointer, let's point to tmpTex->data[0]
if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL)
{
// Oops looks like we won't have enough RAM to allocate an array of pointer....
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
free(tmpTex->data );
tmpTex->data = NULL;
return;
}
//FCS: Hm, it looks like we are flipping the image vertically.
// Since iOS did not do it, we may have to not to that. If result is
// messed up, just swap to: row_pointers[ i] = ....
for (i = 0; i < height; ++i)
row_pointers[height - 1 - i] = tmpTex->data[0] + i * rowbytes;
//row_pointers[ i] = tmpTex->data[0] + i*rowbytes;
//Decompressing PNG to RAW where row_pointers are pointing (tmpTex->data[0])
png_read_image(png_ptr, row_pointers);
//Last but not least:
// Free LIBPNG internal state.
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
//Free the decompression buffer
free(row_pointers);
zip_fclose(file);
}
以下是它们在OpenGL中的呈现方式:
void UpLoadTextureToGPUF(texture_t* texture)
{
int i,mipMapDiv;
if (!texture || !texture->data || texture->textureId != 0)
return;
glGenTextures(1, &texture->textureId);
glBindTexture(GL_TEXTURE_2D, texture->textureId);
if (texture->format == TEXTURE_GL_RGB ||texture->format == TEXTURE_GL_RGBA)
{
glTexParameterf(GL_TEXTURE_2D,GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->width, texture->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture->data[0]);
free(texture->data[0]);
texture->data[0] = 0;
}
else
{
glTexParameterf(GL_TEXTURE_2D,GL_GENERATE_MIPMAP, GL_FALSE);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, texture->format, texture->width,texture-> height, 0, texture->dataLength[0], texture->data[0]);
//printf("Uploading mipmapp %d w=%d, h=%d, size=%d\n",0,texture->width,texture-> height,texture->dataLength[0]);
mipMapDiv = 2;
for (i=1; i < texture->numMipmaps; i++,mipMapDiv*=2)
{
glCompressedTexImage2D(GL_TEXTURE_2D, i, texture->format, texture->width/mipMapDiv,texture-> height/mipMapDiv, 0, texture->dataLength[i], texture->data[i]);
// printf("Uploading mipmapp %d w=%d, h=%d, size=%d\n",i,texture->width/mipMapDiv,texture-> height/mipMapDiv,texture->dataLength[i]);
free(texture->data[i]);
texture->data[i] = 0;
}
}
//Using mipMapping to reduce bandwidth consumption
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
SCR_CheckErrors("Loading texture",texture->path);
free(texture->dataLength);
texture->dataLength = 0;
free(texture->data);
texture->data = 0;
texture->memLocation = TEXT_MEM_LOC_VRAM;
if (texture->file != NULL)
FS_CloseFile(texture->file);
}
SCR_CheckErrors()
会进行一些错误检查(但不会打印错误):
void SCR_CheckErrors(char* step, char* details)
{
GLenum err = glGetError();
switch (err) {
case GL_INVALID_ENUM:printf("Error GL_INVALID_ENUM %s, %s\n", step,details); break;
case GL_INVALID_VALUE:printf("Error GL_INVALID_VALUE %s, %s\n", step,details); break;
case GL_INVALID_OPERATION:printf("Error GL_INVALID_OPERATION %s, %s\n", step,details); break;
case GL_OUT_OF_MEMORY:printf("Error GL_OUT_OF_MEMORY %s, %s\n", step,details); break;
case GL_NO_ERROR: break;
default : printf("Error UNKNOWN %s, %s\n", step,details);break;
}
}