New: rendering in background mode (blender -b) now prints a percentage to
[blender.git] / source / blender / render / intern / source / vanillaRenderPipe.c
1 /**
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  * vanillaRenderPipe.c
31  *
32  * 28-06-2000 nzc
33  *
34  * $Id$
35  *
36  */
37
38 /*
39   The render pipe
40   ---------------
41
42   The overall results of the render pass should end up in R.rectot. This 
43   buffer already exists, and although its contents may change, its location
44   may not. A lot of other routines depend on it!
45
46 */
47
48 /* global includes */
49 #include <math.h>
50 #include <limits.h>       /* INT_MIN,MAX are used here                       */
51 #include <stdlib.h>
52 #include "MTC_vectorops.h"
53 #include "MTC_matrixops.h"
54 #include "MEM_guardedalloc.h"
55
56 #include "DNA_camera_types.h"
57 #include "DNA_object_types.h"
58 #include "BKE_global.h"
59
60 /* local includes (from the render module) */
61 #include "RE_callbacks.h"
62 #include "render.h"       /* all kinds of stuff                              */
63 #include "render_intern.h"
64 #include "zbuf.h"         /* for vergzvlak, zbufclip, zbufclipwire           */
65 #include "edgeRender.h"   /* all edge rendering stuff                        */
66 #include "pixelshading.h" /* painting the pixels                             */
67 #include "rendercore.h"
68
69 /* general calculus and data manipulation, also local                        */
70 #include "gammaCorrectionTables.h"
71 #include "jitter.h"
72 #include "pixelblending.h"
73 #include "zbufferdatastruct.h"
74
75 /* own includes */
76 #include "vanillaRenderPipe.h"
77 #include "vanillaRenderPipe_int.h"
78
79 #ifdef HAVE_CONFIG_H
80 #include <config.h>
81 #endif
82
83 /* crud */
84 #define MIN2(x,y)               ( (x)<(y) ? (x) : (y) )
85
86 /* ------------------------------------------------------------------------- */
87 /* Debug defines: disable all for production level code.                     */
88 /* These variables control faking of rendered colours, extra tracing,        */
89 /* extra error checking and such.                                            */
90 /* ------------------------------------------------------------------------- */
91
92 /* if defined: _very_ explicit tracing and checking enabled                  */
93 /*  #define RE_FULL_SAFETY */
94 /* if defined: use 'simple' alpha thresholding on oversampling               */
95 /* #define RE_SIMPLE_ALPHA_THRESHOLD */
96
97 /* ------------------------------------------------------------------------- */
98
99 /* ------------------------------------------------------------------------- */
100
101 /* External : -------------------------------------------------------------- */
102
103 extern float centLut[16];    /* Lookup for jitter offsets.                   */
104 extern unsigned int  Zsample;        /* Nr. of the currently active oversample. This */
105                              /* counter must be set explicitly by the        */
106                              /* function that builds the z-buffer.           */
107                              /* The buffer-filling functions use it.         */
108 extern float Zjitx,Zjity;    /* The x,y values for jitter offset             */
109
110 extern float Zmulx, Zmuly;   /* Some kind of scale?                          */
111
112 extern unsigned int Zvlnr;           /* Face rendering pointer and counter: these    */
113 extern VlakRen *Zvlr;        /* are used for 'caching' render results.       */
114
115  /* These function pointers are used for z buffer filling.    */
116 extern void (*zbuffunc)(float *, float *, float *);
117 extern void (*zbuflinefunc)(float *, float *);
118
119 extern char cmask[256];      /* When a pixel is supersampled, we must        */
120 extern char *centmask;       /* compute its colour on a point _on_ the face. */
121                              /* These two are used to compute an offset to   */
122                              /* guarantee we use valid coordinates.          */
123
124 /* unsorted */
125 extern float fmask[256];
126 extern unsigned short usegamtab, shortcol[4], 
127         *mask1[9], *mask2[9],/*   *igamtab1, */ *igamtab2/*,   *gamtab */;
128
129 extern RE_APixstrExt *APixbufExt;/*Zbuffer: linked list of face, halo indices*/
130
131 /* Globals : --------------------------------------------------------------- */
132
133 RE_COLBUFTYPE *AColourBuffer; /* Buffer for colours of 1 line of pixels      */
134 static int     Aminy;         /* y value of first line in the accu buffer    */
135 static int     Amaxy;         /* y value of last line in the accu buffer     */
136                               /* -also used to clip when zbuffering          */
137
138 /* Buffer width refers to the size of the buffers we build. Image size is    */
139 /* the same as R.rectx, R.recty.                                             */
140 static int     imageHeight;   /* image size in pixels in y direction         */
141 static int     imageWidth;    /* image size in pixels in x direction         */
142 static int     bufferHeight;  /* image size in pixels in y direction         */
143 static int     bufferWidth;   /* image size in pixels in x direction         */
144 static int     zBufferWidth;  /* special width because zbuffer needs to be   */
145                               /* wider */
146
147 static int     Azvoordeel;    /* A small offset for transparent rendering.   */
148 int            alphaLUT[32];  /* alpha lookuptable, for oversampling         */
149                               /* Its function has been superceded because    */
150                               /* pixels are always integrated. This          */
151                               /* performs the same normalization.            */
152 int            osaNr;         /* The oversample number. I keep it            */
153                               /* separately here, because I treat no OSA     */
154                               /* as if it were osa=1.                        */
155 RE_COLBUFTYPE  collector[4];  /* used throughout as pixel colour accu        */
156 RE_COLBUFTYPE  sampcol[RE_MAX_OSA_COUNT * 4]; /* subpixel accu buffer        */
157
158 /* ------------------------------------------------------------------------- */
159 /* Local (for now) */
160 /*  void integrateStack(struct RE_faceField* stack, */
161 /*                                      int ptr, */
162 /*                                      float x,  */
163 /*                                      float y,  */
164 /*                                      int osaNr); */
165 void integratePerSubStack(struct RE_faceField* stack,
166                                                   int ptr,
167                                                   float x, 
168                                                   float y, 
169                                                   int osaNr);
170
171 /* ------------------------------------------------------------------------- */
172
173 void zBufShadeAdvanced()
174 {
175     int      y, keepLooping = 1;
176     float xjit = 0.0, yjit = 0.0;
177
178     Zjitx=Zjity= -0.5; /* jitter preset: 0.5 pixel */
179
180         /* EDGE: for edge rendering we should compute a larger buffer, but this  */
181         /* may require modifications at a deeper level. For now, we just         */
182         /* 'ignore' edge pixels.                                                 */
183         imageHeight  = R.recty;
184         imageWidth   = R.rectx;
185         bufferHeight = R.recty;
186         bufferWidth  = R.rectx;
187    
188     /* Set osaNr. Treat 'no osa' as 'osa = 1' */
189     if(R.r.mode & R_OSA) {
190                 osaNr = R.osa;
191                 if(osaNr > 16) { /* check was moved from calcZBufLine */
192                         printf("zBufShadeAdvanced> osa too large (internal error)\n");
193                         G.afbreek= 1;
194                         return;
195                 }
196     } else {
197         /* little hack */
198         osaNr = 1;
199         xjit = jit[0][0];
200         yjit = jit[0][1];
201         jit[0][0] = 0.45;
202         jit[0][1] = 0.45;        
203     }
204
205     RE_setwindowclip(0, -1); /* just to be sure, reset the view matrix       */
206
207         initRenderBuffers(bufferWidth);
208
209         /* ugh! should be converted sooner!! */
210         switch (R.r.alphamode) {
211         case R_ALPHAKEY:        
212                 setSkyBlendingMode(RE_ALPHA_KEY);
213                 break;
214         case R_ALPHAPREMUL:     
215                 setSkyBlendingMode(RE_ALPHA_PREMUL);
216                 break;
217 /* not there... this is the default case */
218 /*      case R_ALPHASKY:         */
219 /*              setSkyBlendingMode(RE_ALPHA_SKY); */
220 /*              break; */
221         default:
222                 setSkyBlendingMode(RE_ALPHA_SKY);               
223         }
224         
225     y = 0;
226     while ( (y < bufferHeight) && keepLooping) {
227                 calcZBufLine(y);
228
229                 renderZBufLine(y);
230                 transferColourBufferToOutput(y);
231                 
232                 if(y & 1) RE_local_render_display(y-1, y, imageWidth, imageHeight, R.rectot);           
233
234                 if(RE_local_test_break()) keepLooping = 0;
235                 y++; 
236     }
237         freeRenderBuffers();
238
239         /* Edge rendering is done purely as a post-effect                        */
240         if(R.r.mode & R_EDGE) {
241                 addEdges((char*)R.rectot, imageWidth, imageHeight,
242                          osaNr,
243                          R.r.edgeint, R.r.same_mat_redux,
244                          G.compat, G.notonlysolid,
245                          R.r.edgeR, R.r.edgeG, R.r.edgeB);
246         }
247
248         add_halo_flare(); /* from rendercore */
249         
250         if (!(R.r.mode & R_OSA)) {
251                 jit[0][0] = xjit;
252                 jit[0][1] = yjit; 
253         }
254     
255 } /* end of void zbufshadeAdvanced() */
256
257 /* ------------------------------------------------------------------------- */
258
259 void initRenderBuffers(int bwidth) 
260 {
261
262     /* The +1 is needed because the fill-functions use a +1 offset when      */
263     /* filling in pixels. Mind that also the buffer-clearing function needs  */
264     /* this offset (done in calcZBufLine).                                   */
265         /* The offset is wrong: it shouldn't be there. I need to fix this still. */
266     AColourBuffer = MEM_callocN(4 * sizeof(RE_COLBUFTYPE) * bwidth, 
267                             "Acolrow");
268         zBufferWidth = bwidth + 1;
269         initZbuffer(bwidth + 1);
270
271     Aminy= -1000; /* indices of lines in the z buffer: no lines buffered     */
272     Amaxy= -1000;
273
274         /* Use slider when the gamma button is pressed. */
275         if (R.r.mode & R_GAMMA) {               
276                 makeGammaTables(R.r.gamma);
277                 setDoGamma(1);
278         } else {
279                 /*
280                   Needed for spotlights! Maybe a separate gammatable would be
281                   required here
282                 */
283                 makeGammaTables(1.0);
284                 setDoGamma(0);
285         }
286
287 } /* End of void initZBuffers(void) */
288
289 /* ------------------------------------------------------------------------- */
290
291 void freeRenderBuffers(void) {  
292     if (AColourBuffer) MEM_freeN(AColourBuffer);
293         freeZbuffer();
294 } /* End of void freeZBuffers(void) */
295
296 /* ------------------------------------------------------------------------- */
297
298 void calcZBufLine(int y)
299 {
300
301     int part;
302     int keepLooping = 1;
303
304     if(y<0) return;
305
306         /* zbuffer fix: here? */
307         Zmulx= ((float) bufferWidth)/2.0;
308         Zmuly= ((float) bufferHeight)/2.0;
309
310         
311         /* use these buffer fill functions */    
312         zbuffunc     = zBufferFillFace;
313         zbuflinefunc = zBufferFillEdge;
314             
315     /* (FORALL y: Aminy =< y =< Amaxy: y is buffered)                        */
316     if( (y < Aminy) || (y > Amaxy)) {
317         /* prepare buffer */
318         part  = (y/RE_ZBUFLEN);     /* These two lines are mystifying me...  */
319         Aminy = part * RE_ZBUFLEN;  /* Possibly for rounding things?         */
320         Amaxy = Aminy + RE_ZBUFLEN - 1;
321 /*          if(Amaxy >= R.recty) Amaxy = R.recty-1; */
322         if(Amaxy >= bufferHeight) Amaxy = bufferHeight - 1;
323                 resetZbuffer();
324         
325         Zsample = 0; /* Zsample is used internally !                         */
326         while ( (Zsample < osaNr) && keepLooping ) {
327             /* Apply jitter to this pixel. The jitter offsets are globals.   */
328             /* They are added in zbufclip()                                  */
329             /* Negative: these offsets are added to the vertex coordinates   */
330             /* so it equals translating viewpoint over the positive vector.  */
331             Zjitx= -jit[Zsample][0];
332             Zjity= -jit[Zsample][1];
333
334             keepLooping = fillZBufDistances();
335             
336             if(RE_local_test_break()) keepLooping = 0;
337             Zsample++;
338         }
339     };
340     
341 } /*End of void calcZBufLine(int y) */
342
343 /* ------------------------------------------------------------------------- */
344
345 int countAndSortPixelFaces(int zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE], 
346                            RE_APixstrExt *ap)
347 {
348     int totvlak;          /* face counter                          */
349     int i;                /* generic counter                       */
350
351     totvlak= 0;
352     while(ap) {
353         for(i=0; i<4; i++) {
354             if(ap->t[i]) {
355                 zrow[totvlak][0] = ap->zmin[i];
356                 zrow[totvlak][1] = ap->p[i];
357                 zrow[totvlak][2] = ap->mask[i];
358                 zrow[totvlak][3] = ap->t[i]; 
359                 zrow[totvlak][4] = ap->zmax[i];
360                 totvlak++;
361                 if(totvlak > (RE_MAX_FACES_PER_PIXEL - 1)) 
362                                 {
363                     totvlak = (RE_MAX_FACES_PER_PIXEL - 1);
364                                 }
365             } else break;
366         };
367         ap= ap->next;
368     }
369     
370     if(totvlak==2) { /* Sort faces ----------------------------- */
371         if(zrow[0][0] < zrow[1][0]) {
372             i= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= i;
373             i= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= i;
374             i= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= i;
375             i= zrow[0][3]; zrow[0][3]= zrow[1][3]; zrow[1][3]= i;
376             i= zrow[0][4]; zrow[0][4]= zrow[1][4]; zrow[1][4]= i;
377         } /* else: two faces, and ordering is ok */                    
378     } else if (totvlak != 1) qsort(zrow, totvlak, 
379                                    sizeof(int)*RE_PIXELFIELDSIZE, vergzvlak);   
380     return totvlak;
381 } /* end of int countAndSortPixelFaces(int* zrow,RE_APixstrExt *ap ) */
382
383 /* ------------------------------------------------------------------------- */
384 /* Oversampler v3 - check CVS for older versions                             */
385 /*                                                                           */
386 /* In this version, I have split up the rendering into several parts, so I   */
387 /* can generate better profiles.                                             */
388 /*                                                                           */
389 /* - multiple blend functions ?                                              */
390 /* - x-rays?                                                                 */
391 /* - volumetric stuff ?                                                      */
392 /* - maybe the oversampling should move to the shading part                  */
393 /*                                                                           */
394 /* ------------------------------------------------------------------------- */
395
396 /* These variables describe the buffers needed for the oversampling.         */
397 /* 1. A bit vector with flags to indicate which pixels have received colour. */
398 static int            VR_covered = 0;
399 /* 2. The local vector collector, for resolving conflicts only. */
400 static int            VR_cbuf[RE_MAX_FACES_PER_PIXEL][2];
401
402 /** 
403  * Analyze the z-buffer, and pre-sample the colours.
404  */
405 int composeStack(int zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE],
406                                  struct RE_faceField* stack, int ptr,
407                                  int totvlak, float x, float y, int osaNr) {
408
409     float  xs = 0.0;
410     float  ys = 0.0;  /* coordinates for the render-spot              */
411
412     float  alphathreshold[RE_MAX_OSA_COUNT];
413         float colbuf[4];
414     int    inconflict          = 0;
415     int    saturationthreshold = 0;
416     int    saturated           = 0;
417         int    i                   = 0;
418         int    Ccount              = 0;
419     int    Cthresh             = 0;
420         int    save_totvlak        = totvlak;
421         int    fullsubpixelflags   = 0;
422
423         VR_covered = 0;
424     for(i = 0; i < osaNr; i++) alphathreshold[i] = 0.0;
425     saturationthreshold = ( (1<<osaNr) - 1);
426
427     while ( (!saturated || (saturated && inconflict) ) && (totvlak > 0) ) {
428         totvlak--;
429                         
430         i= centmask[ zrow[totvlak][RE_MASK] ]; /* recenter sample position - */
431         xs= (float)x+centLut[i &  15];
432         ys= (float)y+centLut[i >> 4];
433         
434         /* stack face ----------- */
435                 stack[ptr].mask     = zrow[totvlak][RE_MASK];
436                 stack[ptr].data     = renderPixel(xs, ys, zrow[totvlak], stack[ptr].mask);
437                 stack[ptr].faceType = zrow[totvlak][RE_TYPE];
438         cpFloatColV(collector, stack[ptr].colour);
439
440                 /* This is done so that spothalos are properly overlayed on halos    */
441                 /* maybe we need to check the colour here...                         */
442                 if(zrow[totvlak][RE_TYPE] & RE_POLY) VR_covered |= zrow[totvlak][RE_MASK]; 
443                 
444         /* calculate conflict parameters: ---------------------------------- */
445         if( zrow[totvlak][RE_ZMIN] < Cthresh ) {
446             inconflict = 1;
447                         /* Prevent from switching on bad data. This may be done more     */
448                         /* efficiently later on. It is _quite_ important.                */
449                         if (totvlak == save_totvlak - 1) Ccount = 0;
450                         else if(Ccount == 0)             Ccount = 2;
451                         else                             Ccount++;
452                         stack[ptr].conflictCount = Ccount;
453             if (zrow[totvlak][RE_ZMAX] > Cthresh) 
454                                 Cthresh = zrow[totvlak][RE_ZMAX]; 
455         } else { 
456             Cthresh         = zrow[totvlak][RE_ZMAX];
457             Ccount          = 0;
458                         stack[ptr].conflictCount = 0;
459             if (totvlak > 0 )
460                                 inconflict = (zrow[totvlak-1][RE_ZMIN] < Cthresh);
461                         else inconflict = 0;
462         }
463
464                 ptr++;
465                 
466                 /* alpha threshold ------------------------------------------------- */
467                 /* There are currently two ways of blending: alpha-over, and add.    */
468                 /* Add-blending does strange things, in the sense that alpha is      */
469                 /* simply added, and colour is sort of alpha-over blended. Using the */
470                 /* same thresholding relation seems to work ok. For less than unity  */
471                 /* add factor, the alpha threshold may rise faster, but currently we */
472                 /* do not check for this factor.                                     */
473                 for(i = 0; i < osaNr; i++) {
474                         if ( zrow[totvlak][RE_MASK] & (1<<i)) {
475                                 alphathreshold[i] += 
476                                         ((1.0 - alphathreshold[i]) * collector[3]);
477                                 if (alphathreshold[i] > RE_FULL_ALPHA_FLOAT) 
478                                         fullsubpixelflags |= (1<<i);
479                         }
480                 }
481                 saturated = (fullsubpixelflags >= saturationthreshold);
482
483     } /* done stacking ----------------------------------------------------- */
484
485         /*
486           STACK_SKY Sometimes, a sky pixel is needed. Since there are
487           some issues with mist/ ztra/ env, I always put the sky here.
488         */
489 /*      if (!saturated) { */
490         totvlak--;
491
492         xs= (float)x;
493         ys= (float)y;
494
495         /* code identical for rendering empty sky pixel */
496         renderSkyPixelFloat(xs, ys);
497         cpFloatColV(collector, colbuf);
498
499         if(R.flag & R_LAMPHALO) {
500                 renderSpotHaloPixel(x, y, collector);
501                 addAlphaOverFloat(colbuf, collector);
502         }
503
504         stack[ptr].faceType      = RE_SKY;
505         cpFloatColV(colbuf, stack[ptr].colour);
506         stack[ptr].data          = NULL;
507         stack[ptr].mask          = 0xFFFF;
508         stack[ptr].conflictCount = 0;
509         ptr++;
510 /*      } */
511
512         /* Index of the top of the stack */
513         return ptr;
514 }
515
516 /*
517   Start resolving the conflict: the stack is primed to the top-most valid
518   layer on the stack. Call this layer n. Layer n has a conflict count of c.
519   This means layers [ n - c, ..., n ]
520  */
521 int resolveConflict(struct RE_faceField* stack, int ptr, float x, float y) {
522         int face;
523     int layer;
524     float dx, dy;
525         float xs = 0.0;
526         float ys = 0.0;  /* coordinates for the render-spot              */
527         int i;
528
529     for(i = 0; i< osaNr; i++) { /* per bin, buffer all faces         */
530                 dx = jit[i][0];
531         dy = jit[i][1];
532         xs = (float)x + dx;
533                 ys = (float)y + dy;   
534
535                 face = 0;  /* only counts covering faces ------------------- */
536         layer = 0; /* counts all faces ----------------------------- */
537
538         while (layer < stack[ptr].conflictCount) {
539                         if ( (1<<i) & stack[ptr - layer].mask)  {
540                                 VR_cbuf[face][0] = 
541                                         calcDepth(xs, ys, 
542                                                           stack[ptr - layer].data,
543                                                           stack[ptr - layer].faceType);
544                 VR_cbuf[face][1] = ptr - layer;
545                 face++;
546                         }
547                         layer++;
548         }
549         qsort(VR_cbuf, face, sizeof(int)*2, vergzvlak); 
550         for(layer = 0; layer < face; layer++) {
551                         blendOverFloat(stack[VR_cbuf[layer][1]].faceType, /* type */
552                                                    sampcol + (4 * i),                 /* dest */
553                                                    stack[VR_cbuf[layer][1]].colour,   /* src */
554                                                    stack[VR_cbuf[layer][1]].data);    /* data */
555                 }
556         }
557
558         /* The number of layers that were handled. This is how many layers the   */
559         /* top-level algorithm needs to skip.                                    */
560         return stack[ptr].conflictCount;
561 }
562
563 /* The colour stack is blended down in a pretty straight-forward manner, or  */
564 /* a part of the stack is re-evaluated to resolve the conflict.              */
565 /* About 25-30% of rendering time is eaten here!                             */
566 void integrateStack(struct RE_faceField* stack, int ptr,
567                                         float x, 
568                                         float y, 
569                                         int osaNr) {
570         /* sample the colour stack: back to front ----------------------------   */
571         /*    is there a possible way to ignore alpha? this would save 25% work  */
572         ptr--;
573         /* Little different now: let ptr point to the topmost valid face.*/
574         while (ptr >= 0) {
575                 if (stack[ptr].conflictCount == 0) {
576                         /*
577                           No conflict: sample one colour into multiple bins
578                         */
579                         blendOverFloatRow(stack[ptr].faceType, 
580                                                           sampcol, 
581                                                           stack[ptr].colour,
582                                                           stack[ptr].data, 
583                                                           stack[ptr].mask, 
584                                                           osaNr);
585                         ptr--;
586                 } else {
587                         /*
588                           Recalc all z-values, and integrate per sub-pixel. 
589                         */
590                         ptr -= resolveConflict(stack, ptr, x, y);
591                 }
592         }
593
594         /* Done sampling. Now we still need to fill in pixels that were not      */
595         /* covered at all It seems strange that we have to check for empty alpha */
596         /* but somehow this is necessary. Check out the cover condition :)....   */
597
598         /* It is important that we find a more efficient algorithm here, because */
599         /* this little loop eats _lots_ of cycles.                               */
600
601         /* Should be integrated in the rest of the rendering... */
602
603         if(R.flag & R_LAMPHALO) {
604                 float halocol[4];
605                 int i;
606                 
607                 renderSpotHaloPixel(x, y, halocol);
608                 /* test seems to be wrong? */
609                 if (halocol[3] > RE_EMPTY_COLOUR_FLOAT) {
610                         for (i = 0; i < osaNr; i++) { 
611                                 /* here's a pinch: if the pixel was only covered by a halo,  */
612                                 /* we still need to fill spothalo. How do we detect this?    */
613                                 if (!(VR_covered & (1 << i)))
614                                         /* maybe a copy is enough here... */
615                                         addAlphaOverFloat(sampcol + (4 * i), halocol);
616                         }
617                 }
618         } 
619 }
620
621 /**
622  * New approach: sample substacks. Each substack is first copied into
623  * a stack buffer, and then blended down.
624  * */
625 void integratePerSubStack(struct RE_faceField* stack,
626                                                   int ptr,
627                                                   float x, 
628                                                   float y, 
629                                                   int osaNr) {
630         int i = 0;
631         int j = 0;
632         int k = 0;
633         int l = 0;
634         int filterMask = 0;
635         /* next step would be to improve on the substack, I guess */
636         int subStack[RE_MAX_FACES_PER_PIXEL + 1];
637         float colSubStack[4 * (RE_MAX_FACES_PER_PIXEL + 1)];
638         int subStackPtr = 0;
639         int subStackSize = 0;
640         float xs, ys;
641
642         
643         while (i < osaNr) {
644                 xs = x + jit[i][0];
645                 ys = y + jit[i][1];
646                 
647                 /*
648                  *  1. Copy all relevant faces. Mind that stack is built from
649                  *  low index = low z to high index =high z. The sub-stack is
650                  *  exactly the other way around! (low index = high z)
651                  */
652                 filterMask = (1 << i);
653                 subStackPtr = 0;
654                 j = ptr - 1; /* the topmost valid face */
655                 while (j >= 0) {
656                         if (stack[j].conflictCount) {
657                                 /* Conflict: we sort the faces for distance right
658                                  * away. We could adapt conflict count, and adjust the
659                                  * stack later on, but that's really doing too much,
660                                  * too complicated. This is just fine.
661                                  * */
662                                 k = 0;
663                                 l = 0;
664                                 /* check whether the face intersects, and if so,
665                  * stores depth */
666                                 while (k < stack[j].conflictCount) {
667                                         if (stack[j - k].mask & filterMask) {
668                                                 VR_cbuf[l][0] = calcDepth(xs, ys,
669                                                                                                   stack[j - k].data,
670                                                                                                   stack[j - k].faceType);
671                                                 VR_cbuf[l][1] = j - k;
672                                                 l++;
673                                         }
674                                         k++;
675                                 }
676                                 /* VR_cbuf now contains l pairs (distance, stackindex) */
677                                 qsort(VR_cbuf, l, sizeof(int)*2, vergzvlak); 
678                                 /*
679                                  * Now we put the sorted indices on the
680                                  * substack. qsort delivers low index = low z, which
681                                  * is the right wrong order for the substack */
682                                 k = 0;
683                                 while (k < l) {
684                                         subStack[subStackPtr] = VR_cbuf[k][1];
685                                         cpFloatColV(stack[VR_cbuf[k][1]].colour, &colSubStack[4*subStackPtr]);
686                                         subStackPtr++;
687                                         k++;
688                                 }
689                                 
690                                 j -= stack[j].conflictCount;
691                         } else {
692                                 /* no conflict */
693                                 if (stack[j].mask & filterMask) {
694                                         subStack[subStackPtr] = j;
695                                         cpFloatColV(stack[j].colour, &colSubStack[4*subStackPtr]);
696                                         subStackPtr++;
697                                 }
698                                 j--;
699                         }
700                 }
701                 subStackSize = subStackPtr;
702                 
703                 /* 2. Operations on the faces can go here for now. I might
704                  * want to mix this code with the blending. Currently, I only
705                  * handle env/ztra faces. It's a dirty patch now...*/
706                 subStackPtr = subStackSize - 1;
707                 while (subStackPtr >= 0) {
708                         /* we can make a general meachanism here for operations */
709                         if (stack[subStack[subStackPtr]].faceType == RE_POLY){ 
710                                 VlakRen* vlr = (VlakRen*) stack[subStack[subStackPtr]].data;
711                                 if (vlr->mat) {
712                                         /* ENV faces */
713                                         if (vlr->mat->mode & MA_ENV) {
714                                                 int m;
715                                                 colSubStack[4*subStackPtr]       = 0.0;
716                                                 colSubStack[(4*subStackPtr) + 1] = 0.0;
717                                                 colSubStack[(4*subStackPtr) + 2] = 0.0;
718                                                 colSubStack[(4*subStackPtr) + 3] = 0.0;
719                                                 m = subStackPtr - 1;
720                                                 while (m >= 0) {
721                                                         if (stack[subStack[m]].faceType != RE_SKY) {
722                                                                 colSubStack[4*m]       = 0.0;
723                                                                 colSubStack[(4*m) + 1] = 0.0;
724                                                                 colSubStack[(4*m) + 2] = 0.0;
725                                                                 colSubStack[(4*m) + 3] = 0.0;
726                                                         }
727                                                         m--;
728                                                 }
729                                         }
730                                         /* ZTRA faces */
731                                         else if (!(vlr->mat->mode & MA_ZTRA)) { 
732                                                 int m;
733                                                 m = subStackPtr - 1;
734                                                 while (m >= 0) {
735                                                         if (stack[subStack[m]].faceType != RE_SKY) {
736                                                                 colSubStack[4*m]       = 0.0;
737                                                                 colSubStack[(4*m) + 1] = 0.0;
738                                                                 colSubStack[(4*m) + 2] = 0.0;
739                                                                 colSubStack[(4*m) + 3] = 0.0;
740                                                         }
741                                                         m--;
742                                                 }
743                                         }
744                                 }
745                         }
746                         subStackPtr--;
747                 }
748                 
749                 /* 3. blend down */
750                 subStackPtr = 0;
751         while( subStackPtr < subStackSize ) {
752                         blendOverFloat(stack[subStack[subStackPtr]].faceType, /* type */
753                                                    sampcol + (4 * i),                 /* dest */
754                                                    &colSubStack[4 * subStackPtr],
755                                                    stack[subStack[subStackPtr]].data);    /* data */
756                         subStackPtr++;
757                 }
758                 
759                 i++;
760         }
761 }
762
763
764
765 /* ------------------------------------------------------------------------- */
766 /* Rendering: per line                                                       */
767 /*                                                                           */
768 /* For each pixel in this line, we render as follows:                        */
769 /* a. Count the number of objects buffered for this pixel, and sort on z     */
770 /* ------- Result is left in zrow                                            */
771 /* b. Shade the pixel:                                                       */
772 /*  1. From front to back: calculate the colour for this object              */
773 /*  2. Blend this colour in with the already calculated colour               */
774 /*    Repeat 1. and 2. until no faces remain.                                */
775 /*  For each pixel, a face is only rendered once, even if it is              */
776 /*  jittered. All subpixels get the colour of the weighted centre            */
777 /*  of the jitter-positions this face covers.                                */
778 /* ------- Result is left in sampcol[]                                       */
779 /* c. Copy the result to the colour buffer                                   */
780 /* d. Do gamma-corrected blending                                            */
781 /*                                                                           */
782 /* zrow may need some clarification:                                         */
783 /* 0 - min. distance                                                         */
784 /* 1 - face/halo index                                                       */
785 /* 2 - masks                                                                 */
786 /* 3 - type RE_POLY or RE_HALO                                               */
787 /* 4 - max. distance                                                         */
788 /* It is used to store copies of RE_APixstrExt records. These are sorted for */
789 /* distance, and then used for rendering pixels. zrow might be replaced by   */
790 /* an RE_APixstrExt* array                                                   */
791 /* - redo the numbering to something more logical                            */
792 void renderZBufLine(int y) {
793     int  zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE];
794     RE_APixstrExt *ap;       /* iterator for the face-lists                  */
795         int apteller;
796     int x;                   /* pixel counter                                */
797     RE_COLBUFTYPE *colbuf;   /* pointer into the line buffer                 */
798     RE_COLBUFTYPE *j = NULL; /* generic pixel pointer                        */
799     int i;                   /* yet another counter                          */
800     int stackDepth;          /* faces-behind-this-pixel counter              */
801         struct RE_faceField RE_OSAstack[RE_MAX_FACES_PER_PIXEL + 1]; 
802         int RE_OSAstack_ptr;    /* Points to the lowest empty field. The indexed */
803                             /* field is NOT readable.                        */
804         
805     /* Prepare buffers and iterators */
806     colbuf    = AColourBuffer;
807     eraseColBuf(AColourBuffer);
808     ap        = APixbufExt + (zBufferWidth * (y - Aminy));
809         apteller  = (zBufferWidth * (y - Aminy));
810         
811     /* Rendering: give the right colour to this pixel (shade it) */
812         for( x = 0; x < bufferWidth; x++, ap++, colbuf+=4) {
813                 if(ap->t[0]) {
814             /* reset sample collector */
815             j = sampcol;
816             for(i = 0; i < osaNr; i++, j+=4) { 
817                 j[0] = RE_ZERO_COLOUR_FLOAT; j[1] = RE_ZERO_COLOUR_FLOAT; 
818                 j[2] = RE_ZERO_COLOUR_FLOAT; j[3] = RE_ZERO_COLOUR_FLOAT;
819             };
820
821             /* a. count and sort number of faces */
822             stackDepth = countAndSortPixelFaces(zrow, ap);
823                         
824             /* b,c. oversample all subpixels, then integrate                 */
825                         RE_OSAstack_ptr = 0;
826                         RE_OSAstack_ptr = composeStack(zrow,
827                                                                                    RE_OSAstack, RE_OSAstack_ptr,
828                                                                                    stackDepth, x, y, osaNr);
829                         integratePerSubStack(RE_OSAstack, RE_OSAstack_ptr, 
830                                                                  x, y, osaNr); 
831                         
832                         /* d. Gamma corrected blending                                   */
833                         sampleFloatColV2FloatColV(sampcol, colbuf, osaNr);
834                 } else {
835                         /* Remember to do things back-to-front!                          */
836                         
837                         /* This is a bit dirty. Depending on sky-mode, the pixel is      */
838                         /* blended in differently.                                       */
839                         renderSkyPixelFloat(x, y);
840                         cpFloatColV(collector, colbuf);
841
842                         /* Spothalos are part of the normal pixelshader, so for covered  */
843                         /* pixels they are handled ok. They are 'normally' alpha blended */
844                         /* onto the existing colour in the collector.                    */
845                         if(R.flag & R_LAMPHALO) {
846                                 renderSpotHaloPixel(x, y, collector);
847                                 addAlphaOverFloat(colbuf, collector);
848                         }
849                         
850                 }
851     } /* End of pixel loop */
852     
853 } /* End of void renderZBufLine(int y) */
854
855
856 /* ------------------------------------------------------------------------- */
857
858 int fillZBufDistances() 
859 {
860     int keepLooping = 1;
861
862     keepLooping = zBufferAllFaces(); /* Solid and transparent faces*/
863     keepLooping = zBufferAllHalos() && keepLooping; /* ...and halos*/
864     return keepLooping;
865
866 } /* End of void fillZBufDistances() */
867
868 /* ------------------------------------------------------------------------- */
869 /* Transparent faces and the 'Azvoordeel'                                    */
870 /* A transparent face can get a z-offset, which is a                         */
871 /* way of pretending the face is a bit closer than it                        */
872 /* actually is. This is used in animations, when faces                       */
873 /* that are used to glue on animated characters, items,                      */
874 /* et. need their shadows to be drawn on top of the                          */
875 /* objects they stand on. The Azvoordeel is added to                         */
876 /* the calculated z-coordinate in the buffer-fill                            */
877 /* procedures.                                                               */
878
879 /*  static int RE_treat_face_as_opaque; */
880
881 int zBufferAllFaces(void) 
882 {
883     int keepLooping = 1; 
884     int faceCounter; /* counter for face number */
885     float vec[3], hoco[4], mul, zval, fval; 
886     Material *ma=0;
887     
888     faceCounter = 0;
889
890 /*      printf("Going to buffer faces:\n"); */
891 /*      printf("\tfirst pass:\n"); */
892
893 /*      RE_treat_face_as_opaque = 1; */
894         
895         while ( (faceCounter < R.totvlak) && keepLooping) {
896                 if((faceCounter & 255)==0) { Zvlr= R.blovl[faceCounter>>8]; }
897                 else Zvlr++;
898                 
899                 ma= Zvlr->mat;
900                 
901                 /* VERY dangerous construction... zoffs is set by a slide in the ui */
902                 /* so it should be safe...                                          */
903                 if((ma->mode & (MA_ZTRA)) && (ma->zoffs != 0.0)) {
904                         mul= 0x7FFFFFFF;
905                         zval= mul*(1.0+Zvlr->v1->ho[2]/Zvlr->v1->ho[3]);
906                         
907                         VECCOPY(vec, Zvlr->v1->co);
908                         /* z is negatief, wordt anders geclipt */ 
909                         vec[2]-= ma->zoffs;
910                         RE_projectverto(vec, hoco); /* vec onto hoco */
911                         fval= mul*(1.0+hoco[2]/hoco[3]);
912                         
913                         Azvoordeel= (int) fabs(zval - fval );
914                 } else {
915                         Azvoordeel= 0;
916                 } 
917                 /* face number is used in the fill functions */
918                 Zvlnr = faceCounter + 1;
919                 
920                 if(Zvlr->flag & R_VISIBLE) { /* might test for this sooner...  */
921                         
922                         if(ma->mode & (MA_WIRE)) zbufclipwire(Zvlr);
923                         else {
924                                 zbufclip(Zvlr->v1->ho,   Zvlr->v2->ho,   Zvlr->v3->ho, 
925                                                  Zvlr->v1->clip, Zvlr->v2->clip, Zvlr->v3->clip);
926                                 if(Zvlr->v4) {
927                                         Zvlnr+= 0x800000; /* in a sense, the 'adjoint' face */
928                                         zbufclip(Zvlr->v1->ho,   Zvlr->v3->ho,   Zvlr->v4->ho, 
929                                                          Zvlr->v1->clip, Zvlr->v3->clip, Zvlr->v4->clip);
930                                 }
931                         }
932                 }
933                 if(RE_local_test_break()) keepLooping = 0; 
934                 faceCounter++;
935         }
936         
937     return keepLooping;
938 } /* End of int zBufferAllFaces(void) */
939
940 /* ------------------------------------------------------------------------- */
941 /* We cheat a little here: we only fill the halo on the first pass, and we   */
942 /* set a full complement of mask flags. This can be done because we consider */
943 /* halos to be flat (billboards), so we do not have to correct the z range   */
944 /* every time we insert a halo. Also, halos fall off to zero at the edges,   */
945 /* so we can safely render them in pixels where they do not exist.           */
946 int zBufferAllHalos(void)
947 {
948     HaloRen *har = NULL;
949     unsigned int haloCounter = 0;
950     int dist = 0;
951     int keepLooping = 1;
952     short miny = 0, maxy = 0, minx = 0, maxx = 0;
953     short ycount = 0, xcount = 0;
954     RE_APixstrExt *ap, *apoffset;
955     int mask; /* jitter mask */
956
957         if (!Zsample) 
958         {
959                 mask = (1 << osaNr) - 1 ; /* Fill all samples together */
960     
961                 while ( (haloCounter < R.tothalo) && keepLooping) {
962                         if((haloCounter & 255)==0) har= R.bloha[haloCounter>>8];
963                         else har++;
964
965                         /* Halos are sometimes wrongly kicked out of the box they belong   */
966                         /* in...                                                           */
967                         
968                         /* Only buffer the current alpha buffer contents!!! The line       */
969                         /* indices have already been clipped to picture size.              */ 
970                         minx = floor(har->xs - har->rad) - 1; /* assume min =< max is true*/
971                         if (minx < 0 ) minx = 0;
972                         maxx = ceil(har->xs + har->rad ) + 1;
973                         /* Do the extra -1 because of the +1 later on. I guess halos might */
974                         /* have to start one pixel sooner? Or maybe the lower clip should  */
975                         /* be adjusted                                                     */
976                         if (maxx >= zBufferWidth - 1) maxx = zBufferWidth - 2;
977
978                         miny = har->miny;
979                         if (miny < Aminy) miny = Aminy;
980                         maxy = har->maxy;
981                         if (maxy > Amaxy) maxy = Amaxy;
982                         
983                         if ( (minx <= maxx) && (miny <= maxy)) {            
984                                 /* distance to this halo? */
985                                 dist = har->zBufDist /*   * R.ycor  */;
986                                 /* strange that the ycor influences the z coordinate ..*/
987                                 ycount = miny;
988                                 while (ycount <= maxy) {
989                                         apoffset = APixbufExt + (zBufferWidth * (ycount - Aminy));
990                                         ap = apoffset + minx;
991                                         xcount = minx;
992                                         while (xcount <= maxx) {    
993                                                 insertFlatObjectNoOsa(ap, haloCounter, RE_HALO, dist, mask);
994                                                 xcount++;
995                                                 ap++;
996                                         }
997                                         ycount++;
998                                 }
999                         }
1000                         if(RE_local_test_break()) keepLooping = 0;
1001                         haloCounter++;
1002                 }
1003         } 
1004
1005     return keepLooping;
1006 } /* end of int zbufferAllHalos(void) */
1007
1008 /* ------------------------------------------------------------------------- */
1009 void zBufferFillHalo(void)
1010 {
1011     /* so far, intentionally empty */
1012 } /* end of void zBufferFillHalo(void) */
1013
1014 /* ------------------------------------------------------------------------- */
1015 void zBufferFillFace(float *v1, float *v2, float *v3)  
1016 {
1017         /* Coordinates of the vertices are specified in ZCS */
1018         int apteller, apoffsetteller;
1019         double z0; /* used as temp var*/
1020         double xx1;
1021         double zxd,zyd,zy0, tmp;
1022         float *minv,*maxv,*midv;
1023         register int zverg,zvlak,x;
1024         int my0,my2,sn1,sn2,rectx,zd;
1025         int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2, mask;
1026
1027         /* These used to be doubles.  We may want to change them back if the     */
1028         /* loss of accuracy proves to be a problem? There does not seem to be    */
1029         /* any performance issues here, so I'll just keep the doubles.           */
1030         /*      float vec0[3], vec1[3], vec2[3]; */
1031         double vec0[3], vec1[3], vec2[3];
1032
1033         /* MIN MAX */
1034         /* sort vertices for min mid max y value */
1035         if(v1[1]<v2[1]) {
1036                 if(v2[1]<v3[1])      { minv=v1; midv=v2; maxv=v3;}
1037                 else if(v1[1]<v3[1]) { minv=v1; midv=v3; maxv=v2;}
1038                 else                 { minv=v3; midv=v1; maxv=v2;}
1039         }
1040         else {
1041                 if(v1[1]<v3[1])          { minv=v2; midv=v1; maxv=v3;}
1042                 else if(v2[1]<v3[1]) { minv=v2; midv=v3; maxv=v1;}
1043                 else                 { minv=v3; midv=v2; maxv=v1;}
1044         }
1045
1046         if(minv[1] == maxv[1]) return;  /* security to remove 'zero' size faces */
1047
1048         my0  = ceil(minv[1]);
1049         my2  = floor(maxv[1]);
1050         omsl = floor(midv[1]);
1051
1052         /* outside the current z buffer slice: clip whole face */
1053         if( (my2 < Aminy) || (my0 > Amaxy)) return;
1054
1055         if(my0<Aminy) my0= Aminy;
1056
1057         /* EDGES : THE LONGEST */
1058         xx1= maxv[1]-minv[1];
1059         if(xx1>2.0/65536.0) {
1060                 z0= (maxv[0]-minv[0])/xx1;
1061                 
1062                 tmp= (-65536.0*z0);
1063                 dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
1064                 
1065                 tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
1066                 xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
1067         }
1068         else {
1069                 dx0= 0;
1070                 xs0= 65536.0*(MIN2(minv[0],maxv[0]));
1071         }
1072         /* EDGES : THE TOP ONE */
1073         xx1= maxv[1]-midv[1];
1074         if(xx1>2.0/65536.0) {
1075                 z0= (maxv[0]-midv[0])/xx1;
1076                 
1077                 tmp= (-65536.0*z0);
1078                 dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
1079                 
1080                 tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
1081                 xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
1082         }
1083         else {
1084                 dx1= 0;
1085                 xs1= 65536.0*(MIN2(midv[0],maxv[0]));
1086         }
1087         /* EDGES : THE BOTTOM ONE */
1088         xx1= midv[1]-minv[1];
1089         if(xx1>2.0/65536.0) {
1090                 z0= (midv[0]-minv[0])/xx1;
1091                 
1092                 tmp= (-65536.0*z0);
1093                 dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
1094                 
1095                 tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
1096                 xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
1097         }
1098         else {
1099                 dx2= 0;
1100                 xs2= 65536.0*(MIN2(minv[0],midv[0]));
1101         }
1102
1103         /* ZBUF DX DY */
1104         /* xyz_1 = v_1 - v_2 */
1105         MTC_diff3DFF(vec1, v1, v2);
1106         /* xyz_2 = v_2 - v_3 */
1107         MTC_diff3DFF(vec2, v2, v3);
1108         /* xyz_0 = xyz_1 cross xyz_2 */
1109         MTC_cross3Double(vec0, vec1, vec2);
1110
1111         /* cross product of two of the sides is 0 => this face is too small */
1112         if(vec0[2]==0.0) return;
1113
1114         if(midv[1] == maxv[1]) omsl= my2;
1115         if(omsl < Aminy) omsl= Aminy-1;  /* make sure it takes the first loop entirely */
1116
1117         while (my2 > Amaxy) {  /* my2 can be larger */
1118                 xs0+=dx0;
1119                 if (my2<=omsl) {
1120                         xs2+= dx2;
1121                 }
1122                 else{
1123                         xs1+= dx1;
1124                 }
1125                 my2--;
1126         }
1127
1128         xx1= (vec0[0]*v1[0]+vec0[1]*v1[1])/vec0[2]+v1[2];
1129
1130         zxd= -vec0[0]/vec0[2];
1131         zyd= -vec0[1]/vec0[2];
1132         zy0= my2*zyd+xx1;
1133         zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
1134
1135         /* start-ofset in rect */
1136         /*      rectx= R.rectx;  */
1137         /* I suspect this var needs very careful setting... When edge rendering  */
1138         /* is on, this is strange */
1139         rectx = zBufferWidth;
1140         apoffsetteller = rectx*(my2-Aminy);
1141
1142         mask= 1<<Zsample;
1143         zvlak= Zvlnr;
1144
1145         xs3= 0;         /* flag */
1146         if(dx0>dx1) {
1147                 MTC_swapInt(&xs0, &xs1);
1148                 MTC_swapInt(&dx0, &dx1);
1149                 xs3= 1; /* flag */
1150
1151         }
1152
1153         for(y=my2;y>omsl;y--) {
1154
1155                 sn1= xs0>>16;
1156                 xs0+= dx0;
1157
1158                 sn2= xs1>>16;
1159                 xs1+= dx1;
1160
1161                 sn1++;
1162
1163                 if(sn2>=rectx) sn2= rectx-1;
1164                 if(sn1<0) sn1= 0;
1165                 zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
1166                 apteller = apoffsetteller + sn1;
1167                 x= sn2-sn1;
1168                 
1169                 zverg-= Azvoordeel;
1170                 
1171                 while(x>=0) {
1172                         insertObject(apteller, /*  RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, zverg, mask);
1173                         zverg+= zd;
1174                         apteller++;
1175                         x--;
1176                 }
1177                 zy0-= zyd;
1178                 apoffsetteller -= rectx;
1179         }
1180
1181         if(xs3) {
1182                 xs0= xs1;
1183                 dx0= dx1;
1184         }
1185         if(xs0>xs2) {
1186                 xs3= xs0;
1187                 xs0= xs2;
1188                 xs2= xs3;
1189                 xs3= dx0;
1190                 dx0= dx2;
1191                 dx2= xs3;
1192         }
1193
1194         for(; y>=my0; y--) {
1195
1196                 sn1= xs0>>16;
1197                 xs0+= dx0;
1198
1199                 sn2= xs2>>16;
1200                 xs2+= dx2;
1201
1202                 sn1++;
1203
1204                 if(sn2>=rectx) sn2= rectx-1;
1205                 if(sn1<0) sn1= 0;
1206                 zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
1207                 apteller = apoffsetteller + sn1;
1208                 x= sn2-sn1;
1209       
1210                 zverg-= Azvoordeel;
1211       
1212                 while(x>=0) {
1213                         insertObject(apteller, /*  RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, zverg, mask);
1214                         zverg+= zd;
1215                         apteller++;
1216                         x--;
1217                 }
1218                 
1219                 zy0-=zyd;
1220                 apoffsetteller -= rectx;
1221         }
1222 } /* end of void zBufferFillFace(float *v1, float *v2, float *v3) */
1223
1224 /* ------------------------------------------------------------------------- */
1225
1226 void zBufferFillEdge(float *vec1, float *vec2)
1227 {
1228         int apteller;
1229         int start, end, x, y, oldx, oldy, ofs;
1230         int dz, vergz, mask;
1231         float dx, dy;
1232         float v1[3], v2[3];
1233         
1234         dx= vec2[0]-vec1[0];
1235         dy= vec2[1]-vec1[1];
1236         
1237         if(fabs(dx) > fabs(dy)) {
1238
1239                 /* all lines from left to right */
1240                 if(vec1[0]<vec2[0]) {
1241                         VECCOPY(v1, vec1);
1242                         VECCOPY(v2, vec2);
1243                 }
1244                 else {
1245                         VECCOPY(v2, vec1);
1246                         VECCOPY(v1, vec2);
1247                         dx= -dx; dy= -dy;
1248                 }
1249
1250                 start= floor(v1[0]);
1251                 end= start+floor(dx);
1252                 if(end >= zBufferWidth) end = zBufferWidth - 1;
1253                 
1254                 oldy= floor(v1[1]);
1255                 dy/= dx;
1256                 
1257                 vergz= v1[2];
1258                 vergz-= Azvoordeel;
1259                 dz= (v2[2]-v1[2])/dx;
1260                 
1261                 apteller = zBufferWidth*(oldy-Aminy) +start;
1262                 mask  = 1<<Zsample;     
1263                 
1264                 if(dy<0) ofs= -zBufferWidth;
1265                 else ofs= zBufferWidth;
1266                 
1267                 for(x= start; x<=end; x++, /*  ap++, */ apteller++) {
1268                         
1269                         y= floor(v1[1]);
1270                         if(y!=oldy) {
1271                                 oldy= y;
1272                                 apteller += ofs;
1273                         }
1274                         
1275                         if(x>=0 && y>=Aminy && y<=Amaxy) {
1276                                 insertObject(apteller, /*  RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, vergz, mask);
1277                         }
1278                         
1279                         v1[1]+= dy;
1280                         vergz+= dz;
1281                 }
1282         }
1283         else {
1284         
1285                 /* all lines from top to bottom */
1286                 if(vec1[1]<vec2[1]) {
1287                         VECCOPY(v1, vec1);
1288                         VECCOPY(v2, vec2);
1289                 }
1290                 else {
1291                         VECCOPY(v2, vec1);
1292                         VECCOPY(v1, vec2);
1293                         dx= -dx; dy= -dy;
1294                 }
1295
1296                 start= floor(v1[1]);
1297                 end= start+floor(dy);
1298                 
1299                 if(start>Amaxy || end<Aminy) return;
1300                 
1301                 if(end>Amaxy) end= Amaxy;
1302                 
1303                 oldx= floor(v1[0]);
1304                 dx/= dy;
1305                 
1306                 vergz= v1[2];
1307                 vergz-= Azvoordeel;
1308                 dz= (v2[2]-v1[2])/dy;
1309
1310                 apteller = zBufferWidth*(start-Aminy) +oldx;
1311                 
1312                 mask= 1<<Zsample;
1313                                 
1314                 if(dx<0) ofs= -1;
1315                 else ofs= 1;
1316
1317                 for(y= start; y<=end; y++, apteller += zBufferWidth) {
1318                         
1319                         x= floor(v1[0]);
1320                         if(x!=oldx) {
1321                                 oldx= x;
1322                                 apteller += ofs;
1323                         }
1324                         
1325                         if(x>=0 && y>=Aminy && (x < zBufferWidth)) {
1326                                 insertObject(apteller, /*  RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, vergz, mask);
1327                         }
1328                         
1329                         v1[0]+= dx;
1330                         vergz+= dz;
1331                 }
1332         }
1333 } /* End of void zBufferFillEdge(float *vec1, float *vec2) */
1334
1335
1336 /* ------------------------------------------------------------------------- */
1337 /* Colour buffer related:                                                    */
1338 /* This transforms the 4 inputvalues RE_COLBUFTYPE to a new value            */
1339 /* It expects the values R.r.postigamma, R.r.postmul and R.r.postadd.         */
1340 /* This is the standard transformation, more elaborate tools are for later.  */
1341 /* ------------------------------------------------------------------------- */
1342 void std_transFloatColV2CharColV( RE_COLBUFTYPE *buf, char *target)
1343 {
1344         float fval;
1345         
1346         /* alpha */
1347         if(buf[3]<=0.0) target[3]= 0;
1348         else if(buf[3]>1.0) target[3]= 255;
1349         else target[3]= 255.0*buf[3];
1350         
1351         if(R.r.postgamma==1.0) {
1352                 /* r */
1353                 fval= R.r.postmul*buf[0] + R.r.postadd;
1354                 if(fval<=0.0) target[0]= 0;
1355                 else if(fval>1.0) target[0]= 255;
1356                 else target[0]= 255.0*fval;
1357
1358                 /* g */
1359                 fval= R.r.postmul*buf[1] + R.r.postadd;
1360                 if(fval<=0.0) target[1]= 0;
1361                 else if(fval>1.0) target[1]= 255;
1362                 else target[1]= 255.0*fval;
1363
1364                 /* b */
1365                 fval= R.r.postmul*buf[2] + R.r.postadd;
1366                 if(fval<=0.0) target[2]= 0;
1367                 else if(fval>1.0) target[2]= 255;
1368                 else target[2]= 255.0*fval;
1369
1370         }
1371         else {
1372                 /* putting the postmul within the pow() gives an
1373                  * easier control for the user, values from 1.0-2.0
1374                  * are relevant then
1375                  */
1376         
1377         
1378                 /* r */
1379                 fval= pow(R.r.postmul*buf[0], R.r.postigamma) + R.r.postadd;
1380                 if(fval<=0.0) target[0]= 0;
1381                 else if(fval>1.0) target[0]= 255;
1382                 else target[0]= 255.0*fval;
1383
1384                 /* g */
1385                 fval=pow( R.r.postmul*buf[1], R.r.postigamma) + R.r.postadd;
1386                 if(fval<=0.0) target[1]= 0;
1387                 else if(fval>1.0) target[1]= 255;
1388                 else target[1]= 255.0*fval;
1389
1390                 /* b */
1391                 fval= pow(R.r.postmul*buf[2], R.r.postigamma) + R.r.postadd;
1392                 if(fval<=0.0) target[2]= 0;
1393                 else if(fval>1.0) target[2]= 255;
1394                 else target[2]= 255.0*fval;
1395         }
1396
1397 } /* end of void std_transFloatColV2CharColV( RE_COLBUFTYPE *buf, uchar *target) */
1398
1399
1400 /* ----------------------------------------------------------------------------
1401
1402   Colour buffer related:
1403   
1404   The colour buffer is a buffer of a single screen line. It contains        
1405   four fields of type RE_COLBUFTYPE per pixel.
1406
1407   We can do several post-process steps. I would prefer to move them outside
1408   the render module later on, but it's ok to leave it here for now. For the
1409   time being, we have:
1410   - post-process function
1411     Does some operations with the colours.
1412         - Multiply with some factor
1413         - Add constant offset
1414         - Apply extra gamma correction (seems weird...)
1415   - key-alpha correction
1416     Key alpha means 'un-applying' the alpha. For fully covered pixels, this
1417         operation has no effect.
1418
1419 ---------------------------------------------------------------------------- */
1420 void transferColourBufferToOutput(int y)
1421 {
1422     /* Copy the contents of AColourBuffer to R.rectot + y * R.rectx */
1423     int x = 0;
1424     RE_COLBUFTYPE *buf = AColourBuffer;
1425     char *target = (char*) (R.rectot + (y * imageWidth));
1426
1427         /* Copy the first <imageWidth> pixels. We can do some more clipping on    */
1428         /* the z buffer, I think.                                                 */
1429         while (x < imageWidth) {
1430
1431                 std_transFloatColV2CharColV(buf, target);
1432                 
1433                 /* old function was: leave it for test */
1434 /*              cpFloatColV2CharColV(buf, target); */
1435
1436                 /*
1437                   Key-alpha mode:
1438                   Need to un-apply alpha if alpha is non-full. For full alpha,
1439                   the operation doesn't have effect. Do this after the post-
1440                   processing, so we can still use the benefits of that.
1441
1442                 */
1443
1444                 if (getSkyBlendingMode() == RE_ALPHA_KEY) {  
1445                         applyKeyAlphaCharCol(target);
1446                 }                               
1447                 
1448         target+=4;
1449         buf+=4;
1450         x++;
1451     }
1452 } /* end of void transferColourBufferToOutput(int y) */
1453
1454 /* ------------------------------------------------------------------------- */
1455
1456 void eraseColBuf(RE_COLBUFTYPE *buf) {
1457     /* By definition, the buffer's length is 4 * R.rectx items */
1458     int i = 0;
1459 /*      while (i < 4 * R.rectx) { */
1460     while (i < 4 * bufferWidth) {
1461         *buf = RE_ZERO_COLOUR_FLOAT;
1462         buf++; i++;
1463     }
1464 } /* End of void eraseColBuf(RE_COLBUFTYPE *buf) */
1465
1466 /* ------------------------------------------------------------------------- */
1467
1468 int calcDepth(float x, float y, void *data, int type)
1469 {
1470     float view[3];
1471         
1472     if (type & RE_POLY) {
1473         VlakRen* vlr = (VlakRen*) data;
1474         VertRen* v1;
1475         float dvlak, deler, fac, hoco_z, hoco_w;
1476         int zbuf_co;
1477         
1478         v1 = vlr->v1;
1479         
1480         /* vertex dot face normal: WCS */
1481         dvlak= v1->co[0]*vlr->n[0]+v1->co[1]*vlr->n[1]+v1->co[2]*vlr->n[2]; 
1482         
1483         /* jitter has been added to x, y ! */
1484         /* view vector view: screen coords */
1485                 view[0]= (x+(R.xstart) + 0.5  );
1486         
1487         if(R.flag & R_SEC_FIELD) {
1488             if(R.r.mode & R_ODDFIELD) view[1]= (y + R.ystart)*R.ycor;
1489             else view[1]= (y+R.ystart + 1.0)*R.ycor;
1490         } else view[1]= (y+R.ystart  + 0.5 )*R.ycor;
1491         
1492
1493                 /* for pano, another rotation in the xz plane is needed.... */
1494
1495         /* this is ok, in WCS */
1496         view[2]= -R.viewfac;  /* distance to viewplane */
1497         
1498         /* face normal dot view vector: but how can this work? */
1499                 deler = MTC_dot3Float(vlr->n, view);
1500         if (deler!=0.0) fac = dvlak/deler;
1501         else fac = 0.0;
1502         
1503         /* indices are wrong.... but gives almost the right value? */
1504         hoco_z =  (fac*view[2]) * R.winmat[2][2] + R.winmat[3][2]; 
1505         hoco_w =  (fac*view[2]) * R.winmat[2][3] + R.winmat[3][3]; 
1506         
1507         zbuf_co = 0x7FFFFFFF*(hoco_z/hoco_w);            
1508         
1509         return  zbuf_co; /* z component of R.co */
1510     } else if (type & RE_HALO) {
1511         HaloRen* har = (HaloRen*) data;
1512         return har->zBufDist;
1513     }
1514     return 0;
1515 } /* end of int calcDepth(float x, float y, void* data, int type) */
1516
1517 /* Maybe these two should be in pixelblendeing.c---------------------------- */
1518
1519 void blendOverFloat(int type, float* dest, float* source, void* data)
1520 {
1521
1522     if (type & RE_POLY) {
1523         VlakRen *ver = (VlakRen*) data;
1524         if ((ver->mat != NULL) && (ver->mat->add > RE_FACE_ADD_THRESHOLD)) {
1525             char addf = (char) (ver->mat->add * 255.0);
1526             addalphaAddfacFloat(dest, source, addf);
1527         }
1528         else
1529             addAlphaOverFloat(dest, source);
1530     } else if (type & RE_HALO) {
1531         HaloRen *har= (HaloRen*) data;
1532         addalphaAddfacFloat(dest, source, har->add);
1533     } else if (type & RE_SKY) {
1534                 addAlphaOverFloat(dest, source);
1535         }
1536
1537 } /* end of void blendOverFloat(int , float*, float*, void*) */
1538
1539 /* ------------------------------------------------------------------------- */
1540 void blendOverFloatRow(int type, float* dest, float* source, 
1541                        void* data, int mask, int osaNr) 
1542 {
1543     
1544     if (type & RE_POLY) {
1545         VlakRen *ver = (VlakRen*) data;
1546         if ((ver->mat != NULL) 
1547             && (ver->mat->add > RE_FACE_ADD_THRESHOLD)) {
1548             char addf = (ver->mat->add * 255.0);
1549             addAddSampColF(dest, source, mask, osaNr, addf);
1550         } else {
1551             addOverSampColF(dest, source, mask, osaNr);
1552         }
1553     } else if (type & RE_HALO) {
1554         HaloRen *har = (HaloRen*) data;
1555         addAddSampColF(dest, source, mask, osaNr, har->add);
1556     } else if (type & RE_SKY) {
1557             addOverSampColF(dest, source, mask, osaNr);         
1558         }
1559 } /* end of void blendOverFloatRow(int, float*, float*, void*) */
1560
1561 /* ------------------------------------------------------------------------- */
1562
1563 /* eof vanillaRenderPipe.c */