minor GLchan-related changes
[mesa.git] / src / mesa / swrast / s_fog.c
1 /* $Id: s_fog.c,v 1.6 2001/01/02 21:09:50 brianp 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 #include "glheader.h"
29 #include "colormac.h"
30 #include "context.h"
31 #include "macros.h"
32 #include "mmath.h"
33
34 #include "s_context.h"
35 #include "s_fog.h"
36 #include "s_pb.h"
37
38
39 /*
40 * Apply fog to an array of RGBA pixels.
41 * Input: n - number of pixels
42 * fog - array of interpolated screen-space fog coordinates in [0..1]
43 * red, green, blue, alpha - pixel colors
44 * Output: red, green, blue, alpha - fogged pixel colors
45 */
46 void
47 _mesa_fog_rgba_pixels( const GLcontext *ctx,
48 GLuint n,
49 const GLfixed fog[],
50 GLchan rgba[][4] )
51 {
52 const GLchan rFog = FLOAT_TO_CHAN(ctx->Fog.Color[RCOMP]);
53 const GLchan gFog = FLOAT_TO_CHAN(ctx->Fog.Color[GCOMP]);
54 const GLchan bFog = FLOAT_TO_CHAN(ctx->Fog.Color[BCOMP]);
55 GLuint i;
56
57 #if CHAN_TYPE == GL_FLOAT
58 for (i = 0; i < n; i++) {
59 const GLfixed cf = CLAMP(fog[i], 0, FIXED_ONE);
60 const GLfloat f = FixedToFloat(cf);
61 const GLfloat g = 1.0F - f;
62 rgba[i][RCOMP] = f * rgba[i][RCOMP] + g * rFog;
63 rgba[i][GCOMP] = f * rgba[i][GCOMP] + g * gFog;
64 rgba[i][BCOMP] = f * rgba[i][BCOMP] + g * bFog;
65 }
66 #else
67 for (i = 0; i < n; i++) {
68 const GLfixed f = CLAMP(fog[i], 0, FIXED_ONE);
69 const GLfixed g = FIXED_ONE - f;
70 rgba[i][0] = (f * rgba[i][0] + g * rFog) >> FIXED_SHIFT;
71 rgba[i][1] = (f * rgba[i][1] + g * gFog) >> FIXED_SHIFT;
72 rgba[i][2] = (f * rgba[i][2] + g * bFog) >> FIXED_SHIFT;
73 }
74 #endif
75 }
76
77
78
79 /*
80 * Apply fog to an array of color index pixels.
81 * Input: n - number of pixels
82 * z - array of integer depth values
83 * index - pixel color indexes
84 * Output: index - fogged pixel color indexes
85 */
86 void
87 _mesa_fog_ci_pixels( const GLcontext *ctx,
88 GLuint n, const GLfixed fog[], GLuint index[] )
89 {
90 GLuint idx = ctx->Fog.Index;
91 GLuint i;
92
93 for (i=0;i<n;i++) {
94 GLfloat f = FixedToFloat(CLAMP(fog[i], 0, FIXED_ONE));
95 index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * idx);
96 }
97 }
98
99
100
101 /*
102 * Calculate fog coords from window z values
103 * Input: n - number of pixels
104 * z - array of integer depth values
105 * red, green, blue, alpha - pixel colors
106 * Output: red, green, blue, alpha - fogged pixel colors
107 *
108 * Use lookup table & interpolation?
109 */
110 void
111 _mesa_win_fog_coords_from_z( const GLcontext *ctx,
112 GLuint n,
113 const GLdepth z[],
114 GLfixed fogcoord[] )
115 {
116 const GLboolean ortho = (ctx->ProjectionMatrix.m[15] != 0.0F);
117 const GLfloat p10 = ctx->ProjectionMatrix.m[10];
118 const GLfloat p14 = ctx->ProjectionMatrix.m[14];
119 const GLfloat tz = ctx->Viewport._WindowMap.m[MAT_TZ];
120 const GLfloat szInv = 1.0F / ctx->Viewport._WindowMap.m[MAT_SZ];
121 GLuint i;
122
123 /*
124 * Note: to compute eyeZ from the ndcZ we have to solve the following:
125 *
126 * p[10] * eyeZ + p[14] * eyeW
127 * ndcZ = ---------------------------
128 * p[11] * eyeZ + p[15] * eyeW
129 *
130 * Thus:
131 *
132 * p[14] * eyeW - p[15] * eyeW * ndcZ
133 * eyeZ = ----------------------------------
134 * p[11] * ndcZ - p[10]
135 *
136 * If we note:
137 * a) if using an orthographic projection, p[11] = 0 and p[15] = 1.
138 * b) if using a perspective projection, p[11] = -1 and p[15] = 0.
139 * c) we assume eyeW = 1 (not always true- glVertex4)
140 *
141 * Then we can simplify the calculation of eyeZ quite a bit. We do
142 * separate calculations for the orthographic and perspective cases below.
143 * Note that we drop a negative sign or two since they don't matter.
144 */
145
146 switch (ctx->Fog.Mode) {
147 case GL_LINEAR:
148 {
149 GLfloat fogEnd = ctx->Fog.End;
150 GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
151 if (ortho) {
152 for (i=0;i<n;i++) {
153 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
154 GLfloat eyez = (ndcz - p14) / p10;
155 if (eyez < 0.0)
156 eyez = -eyez;
157 fogcoord[i] = FloatToFixed((fogEnd - eyez) * fogScale);
158 }
159 }
160 else {
161 /* perspective */
162 for (i=0;i<n;i++) {
163 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
164 GLfloat eyez = p14 / (ndcz + p10);
165 if (eyez < 0.0)
166 eyez = -eyez;
167 fogcoord[i] = FloatToFixed((fogEnd - eyez) * fogScale);
168 }
169 }
170 }
171 break;
172 case GL_EXP:
173 if (ortho) {
174 for (i=0;i<n;i++) {
175 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
176 GLfloat eyez = (ndcz - p14) / p10;
177 if (eyez < 0.0)
178 eyez = -eyez;
179 fogcoord[i] = FloatToFixed(exp( -ctx->Fog.Density * eyez ));
180 }
181 }
182 else {
183 /* perspective */
184 for (i=0;i<n;i++) {
185 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
186 GLfloat eyez = p14 / (ndcz + p10);
187 if (eyez < 0.0)
188 eyez = -eyez;
189 fogcoord[i] = FloatToFixed(exp( -ctx->Fog.Density * eyez ));
190 }
191 }
192 break;
193 case GL_EXP2:
194 {
195 GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
196 if (ortho) {
197 for (i=0;i<n;i++) {
198 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
199 GLfloat eyez = (ndcz - p14) / p10;
200 GLfloat tmp = negDensitySquared * eyez * eyez;
201 #if defined(__alpha__) || defined(__alpha)
202 /* XXX this underflow check may be needed for other systems*/
203 if (tmp < FLT_MIN_10_EXP)
204 tmp = FLT_MIN_10_EXP;
205 #endif
206 fogcoord[i] = FloatToFixed(exp( tmp ));
207 }
208 }
209 else {
210 /* perspective */
211 for (i=0;i<n;i++) {
212 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
213 GLfloat eyez = p14 / (ndcz + p10);
214 GLfloat tmp = negDensitySquared * eyez * eyez;
215 #if defined(__alpha__) || defined(__alpha)
216 /* XXX this underflow check may be needed for other systems*/
217 if (tmp < FLT_MIN_10_EXP)
218 tmp = FLT_MIN_10_EXP;
219 #endif
220 fogcoord[i] = FloatToFixed(exp( tmp ));
221 }
222 }
223 }
224 break;
225 default:
226 gl_problem(ctx, "Bad fog mode in _mesa_win_fog_coords_from_z");
227 return;
228 }
229 }
230
231
232 /*
233 * Apply fog to an array of RGBA pixels.
234 * Input: n - number of pixels
235 * z - array of integer depth values
236 * red, green, blue, alpha - pixel colors
237 * Output: red, green, blue, alpha - fogged pixel colors
238 */
239 void
240 _mesa_depth_fog_rgba_pixels( const GLcontext *ctx,
241 GLuint n, const GLdepth z[], GLchan rgba[][4] )
242 {
243 GLfixed fog[PB_SIZE];
244 ASSERT(n <= PB_SIZE);
245 _mesa_win_fog_coords_from_z( ctx, n, z, fog );
246 _mesa_fog_rgba_pixels( ctx, n, fog, rgba );
247 }
248
249
250 /*
251 * Apply fog to an array of color index pixels.
252 * Input: n - number of pixels
253 * z - array of integer depth values
254 * index - pixel color indexes
255 * Output: index - fogged pixel color indexes
256 */
257 void
258 _mesa_depth_fog_ci_pixels( const GLcontext *ctx,
259 GLuint n, const GLdepth z[], GLuint index[] )
260 {
261 GLfixed fog[PB_SIZE];
262 ASSERT(n <= PB_SIZE);
263 _mesa_win_fog_coords_from_z( ctx, n, z, fog );
264 _mesa_fog_ci_pixels( ctx, n, fog, index );
265 }
266