3dphotoshoot
view src/texture.c @ 20:c14613d27a3a
writing a C++ shader class for this
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 11 Jun 2015 02:53:43 +0300 |
parents | |
children |
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <assert.h>
6 #include "opengl.h"
7 #include "texture.h"
8 #include "imago2.h"
9 #include "rbtree.h"
10 #include "assman.h"
12 static size_t ioread(void *buf, size_t bytes, void *uptr);
13 static long ioseek(long offs, int whence, void *uptr);
14 static unsigned int next_pow2(unsigned int x);
16 static struct rbtree *texdb;
18 int load_texture(struct texture *tex, const char *fname)
19 {
20 struct img_pixmap img;
21 struct img_io io;
22 ass_file *fp;
24 printf("loading texture: %s\n", fname);
26 if(!(fp = ass_fopen(fname, "rb"))) {
27 fprintf(stderr, "failed to open texture file: %s: %s\n", fname, strerror(errno));
28 return -1;
29 }
30 io.uptr = fp;
31 io.read = ioread;
32 io.write = 0;
33 io.seek = ioseek;
35 img_init(&img);
36 if(img_read(&img, &io) == -1) {
37 fprintf(stderr, "failed to load texture file: %s\n", fname);
38 ass_fclose(fp);
39 return -1;
40 }
41 img_convert(&img, IMG_FMT_RGBA32);
43 tex->img_width = img.width;
44 tex->img_height = img.height;
45 tex->width = next_pow2(img.width);
46 tex->height = next_pow2(img.height);
48 printf(" %dx%d (tex: %dx%d)\n", tex->img_width, tex->img_height, tex->width, tex->height);
50 glGenTextures(1, &tex->texid);
51 glBindTexture(GL_TEXTURE_2D, tex->texid);
52 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
53 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
55 #ifdef __GLEW_H__
56 if(GLEW_SGIS_generate_mipmap) {
57 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
58 #endif
59 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->width, tex->height, 0,
60 GL_RGBA, GL_UNSIGNED_BYTE, img.pixels);
61 #ifdef __GLEW_H__
62 } else {
63 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, tex->width, tex->height,
64 GL_RGBA, GL_UNSIGNED_BYTE, img.pixels);
65 }
66 #endif
68 #ifdef GL_ES_VERSION_2_0
69 glGenerateMipmap(GL_TEXTURE_2D);
70 #endif
72 return 0;
73 }
75 struct texture *get_texture(const char *fname)
76 {
77 struct texture *tex;
78 struct rbnode *node;
80 if(!(texdb = rb_create(RB_KEY_STRING))) {
81 static int err_printed;
82 if(!err_printed) {
83 fprintf(stderr, "failed to create texture database\n");
84 err_printed = 1;
85 }
86 return 0;
87 }
89 if((node = rb_find(texdb, (void*)fname))) {
90 return rb_node_data(node);
91 }
93 if(!(tex = malloc(sizeof *tex))) {
94 fprintf(stderr, "failed to load texture \"%s\": %s\n", fname, strerror(errno));
95 return 0;
96 }
97 if(load_texture(tex, fname) == -1) {
98 free(tex);
99 return 0;
100 }
102 if(rb_insert(texdb, (void*)fname, tex) == -1) {
103 fprintf(stderr, "failed to insert texture into the texture database\n");
104 }
105 return tex;
106 }
109 #define DBG_TEX_SZ 64
110 int gen_debug_texture(struct texture *tex)
111 {
112 static unsigned char *pixels;
114 if(!pixels) {
115 int i, j;
116 unsigned char *pptr;
117 pptr = pixels = malloc(DBG_TEX_SZ * DBG_TEX_SZ * 4);
118 assert(pixels);
120 for(i=0; i<DBG_TEX_SZ; i++) {
121 for(j=0; j<DBG_TEX_SZ; j++) {
122 int chess = ((j >> 3) & 1) == ((i >> 3) & 1);
123 *pptr++ = chess ? 255 : 64;
124 *pptr++ = 128;
125 *pptr++ = chess ? 64 : 255;
126 *pptr++ = 255; /* alpha */
127 }
128 }
129 }
131 if(!tex->texid) {
132 glGenTextures(1, &tex->texid);
133 }
135 glBindTexture(GL_TEXTURE_2D, tex->texid);
136 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
137 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
138 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DBG_TEX_SZ, DBG_TEX_SZ, 0, GL_RGBA,
139 GL_UNSIGNED_BYTE, pixels);
141 tex->width = tex->img_width = tex->height = tex->img_height = DBG_TEX_SZ;
142 return 0;
143 }
146 static size_t ioread(void *buf, size_t bytes, void *uptr)
147 {
148 return ass_fread(buf, 1, bytes, uptr);
149 }
151 static long ioseek(long offs, int whence, void *uptr)
152 {
153 return ass_fseek(uptr, offs, whence);
154 }
156 static unsigned int next_pow2(unsigned int x)
157 {
158 x--;
159 x = (x >> 1) | x;
160 x = (x >> 2) | x;
161 x = (x >> 4) | x;
162 x = (x >> 8) | x;
163 x = (x >> 16) | x;
164 return x + 1;
165 }