/* * texture.c * * Handle textures * * (c) 2008 Thomas White * * thrust3d - a silly game * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "render.h" void texture_load(RenderContext *ctx, char *name) { FILE *fh; png_bytep header; png_structp png_ptr; png_infop info_ptr; png_infop end_info; unsigned int width; unsigned int height; unsigned int bit_depth; unsigned int channels; png_bytep *row_pointers; unsigned int x; unsigned int y; char tmp[128]; uint8_t *texels; /* Open file */ snprintf(tmp, 127, "%s/textures/%s.png", DATADIR, name); fh = fopen(tmp, "rb"); if ( !fh ) { fprintf(stderr, "Couldn't open texture file '%s'\n", tmp); return ; } /* Check it's actually a PNG file */ header = malloc(8); fread(header, 1, 8, fh); if ( png_sig_cmp(header, 0, 8)) { fprintf(stderr, "Texture file '%s' is not a PNG file.\n", tmp); free(header); fclose(fh); return; } free(header); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if ( !png_ptr ) { fprintf(stderr, "Couldn't create PNG read structure.\n"); fclose(fh); return ; } info_ptr = png_create_info_struct(png_ptr); if ( !info_ptr ) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fprintf(stderr, "Couldn't create PNG info structure.\n"); fclose(fh); return; } end_info = png_create_info_struct(png_ptr); if ( !end_info ) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); printf("Couldn't create PNG end info structure.\n"); fclose(fh); return; } if ( setjmp(png_jmpbuf(png_ptr)) ) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fh); fprintf(stderr, "PNG read failed.\n"); return; } png_init_io(png_ptr, fh); png_set_sig_bytes(png_ptr, 8); /* Read! */ png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); channels = png_get_channels(png_ptr, info_ptr); if ( bit_depth != 8 ) { fprintf(stderr, "Texture image '%s' isn't 8 bits per channel per pixel.\n", tmp); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fh); return; } if ( channels != 4 ) { fprintf(stderr, "Texture image '%s' doesn't have 4 channels.\n", tmp); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fh); return; } /* Get image data */ row_pointers = png_get_rows(png_ptr, info_ptr); texels = malloc(4*width*height); for ( y=0; ytextures[ctx->num_textures].texname)); glBindTexture(GL_TEXTURE_2D, ctx->textures[ctx->num_textures].texname); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texels); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8, width, height, GL_RGBA, GL_UNSIGNED_BYTE, texels); free(texels); ctx->textures[ctx->num_textures].name = name; ctx->num_textures++; png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fh); } Texture *texture_lookup(RenderContext *ctx, const char *name) { int i, found; found = 0; for ( i=0; inum_textures; i++ ) { if ( strcmp(ctx->textures[i].name, name) == 0 ) { found = 1; break; } } if ( found == 0 ) { return NULL; } return &(ctx->textures[i]); } void texture_free_all(RenderContext *ctx) { int i; for ( i=0; inum_textures; i++ ) { glDeleteTextures(1, &(ctx->textures[ctx->num_textures].texname)); } }