source: trunk/src/opengl/mesa/shade.c@ 3721

Last change on this file since 3721 was 3598, checked in by jeroen, 25 years ago

* empty log message *

File size: 10.5 KB
Line 
1/* $Id: shade.c,v 1.2 2000-05-23 20:40:53 jeroen Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 *
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28
29
30
31#ifdef PC_HEADER
32#include "all.h"
33#else
34#include "glheader.h"
35#include "light.h"
36#include "macros.h"
37#include "mmath.h"
38#include "shade.h"
39#include "pipeline.h"
40#include "types.h"
41#include "simple_list.h"
42#endif
43
44
45
46
47
48#define GET_SHINE_TAB_ENTRY( tab, dp, result ) \
49do { \
50 int k = (int) (dp * SHINE_TABLE_SIZE); \
51 result = tab->tab[k]; \
52} while(0)
53
54
55/* Combinatorics:
56 * rgba_spec/rgba/rgba_fast/ci
57 * one_side/two_side
58 * compacted_normals/ordinary_normals
59 * cull_mask/no_cull_mask
60 *
61 * We end up with an award-winning 32 seperate lighting functions.
62 */
63
64
65/* Table of all the shading functions.
66 */
67gl_shade_func gl_shade_func_tab[0x20];
68
69
70/* The original case where the normal for vertex[j] is normal[j],
71 * both stride-aware, and every normal is present.
72 */
73#define NEXT_NORMAL STRIDE_F(normal, nstride), mask++
74#define NEXT_VERTEX_NORMAL STRIDE_F(normal, nstride), mask++
75#define STATE_CHANGE(a,b) 1
76#define COMPACTED 0
77
78#define TAG(x) x##_one_sided_masked
79#define INVALID(x) 0
80#define IDX CULL_MASK_ACTIVE
81#define LIGHT_FRONT(x) 1
82#define LIGHT_REAR(x) 0
83#define LIGHT_SIDE(x,y) 1
84#define CULL(x) !((x)&VERT_FACE_FLAGS)
85#define NR_SIDES 1
86#include "shade_tmp.h"
87
88#define TAG(x) x##_one_sided
89#define INVALID(x) 0
90#define IDX 0
91#define LIGHT_FRONT(x) 1
92#define LIGHT_REAR(x) 0
93#define LIGHT_SIDE(x,y) 1
94#define CULL(x) 0
95#define NR_SIDES 1
96#include "shade_tmp.h"
97
98#define TAG(x) x##_two_sided_masked
99#define INVALID(x) ((x)&invalid)
100#define IDX SHADE_TWOSIDE|CULL_MASK_ACTIVE
101#define LIGHT_FRONT(f) ((f)&VERT_FACE_FRONT)
102#define LIGHT_REAR(f) ((f)&VERT_FACE_REAR)
103#define LIGHT_SIDE(x,y) ((x)&(y))
104#define CULL(x) !((x)&VERT_FACE_FLAGS)
105#define NR_SIDES 2
106#include "shade_tmp.h"
107
108#define TAG(x) x##_two_sided
109#define INVALID(x) 0
110#define IDX SHADE_TWOSIDE
111#define LIGHT_FRONT(f) 1
112#define LIGHT_REAR(f) 1
113#define LIGHT_SIDE(x,y) 1
114#define CULL(x) 0
115#define NR_SIDES 2
116#include "shade_tmp.h"
117
118#undef NEXT_NORMAL
119#undef NEXT_VERTEX_NORMAL
120#undef STATE_CHANGE
121#undef COMPACTED
122
123/* The 'compacted normal' case, where we have a sparse list of normals
124 * with flags indicating a new (valid) normal, as now built by the
125 * 'glVertex' API routines. We have a small bonus in that we know
126 * in advance that the normal stride must be 3 floats.
127 */
128#define NEXT_NORMAL ((flags[j]&VERT_NORM) ? normal=first_normal[j],mask=&cullmask[j] : 0)
129#define NEXT_VERTEX_NORMAL ((flags[j]&VERT_NORM) ? normal=first_normal[j],mask=&cullmask[j] : 0)
130#define STATE_CHANGE(a,b) (a & b)
131#define COMPACTED 1
132
133
134#define TAG(x) x##_one_sided_masked_compacted
135#define INVALID(x) 0
136#define IDX COMPACTED_NORMALS|CULL_MASK_ACTIVE
137#define LIGHT_FRONT(x) 1
138#define LIGHT_REAR(x) 0
139#define LIGHT_SIDE(x,y) 1
140#define CULL(x) !((x)&VERT_FACE_FLAGS)
141#define NR_SIDES 1
142#include "shade_tmp.h"
143
144#define TAG(x) x##_one_sided_compacted
145#define INVALID(x) 0
146#define IDX COMPACTED_NORMALS
147#define LIGHT_FRONT(x) 1
148#define LIGHT_REAR(x) 0
149#define LIGHT_SIDE(x,y) 1
150#define CULL(x) 0
151#define NR_SIDES 1
152#include "shade_tmp.h"
153
154#define TAG(x) x##_two_sided_masked_compacted
155#define INVALID(x) ((x)&invalid)
156#define IDX COMPACTED_NORMALS|SHADE_TWOSIDE
157#define LIGHT_FRONT(f) ((f)&VERT_FACE_FRONT)
158#define LIGHT_REAR(f) ((f)&VERT_FACE_REAR)
159#define LIGHT_SIDE(x,y) ((x)&(y))
160#define CULL(x) !((x)&VERT_FACE_FLAGS)
161#define NR_SIDES 2
162#include "shade_tmp.h"
163
164#define TAG(x) x##_two_sided_compacted
165#define INVALID(x) 0
166#define IDX COMPACTED_NORMALS|CULL_MASK_ACTIVE|SHADE_TWOSIDE
167#define LIGHT_FRONT(f) 1
168#define LIGHT_REAR(f) 1
169#define LIGHT_SIDE(x,y) 1
170#define CULL(x) 0
171#define NR_SIDES 2
172#include "shade_tmp.h"
173
174#undef COMPACTED
175#undef NEXT_NORMAL
176#undef NEXT_VERTEX_NORMAL
177#undef STATE_CHANGE
178
179
180
181void gl_init_shade( void )
182{
183 init_shade_tab_one_sided();
184 init_shade_tab_one_sided_masked();
185 init_shade_tab_one_sided_compacted();
186 init_shade_tab_one_sided_masked_compacted();
187
188 init_shade_tab_two_sided();
189 init_shade_tab_two_sided_masked();
190 init_shade_tab_two_sided_compacted();
191 init_shade_tab_two_sided_masked_compacted();
192}
193
194void gl_update_lighting_function( GLcontext *ctx )
195{
196 GLuint idx;
197
198 if (ctx->Visual->RGBAflag) {
199 if (ctx->Light.NeedVertices) {
200 if (ctx->Texture.Enabled &&
201 ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR)
202 idx = SHADE_RGBA_SPEC;
203 else
204 idx = SHADE_RGBA_VERTICES;
205 }
206 else
207 idx = SHADE_RGBA_NORMALS;
208 }
209 else
210 idx = 0;
211
212 if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
213 idx |= SHADE_TWOSIDE;
214 }
215
216
217 ctx->shade_func_flags = idx;
218}
219
220
221
222/* This has been split off to allow the normal shade routines to
223 * get a little closer to the vertex buffer, and to use the
224 * GLvector objects directly.
225 */
226void gl_shade_rastpos( GLcontext *ctx,
227 GLfloat vertex[4],
228 GLfloat normal[3],
229 GLfloat Rcolor[4],
230 GLuint *index )
231{
232 GLfloat (*base)[3] = ctx->Light.BaseColor;
233 GLubyte *sumA = ctx->Light.BaseAlpha;
234 struct gl_light *light;
235 GLfloat color[4];
236 GLfloat diffuse = 0, specular = 0;
237
238 COPY_3V(color, base[0]);
239 color[3] = UBYTE_COLOR_TO_FLOAT_COLOR( sumA[0] );
240
241 foreach (light, &ctx->Light.EnabledList) {
242 GLfloat n_dot_h;
243 GLfloat attenuation = 1.0;
244 GLfloat VP[3];
245 GLfloat n_dot_VP;
246 GLfloat *h;
247 GLfloat contrib[3];
248 GLboolean normalized;
249
250 if (!(light->Flags & LIGHT_POSITIONAL)) {
251 COPY_3V(VP, light->VP_inf_norm);
252 attenuation = light->VP_inf_spot_attenuation;
253 }
254 else {
255 GLfloat d;
256
257 SUB_3V(VP, light->Position, vertex);
258 d = LEN_3FV( VP );
259
260 if ( d > 1e-6) {
261 GLfloat invd = 1.0F / d;
262 SELF_SCALE_SCALAR_3V(VP, invd);
263 }
264 attenuation = 1.0F / (light->ConstantAttenuation + d *
265 (light->LinearAttenuation + d *
266 light->QuadraticAttenuation));
267
268 if (light->Flags & LIGHT_SPOT)
269 {
270 GLfloat PV_dot_dir = - DOT3(VP, light->NormDirection);
271
272 if (PV_dot_dir<light->CosCutoff) {
273 continue;
274 }
275 else
276 {
277 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
278 int k = (int) x;
279 GLfloat spot = (GLfloat) (light->SpotExpTable[k][0]
280 + (x-k)*light->SpotExpTable[k][1]);
281 attenuation *= spot;
282 }
283 }
284 }
285
286 if (attenuation < 1e-3)
287 continue;
288
289 n_dot_VP = DOT3( normal, VP );
290
291 if (n_dot_VP < 0.0F) {
292 ACC_SCALE_SCALAR_3V(color, attenuation, light->MatAmbient[0]);
293 continue;
294 }
295
296 COPY_3V(contrib, light->MatAmbient[0]);
297 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->MatDiffuse[0]);
298 diffuse += n_dot_VP * light->dli * attenuation;
299
300 if (light->IsMatSpecular[0]) {
301 if (ctx->Light.Model.LocalViewer) {
302 GLfloat v[3];
303 COPY_3V(v, vertex);
304 NORMALIZE_3FV(v);
305 SUB_3V(VP, VP, v);
306 h = VP;
307 normalized = 0;
308 }
309 else if (light->Flags & LIGHT_POSITIONAL) {
310 h = VP;
311 ACC_3V(h, ctx->EyeZDir);
312 normalized = 0;
313 }
314 else {
315 h = light->h_inf_norm;
316 normalized = 1;
317 }
318
319 n_dot_h = DOT3(normal, h);
320
321 if (n_dot_h > 0.0F) {
322 struct gl_material *mat = &ctx->Light.Material[0];
323 GLfloat spec_coef;
324 GLfloat shininess = mat->Shininess;
325
326 if (!normalized) {
327 n_dot_h *= n_dot_h;
328 n_dot_h /= LEN_SQUARED_3FV( h );
329 shininess *= .5;
330 }
331
332 if (n_dot_h>1.0) {
333 spec_coef = (GLfloat) pow( n_dot_h, shininess );
334 }
335 else {
336 struct gl_shine_tab *tab = ctx->ShineTable[0];
337 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
338 }
339
340 if (spec_coef > 1.0e-10) {
341 ACC_SCALE_SCALAR_3V( contrib, spec_coef,
342 light->MatSpecular[0]);
343 specular += spec_coef * light->sli * attenuation;
344 }
345 }
346 }
347
348 ACC_SCALE_SCALAR_3V( color, attenuation, contrib );
349 }
350
351 if (ctx->Visual->RGBAflag) {
352 Rcolor[0] = CLAMP(color[0], 0.0F, 1.0F);
353 Rcolor[1] = CLAMP(color[1], 0.0F, 1.0F);
354 Rcolor[2] = CLAMP(color[2], 0.0F, 1.0F);
355 Rcolor[3] = CLAMP(color[3], 0.0F, 1.0F);
356 }
357 else {
358 struct gl_material *mat = &ctx->Light.Material[0];
359 GLfloat d_a = mat->DiffuseIndex - mat->AmbientIndex;
360 GLfloat s_a = mat->SpecularIndex - mat->AmbientIndex;
361 GLfloat ind = mat->AmbientIndex
362 + diffuse * (1.0F-specular) * d_a
363 + specular * s_a;
364 if (ind > mat->SpecularIndex) {
365 ind = mat->SpecularIndex;
366 }
367 *index = (GLuint) (GLint) ind;
368 }
369
370}
371
Note: See TracBrowser for help on using the repository browser.