Moved the software rasterizer to a new directory.
[mesa.git] / src / mesa / main / fog.c
1 /* $Id: fog.c,v 1.27 2000/10/31 18:09:44 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2000 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 #ifdef PC_HEADER
29 #include "all.h"
30 #else
31 #include "glheader.h"
32 #include "colormac.h"
33 #include "context.h"
34 #include "fog.h"
35 #include "macros.h"
36 #include "mmath.h"
37 #include "types.h"
38 #include "xform.h"
39 #endif
40
41
42
43 void
44 _mesa_Fogf(GLenum pname, GLfloat param)
45 {
46 _mesa_Fogfv(pname, &param);
47 }
48
49
50 void
51 _mesa_Fogi(GLenum pname, GLint param )
52 {
53 GLfloat fparam = (GLfloat) param;
54 _mesa_Fogfv(pname, &fparam);
55 }
56
57
58 void
59 _mesa_Fogiv(GLenum pname, const GLint *params )
60 {
61 GLfloat p[4];
62 switch (pname) {
63 case GL_FOG_MODE:
64 case GL_FOG_DENSITY:
65 case GL_FOG_START:
66 case GL_FOG_END:
67 case GL_FOG_INDEX:
68 case GL_FOG_COORDINATE_SOURCE_EXT:
69 p[0] = (GLfloat) *params;
70 break;
71 case GL_FOG_COLOR:
72 p[0] = INT_TO_FLOAT( params[0] );
73 p[1] = INT_TO_FLOAT( params[1] );
74 p[2] = INT_TO_FLOAT( params[2] );
75 p[3] = INT_TO_FLOAT( params[3] );
76 break;
77 default:
78 /* Error will be caught later in _mesa_Fogfv */
79 ;
80 }
81 _mesa_Fogfv(pname, p);
82 }
83
84
85 void
86 _mesa_Fogfv( GLenum pname, const GLfloat *params )
87 {
88 GET_CURRENT_CONTEXT(ctx);
89 GLenum m;
90
91 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glFog");
92
93 switch (pname) {
94 case GL_FOG_MODE:
95 m = (GLenum) (GLint) *params;
96 if (m==GL_LINEAR || m==GL_EXP || m==GL_EXP2) {
97 ctx->Fog.Mode = m;
98 }
99 else {
100 gl_error( ctx, GL_INVALID_ENUM, "glFog" );
101 return;
102 }
103 break;
104 case GL_FOG_DENSITY:
105 if (*params<0.0) {
106 gl_error( ctx, GL_INVALID_VALUE, "glFog" );
107 return;
108 }
109 else {
110 ctx->Fog.Density = *params;
111 }
112 break;
113 case GL_FOG_START:
114 ctx->Fog.Start = *params;
115 break;
116 case GL_FOG_END:
117 ctx->Fog.End = *params;
118 break;
119 case GL_FOG_INDEX:
120 ctx->Fog.Index = *params;
121 break;
122 case GL_FOG_COLOR:
123 ctx->Fog.Color[0] = params[0];
124 ctx->Fog.Color[1] = params[1];
125 ctx->Fog.Color[2] = params[2];
126 ctx->Fog.Color[3] = params[3];
127 break;
128 case GL_FOG_COORDINATE_SOURCE_EXT: {
129 GLenum p = (GLenum)(GLint) *params;
130 if (p == GL_FOG_COORDINATE_EXT || p == GL_FRAGMENT_DEPTH_EXT)
131 ctx->Fog.FogCoordinateSource = p;
132 else
133 gl_error( ctx, GL_INVALID_ENUM, "glFog" );
134 break;
135 }
136 default:
137 gl_error( ctx, GL_INVALID_ENUM, "glFog" );
138 return;
139 }
140
141 if (ctx->Driver.Fogfv) {
142 (*ctx->Driver.Fogfv)( ctx, pname, params );
143 }
144
145 ctx->NewState |= _NEW_FOG;
146 }
147
148
149
150
151
152 static GLvector1f *get_fogcoord_ptr( GLcontext *ctx, GLvector1f *tmp )
153 {
154 struct vertex_buffer *VB = ctx->VB;
155
156 if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT) {
157 if (!ctx->NeedEyeCoords) {
158 GLfloat *m = ctx->ModelView.m;
159 GLfloat plane[4];
160
161 plane[0] = m[2];
162 plane[1] = m[6];
163 plane[2] = m[10];
164 plane[3] = m[14];
165
166 /* Full eye coords weren't required, just calculate the
167 * eye Z values.
168 */
169 gl_dotprod_tab[0][VB->ObjPtr->size](&VB->Eye, 2,
170 VB->ObjPtr, plane, 0 );
171
172 tmp->data = &(VB->Eye.data[0][2]);
173 tmp->start = VB->Eye.start+2;
174 tmp->stride = VB->Eye.stride;
175 return tmp;
176 }
177 else
178 {
179 if (VB->EyePtr->size < 2)
180 gl_vector4f_clean_elem( &VB->Eye, VB->Count, 2 );
181
182 tmp->data = &(VB->EyePtr->data[0][2]);
183 tmp->start = VB->EyePtr->start+2;
184 tmp->stride = VB->EyePtr->stride;
185 return tmp;
186 }
187 } else
188 return VB->FogCoordPtr;
189 }
190
191
192 /* Use lookup table & interpolation?
193 */
194 static void
195 make_win_fog_coords( struct vertex_buffer *VB,
196 GLvector1f *fogcoord)
197 {
198 const GLcontext *ctx = VB->ctx;
199 GLfloat end = ctx->Fog.End;
200 GLfloat *v = fogcoord->start;
201 GLuint stride = fogcoord->stride;
202 GLuint n = VB->Count - VB->Start;
203 GLfloat *out;
204 GLfloat d;
205 GLuint i;
206
207 VB->FogCoordPtr = VB->store.FogCoord;
208 out = VB->FogCoordPtr->data + VB->Start;
209
210 switch (ctx->Fog.Mode) {
211 case GL_LINEAR:
212 d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
213 for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
214 out[i] = (end - ABSF(*v)) * d;
215 if (0) fprintf(stderr, "z %f out %f\n", *v, out[i]);
216 }
217 break;
218 case GL_EXP:
219 d = -ctx->Fog.Density;
220 for ( i = 0 ; i < n ; i++, STRIDE_F(v,stride)) {
221 out[i] = exp( d*ABSF(*v) );
222 if (0) fprintf(stderr, "z %f out %f\n", *v, out[i]);
223 }
224 break;
225 case GL_EXP2:
226 d = -(ctx->Fog.Density*ctx->Fog.Density);
227 for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
228 GLfloat z = *v;
229 out[i] = exp( d*z*z );
230 if (0) fprintf(stderr, "z %f out %f\n", *v, out[i]);
231 }
232 break;
233 default:
234 gl_problem(ctx, "Bad fog mode in make_fog_coord");
235 return;
236 }
237 }
238
239
240 void
241 _mesa_make_win_fog_coords( struct vertex_buffer *VB )
242 {
243 GLvector1f tmp;
244
245 make_win_fog_coords( VB, get_fogcoord_ptr( VB->ctx, &tmp ) );
246 }
247