1 /* $Id: s_pointtemp.h,v 1.16 2002/05/27 17:04:53 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
29 * Point rendering template code.
31 * Set FLAGS = bitwise-OR of the following tokens:
33 * RGBA = do rgba instead of color index
34 * SMOOTH = do antialiasing
35 * TEXTURE = do texture coords
36 * SPECULAR = do separate specular color
37 * LARGE = do points with diameter > 1 pixel
38 * ATTENUATE = compute point size attenuation
39 * SPRITE = GL_NV_point_sprite
41 * Notes: LARGE and ATTENUATE are exclusive of each other.
42 * TEXTURE requires RGBA
43 * SPECULAR requires TEXTURE
48 * NOTES on antialiased point rasterization:
50 * Let d = distance of fragment center from vertex.
52 * fragment has 100% coverage
53 * else if d > rmax2 then
54 * fragment has 0% coverage
56 * fragment has % coverage = (d - rmin2) / (rmax2 - rmin2)
62 NAME ( GLcontext
*ctx
, const SWvertex
*vert
)
67 #if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE)
73 #if (FLAGS & RGBA) && (FLAGS & SMOOTH)
74 const GLchan red
= vert
->color
[0];
75 const GLchan green
= vert
->color
[1];
76 const GLchan blue
= vert
->color
[2];
77 const GLchan alpha
= vert
->color
[3];
80 struct sw_span
*span
= SWRAST_CONTEXT(ctx
)->span
;
82 /* Cull primitives with malformed coordinates.
85 float tmp
= vert
->win
[0] + vert
->win
[1];
86 if (IS_INF_OR_NAN(tmp
))
90 INIT_SPAN(span
, GL_POINT
, 0, SPAN_FOG
, SPAN_XY
| SPAN_Z
);
91 span
->fog
= vert
->fog
;
96 /* because we need per-fragment alpha values */
97 span
->arrayMask
|= SPAN_RGBA
;
99 /* same RGBA for all fragments */
100 span
->interpMask
|= SPAN_RGBA
;
101 span
->red
= ChanToFixed(vert
->color
[0]);
102 span
->green
= ChanToFixed(vert
->color
[1]);
103 span
->blue
= ChanToFixed(vert
->color
[2]);
104 span
->alpha
= ChanToFixed(vert
->color
[3]);
105 span
->redStep
= span
->greenStep
= span
->blueStep
= span
->alphaStep
= 0;
109 span
->interpMask
|= SPAN_SPEC
;
110 span
->specRed
= ChanToFixed(vert
->specular
[0]);
111 span
->specGreen
= ChanToFixed(vert
->specular
[1]);
112 span
->specBlue
= ChanToFixed(vert
->specular
[2]);
113 span
->specRedStep
= span
->specGreenStep
= span
->specBlueStep
= 0;
116 span
->interpMask
|= SPAN_INDEX
;
117 span
->index
= IntToFixed(vert
->index
);
121 /* but not used for sprite mode */
122 span
->interpMask
|= SPAN_TEXTURE
;
123 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
124 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
125 const GLfloat q
= vert
->texcoord
[u
][3];
126 const GLfloat invQ
= (q
== 0.0 || q
== 1.0) ? 1.0 : (1.0 / q
);
127 span
->tex
[u
][0] = vert
->texcoord
[u
][0] * invQ
;
128 span
->tex
[u
][1] = vert
->texcoord
[u
][1] * invQ
;
129 span
->tex
[u
][2] = vert
->texcoord
[u
][2] * invQ
;
131 span
->texStepX
[u
][0] = span
->texStepY
[u
][0] = 0.0;
132 span
->texStepX
[u
][1] = span
->texStepY
[u
][1] = 0.0;
133 span
->texStepX
[u
][2] = span
->texStepY
[u
][2] = 0.0;
134 span
->texStepX
[u
][3] = span
->texStepY
[u
][3] = 0.0;
139 span
->arrayMask
|= SPAN_COVERAGE
;
142 span
->arrayMask
|= SPAN_TEXTURE
;
145 #if FLAGS & ATTENUATE
146 if (vert
->pointSize
>= ctx
->Point
.Threshold
) {
147 size
= MIN2(vert
->pointSize
, ctx
->Point
.MaxSize
);
151 GLfloat dsize
= vert
->pointSize
/ ctx
->Point
.Threshold
;
152 size
= MAX2(ctx
->Point
.Threshold
, ctx
->Point
.MinSize
);
153 alphaAtten
= dsize
* dsize
;
155 #elif FLAGS & (LARGE | SMOOTH | SPRITE)
156 size
= ctx
->Point
._Size
;
159 #if FLAGS & (LARGE | ATTENUATE | SMOOTH | SPRITE)
162 const GLfloat radius
= 0.5F
* size
;
163 const GLint z
= (GLint
) (vert
->win
[2]);
166 const GLfloat rmin
= radius
- 0.7071F
; /* 0.7071 = sqrt(2)/2 */
167 const GLfloat rmax
= radius
+ 0.7071F
;
168 const GLfloat rmin2
= MAX2(0.0F
, rmin
* rmin
);
169 const GLfloat rmax2
= rmax
* rmax
;
170 const GLfloat cscale
= 1.0F
/ (rmax2
- rmin2
);
171 const GLint xmin
= (GLint
) (vert
->win
[0] - radius
);
172 const GLint xmax
= (GLint
) (vert
->win
[0] + radius
);
173 const GLint ymin
= (GLint
) (vert
->win
[1] - radius
);
174 const GLint ymax
= (GLint
) (vert
->win
[1] + radius
);
177 GLint xmin
, xmax
, ymin
, ymax
;
178 GLint iSize
= (GLint
) (size
+ 0.5F
);
180 iSize
= MAX2(1, iSize
);
184 xmin
= (GLint
) (vert
->win
[0] - iRadius
);
185 xmax
= (GLint
) (vert
->win
[0] + iRadius
);
186 ymin
= (GLint
) (vert
->win
[1] - iRadius
);
187 ymax
= (GLint
) (vert
->win
[1] + iRadius
);
191 xmin
= (GLint
) vert
->win
[0] - iRadius
+ 1;
192 xmax
= xmin
+ iSize
- 1;
193 ymin
= (GLint
) vert
->win
[1] - iRadius
+ 1;
194 ymax
= ymin
+ iSize
- 1;
199 for (y
= ymin
; y
<= ymax
; y
++) {
200 for (x
= xmin
; x
<= xmax
; x
++) {
205 /* compute coverage */
206 const GLfloat dx
= x
- vert
->win
[0] + 0.5F
;
207 const GLfloat dy
= y
- vert
->win
[1] + 0.5F
;
208 const GLfloat dist2
= dx
* dx
+ dy
* dy
;
210 if (dist2
>= rmin2
) {
211 /* compute partial coverage */
212 span
->coverage
[count
] = 1.0F
- (dist2
- rmin2
) * cscale
;
214 span
->coverage
[count
] *= 15.0; /* coverage in [0,15] */
219 span
->coverage
[count
] = 1.0F
;
222 span
->xArray
[count
] = x
;
223 span
->yArray
[count
] = y
;
224 span
->zArray
[count
] = z
;
227 span
->color
.rgba
[count
][RCOMP
] = red
;
228 span
->color
.rgba
[count
][GCOMP
] = green
;
229 span
->color
.rgba
[count
][BCOMP
] = blue
;
230 #if FLAGS & ATTENUATE
231 span
->color
.rgba
[count
][ACOMP
] = (GLchan
) (alpha
* alphaAtten
);
233 span
->color
.rgba
[count
][ACOMP
] = alpha
;
239 /* not smooth (square points) */
240 span
->xArray
[count
] = x
;
241 span
->yArray
[count
] = y
;
242 span
->zArray
[count
] = z
;
244 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
245 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
246 if (ctx
->Point
.CoordReplace
[u
]) {
247 GLfloat s
= 0.5F
+ (x
+ 0.5F
- vert
->win
[0]) / size
;
248 GLfloat t
= 0.5F
- (y
+ 0.5F
- vert
->win
[1]) / size
;
249 span
->texcoords
[u
][count
][0] = s
;
250 span
->texcoords
[u
][count
][1] = t
;
251 span
->texcoords
[u
][count
][3] = 1.0F
;
252 if (ctx
->Point
.SpriteRMode
== GL_ZERO
)
253 span
->texcoords
[u
][count
][2] = 0.0F
;
254 else if (ctx
->Point
.SpriteRMode
== GL_S
)
255 span
->texcoords
[u
][count
][2] = vert
->texcoord
[u
][0];
257 span
->texcoords
[u
][count
][2] = vert
->texcoord
[u
][2];
260 COPY_4V(span
->texcoords
[u
][count
], vert
->texcoord
[u
]);
272 #else /* LARGE | ATTENUATE | SMOOTH | SPRITE */
276 span
->xArray
[0] = (GLint
) vert
->win
[0];
277 span
->yArray
[0] = (GLint
) vert
->win
[1];
278 span
->zArray
[0] = (GLint
) vert
->win
[2];
282 #endif /* LARGE || ATTENUATE || SMOOTH */
284 ASSERT(span
->end
> 0);
286 #if FLAGS & (TEXTURE | SPRITE)
287 if (ctx
->Texture
._ReallyEnabled
)
288 _mesa_write_texture_span(ctx
, span
);
290 _mesa_write_rgba_span(ctx
, span
);
292 _mesa_write_rgba_span(ctx
, span
);
294 _mesa_write_index_span(ctx
, span
);