[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [12211] branches/soc-2007-joeedh/source/ blender/render/intern/source: Split most of the DSM code from zbuf. c into new file dsm.c.
Joseph Eagar
joeedh at gmail.com
Sat Oct 6 20:03:37 CEST 2007
Revision: 12211
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=12211
Author: joeedh
Date: 2007-10-06 20:03:37 +0200 (Sat, 06 Oct 2007)
Log Message:
-----------
Split most of the DSM code from zbuf.c into new file dsm.c.
Modified Paths:
--------------
branches/soc-2007-joeedh/source/blender/render/intern/source/zbuf.c
Added Paths:
-----------
branches/soc-2007-joeedh/source/blender/render/intern/source/dsm.c
Added: branches/soc-2007-joeedh/source/blender/render/intern/source/dsm.c
===================================================================
--- branches/soc-2007-joeedh/source/blender/render/intern/source/dsm.c (rev 0)
+++ branches/soc-2007-joeedh/source/blender/render/intern/source/dsm.c 2007-10-06 18:03:37 UTC (rev 12211)
@@ -0,0 +1,1043 @@
+/**
+ * $Id: dsm.c 12209 2007-10-04 21:41:36Z joeedh $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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) 2007 by the Blender Foundation.
+ * All rights reserved. Copyright is specifically transferred to
+ * the blender foundation by Joseph Eagar.
+ *
+ * Contributors: Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <float.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_threads.h"
+#include "BLI_jitter.h"
+#include "BLI_memarena.h"
+
+#include "BKE_tile.h"
+#include "BKE_dsm.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_curve_types.h"
+
+#include "RE_render_ext.h"
+#include "RE_shader_ext.h"
+
+#include "gammaCorrectionTables.h"
+#include "pixelblending.h"
+#include "render_types.h"
+#include "renderpipeline.h"
+#include "renderdatabase.h"
+#include "rendercore.h"
+#include "shadbuf.h"
+#include "shading.h"
+#include "sss.h"
+#include "zbuf.h"
+
+#include "MEM_guardedalloc.h"
+
+static TCS_TilePool *deepbuffer_pool = NULL;
+
+/* prototypes */
+void DSM_DoTile(Render *re, ShadBuf *buf, DSMTile *tile, DSMBuffer *dbuf);
+int zbuffer_dsm(Render *re, RenderPart *pa, APixstr *APixbuf,
+ ListBase *apsmbase, unsigned int lay, float clipend,
+ ShadBuf *buf, ListBase *vlackbucket);
+
+static void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco);
+static APixstr *addpsmainA(ListBase *lb);
+static void freepsA(ListBase *lb);
+static APixstr *addpsA(ZSpan *zspan);
+
+void DSM_MakeTilePool(int maxbytes)
+{
+ deepbuffer_pool = TCS_MakePool(maxbytes, "dsm");
+}
+
+void DSM_FreeTilePool(void)
+{
+ if (deepbuffer_pool) TCS_FreePool(deepbuffer_pool);
+ deepbuffer_pool = NULL;
+}
+
+/*doesn't actually free the DSMBuffer struct, only direct data*/
+void DSM_FreeBuffer(DSMBuffer *dbuf)
+{
+ int i;
+
+ printf("freeing!\n");
+
+ for (i=0; i<dbuf->tilex*dbuf->tiley; i++) {
+ //printf("freeing tile arena!\n");
+
+ TCS_FreeTile(&dbuf->vfunc_rect[i]);
+ if (dbuf->vfunc_rect[i].arena) BLI_memarena_free(dbuf->vfunc_rect[i].arena);
+ }
+ MEM_freeN(dbuf->vfunc_rect);
+}
+
+#define FINDMINMAX(minx, miny, maxx, maxy, co) {\
+ if (co[0] < minx) minx = co[0];\
+ if (co[0] > maxx) maxx = co[0];\
+ if (co[1] < miny) miny = co[1];\
+ if (co[1] > maxy) maxy = co[1];}
+
+#define FINDBOUNDS(minx, miny, maxx, maxy, vlr) {\
+ minx = miny = 232634.0f;\
+ maxx = maxy = -2342343.0f;\
+ hoco_to_zco(&span, co, vlr->v1->ho);\
+ FINDMINMAX(minx, miny, maxx, maxy, co)\
+ hoco_to_zco(&span, co, vlr->v2->ho);\
+ FINDMINMAX(minx, miny, maxx, maxy, co)\
+ hoco_to_zco(&span, co, vlr->v3->ho);\
+ FINDMINMAX(minx, miny, maxx, maxy, co)\
+ if (vlr->v4) {\
+ hoco_to_zco(&span, co, vlr->v4->ho);\
+ FINDMINMAX(minx, miny, maxx, maxy, co) } }
+
+void DSM_FreeZbufferBucket(ListBase *bucket)
+{
+ VlakBucket *vbucket, *next;
+
+ for (vbucket=bucket->first; vbucket; vbucket=next) {
+ next = vbucket->next;
+ MEM_freeN(vbucket);
+ }
+}
+
+ListBase *DSM_FillZbufferBuckets(Render *re, int sizex, int sizey, int tsizex,
+ int tsizey, int tilex, int tiley, float borderx, float bordery)
+{
+ ListBase *buckets = MEM_callocN(sizeof(ListBase)*tilex*tiley, "zbucket rect");
+ VlakBucket *vlakbp;
+ VlakRen *vlr;
+ int x, y, i;
+ float minx, miny, maxx, maxy, mulx, muly, co[4];
+ ZSpan span;
+
+ memset(&span, 0, sizeof(span));
+ span.hoco_to_zco = NULL;
+ span.zmulx = mulx = ((float)sizex) / 2.0;
+ span.zmuly = muly = ((float)sizey) / 2.0;
+
+ span.zofsx = -0.5;
+ span.zofsy = -0.5;
+
+ for (i=0; i<re->totvlak; i++) {
+ if((i & 255)==0)
+ vlr= re->vlaknodes[i>>8].vlak;
+ else vlr++;
+
+ FINDBOUNDS(minx, miny, maxx, maxy, vlr);
+
+ /*if min[x/y] and max[x/y] are the same,
+ add 1 to max[x/y] and subtract 1
+ from min[x/y]. 1 is subtracted from min[x/y]
+ to handle theoretical cases of simply adding 1
+ to max[x/y] not working*/
+ minx -= borderx;
+ miny -= bordery;
+ maxx += borderx;
+ maxy += bordery;
+ if (maxx == minx) {
+ maxx += 1;
+ minx -= 1;
+ }
+ if (maxy == miny) {
+ maxy += 1;
+ miny -= 1;
+ }
+
+ if (maxx < 0) maxx = 0;
+ if (maxx >= sizex) maxx = sizex-1;
+ if (minx < 0) minx = 0;
+ if (minx >= sizex) minx = sizex-1;
+
+ if (maxy < 0) maxy = 0;
+ if (maxy >= sizey) maxy = sizey-1;
+ if (miny < 0) miny = 0;
+ if (miny >= sizey) miny = sizey-1;
+
+ minx /= tsizex;
+ miny /= tsizey;
+ maxx /= tsizex;
+ maxy /= tsizey;
+
+ //printf("after conversion, minx: %f, miny: %f, maxx: %f, maxy: %f\n", minx, miny, maxx, maxy);
+
+ for (x=minx; x<maxx; x++) {
+ for (y=miny; y<maxy; y++) {
+ vlakbp = buckets[y*tilex+x].last;
+ if (!vlakbp || (vlakbp && vlakbp->used == MAX_VLACKBUCKET)) {
+ vlakbp = MEM_mallocN(sizeof(VlakBucket), "VlackBucket");
+ vlakbp->used = 0;
+ BLI_addtail(&buckets[y*tilex+x], vlakbp);
+ }
+
+ vlakbp->nodes[vlakbp->used++] = vlr;
+ }
+ }
+ }
+
+ return buckets;
+}
+
+void DSM_CreateBuffer(Render *re, ShadBuf *buf, int tilesize)
+{
+ DSMBuffer *dbuf = MEM_mapallocN(sizeof(DSMBuffer), "DSMBuffer");
+ DSMTile *tile;
+ float fac;
+ int x, y;
+
+ if (tilesize > buf->size) tilesize = buf->size;
+
+ TCS_InitBuffer(&TCS_DeepShadowBuffer, dbuf);
+
+ if (deepbuffer_pool == NULL) printf("oh EVVVIL!\n");
+
+ /*use 7500 max elements for the 2 preallocated
+ pixel arrays DSM_DoTile() allocates. the *6
+ iirc is because the visibilty function calculation
+ kindof expands things (note this is usually more then
+ compensated by the final visibility function compression).*/
+ dbuf->max_depth = 15500*6;
+
+ dbuf->tsizex = dbuf->tsizey = tilesize;
+ dbuf->sizex = dbuf->sizey = buf->size;
+ dbuf->tilex = dbuf->tiley = buf->size / tilesize;
+
+ /*add extra tiles if necassary.
+
+ python tests indicated the + 0.000001 is needed; I have no idea why,
+ some sort of numerical error I assume. of course python uses doubles and
+ not floats, but I rather doubt that floats are going to behave any better.*/
+ fac = ((float)buf->size/(float)tilesize) + 0.0000001;
+
+ if ((int)((fac - (int)fac)*(float)tilesize) > 0.000001) {
+ dbuf->tilex += 1;
+ dbuf->tiley += 1;
+ }
+
+
+ dbuf->buckets = DSM_FillZbufferBuckets(re, dbuf->sizex, dbuf->sizey,
+ dbuf->tsizex, dbuf->tsizey, dbuf->tilex,
+ dbuf->tiley, buf->soft, buf->soft);
+
+ dbuf->vfunc_rect = MEM_mapallocN(sizeof(DSMTile)*dbuf->tilex*dbuf->tiley, "dsm tiles");
+
+ buf->dsmbuffer = dbuf;
+
+ if (G.rt==44) *((int*)0L) = 0;
+
+ for (y=0; y<dbuf->tiley; y++) {
+ for (x=0; x<dbuf->tilex; x++) {
+ tile = &dbuf->vfunc_rect[y*dbuf->tilex+x];
+
+ /*right and top border tiles arn't always the same size as the others*/
+ if (x == dbuf->tilex-1) tile->sizex = dbuf->sizex - dbuf->tsizex*x; //dbuf->sizex - dbuf->tsizex*(x-1); //tilesize - (tilesize*x - dbuf->sizex);
+ else tile->sizex = dbuf->tsizex;
+
+ if (y == dbuf->tiley-1) tile->sizey = dbuf->sizey - dbuf->tsizey*y;//tilesize - (tilesize*y - dbuf->sizey);
+ else tile->sizey = dbuf->tsizey;
+
+ tile->x = x;
+ tile->y = y;
+
+ tile->arena = BLI_memarena_new(DSM_TILE_MEMARENASIZE); /*FIXMEGREP: tweak this to find optimal value.*/
+ BLI_memarena_use_mapalloc(tile->arena);
+ tile->r_rect = BLI_memarena_alloc(tile->arena, sizeof(void*)*tile->sizex*tile->sizey);
+ tile->g_rect = BLI_memarena_alloc(tile->arena, sizeof(void*)*tile->sizex*tile->sizey);
+ tile->b_rect = BLI_memarena_alloc(tile->arena, sizeof(void*)*tile->sizex*tile->sizey);
+
+ printf("Rendering a dsm shadow tile! Tile %d of %d\n", y*dbuf->tilex+x, dbuf->tilex*dbuf->tiley);
+ DSM_DoTile(re, buf, tile, dbuf);
+ _DSM_maketile((TCS_TileBuffer*)dbuf, deepbuffer_pool, (TCS_Tile*)tile);
+ DSM_FreeZbufferBucket(&dbuf->buckets[tile->y*dbuf->tilex+tile->x]);
+ }
+ }
+
+ /*free vlak bucket rect, we don't need it any more.
+ the actual vlack buckets were freed in the above loop.*/
+ MEM_freeN(dbuf->buckets);
+}
+
+typedef struct _ClrEntry {
+ struct _ClrEntry *next, *prev;
+ ListBase *srclist;
+ int depth;
+ int p;
+ int ispolygon;
+ int samplenr;
+ float value;
+ int index; /* color component index */
+} _ClrEntry;
+
+/* comparison function for qsort, used in DSM_DoTile to sort pixel samples. */
+static int dsmvergzvlak(const void *a1, const void *a2)
+{
+ const _ClrEntry *x1=a1, *x2=a2;
+
+ if( x1->depth < x2->depth ) return -1;
+ else if( x1->depth > x2->depth) return 1;
+ /*ok they both have the same depth, sort by opacity*/
+ else {
+ if (x1->value < x2->value) return 1;
+ else if (x1->value > x2->value) return -1;
+ else return 0;
+ }
+}
+
+/*
+ This function removes extraneous points
+ from a density function. It works by
+ casting a triangular "beam" from a vertex,
+ then clipping it with subsequent vertices's
+ opacity - err and opacity + err, until it
+ no longer exists.
+
+ See original Deep Shadow Maps paper for more details.
+*/
+static void DSM_CompressFunction(MemArena *arena, DSMFunction *func, float error)
+{
+ DSMLayerSample *samp = func->samples, *cursamp, *newsamp;
+ /*start and end are slopes*/
+ double start, end, ostartpoint, oendpoint, startpoint = -1, endpoint = -1, err=error/2.0;
+ int totface=0, a=0, olda, count=0;
+
+ //if (err==0) err = 0.001;
+
+ cursamp = func->samples;
+
+ if (G.rt == 43) {
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list