remove deprecated luminance texture generation
[voxelands-alt.git] / src / graphics / material.c
blob6d6e0678b5cf7c04eb35e6417518a5b2074d7482
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 struct {
27 material_t *materials;
28 int ids;
29 GLuint current_texture;
30 uint8_t culling;
31 uint8_t blended;
32 GLenum blend_mode;
33 } mat_data ={
34 NULL,
39 GL_ZERO
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++;
47 mat->name[0] = 0;
48 mat->options = MATOPT_BFCULL;
49 mat->tex = NULL;
50 mat->next = NULL;
51 mat->shininess = 1.0;
52 mat->reflectivity = 0.0;
53 mat->bumpiness = 0.0;
55 mat_data.materials = list_push(&mat_data.materials,mat);
57 return mat;
60 /* free a material */
61 void mat_free(material_t *mat)
63 if (!mat)
64 return;
66 mat_data.materials = list_remove(&mat_data.materials,mat);
68 if (mat->tex)
69 tex_free(mat->tex);
71 free(mat);
74 /* create a material from a texture */
75 material_t *mat_from_tex(texture_t *tex)
77 material_t *mat = mat_create();
78 mat->tex = tex;
79 strcpy(mat->name,tex->name);
81 return mat;
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);
91 return mat;
94 /* update a material from pixel data */
95 material_t *mat_update_pixels(material_t *mat, image_t *p)
97 if (!mat)
98 return mat_from_pixels(p);
100 mat->tex = tex_update_pixels(mat->tex,p);
102 return mat;
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);
111 if (!mat->tex) {
112 mat_free(mat);
113 return NULL;
116 strcpy(mat->name,mat->tex->name);
118 return mat;
121 /* create a material from a colour */
122 material_t *mat_from_colour(colour_t *c)
124 char buff[100];
125 material_t *mat;
126 snprintf(buff,100,"rgba-%d-%d-%d-%d",c->r,c->g,c->b,c->a);
128 mat = mat_create();
130 mat->tex = tex_from_rgba(1,1,c->r,c->g,c->b,c->a);
131 if (!mat->tex) {
132 mat_free(mat);
133 return NULL;
136 strcpy(mat->name,buff);
138 return mat;
141 /* bind a texture and apply options */
142 int mat_bind_with_opts(GLuint tex, uint32_t options)
144 GLenum e;
146 if (mat_data.current_texture != tex)
147 glBindTexture(GL_TEXTURE_2D,tex);
149 e = glGetError();
150 if (e != GL_NO_ERROR) {
151 char* es = opengl_error_string(e);
152 vlprintf(CN_ERROR, "%s",es);
153 return 1;
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);
162 glCullFace(GL_BACK);
163 mat_data.culling = 1;
165 }else if (mat_data.culling) {
166 glDisable(GL_CULL_FACE);
167 mat_data.culling = 0;
170 /* blending */
171 if ((options&MATOPT_ADDITIVE_BLEND) == MATOPT_ADDITIVE_BLEND) {
172 if (!mat_data.blended) {
173 glEnable(GL_BLEND);
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) {
183 glEnable(GL_BLEND);
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) {
192 glDisable(GL_BLEND);
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);
200 }else{
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);
205 }else{
206 shader_uniform_float(NULL,"alphafunc",0.0);
209 return 0;
212 /* use a material */
213 void mat_use(material_t *mat, shader_t *shader)
215 if (mat->tex) {
216 if (mat->tex->state != 1)
217 tex_generate(mat->tex);
218 if (mat_bind_with_opts(mat->tex->glid,mat->options))
219 mat->tex->state = 0;
220 }else{
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)
252 mat->tex = 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)
267 mat->options = opt;
268 return o;