and now we actually can render stuff, partially
[voxelands-alt.git] / src / graphics / material.c
bloba3ebec607689e29fec3ae603ef8d4d3e5863d0f7
1 /************************************************************************
2 * material.c
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 ************************************************************************/
20 #include "common.h"
21 #include "graphics.h"
22 #include "list.h"
24 #include <string.h>
26 static material_t *mat_list = NULL;
27 static int mat_ids = 0;
29 /* find or create a material called 'name' */
30 material_t *mat_find_or_create(char* name)
32 material_t *mat = mat_list;
33 while (mat) {
34 if (!strcmp(mat->name,name))
35 return mat;
36 mat = mat->next;
39 mat = mat_create();
41 strcpy(mat->name,name);
43 return mat;
46 /* create a new blank material */
47 material_t *mat_create()
49 material_t *mat = malloc(sizeof(material_t));
50 mat->id = mat_ids++;
51 mat->name[0] = 0;
52 mat->options = 0;/* TODO: set to MATOPT_BFCULL;*/
53 mat->tex = NULL;
54 mat->next = NULL;
55 mat->ambient[0] = 1.0;
56 mat->ambient[1] = 1.0;
57 mat->ambient[2] = 1.0;
58 mat->ambient[3] = 1.0;
59 mat->specular[0] = 1.0;
60 mat->specular[1] = 1.0;
61 mat->specular[2] = 1.0;
62 mat->specular[3] = 1.0;
63 mat->diffuse[0] = 1.0;
64 mat->diffuse[1] = 1.0;
65 mat->diffuse[2] = 1.0;
66 mat->diffuse[3] = 1.0;
68 mat_list = list_push(&mat_list,mat);
70 return mat;
73 /* free a material */
74 void mat_free(material_t *mat)
76 if (!mat)
77 return;
79 mat_list = list_remove(&mat_list,mat);
81 if (mat->tex)
82 tex_free(mat->tex);
84 free(mat);
87 /* create a material from a texture */
88 material_t *mat_from_tex(texture_t *tex)
90 material_t *mat = mat_find_or_create(tex->name);
91 if (mat->tex)
92 return mat;
93 mat->tex = tex;
94 strcpy(mat->name,tex->name);
96 return mat;
99 /* create a material from pixel data */
100 material_t *mat_from_pixels(image_t *p)
102 material_t *mat = mat_create();
103 mat->tex = tex_from_pixels(p);
104 strcpy(mat->name,mat->tex->name);
106 return mat;
109 /* update a material from pixel data */
110 material_t *mat_update_pixels(material_t *mat, image_t *p)
112 if (!mat)
113 return mat_from_pixels(p);
115 mat->tex = tex_update_pixels(mat->tex,p);
117 return mat;
120 /* create a material from an image */
121 material_t *mat_from_image(char* type, char* file)
123 material_t *mat = mat_find_or_create(file);
124 if (mat->tex)
125 return mat;
126 mat->tex = tex_from_image(type,file);
127 if (!mat->tex) {
128 mat_free(mat);
129 return NULL;
131 strcpy(mat->name,mat->tex->name);
133 return mat;
136 /* create a material from float diffuse values */
137 material_t *mat_from_dif3f(GLfloat r, GLfloat g, GLfloat b)
139 char buff[100];
140 material_t *mat;
141 snprintf(buff,100,"rgb-%f-%f-%f",r,g,b);
143 mat = mat_find_or_create(buff);
144 if ((mat->options&MATOPT_DIFFUSE) == MATOPT_DIFFUSE)
145 return mat;
147 mat->diffuse[0] = r;
148 mat->diffuse[1] = g;
149 mat->diffuse[2] = b;
151 mat->options |= MATOPT_DIFFUSE;
153 strcpy(mat->name,buff);
155 return mat;
158 /* create a material from unsigned byte diffuse values */
159 material_t *mat_from_dif3ub(uint8_t r, uint8_t g, uint8_t b)
161 GLfloat rf = (GLfloat)r/255.0;
162 GLfloat gf = (GLfloat)g/255.0;
163 GLfloat bf = (GLfloat)b/255.0;
165 return mat_from_dif3f(rf,gf,bf);
168 /* create a material from a colour */
169 material_t *mat_from_colour(colour_t *c)
171 char buff[100];
172 material_t *mat;
173 GLfloat rf = (GLfloat)c->r/255.0;
174 GLfloat gf = (GLfloat)c->g/255.0;
175 GLfloat bf = (GLfloat)c->b/255.0;
176 GLfloat af = (GLfloat)c->a/255.0;
177 snprintf(buff,100,"rgba-%.3f-%.3f-%.3f-%.3f",rf,gf,bf,af);
179 mat = mat_find_or_create(buff);
180 if ((mat->options&MATOPT_DIFFUSE) == MATOPT_DIFFUSE)
181 return mat;
183 mat->diffuse[0] = rf;
184 mat->diffuse[1] = gf;
185 mat->diffuse[2] = bf;
186 mat->diffuse[3] = af;
188 mat->options |= MATOPT_DIFFUSE;
190 strcpy(mat->name,buff);
192 return mat;
195 /* use a material */
196 void mat_use(material_t *mat)
198 if (mat->tex) {
199 if (mat->tex->state != 1)
200 tex_generate(mat->tex);
201 glGetError();
202 glEnable(GL_TEXTURE_2D);
203 glActiveTexture(GL_TEXTURE0);
204 glBindTexture(GL_TEXTURE_2D,mat->tex->tex);
205 if (glGetError() != GL_NO_ERROR)
206 mat->tex->state = 0;
207 }else{
208 glDisable(GL_TEXTURE_2D);
211 if ((mat->options&MATOPT_DIFFUSE) == MATOPT_DIFFUSE) {
212 glColor4f(mat->diffuse[0],mat->diffuse[1],mat->diffuse[2],mat->diffuse[3]);
213 }else{
214 glColor4f(1.0,1.0,1.0,1.0);
217 /* options */
218 opengl_backfacecull_setter((mat->options&MATOPT_BFCULL));
220 return;
221 /* specular and ambient doesn't work well (if at all) with
222 * glDrawElements() so ignore them
223 * TODO: a better solution *
225 if ((mat->options&MATOPT_SPECULAR) == MATOPT_SPECULAR) {
226 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat->specular);
227 }else{
228 GLfloat spc[4] = {1.0,1.0,1.0,1.0};
229 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spc);
232 if ((mat->options&MATOPT_AMBIENT) == MATOPT_AMBIENT) {
233 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat->ambient);
234 }else{
235 GLfloat amb[4] = {1.0,1.0,1.0,1.0};
236 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb);
239 if ((mat->options&MATOPT_SPECULAR) == MATOPT_SPECULAR) {
240 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat->specular);
241 }else{
242 GLfloat spc[4] = {1.0,1.0,1.0,1.0};
243 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spc);
246 if ((mat->options&MATOPT_SPECULAR) == MATOPT_SPECULAR) {
247 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat->specular);
248 }else{
249 GLfloat spc[4] = {1.0,1.0,1.0,1.0};
250 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spc);
252 GL_EMISSION,
253 GL_SHININESS, */
254 /* GLfloat tmp[4] = {0.1,0.1,0.1,0.1}; */
255 /* glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,tmp); */
257 /* tmp[0] = 0.0; */
258 /* tmp[1] = 0.0; */
259 /* tmp[2] = 0.0; */
260 /* glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,tmp); */
263 /* set the name of a material */
264 void mat_name(material_t *mat, char* name)
266 strncpy(mat->name,name,100);
269 /* set the texture of a material */
270 void mat_tex(material_t *mat, texture_t *tex)
272 mat->tex = tex;
275 /* set the texture of a material from an image file */
276 void mat_tex_file(material_t *mat, char* type, char* file)
278 mat->tex = tex_from_image(type,file);
279 strcpy(mat->name,mat->tex->name);
282 /* set the ambient values of a material from float values */
283 void mat_amb3f(material_t *mat, GLfloat r, GLfloat g, GLfloat b)
285 mat->ambient[0] = r;
286 mat->ambient[1] = g;
287 mat->ambient[2] = b;
289 mat->options |= MATOPT_AMBIENT;
292 /* set the ambient values of a material from unsigned byte values */
293 void mat_amb3ub(material_t *mat, uint8_t r, uint8_t g, uint8_t b)
295 mat->ambient[0] = (GLfloat)r/255.0;
296 mat->ambient[1] = (GLfloat)g/255.0;
297 mat->ambient[2] = (GLfloat)b/255.0;
299 mat->options |= MATOPT_AMBIENT;
302 /* set the diffuse values of a material from float values */
303 void mat_dif3f(material_t *mat, GLfloat r, GLfloat g, GLfloat b)
305 mat->diffuse[0] = r;
306 mat->diffuse[1] = g;
307 mat->diffuse[2] = b;
309 mat->options |= MATOPT_DIFFUSE;
312 /* set the diffuse values of a material from unsigned byte values */
313 void mat_dif3ub(material_t *mat, uint8_t r, uint8_t g, uint8_t b)
315 mat->diffuse[0] = (GLfloat)r/255.0;
316 mat->diffuse[1] = (GLfloat)g/255.0;
317 mat->diffuse[2] = (GLfloat)b/255.0;
319 mat->options |= MATOPT_DIFFUSE;
322 /* set the specular values of a material from float values */
323 void mat_spc3f(material_t *mat, GLfloat r, GLfloat g, GLfloat b)
325 mat->specular[0] = r;
326 mat->specular[1] = g;
327 mat->specular[2] = b;
329 mat->options |= MATOPT_SPECULAR;
332 /* set the specular values of a material from unsigned byte values */
333 void mat_spc3ub(material_t *mat, uint8_t r, uint8_t g, uint8_t b)
335 mat->specular[0] = (GLfloat)r/255.0;
336 mat->specular[1] = (GLfloat)g/255.0;
337 mat->specular[2] = (GLfloat)b/255.0;
339 mat->options |= MATOPT_SPECULAR;
342 /* set the alpha value of a material from float data */
343 void mat_alf(material_t *mat, GLfloat d)
345 mat->diffuse[3] = d;
346 mat->options |= MATOPT_DIFFUSE;
349 /* set the alpha values of a material from unsigned byte data */
350 void mat_alub(material_t *mat, uint8_t d)
352 mat->diffuse[3] = (GLfloat)d/255.0;
354 mat->options |= MATOPT_DIFFUSE;
357 /* set the options for a material, return the previous options */
358 uint32_t mat_options(material_t *mat, uint32_t opt)
360 uint32_t o = mat->options;
361 if (opt != MATOPT_GET)
362 mat->options = opt;
363 return o;