1 /************************************************************************
3 * voxelands - 3d voxel world sandbox game
4 * Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 ************************************************************************/
34 /* generate the hardware texture */
35 int tex_generate(texture_t
*tex
)
38 GL_TEXTURE_CUBE_MAP_POSITIVE_Z
,
39 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
,
40 GL_TEXTURE_CUBE_MAP_POSITIVE_X
,
41 GL_TEXTURE_CUBE_MAP_NEGATIVE_X
,
42 GL_TEXTURE_CUBE_MAP_POSITIVE_Y
,
43 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
53 /* can't generate a texture if there's no data or no OpenGL */
54 if (!tex
|| !wm_data
.isinit
)
59 /* delete the old texture, if it exists */
61 glDeleteTextures(1, &tex
->glid
);
63 if (e
!= GL_NO_ERROR
) {
64 char* es
= opengl_error_string(e
);
65 vlprintf(CN_ERROR
, "%d %s",__LINE__
,es
);
70 /* create a new texture */
71 glGenTextures(1, &tex
->glid
);
73 if (e
!= GL_NO_ERROR
) {
74 char* es
= opengl_error_string(e
);
75 vlprintf(CN_ERROR
, "%d %s",__LINE__
,es
);
79 glActiveTexture(GL_TEXTURE0
);
80 glBindTexture(tex
->type
, tex
->glid
);
82 if (e
!= GL_NO_ERROR
) {
83 char* es
= opengl_error_string(e
);
84 vlprintf(CN_ERROR
, "%d %s",__LINE__
,es
);
88 b
= opengl_has_bilinear();
89 t
= opengl_has_trilinear();
90 m
= opengl_has_mipmap();
93 if (tex
->type
== GL_TEXTURE_CUBE_MAP
)
96 if (tex
->type
== GL_TEXTURE_CUBE_MAP
) {
101 /* draw the pixels to the texture */
102 glTexImage2D(type
, 0, GL_RGBA8
, tex
->px
[i
].w
, tex
->px
[i
].h
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, tex
->px
[i
].pixels
);
104 if (e
!= GL_NO_ERROR
) {
105 char* es
= opengl_error_string(e
);
106 vlprintf(CN_ERROR
, "%d %s",__LINE__
,es
);
112 glGenerateMipmap(tex
->type
);
113 glTexParameteri(tex
->type
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
114 glTexParameteri(tex
->type
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
118 glTexParameteri(tex
->type
,GL_TEXTURE_MAG_FILTER
,GL_LINEAR
);
120 glTexParameteri(tex
->type
,GL_TEXTURE_MIN_FILTER
,GL_LINEAR_MIPMAP_LINEAR
);
122 glTexParameteri(tex
->type
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
125 glTexParameteri(tex
->type
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
126 glTexParameteri(tex
->type
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
128 glTexParameteri(tex
->type
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
129 glTexParameteri(tex
->type
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
132 if (opengl_has_anisotropic()) {
133 float ma
= opengl_max_anisotropic();
134 glTexParameterf(tex
->type
, GL_TEXTURE_MAX_ANISOTROPY_EXT
, ma
);
138 if (e
!= GL_NO_ERROR
) {
139 char* es
= opengl_error_string(e
);
140 vlprintf(CN_ERROR
, "%d %s",__LINE__
,es
);
144 if (tex
->type
== GL_TEXTURE_CUBE_MAP
) {
145 glTexParameteri(GL_TEXTURE_CUBE_MAP
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
146 glTexParameteri(GL_TEXTURE_CUBE_MAP
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
154 /* add a new image to the cache */
155 texture_t
*tex_create()
157 texture_t
*tex
= malloc(sizeof(texture_t
));
167 tex
->id
= tex_data
.ids
++;
169 tex
->type
= GL_TEXTURE_2D
;
172 tex_data
.textures
= list_push(&tex_data
.textures
,tex
);
178 void tex_free(texture_t
*tex
)
182 tex_data
.textures
= list_remove(&tex_data
.textures
,tex
);
184 glDeleteTextures(1, &tex
->glid
);
185 if (tex
->px
&& tex
->type
== GL_TEXTURE_CUBE_MAP
)
190 /* load an image to a texture */
191 texture_t
*tex_from_image(char* type
, char* file
)
197 t
= tex_data
.textures
;
199 if (!strcmp(t
->name
,file
))
204 p
= image_load(type
,file
);
209 r
= math_rand_range(0,255);
210 g
= math_rand_range(0,255);
211 b
= math_rand_range(0,255);
212 return tex_from_rgba(32,32,r
,g
,b
,255);
215 /* and make a texture out of it */
216 t
= tex_from_pixels(p
);
218 strncpy(t
->name
,file
,256);
223 /* create a texture cube */
224 texture_t
*tex_from_box(char* front
, char* back
, char* left
, char* right
, char* top
, char* bottom
)
230 p
[0] = image_load("texture",front
);
233 p
[1] = image_load("texture",back
);
236 p
[2] = image_load("texture",left
);
239 p
[3] = image_load("texture",right
);
242 p
[4] = image_load("texture",top
);
245 p
[5] = image_load("texture",bottom
);
253 snprintf(t
->name
,256,"box-%s-%s-%s-%s-%s-%s",front
,back
,left
,right
,top
,bottom
);
255 t
->type
= GL_TEXTURE_CUBE_MAP
;
257 t
->px
= malloc(sizeof(image_t
)*6);
265 t
->xf
= 1.0/(GLfloat
)p
[0]->w
;
266 t
->yf
= 1.0/(GLfloat
)p
[0]->h
;
268 for (i
=0; i
<6; i
++) {
269 t
->px
[i
].w
= p
[i
]->w
;
270 t
->px
[i
].h
= p
[i
]->h
;
271 t
->px
[i
].pixels
= p
[i
]->pixels
;
277 /* create a texture from pixel data */
278 texture_t
*tex_from_pixels(image_t
*px
)
291 tex
->xf
= 1.0/(GLfloat
)px
->w
;
292 tex
->yf
= 1.0/(GLfloat
)px
->h
;
294 if (tex_generate(tex
))
300 /* update a texture from pixel data */
301 texture_t
*tex_update_pixels(texture_t
*tex
, image_t
*px
)
304 return tex_from_pixels(px
);
309 tex
->xf
= 1.0/(GLfloat
)px
->w
;
310 tex
->yf
= 1.0/(GLfloat
)px
->h
;
312 if (tex_generate(tex
))
320 /* create a transparent texture */
321 texture_t
*tex_from_rgba(int x
, int y
, uint8_t r
, uint8_t g
, uint8_t b
, uint8_t a
)
327 snprintf(n
,256,"rgba-%u-%u-%u-%u-%d-%d",r
,g
,b
,a
,x
,y
);
329 t
= tex_data
.textures
;
331 if (!strcmp(t
->name
,n
))
336 p
= image_rgba(x
,y
,r
,g
,b
,a
);
340 t
= tex_from_pixels(p
);