TinyGL 0.4.1 for MinGW
light.c
Go to the documentation of this file.
1#include "zgl.h"
2#include "msghandling.h"
3
5{
6 int mode=p[1].i;
7 int type=p[2].i;
8 int i;
9 GLMaterial *m;
10
11 if (mode == GL_FRONT_AND_BACK) {
12 p[1].i=GL_FRONT;
13 glopMaterial(c,p);
14 mode=GL_BACK;
15 }
16 if (mode == GL_FRONT) m=&c->materials[0];
17 else m=&c->materials[1];
18
19 switch(type) {
20 case GL_EMISSION:
21 for(i=0;i<4;i++)
22 m->emission.v[i]=p[3 + i].f;
23 break;
24 case GL_AMBIENT:
25 for(i=0;i<4;i++)
26 m->ambient.v[i]=p[3 + i].f;
27 break;
28 case GL_DIFFUSE:
29 for(i=0;i<4;i++)
30 m->diffuse.v[i]=p[3 + i].f;
31 break;
32 case GL_SPECULAR:
33 for(i=0;i<4;i++)
34 m->specular.v[i]=p[3 + i].f;
35 break;
36 case GL_SHININESS:
37 m->shininess=p[3].f;
39 break;
41 for(i=0;i<4;i++)
42 m->diffuse.v[i]=p[3 + i].f;
43 for(i=0;i<4;i++)
44 m->ambient.v[i]=p[3 + i].f;
45 break;
46 default:
47 assert(0);
48 }
49}
50
52{
53 int mode=p[1].i;
54 int type=p[2].i;
55
58}
59
61{
62 int light=p[1].i;
63 int type=p[2].i;
64 V4 v;
65 GLLight *l;
66 int i;
67
68 assert(light >= GL_LIGHT0 && light < GL_LIGHT0+MAX_LIGHTS );
69
70 l=&c->lights[light-GL_LIGHT0];
71
72 for(i=0;i<4;i++) v.v[i]=p[3+i].f;
73
74 switch(type) {
75 case GL_AMBIENT:
76 l->ambient=v;
77 break;
78 case GL_DIFFUSE:
79 l->diffuse=v;
80 break;
81 case GL_SPECULAR:
82 l->specular=v;
83 break;
84 case GL_POSITION:
85 {
86 V4 pos;
87 gl_M4_MulV4(&pos,c->matrix_stack_ptr[0],&v);
88
89 l->position=pos;
90
91 if (l->position.v[3] == 0) {
92 l->norm_position.X=pos.X;
93 l->norm_position.Y=pos.Y;
94 l->norm_position.Z=pos.Z;
95
97 }
98 }
99 break;
101 for(i=0;i<3;i++) {
102 l->spot_direction.v[i]=v.v[i];
103 l->norm_spot_direction.v[i]=v.v[i];
104 }
106 break;
107 case GL_SPOT_EXPONENT:
108 l->spot_exponent=v.v[0];
109 break;
110 case GL_SPOT_CUTOFF:
111 {
112 float a=v.v[0];
113 assert(a == 180 || (a>=0 && a<=90));
114 l->spot_cutoff=a;
115 if (a != 180) l->cos_spot_cutoff=cos(a * M_PI / 180.0);
116 }
117 break;
119 l->attenuation[0]=v.v[0];
120 break;
122 l->attenuation[1]=v.v[0];
123 break;
125 l->attenuation[2]=v.v[0];
126 break;
127 default:
128 assert(0);
129 }
130}
131
132
134{
135 int pname=p[1].i;
136 int i;
137
138 switch(pname) {
140 for(i=0;i<4;i++)
141 c->ambient_light_model.v[i]=p[2 + i].f;
142 break;
144 c->local_light_model=(int)p[2].f;
145 break;
147 c->light_model_two_side = (int)p[2].f;
148 break;
149 default:
150 tgl_warning("glopLightModel: illegal pname: 0x%x\n", pname);
151 //assert(0);
152 break;
153 }
154}
155
156
157static inline float clampf(float a,float min,float max)
158{
159 if (a<min) return min;
160 else if (a>max) return max;
161 else return a;
162}
163
164void gl_enable_disable_light(GLContext *c,int light,int v)
165{
166 GLLight *l=&c->lights[light];
167 if (v && !l->enabled) {
168 l->enabled=1;
169 l->next=c->first_light;
170 c->first_light=l;
171 l->prev=NULL;
172 } else if (!v && l->enabled) {
173 l->enabled=0;
174 if (l->prev == NULL) c->first_light=l->next;
175 else l->prev->next=l->next;
176 if (l->next != NULL) l->next->prev=l->prev;
177 }
178}
179
180/* non optimized lightening model */
182{
183 float R,G,B,A;
184 GLMaterial *m;
185 GLLight *l;
186 V3 n,s,d;
187 float dist,tmp,att,dot,dot_spot,dot_spec;
188 int twoside = c->light_model_two_side;
189
190 m=&c->materials[0];
191
192 n.X=v->normal.X;
193 n.Y=v->normal.Y;
194 n.Z=v->normal.Z;
195
196 R=m->emission.v[0]+m->ambient.v[0]*c->ambient_light_model.v[0];
197 G=m->emission.v[1]+m->ambient.v[1]*c->ambient_light_model.v[1];
198 B=m->emission.v[2]+m->ambient.v[2]*c->ambient_light_model.v[2];
199 A=clampf(m->diffuse.v[3],0,1);
200
201 for(l=c->first_light;l!=NULL;l=l->next) {
202 float lR,lB,lG;
203
204 /* ambient */
205 lR=l->ambient.v[0] * m->ambient.v[0];
206 lG=l->ambient.v[1] * m->ambient.v[1];
207 lB=l->ambient.v[2] * m->ambient.v[2];
208
209 if (l->position.v[3] == 0) {
210 /* light at infinity */
211 d.X=l->norm_position.v[0];
212 d.Y=l->norm_position.v[1];
213 d.Z=l->norm_position.v[2];
214 att=1;
215 } else {
216 /* distance attenuation */
217 d.X=l->position.v[0]-v->ec.v[0];
218 d.Y=l->position.v[1]-v->ec.v[1];
219 d.Z=l->position.v[2]-v->ec.v[2];
220 dist=sqrt(d.X*d.X+d.Y*d.Y+d.Z*d.Z);
221 if (dist>1E-10f) {
222 tmp=1/dist;
223 d.X*=tmp;
224 d.Y*=tmp;
225 d.Z*=tmp;
226 }
227 att=1.0f/(l->attenuation[0]+dist*(l->attenuation[1]+
228 dist*l->attenuation[2]));
229 }
230 dot=d.X*n.X+d.Y*n.Y+d.Z*n.Z;
231 if (twoside && dot < 0) dot = -dot;
232 if (dot>0) {
233 /* diffuse light */
234 lR+=dot * l->diffuse.v[0] * m->diffuse.v[0];
235 lG+=dot * l->diffuse.v[1] * m->diffuse.v[1];
236 lB+=dot * l->diffuse.v[2] * m->diffuse.v[2];
237
238 /* spot light */
239 if (l->spot_cutoff != 180) {
240 dot_spot=-(d.X*l->norm_spot_direction.v[0]+
241 d.Y*l->norm_spot_direction.v[1]+
242 d.Z*l->norm_spot_direction.v[2]);
243 if (twoside && dot_spot < 0) dot_spot = -dot_spot;
244 if (dot_spot < l->cos_spot_cutoff) {
245 /* no contribution */
246 continue;
247 } else {
248 /* TODO: optimize */
249 if (l->spot_exponent > 0) {
250 att=att*pow(dot_spot,l->spot_exponent);
251 }
252 }
253 }
254
255 /* specular light */
256
257 if (c->local_light_model) {
258 V3 vcoord;
259 vcoord.X=v->ec.X;
260 vcoord.Y=v->ec.Y;
261 vcoord.Z=v->ec.Z;
262 gl_V3_Norm(&vcoord);
263 s.X=d.X-vcoord.X;
264 s.Y=d.Y-vcoord.X;
265 s.Z=d.Z-vcoord.X;
266 } else {
267 s.X=d.X;
268 s.Y=d.Y;
269 s.Z=d.Z+1.0;
270 }
271 dot_spec=n.X*s.X+n.Y*s.Y+n.Z*s.Z;
272 if (twoside && dot_spec < 0) dot_spec = -dot_spec;
273 if (dot_spec>0) {
274 GLSpecBuf *specbuf;
275 int idx;
276 tmp=sqrt(s.X*s.X+s.Y*s.Y+s.Z*s.Z);
277 if (tmp > 1E-3) {
278 dot_spec=dot_spec / tmp;
279 }
280
281 /* TODO: optimize */
282 /* testing specular buffer code */
283 /* dot_spec= pow(dot_spec,m->shininess);*/
284 specbuf = specbuf_get_buffer(c, m->shininess_i, m->shininess);
285 idx = (int)(dot_spec*SPECULAR_BUFFER_SIZE);
287 dot_spec = specbuf->buf[idx];
288 lR+=dot_spec * l->specular.v[0] * m->specular.v[0];
289 lG+=dot_spec * l->specular.v[1] * m->specular.v[1];
290 lB+=dot_spec * l->specular.v[2] * m->specular.v[2];
291 }
292 }
293
294 R+=att * lR;
295 G+=att * lG;
296 B+=att * lB;
297 }
298
299 v->color.v[0]=clampf(R,0,1);
300 v->color.v[1]=clampf(G,0,1);
301 v->color.v[2]=clampf(B,0,1);
302 v->color.v[3]=A;
303}
304
#define M_PI
Definition: gears.c:24
@ GL_BACK
Definition: gl.h:120
@ GL_FRONT_AND_BACK
Definition: gl.h:184
@ GL_EMISSION
Definition: gl.h:176
@ GL_SPOT_DIRECTION
Definition: gl.h:178
@ GL_LIGHT0
Definition: gl.h:159
@ GL_CONSTANT_ATTENUATION
Definition: gl.h:169
@ GL_SPOT_CUTOFF
Definition: gl.h:168
@ GL_AMBIENT
Definition: gl.h:172
@ GL_LIGHT_MODEL_TWO_SIDE
Definition: gl.h:181
@ GL_SHININESS
Definition: gl.h:175
@ GL_LIGHT_MODEL_LOCAL_VIEWER
Definition: gl.h:182
@ GL_LINEAR_ATTENUATION
Definition: gl.h:170
@ GL_QUADRATIC_ATTENUATION
Definition: gl.h:171
@ GL_SPOT_EXPONENT
Definition: gl.h:167
@ GL_POSITION
Definition: gl.h:177
@ GL_SPECULAR
Definition: gl.h:174
@ GL_FRONT
Definition: gl.h:119
@ GL_LIGHT_MODEL_AMBIENT
Definition: gl.h:183
@ GL_AMBIENT_AND_DIFFUSE
Definition: gl.h:179
@ GL_DIFFUSE
Definition: gl.h:173
void gl_enable_disable_light(GLContext *c, int light, int v)
Definition: light.c:164
void gl_shade_vertex(GLContext *c, GLVertex *v)
Definition: light.c:181
void glopMaterial(GLContext *c, GLParam *p)
Definition: light.c:4
void glopLight(GLContext *c, GLParam *p)
Definition: light.c:60
void glopLightModel(GLContext *c, GLParam *p)
Definition: light.c:133
void glopColorMaterial(GLContext *c, GLParam *p)
Definition: light.c:51
void tgl_warning(const char *format,...)
Definition: msghandling.c:15
GLSpecBuf * specbuf_get_buffer(GLContext *c, const int shininess_i, const float shininess)
Definition: specbuf.c:19
#define SPECULAR_BUFFER_RESOLUTION
Definition: specbuf.h:9
#define SPECULAR_BUFFER_SIZE
Definition: specbuf.h:7
Definition: zgl.h:159
GLMaterial materials[2]
Definition: zgl.h:172
GLLight * first_light
Definition: zgl.h:165
V4 ambient_light_model
Definition: zgl.h:166
M4 * matrix_stack_ptr[3]
Definition: zgl.h:193
int current_color_material_mode
Definition: zgl.h:174
int current_color_material_type
Definition: zgl.h:175
GLLight lights[MAX_LIGHTS]
Definition: zgl.h:164
int light_model_two_side
Definition: zgl.h:169
int local_light_model
Definition: zgl.h:167
Definition: zgl.h:59
int enabled
Definition: zgl.h:73
float cos_spot_cutoff
Definition: zgl.h:69
V4 ambient
Definition: zgl.h:60
float spot_exponent
Definition: zgl.h:65
struct GLLight * next
Definition: zgl.h:74
float spot_cutoff
Definition: zgl.h:66
V3 norm_position
Definition: zgl.h:71
V4 specular
Definition: zgl.h:62
V3 norm_spot_direction
Definition: zgl.h:70
struct GLLight * prev
Definition: zgl.h:74
V4 position
Definition: zgl.h:63
V3 spot_direction
Definition: zgl.h:64
float attenuation[3]
Definition: zgl.h:67
V4 diffuse
Definition: zgl.h:61
Definition: zgl.h:77
V4 emission
Definition: zgl.h:78
V4 ambient
Definition: zgl.h:79
V4 specular
Definition: zgl.h:81
int shininess_i
Definition: zgl.h:85
float shininess
Definition: zgl.h:82
V4 diffuse
Definition: zgl.h:80
float buf[SPECULAR_BUFFER_SIZE+1]
Definition: specbuf.h:14
Definition: zgl.h:115
V4 color
Definition: zgl.h:120
V4 ec
Definition: zgl.h:123
V3 normal
Definition: zgl.h:117
Definition: zmath.h:24
float v[3]
Definition: zmath.h:25
Definition: zmath.h:28
float v[4]
Definition: zmath.h:29
Definition: zgl.h:97
int i
Definition: zgl.h:100
float f
Definition: zgl.h:99
#define MAX_LIGHTS
Definition: zgl.h:41
register int a
Definition: zline.h:1
void gl_M4_MulV4(V4 *a, M4 *b, V4 *c)
Definition: zmath.c:88
int gl_V3_Norm(V3 *a)
Definition: zmath.c:245
int tmp
Definition: ztriangle.h:12