This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/render/intern/source/zbufferdatastruct.c
Ton Roosendaal 7fa7826da7 The zblur plugin (aka as DoF) integrated in render. Compared to patch
submitted by Alexander, changes/improvements are:

- Moved to new Panel in Scene buttons "Post Effects". Together with other
  postprocessing options, such as Edge render. It is also not called DoF,
  this because that's a bit pretending too much then. It's a zblur still!
- Made it render Alpha as well
- Made it use and deliver float buffers
- Huge cleanup of zblur.c code, was very messy. It was alling things in render
  code without need even (win matrices, transform faces, etc)
- Fixed errors in using Z values (zbuffer is signed int)
- Removed very weird gamma corrections for front/back half
- Tweaked gaussian table, allow variable 'Sigma' to be set for gauss curve
- Didn't copy 'auto focus' yet. Use of this is very limited, and gives
  false expectations, nor works for rendering anims with deamons well.

Main issue remains: it's not a very advanced feature... I still doubt
very much if this deserves to be released. Spent 2 days on trying to get
the key issues solved, with not much results.

- gauss filter code has weird side effects on large blur size
- having unsharp (blurred) in front also blurs what's around in back.
  only blurred in back with sharp in front works a little bit
- severe aliasing errors... also due the code splitting in 2 halves
- doesnt work with unified yet
- won't work for halos, spot halos or transparant faces

Anyhoo... It was promised to be committed, so now artists can play with it.
Who knows it's useful after all, or some fixes can be implemented. :)
2005-04-23 20:49:23 +00:00

311 lines
8.5 KiB
C

/**
* zbufferdatastruct.c
*
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*
* The z buffer consists of an array of lists. Each list holds the objects
* behind a pixel. These can be sorted for closest distance. Per object,
* we store:
* - object type
* - object index
* - minimum distance
* - maximum distance
* - oversample flags
*
* The buffer was created to fit the new unified renderpipeline. We might
* turn it into an object later on.
*
* The z buffer has an unlimited depth. The oversampling code chops at a
* certain number of faces. This number is defined in
* vanillaRenderPipe_types.h
*
* Version 1 of the z buffer inserted objects by means of linear
* search: we walk along the list until we find the right object or
* until we have to insert a new one. This is terribly inefficient
* when we are dealing with large numbers of objects. Can we find a
* better solution here?
*
* Because we treat halos as billboards, we optimize halo
* insertion. For this purpose the fillFlatObject() functions have
* been implemented. */
#include <string.h>
#include "MEM_guardedalloc.h"
#include "zbufferdatastruct.h"
#include "vanillaRenderPipe_types.h"
#include "render.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
/* if defined: all jittersamples are stored individually. _very_ serious */
/* performance hit ! also gives some buffer size problems in big scenes */
#define RE_INDIVIDUAL_SUBPIXELS
/* ------------------------------------------------------------------------- */
static RE_APixstrExtMain RE_apsemfirst; /* pixstr bookkeeping var */
static short RE_apsemteller = 0; /* pixstr bookkeeping var */
static int RE_zbufferwidth; /* width of the z-buffer (pixels) */
RE_APixstrExt *APixbufExt; /* Zbuffer: linked list of face, halo indices */
/*-RE_APixstrExt------------------------------------------------------------ */
void initZbuffer(int width)
{
APixbufExt = MEM_callocN(RE_ZBUFLEN * width * sizeof(RE_APixstrExt),
"APixbufExt");
RE_zbufferwidth = width;
RE_apsemteller = 0;
RE_apsemfirst.next = NULL;
RE_apsemfirst.ps = NULL;
} /* end of RE_APixstrExt *initZbufferDataStruct() */
/* ------------------------------------------------------------------------- */
void freeZbuffer(void)
{
if (APixbufExt) MEM_freeN(APixbufExt);
freepseA();
} /* end of void freeZbuffer(void) */
/* ------------------------------------------------------------------------- */
void resetZbuffer(void)
{
int len;
freepseA();
len = sizeof(RE_APixstrExt) * RE_zbufferwidth * RE_ZBUFLEN;
memset(APixbufExt, 0, len);
} /* end of void resetZbuffer(void) */
/* ------------------------------------------------------------------------- */
RE_APixstrExt *addpsemainA()
{
RE_APixstrExtMain *psm;
psm= &RE_apsemfirst;
while(psm->next) {
psm= psm->next;
}
psm->next= MEM_callocN(sizeof(RE_APixstrExtMain), "addpsemainA");
psm= psm->next;
/* Initialise the new structure to safe values. Memory that is newly */
/* allocated must be zero... Not sure if that happens everywhere now.*/
psm->next=0;
psm->ps= MEM_callocN(4096*sizeof(RE_APixstrExt),"pixstrext");
RE_apsemteller= 0;
return psm->ps;
} /* End of RE_APixstrExt *addpsemainA() */
/* ------------------------------------------------------------------------- */
void freepseA()
{
RE_APixstrExtMain *psm, *next;
psm= &RE_apsemfirst;
while(psm) {
next= psm->next;
if(psm->ps) {
MEM_freeN(psm->ps);
psm->ps= 0;
}
if(psm!= &RE_apsemfirst) MEM_freeN(psm);
psm= next;
}
RE_apsemfirst.next= 0;
RE_apsemfirst.ps= 0;
RE_apsemteller= 0;
} /* End of void freepseA() */
/* ------------------------------------------------------------------------- */
RE_APixstrExt *addpseA(void)
{
static RE_APixstrExt *prev;
/* eerste PS maken */
if((RE_apsemteller & 4095)==0) prev= addpsemainA();
else prev++;
RE_apsemteller++;
return prev;
} /* End of RE_APixstrExt *addpseA(void) */
/* ------------------------------------------------------------------------- */
void insertObject(int apteller,
int obindex,
int obtype,
int dist,
int mask)
{
/* Guard the insertion if needed? */
RE_APixstrExt* apn = &APixbufExt[apteller];
int all_subpixels= 0; // not used now... (ton)
while(apn) {
if(apn->t[0] == RE_NONE) {
apn->p[0] = obindex; apn->t[0] = obtype;
apn->zmin[0] = dist; apn->zmax[0] = dist;
apn->mask[0] = mask;
break;
}
else if(all_subpixels==0) {
if((apn->p[0] == obindex) && (apn->t[0] & obtype)) {
if(dist < apn->zmin[0]) apn->zmin[0] = dist;
else if(dist > apn->zmax[0]) apn->zmax[0] = dist;
apn->mask[0]|= mask;
break;
}
}
if(apn->t[1] == RE_NONE) {
apn->p[1] = obindex; apn->t[1] = obtype;
apn->zmin[1] = dist; apn->zmax[1] = dist;
apn->mask[1] = mask;
break;
}
else if(all_subpixels==0) {
if((apn->p[1] == obindex) && (apn->t[1] & obtype)) {
if(dist < apn->zmin[1]) apn->zmin[1] = dist;
else if(dist > apn->zmax[1]) apn->zmax[1] = dist;
apn->mask[1]|= mask;
break;
}
}
if(apn->t[2] == RE_NONE) {
apn->p[2] = obindex; apn->t[2] = obtype;
apn->zmin[2] = dist; apn->zmax[2] = dist;
apn->mask[2] = mask;
break;
}
else if(all_subpixels==0) {
if((apn->p[2] == obindex) && (apn->t[2] & obtype)) {
if(dist < apn->zmin[2]) apn->zmin[2] = dist;
else if(dist > apn->zmax[2]) apn->zmax[2] = dist;
apn->mask[2]|= mask;
break;
}
}
if(apn->t[3] == RE_NONE) {
apn->p[3] = obindex; apn->t[3] = obtype;
apn->zmin[3] = dist; apn->zmax[3] = dist;
apn->mask[3] = mask;
break;
}
else if(all_subpixels==0) {
if((apn->p[3] == obindex) && (apn->t[3] & obtype)) {
if(dist < apn->zmin[3]) apn->zmin[3] = dist;
else if(dist > apn->zmax[3]) apn->zmax[3] = dist;
apn->mask[3]|= mask;
break;
}
}
if(apn->next==0) apn->next= addpseA();
apn= apn->next;
}
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
/* This function might be helped by an end-of-list marker */
void insertFlatObjectNoOsa(RE_APixstrExt *ap,
int obindex,
int obtype,
int dist,
int mask)
{
int counter=0;
while(ap) {
if(ap->t[0] == RE_NONE) {
ap->p[0] = obindex; ap->zmin[0] = dist;
ap->zmax[0] = dist; ap->mask[0] = mask;
ap->t[0] = obtype;
break;
}
else if(ap->t[0] & RE_SOLID) if( dist > ap->zmin[0] ) break;
if(ap->t[1] == RE_NONE) {
ap->p[1] = obindex; ap->zmin[1] = dist;
ap->zmax[1] = dist; ap->mask[1] = mask;
ap->t[1] = obtype;
break;
}
else if(ap->t[1] & RE_SOLID) if( dist > ap->zmin[1] ) break;
if(ap->t[2] == RE_NONE) {
ap->p[2] = obindex; ap->zmin[2] = dist;
ap->zmax[2] = dist; ap->mask[2] = mask;
ap->t[2] = obtype;
break;
}
else if(ap->t[2] & RE_SOLID) if( dist > ap->zmin[2] ) break;
if(ap->t[3] == RE_NONE) {
ap->p[3] = obindex; ap->zmin[3] = dist;
ap->zmax[3] = dist; ap->mask[3] = mask;
ap->t[3] = obtype;
break;
}
else if(ap->t[3] & RE_SOLID) if( dist > ap->zmin[3] ) break;
counter+= 4;
if(counter > RE_MAX_FACES_PER_PIXEL) break;
if(ap->next==0) ap->next= addpseA();
ap= ap->next;
};
}
/* ------------------------------------------------------------------------- */
/* EOF */