source: trunk/sys/TinyGL/src/light.c @ 412

Last change on this file since 412 was 1, checked in by alain, 7 years ago

First import

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