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

Last change on this file since 3597 was 2938, checked in by sandervl, 25 years ago

created

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