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 ************************************************************************/
27 material_t
*materials
;
29 GLuint current_texture
;
42 /* create a new blank material */
43 material_t
*mat_create()
45 material_t
*mat
= malloc(sizeof(material_t
));
46 mat
->id
= mat_data
.ids
++;
48 mat
->options
= MATOPT_BFCULL
;
52 mat
->reflectivity
= 0.0;
55 mat_data
.materials
= list_push(&mat_data
.materials
,mat
);
61 void mat_free(material_t
*mat
)
66 mat_data
.materials
= list_remove(&mat_data
.materials
,mat
);
74 /* create a material from a texture */
75 material_t
*mat_from_tex(texture_t
*tex
)
77 material_t
*mat
= mat_create();
79 strcpy(mat
->name
,tex
->name
);
84 /* create a material from pixel data */
85 material_t
*mat_from_pixels(image_t
*p
)
87 material_t
*mat
= mat_create();
88 mat
->tex
= tex_from_pixels(p
);
89 strcpy(mat
->name
,mat
->tex
->name
);
94 /* update a material from pixel data */
95 material_t
*mat_update_pixels(material_t
*mat
, image_t
*p
)
98 return mat_from_pixels(p
);
100 mat
->tex
= tex_update_pixels(mat
->tex
,p
);
105 /* create a material from an image */
106 material_t
*mat_from_image(char* type
, char* file
)
108 material_t
*mat
= mat_create();
110 mat
->tex
= tex_from_image(type
,file
);
116 strcpy(mat
->name
,mat
->tex
->name
);
121 /* create a material from a colour */
122 material_t
*mat_from_colour(colour_t
*c
)
126 snprintf(buff
,100,"rgba-%d-%d-%d-%d",c
->r
,c
->g
,c
->b
,c
->a
);
130 mat
->tex
= tex_from_rgba(1,1,c
->r
,c
->g
,c
->b
,c
->a
);
136 strcpy(mat
->name
,buff
);
141 /* bind a texture and apply options */
142 int mat_bind_with_opts(GLuint tex
, uint32_t options
)
146 if (mat_data
.current_texture
!= tex
)
147 glBindTexture(GL_TEXTURE_2D
,tex
);
150 if (e
!= GL_NO_ERROR
) {
151 char* es
= opengl_error_string(e
);
152 vlprintf(CN_ERROR
, "%s",es
);
156 mat_data
.current_texture
= tex
;
158 /* back face culling */
159 if ((options
&MATOPT_BFCULL
) == MATOPT_BFCULL
) {
160 if (!mat_data
.culling
) {
161 glEnable(GL_CULL_FACE
);
163 mat_data
.culling
= 1;
165 }else if (mat_data
.culling
) {
166 glDisable(GL_CULL_FACE
);
167 mat_data
.culling
= 0;
171 if ((options
&MATOPT_ADDITIVE_BLEND
) == MATOPT_ADDITIVE_BLEND
) {
172 if (!mat_data
.blended
) {
174 glEnable(GL_LINE_SMOOTH
);
175 mat_data
.blended
= 1;
177 if (mat_data
.blend_mode
!= GL_ONE
) {
178 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
179 mat_data
.blend_mode
= GL_ONE
;
181 }else if ((options
&MATOPT_ALPHA_BLEND
) == MATOPT_ALPHA_BLEND
) {
182 if (!mat_data
.blended
) {
184 glEnable(GL_LINE_SMOOTH
);
185 mat_data
.blended
= 1;
187 if (mat_data
.blend_mode
!= GL_ONE_MINUS_SRC_ALPHA
) {
188 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
189 mat_data
.blend_mode
= GL_ONE_MINUS_SRC_ALPHA
;
191 }else if (mat_data
.blended
) {
193 mat_data
.blended
= 0;
194 mat_data
.blend_mode
= GL_ZERO
;
197 if ((options
&MATOPT_SDF_ALPHA
) == MATOPT_SDF_ALPHA
) {
198 if (opengl_has_psdf()) {
199 shader_uniform_float(NULL
,"alphafunc",2.0);
201 shader_uniform_float(NULL
,"alphafunc",1.0);
203 }else if ((options
&MATOPT_ALPHA_TEST
) == MATOPT_ALPHA_TEST
) {
204 shader_uniform_float(NULL
,"alphafunc",1.0);
206 shader_uniform_float(NULL
,"alphafunc",0.0);
213 void mat_use(material_t
*mat
, shader_t
*shader
)
216 if (mat
->tex
->state
!= 1)
217 tex_generate(mat
->tex
);
218 if (mat_bind_with_opts(mat
->tex
->glid
,mat
->options
))
221 mat_bind_with_opts(0,mat
->options
);
224 /* specular values */
225 shader_uniform_float(shader
,"shininess",mat
->shininess
);
226 shader_uniform_float(shader
,"reflectivity",mat
->reflectivity
);
227 shader_uniform_float(shader
,"bumpiness",mat
->bumpiness
);
230 /* set the shininess and reflectivity of a material */
231 void mat_shininess(material_t
*mat
, float shininess
, float reflectivity
)
233 mat
->shininess
= shininess
;
234 mat
->reflectivity
= reflectivity
;
237 /* set the bumpiness (for bump mapping) of a material */
238 void mat_bumpiness(material_t
*mat
, float bumpiness
)
240 mat
->bumpiness
= bumpiness
;
243 /* set the name of a material */
244 void mat_name(material_t
*mat
, char* name
)
246 strncpy(mat
->name
,name
,100);
249 /* set the texture of a material */
250 void mat_tex(material_t
*mat
, texture_t
*tex
)
255 /* set the texture of a material from an image file */
256 void mat_tex_file(material_t
*mat
, char* type
, char* file
)
258 mat
->tex
= tex_from_image(type
,file
);
259 strcpy(mat
->name
,mat
->tex
->name
);
262 /* set the options for a material, return the previous options */
263 uint32_t mat_options(material_t
*mat
, uint32_t opt
)
265 uint32_t o
= mat
->options
;
266 if (opt
!= MATOPT_GET
)