From 12315f4d0e0ae993805f141f64cb8c73c5297311 Mon Sep 17 00:00:00 2001 From: Hans Lambermont Date: Sat, 12 Oct 2002 11:37:38 +0000 Subject: Initial revision --- source/blender/render/intern/Makefile | 37 + .../render/intern/include/RE_DummyShadowBuffer.h | 70 + .../render/intern/include/RE_ShadowBuffer.h | 61 + .../render/intern/include/RE_basicShadowBuffer.h | 94 + .../blender/render/intern/include/RE_callbacks.h | 84 + source/blender/render/intern/include/edgeRender.h | 63 + source/blender/render/intern/include/envmap.h | 49 + .../blender/render/intern/include/errorHandler.h | 69 + .../render/intern/include/gammaCorrectionTables.h | 79 + source/blender/render/intern/include/initrender.h | 59 + source/blender/render/intern/include/jitter.h | 50 + .../render/intern/include/old_zbuffer_types.h | 58 + .../render/intern/include/outerRenderLoop.h | 43 + .../blender/render/intern/include/pixelblending.h | 209 ++ .../render/intern/include/pixelblending_types.h | 61 + .../blender/render/intern/include/pixelshading.h | 122 + source/blender/render/intern/include/renderHelp.h | 63 + .../render/intern/include/renderPreAndPost.h | 43 + .../blender/render/intern/include/render_intern.h | 60 + source/blender/render/intern/include/rendercore.h | 117 + .../blender/render/intern/include/rendercore_int.h | 55 + source/blender/render/intern/include/shadbuf.h | 75 + .../blender/render/intern/include/shadowBuffer.h | 79 + source/blender/render/intern/include/texture.h | 86 + .../render/intern/include/vanillaRenderPipe.h | 49 + .../render/intern/include/vanillaRenderPipe_int.h | 191 ++ .../intern/include/vanillaRenderPipe_types.h | 90 + source/blender/render/intern/include/zbuf.h | 180 ++ source/blender/render/intern/include/zbuf_int.h | 203 ++ source/blender/render/intern/include/zbuf_types.h | 78 + .../render/intern/include/zbufferdatastruct.h | 99 + .../intern/include/zbufferdatastruct_types.h | 77 + source/blender/render/intern/source/Makefile | 60 + .../render/intern/source/RE_DummyShadowBuffer.cpp | 66 + .../render/intern/source/RE_basicShadowBuffer.cpp | 734 +++++ source/blender/render/intern/source/RE_callbacks.c | 159 ++ source/blender/render/intern/source/edgeRender.c | 952 +++++++ source/blender/render/intern/source/envmap.c | 689 +++++ source/blender/render/intern/source/errorHandler.c | 99 + .../render/intern/source/gammaCorrectionTables.c | 168 ++ source/blender/render/intern/source/initrender.c | 1329 +++++++++ source/blender/render/intern/source/jitter.c | 192 ++ .../blender/render/intern/source/outerRenderLoop.c | 515 ++++ .../blender/render/intern/source/pixelblending.c | 919 +++++++ source/blender/render/intern/source/pixelshading.c | 1917 +++++++++++++ source/blender/render/intern/source/renderHelp.c | 294 ++ .../render/intern/source/renderPreAndPost.c | 94 + source/blender/render/intern/source/rendercore.c | 2902 ++++++++++++++++++++ .../blender/render/intern/source/renderdatabase.c | 248 ++ source/blender/render/intern/source/shadbuf.c | 771 ++++++ .../blender/render/intern/source/shadowBuffer.cpp | 100 + .../render/intern/source/vanillaRenderPipe.c | 1654 +++++++++++ source/blender/render/intern/source/zbuf.c | 2329 ++++++++++++++++ .../render/intern/source/zbufferdatastruct.c | 342 +++ 54 files changed, 19286 insertions(+) create mode 100644 source/blender/render/intern/Makefile create mode 100644 source/blender/render/intern/include/RE_DummyShadowBuffer.h create mode 100644 source/blender/render/intern/include/RE_ShadowBuffer.h create mode 100644 source/blender/render/intern/include/RE_basicShadowBuffer.h create mode 100644 source/blender/render/intern/include/RE_callbacks.h create mode 100644 source/blender/render/intern/include/edgeRender.h create mode 100644 source/blender/render/intern/include/envmap.h create mode 100644 source/blender/render/intern/include/errorHandler.h create mode 100644 source/blender/render/intern/include/gammaCorrectionTables.h create mode 100644 source/blender/render/intern/include/initrender.h create mode 100644 source/blender/render/intern/include/jitter.h create mode 100644 source/blender/render/intern/include/old_zbuffer_types.h create mode 100644 source/blender/render/intern/include/outerRenderLoop.h create mode 100644 source/blender/render/intern/include/pixelblending.h create mode 100644 source/blender/render/intern/include/pixelblending_types.h create mode 100644 source/blender/render/intern/include/pixelshading.h create mode 100644 source/blender/render/intern/include/renderHelp.h create mode 100644 source/blender/render/intern/include/renderPreAndPost.h create mode 100644 source/blender/render/intern/include/render_intern.h create mode 100644 source/blender/render/intern/include/rendercore.h create mode 100644 source/blender/render/intern/include/rendercore_int.h create mode 100644 source/blender/render/intern/include/shadbuf.h create mode 100644 source/blender/render/intern/include/shadowBuffer.h create mode 100644 source/blender/render/intern/include/texture.h create mode 100644 source/blender/render/intern/include/vanillaRenderPipe.h create mode 100644 source/blender/render/intern/include/vanillaRenderPipe_int.h create mode 100644 source/blender/render/intern/include/vanillaRenderPipe_types.h create mode 100644 source/blender/render/intern/include/zbuf.h create mode 100644 source/blender/render/intern/include/zbuf_int.h create mode 100644 source/blender/render/intern/include/zbuf_types.h create mode 100644 source/blender/render/intern/include/zbufferdatastruct.h create mode 100644 source/blender/render/intern/include/zbufferdatastruct_types.h create mode 100644 source/blender/render/intern/source/Makefile create mode 100644 source/blender/render/intern/source/RE_DummyShadowBuffer.cpp create mode 100644 source/blender/render/intern/source/RE_basicShadowBuffer.cpp create mode 100644 source/blender/render/intern/source/RE_callbacks.c create mode 100644 source/blender/render/intern/source/edgeRender.c create mode 100644 source/blender/render/intern/source/envmap.c create mode 100644 source/blender/render/intern/source/errorHandler.c create mode 100644 source/blender/render/intern/source/gammaCorrectionTables.c create mode 100644 source/blender/render/intern/source/initrender.c create mode 100644 source/blender/render/intern/source/jitter.c create mode 100644 source/blender/render/intern/source/outerRenderLoop.c create mode 100644 source/blender/render/intern/source/pixelblending.c create mode 100644 source/blender/render/intern/source/pixelshading.c create mode 100644 source/blender/render/intern/source/renderHelp.c create mode 100644 source/blender/render/intern/source/renderPreAndPost.c create mode 100644 source/blender/render/intern/source/rendercore.c create mode 100644 source/blender/render/intern/source/renderdatabase.c create mode 100644 source/blender/render/intern/source/shadbuf.c create mode 100644 source/blender/render/intern/source/shadowBuffer.cpp create mode 100644 source/blender/render/intern/source/vanillaRenderPipe.c create mode 100644 source/blender/render/intern/source/zbuf.c create mode 100644 source/blender/render/intern/source/zbufferdatastruct.c (limited to 'source/blender/render/intern') diff --git a/source/blender/render/intern/Makefile b/source/blender/render/intern/Makefile new file mode 100644 index 00000000000..ee9969a76c8 --- /dev/null +++ b/source/blender/render/intern/Makefile @@ -0,0 +1,37 @@ +# +# $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 ***** +# +# Bounces make to subdirectories. + +SOURCEDIR = source/blender/render/intern +DIRS = source + +include nan_subdirs.mk diff --git a/source/blender/render/intern/include/RE_DummyShadowBuffer.h b/source/blender/render/intern/include/RE_DummyShadowBuffer.h new file mode 100644 index 00000000000..d5308277f6c --- /dev/null +++ b/source/blender/render/intern/include/RE_DummyShadowBuffer.h @@ -0,0 +1,70 @@ +/** + * $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 ***** + */ + +#ifndef RE_DUMMYSHADOWBUFFER_H +#define RE_DUMMYSHADOWBUFFER_H + +#include "RE_ShadowBuffer.h" + +struct LampRen; + +class RE_DummyShadowBuffer : public RE_ShadowBuffer { + + public: + /** + * Make an empty shadow buffer + */ + RE_DummyShadowBuffer(void); + + /** + * Delete and clear this buffer + */ + virtual ~RE_DummyShadowBuffer(void); + + /** + * Place this scene in the buffer + */ + virtual void importScene(struct LampRen* lar); + + /** + * Always return a fixed shadow factor. + * @param inp ignored + * @param shb ignored + * @param shadowResult a vector of 3 floats with rgb shadow values + */ + virtual void readShadowValue(struct ShadBuf *shb, + float inp, + float* shadowResult); + +}; + +#endif /* RE_SHADOWBUFFER_H */ diff --git a/source/blender/render/intern/include/RE_ShadowBuffer.h b/source/blender/render/intern/include/RE_ShadowBuffer.h new file mode 100644 index 00000000000..3b015597bb9 --- /dev/null +++ b/source/blender/render/intern/include/RE_ShadowBuffer.h @@ -0,0 +1,61 @@ +/** + * $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 ***** + */ + +#ifndef RE_SHADOWBUFFER_H +#define RE_SHADOWBUFFER_H + +#include + +struct ShadBuf; +struct LampRen; + +class RE_ShadowBuffer { + + public: + + virtual ~RE_ShadowBuffer(void){}; + /** + * Place this scene in the buffer + */ + virtual void importScene(struct LampRen* lar) = 0; + + /** + * Test the shadow factor at a location in the buffer + * @param shadowResult a vector of 3 floats with rgb shadow values + */ + virtual void readShadowValue(struct ShadBuf *shb, + float inp, + float* shadowResult) = 0; + +}; + +#endif /* RE_SHADOWBUFFER_H */ diff --git a/source/blender/render/intern/include/RE_basicShadowBuffer.h b/source/blender/render/intern/include/RE_basicShadowBuffer.h new file mode 100644 index 00000000000..8d5e9237205 --- /dev/null +++ b/source/blender/render/intern/include/RE_basicShadowBuffer.h @@ -0,0 +1,94 @@ +/** + * $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 ***** + */ + +#ifndef RE_BASICSHADOWBUFFER_H +#define RE_BASICSHADOWBUFFER_H + +#include "RE_ShadowBuffer.h" + +struct LampRen; +struct Lamp; + +class RE_BasicShadowBuffer : public RE_ShadowBuffer { + + private: + + void lrectreadRectz(int x1, int y1, int x2, int y2, char *r1); + int sizeoflampbuf(struct ShadBuf *shb); + int firstreadshadbuf(struct ShadBuf *shb, int xs, int ys, int nr); + float readshadowbuf(struct ShadBuf *shb, int xs, int ys, int zs); + float readshadowbuf_halo(struct ShadBuf *shb, int xs, int ys, int zs); + float *give_jitter_tab(int samp); + + int bias; + + public: + /** + * Make a shadow buffer from these settings + */ + RE_BasicShadowBuffer(struct LampRen *lar, float mat[][4]); + + /** + * Delete and clear this buffer + */ + virtual ~RE_BasicShadowBuffer(void); + + /** + * Calculates shadowbuffers for a vector of shadow-giving lamps + * @param lar The vector of lamps + */ + void importScene(LampRen *lar); + + /** + * Determines the shadow factor for a face and lamp. There is some + * communication with global variables here. + * @param shadres The RGB shadow factors: 1.0 for no shadow, 0.0 for complete + * shadow. There must be a float[3] to write the result to. + * @param shb The shadowbuffer to find the shadow factor in. + * @param inp The inproduct between viewvector and ? + * + */ + virtual void readShadowValue(struct ShadBuf *shb, + float inp, + float* shadowResult); + + /** + * Determines the shadow factor for lamp , between + * and . (Which CS?) + */ + float shadow_halo(LampRen *lar, float *p1, float *p2); + +}; + +#endif /* RE_BASICSHADOWBUFFER_H */ + + diff --git a/source/blender/render/intern/include/RE_callbacks.h b/source/blender/render/intern/include/RE_callbacks.h new file mode 100644 index 00000000000..30734728b4b --- /dev/null +++ b/source/blender/render/intern/include/RE_callbacks.h @@ -0,0 +1,84 @@ +/** + * $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 ***** + * Callbacks to make the renderer interact with calling modules. + */ + +#ifndef RE_CALLBACKS_H +#define RE_CALLBACKS_H + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * Test whether operation should be prematurely terminated. + * + * @returns 0 to continue, any other value to break. + */ + int RE_local_test_break(void); + + /** + * Set a red square with the argument as text as cursor. + */ + void RE_local_timecursor(int i); + + /** + * Render these lines from the renderbuffer on screen (needs better spec) + */ + void RE_local_render_display(int i, int j, int k, int l, unsigned int *m); + + /** + * Initialise a render display (needs better spec) + */ + void RE_local_init_render_display(void); + + /** + * Clear/close a render display (needs better spec) + */ + void RE_local_clear_render_display(short); + + /** + * Print render statistics. + */ + void RE_local_printrenderinfo(double time, int i); + + /** Get the data for the scene to render. */ + void RE_local_get_renderdata(void); + + /** Release the data for the scene that was rendered. */ + void RE_local_free_renderdata(void); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/render/intern/include/edgeRender.h b/source/blender/render/intern/include/edgeRender.h new file mode 100644 index 00000000000..d6e2fcb989e --- /dev/null +++ b/source/blender/render/intern/include/edgeRender.h @@ -0,0 +1,63 @@ +/* + * edgeRender.h + * + * $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 ***** + */ + +#ifndef EDGERENDER_H +#define EDGERENDER_H +/* ------------------------------------------------------------------------- */ + +/** + * Add edges to , which is of size by . Use + * samples, and intensity . indicates an extra shift in the + * image, for backwards compatibility with the old renderpipe. + * indicates which edges should be considered. The edges will be shaded + * to + */ +void +addEdges( + char * targetbuf, + int iw, + int ih, + int osanr, + short int i, + short int i_red, + int compat, + int mode, + float r, + float g, + float b + ); + +/* ------------------------------------------------------------------------- */ + +#endif /* EDGERENDER_H */ diff --git a/source/blender/render/intern/include/envmap.h b/source/blender/render/intern/include/envmap.h new file mode 100644 index 00000000000..62640454151 --- /dev/null +++ b/source/blender/render/intern/include/envmap.h @@ -0,0 +1,49 @@ +/* + * envmap_ext.h + * + * $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 ***** + */ + +#ifndef ENVMAP_EXT_H +#define ENVMAP_EXT_H + +/* no types!!! */ +/* #include "envmap_types.h" */ + +/** + * Make environment maps for all objects in the scene that have an + * environment map as texture. + * (initrender.c) + */ +void make_envmaps(void); + +#endif /* ENVMAP_EXT_H */ + diff --git a/source/blender/render/intern/include/errorHandler.h b/source/blender/render/intern/include/errorHandler.h new file mode 100644 index 00000000000..190cd0c9a35 --- /dev/null +++ b/source/blender/render/intern/include/errorHandler.h @@ -0,0 +1,69 @@ +/* + * errorHandler.h + * + * $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 ***** + */ + +#ifndef ERRORHANDLER_H +#define ERRORHANDLER_H + +/* ------------------------------------------------------------------------- */ +/* error codes */ +enum RE_RENDER_ERROR { + RE_NO_ERROR, + RE_DEPTH_MISMATCH, /* 1. conflict resolution detects a bad z value */ + RE_BAD_FACE_TYPE, /* 2. a face type switch fails */ + RE_BAD_FACE_INDEX, /* 3. tried to do an operation with a bad index */ + RE_BAD_DATA_POINTER, + RE_TRACE_COUNTER, + RE_TOO_MANY_FACES, /* 6. overflow on z-buffer depth */ + RE_EDGERENDER_WRITE_OUTSIDE_BUFFER, /* 7. write value outside buffer */ + RE_CANNOT_ALLOCATE_MEMORY, /* 8. no memory for malloc */ + RE_WRITE_OUTSIDE_COLOUR_BUFFER, /* 9. write outside colour target buffer */ + RE_MAX_ERROR +}; + +/** + * Reset all counters for the error trace + */ +void RE_errortrace_reset(void); + +/** + * Signals an error to screen. Counts repetitive errors + */ +void RE_error(int errType, char* fname); + +/** + * Signals an error, and prints an integer argument + */ +void RE_error_int(int errType, char* fname, int valye); + +#endif /* ERRORHANDLER_H */ diff --git a/source/blender/render/intern/include/gammaCorrectionTables.h b/source/blender/render/intern/include/gammaCorrectionTables.h new file mode 100644 index 00000000000..14c2d2d4a68 --- /dev/null +++ b/source/blender/render/intern/include/gammaCorrectionTables.h @@ -0,0 +1,79 @@ +/* + * gammacorrectiontables.h + * + * $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 ***** + */ + +#ifndef GAMMACORRECTIONTABLES_H +#define GAMMACORRECTIONTABLES_H + + + +/* Default gamma. For most CRTs, gamma ranges from 2.2 to 2.5 (Foley), so */ +/* 2.35 seems appropriate enough. Experience teaches a different number */ +/* though. Old blender: 2.0. It might be nice to make this a slider */ +#define RE_DEFAULT_GAMMA 2.0 +/* This 400 is sort of based on the number of intensity levels needed for */ +/* the typical dynamic range of a medium, in this case CRTs. (Foley) */ +/* (Actually, it says the number should be between 400 and 535.) */ +#define RE_GAMMA_TABLE_SIZE 400 + +/** + * Initialise the gamma lookup tables + */ +void makeGammaTables(float gamma); + +/** + * Returns true if the table is initialised, false otherwise + */ +int gammaTableIsInitialised(void); + +/** + * Apply gamma correction on col + */ +float gammaCorrect(float col); + +/** + * Apply inverse gamma correction on col + */ +float invGammaCorrect(float col); + +/** + * Tell whether or not to do gamma. + */ +int doGamma(void); + +/** + * Set/unset performing gamma corrections. + */ +void setDoGamma(int); + +#endif diff --git a/source/blender/render/intern/include/initrender.h b/source/blender/render/intern/include/initrender.h new file mode 100644 index 00000000000..06c5f032c7d --- /dev/null +++ b/source/blender/render/intern/include/initrender.h @@ -0,0 +1,59 @@ +/* + * initrender_ext.h + * + * $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 ***** + */ + +#ifndef INITRENDER_EXT_H +#define INITRENDER_EXT_H + +/* type includes */ + +#include "DNA_effect_types.h" /* for PartEff type */ +#include "render_types.h" + +/* Functions */ + +void init_def_material(void); +void init_render_jit(int nr); +float calc_weight(float *weight, int i, int j); +void defaultlamp(void); +void schrijfplaatje(char *name); +void initparts(void); +short setpart(short nr); /* return 0 als geen goede part */ +void addparttorect(short nr, Part *part); +void add_to_blurbuf(int blur); +void oldRenderLoop(void); /* Calls the old renderer. Contains the PART and FIELD loops. */ +void render(void); /* Switch between the old and the unified renderer. */ +/* void write_screendump(char *name); not here !*/ + +#endif /* INITRENDER_EXT_H */ + diff --git a/source/blender/render/intern/include/jitter.h b/source/blender/render/intern/include/jitter.h new file mode 100644 index 00000000000..eff8c7bf805 --- /dev/null +++ b/source/blender/render/intern/include/jitter.h @@ -0,0 +1,50 @@ +/* + * jitter.h + * + * $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 ***** + */ + +#ifndef JITTER_H +#define JITTER_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern float jit[64][2]; + +void initjit(float *jit, int num); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/render/intern/include/old_zbuffer_types.h b/source/blender/render/intern/include/old_zbuffer_types.h new file mode 100644 index 00000000000..7eb3159f438 --- /dev/null +++ b/source/blender/render/intern/include/old_zbuffer_types.h @@ -0,0 +1,58 @@ +/** + * $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 ***** + * Datatypes for old zbuffering algorithms. + */ + +#ifndef OLD_ZBUFFER_TYPES_H +#define OLD_ZBUFFER_TYPES_H "$Id$" + +/* ------------------------------------------------------------------------- */ + +typedef struct PixStr +{ + struct PixStr *next; + int vlak0, vlak; + unsigned int z; + unsigned int mask; + short aantal, ronde; +} PixStr; + +/* ------------------------------------------------------------------------- */ + +typedef struct PixStrMain +{ + struct PixStr *ps; + struct PixStrMain *next; +} PixStrMain; + +/* ------------------------------------------------------------------------- */ + +#endif diff --git a/source/blender/render/intern/include/outerRenderLoop.h b/source/blender/render/intern/include/outerRenderLoop.h new file mode 100644 index 00000000000..965516c9525 --- /dev/null +++ b/source/blender/render/intern/include/outerRenderLoop.h @@ -0,0 +1,43 @@ +/* + * outerRenderLoop.h + * + * $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 ***** + */ + +#ifndef OUTERRENDERLOOP_H +#define OUTERRENDERLOOP_H + +/** + * Outer loop for rendering a single picture. + */ +void unifiedRenderingLoop(void); + +#endif diff --git a/source/blender/render/intern/include/pixelblending.h b/source/blender/render/intern/include/pixelblending.h new file mode 100644 index 00000000000..39c439505e0 --- /dev/null +++ b/source/blender/render/intern/include/pixelblending.h @@ -0,0 +1,209 @@ +/* + * pixelblending_ext.h + * external interface for pixelblending + * + * $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 ***** + */ + +#ifndef PIXELBLENDING_EXT_H +#define PIXELBLENDING_EXT_H + +/* local includes */ +#include "vanillaRenderPipe_types.h" + +/* own include */ +#include "pixelblending_types.h" + +/** + * Samples pixel, depending on R.osa setting + */ +int addtosampcol(unsigned short *sampcol, unsigned short *shortcol, int mask); + +/** + * Samples pixel, bring your own R.osa setting + */ +int addToSampCol(unsigned short *sampcol, unsigned short *shortcol, int mask, int osaNr); + +/** + * Halo-add pixel, bring your own R.osa setting, and add factor + */ +void addAddSampColF(float *s, float *d, int m, int osa, char add); + +/** + * Alpha undersamples pixel, bring your own R.osa setting + */ +int addUnderSampColF(float *sampcol, float *dest, int mask, int osaNr); + +/** + * Alpha oversample pixel, bring your own R.osa setting + */ +void addOverSampColF(float *sampcol, float *dest, int mask, int osaNr); + +/** + * Convert a series of oversampled pixels into a single pixel. + * (float vecs to float vec) + */ +void sampleFloatColV2FloatColV(float *sample, float *dest, int osaNr); + +/** + * Convert a series of oversampled pixels into a single pixel. Uses R.osa to + * count the length! (short vecs to short vec) + */ +void sampleShortColV2ShortColV(unsigned short *sample, unsigned short *dest, int osaNr); + +/** + * Take colour , and apply it to using the alpha value of + * . + * @param doel + * @param bron + */ +void addAlphaOverShort(unsigned short *doel, unsigned short *bron); + +/** + * Take colour , and apply it to using the alpha value of + * . + * @param doel + * @param bron + */ +void addAlphaUnderShort(unsigned short *doel, unsigned short *bron); + +/** + * Alpha-over blending for floats. + */ +void addAlphaOverFloat(float *dest, float *source); + +/** + * Alpha-under blending for floats. + */ +void addAlphaUnderFloat(float *dest, float *source); + +/** + * Write a 16-bit-colour colour vector to a 8-bit-colour colour vector. + */ +void cpShortColV2CharColV(unsigned short *source, char *dest); + +/** + * Write a 8-bit-colour colour vector to a 16-bit-colour colour vector. + */ +void cpCharColV2ShortColV(char *source, unsigned short *dest); + +/** + * Write a 32-bit-colour colour vector to a 8-bit-colour colour vector. + */ +void cpIntColV2CharColV(unsigned int *source, char *dest); + +/** + * Write a floating-point-colour colour vector to a 8-bit-colour colour + * vector. Clip colours to [0, 1]. + */ +void cpFloatColV2CharColV(float *source, char *dest); + +/** + * Cpoy a 8-bit-colour vector to floating point colour vector. + */ +void cpCharColV2FloatColV(char *source, float *dest); +/** + * Cpoy a 16-bit-colour vector to floating point colour vector. + */ +void cpShortColV2FloatColV(unsigned short *source, float *dest); + +/** + * Copy a float-colour colour vector. + */ +void cpFloatColV(float *source, float *dest); + +/** + * Copy a 16-bit-colour colour vector. + */ +void cpShortColV(unsigned short *source, unsigned short *dest); + +/** + * Copy an 8-bit-colour colour vector. + */ +void cpCharColV(char *source, char *dest); + +/** + * Add a fraction of to . Result ends up in . + * The internal calculation is done with floats. + * + * col(dest) = (1 - alpha(source)*(1 - addfac)) * dest + source + * alpha(dest) = alpha(source) + alpha (dest) + */ +void addalphaAddfacShort(unsigned short *dest, unsigned short *source, char addfac); + +/** + * Same for floats + */ +void addalphaAddfacFloat(float *dest, float *source, char addfac); + +/** + * Add two halos. Result ends up in . This should be the + * addition of two light sources. So far, I use normal alpha-under blending here. + * The internal calculation is done with floats. The add-factors have to be + * compensated outside this routine. + * col(dest) = s + (1 - alpha(s))d + * alpha(dest) = alpha(s) + (1 - alpha(s))alpha (d) + */ +void addHaloToHaloShort(unsigned short *dest, unsigned short *source); + +/** + * dest = dest + source + */ +void addalphaAddFloat(float *dest, float *source); + +/** ols functions: side effects? +void addalphaUnderFloat(char *doel, char *bron); think this already exists... +void addalphaUnderGammaFloat(char *doel, char *bron); +*/ +/** + * Blend bron under doel, while doing gamma correction + */ +void addalphaUnderGammaFloat(float *doel, float *bron); + +/** + * Transform an premul-alpha 32-bit colour into a key-alpha 32-bit colour. + */ +void applyKeyAlphaCharCol(char* target); + +/* Old blending functions */ +void keyalpha(char *doel); /* maakt premul 255 */ +void addalphaUnder(char *doel, char *bron); +void addalphaUnderGamma(char *doel, char *bron); +void addalphaOver(char *doel, char *bron); +void addalphaAdd(char *doel, char *bron); +void addalphaAddshort(unsigned short *doel, unsigned short *bron); +/* void addalphaAddfac(char *doel, char *bron, char addfac); to ext, temporarily */ +void addalphaAddfacshort(unsigned short *doel, + unsigned short *bron, + short addfac); + + +#endif /* PIXELBLENDING_EXT_H */ diff --git a/source/blender/render/intern/include/pixelblending_types.h b/source/blender/render/intern/include/pixelblending_types.h new file mode 100644 index 00000000000..71e2baa994c --- /dev/null +++ b/source/blender/render/intern/include/pixelblending_types.h @@ -0,0 +1,61 @@ +/* + * pixelblending_types.h + * types pixelblending + * + * $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 ***** + */ + +#ifndef PIXELBLENDING_TYPES_H +#define PIXELBLENDING_TYPES_H + +/* #include "blender.h" */ + +/* Threshold for a 'full' pixel: pixels with alpha above this level are */ +/* considered opaque This is the decimal value for 0xFFF0 / 0xFFFF */ +#define RE_FULL_COLOUR_FLOAT 0.9998 +/* Threshold for an 'empty' pixel: pixels with alpha above this level are */ +/* considered completely transparent. This is the decimal value */ +/* for 0x000F / 0xFFFF */ +#define RE_EMPTY_COLOUR_FLOAT 0.0002 +/* A 100% pixel. Sometimes, seems to be too little.... Hm....... */ +#define RE_UNITY_COLOUR_FLOAT 1.0 +/* A 0% pixel. I wonder how 0 the 0.0 is... */ +#define RE_ZERO_COLOUR_FLOAT 0.0 + +/* threshold for alpha */ +#define RE_FULL_ALPHA_FLOAT 0.9998 + +/* Same set of defines for shorts */ +#define RE_FULL_COLOUR_SHORT 0xFFF0 +#define RE_EMPTY_COLOUR_SHORT 0x0000 + +#endif /* PIXELBLENDING_EXT_H */ + diff --git a/source/blender/render/intern/include/pixelshading.h b/source/blender/render/intern/include/pixelshading.h new file mode 100644 index 00000000000..de75e96a225 --- /dev/null +++ b/source/blender/render/intern/include/pixelshading.h @@ -0,0 +1,122 @@ +/* + * pixelshading.h + * + * These functions determine what actual colour a pixel will have. + * + * $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 ***** + */ + +#ifndef PIXELSHADING_H +#define PIXELSHADING_H + +/* ------------------------------------------------------------------------- */ + +#include "render.h" +#include "vanillaRenderPipe_types.h" +/* ------------------------------------------------------------------------- */ + +/** + * Render the pixel at (x,y) for object ap. Apply the jitter mask. + * Output is given in float collector[4]. The type vector: + * t[0] - min. distance + * t[1] - face/halo index + * t[2] - jitter mask + * t[3] - type ZB_POLY or ZB_HALO + * t[4] - max. distance + * @return pointer to the object + */ +void *renderPixel(float x, float y, int *t); + +/** + * Spothalos on otherwise empty pixels. + */ +void renderSpotHaloPixel(float x, float y, float* colbuf); + +/** + * Set the sky blending to the indicated type. + */ +void setSkyBlendingMode(enum RE_SkyAlphaBlendingType mode); + +/** + * Get the sky blending mode. + */ +enum RE_SkyAlphaBlendingType getSkyBlendingMode(void); +/** + * Render the sky at pixel (x, y). + */ +void renderSkyPixelFloat(float x, float y); + +/* ------------------------------------------------------------------------- */ +/* All these are supposed to be internal. I should move these to a separate */ +/* header. */ + +/** + * Determine colour for pixel at SCS x,y for face . Result end up in + * + * @return pointer to this object's VlakRen + */ +void *renderFacePixel(float x, float y, int vlaknr); + +/** + * Render this pixel for halo haloNr. Leave result in . + * @return pointer to this object's HaloRen + */ +void *renderHaloPixel(float x, float y, int haloNr); + +/** + * Shade the halo at the given location + */ +void shadeHaloFloat(HaloRen *har, float *col, unsigned int zz, + float dist, float xn, float yn, short flarec); + +/** + * Shade a sky pixel on a certain line, into collector[4] + * The x-coordinate (y as well, actually) are communicated through + * R.view[3] + */ +void shadeSkyPixel(float x, float y); + +void shadeSpotHaloPixelFloat(float *col); +void spotHaloFloat(struct LampRen *lar, float *view, float *intens); +void shadeLampLusFloat(void); + +/* this should be replaced by shadeSpotHaloPixelFloat(), but there's */ +/* something completely fucked up here with the arith. */ +/* void renderspothaloFix(unsigned short *col); */ +void renderspothaloFix(float *col); + +/* used by shadeSkyPixel: */ +void shadeSkyPixelFloat(float y); +void fillBackgroundImage(float x, float y); + +/* ------------------------------------------------------------------------- */ + +#endif diff --git a/source/blender/render/intern/include/renderHelp.h b/source/blender/render/intern/include/renderHelp.h new file mode 100644 index 00000000000..7e192a5460e --- /dev/null +++ b/source/blender/render/intern/include/renderHelp.h @@ -0,0 +1,63 @@ +/* + * renderhelp_ext.h + * + * $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 ***** + */ + +#ifndef RENDERHELP_EXT_H +#define RENDERHELP_EXT_H + +#ifdef __cplusplus +extern "C" { +#endif + + /* Push-pop, because this sometimes is necessary... */ + void pushTempPanoPhi(float p); + void popTempPanoPhi(void); + + float getPanoPhi(void); + float getPanovCo(void); + float getPanovSi(void); + void setPanoRot(int part); + + /** Set clip flags on all data entries, using the given projection + * function */ + void setzbufvlaggen( void (*projectfunc)(float *, float *) ); + +/* external for the time being, since the converter calls it. */ +/** Recalculate all normals on renderdata. */ +/* void set_normalflags(void); */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/render/intern/include/renderPreAndPost.h b/source/blender/render/intern/include/renderPreAndPost.h new file mode 100644 index 00000000000..74438f10df7 --- /dev/null +++ b/source/blender/render/intern/include/renderPreAndPost.h @@ -0,0 +1,43 @@ +/* + * renderpreandpost.h + * + * $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 ***** + */ + +#ifndef RENDERPREANDPOST_H +#define RENDERPREANDPOST_H + +void prepareScene(void); +void finalizeScene(void); +void doClipping( void (*projectfunc)(float *, float *) ); + + +#endif diff --git a/source/blender/render/intern/include/render_intern.h b/source/blender/render/intern/include/render_intern.h new file mode 100644 index 00000000000..1f058821b2b --- /dev/null +++ b/source/blender/render/intern/include/render_intern.h @@ -0,0 +1,60 @@ +/* + * render_int.h + * misc internal defines for renderer + * + * $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 ***** + */ + + /* XXX, should die, no good reason to write + * regular (non-file related) endian dependant + * code. + */ +#if defined(__sgi) || defined(__sparc) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +#define RCOMP 3 +#define GCOMP 2 +#define BCOMP 1 +#define ACOMP 0 +#else +#define RCOMP 0 +#define GCOMP 1 +#define BCOMP 2 +#define ACOMP 3 +#endif + +#define VECCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);} +#define QUATCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2); *(v1+3)= *(v2+3);} + +#define CLAMPIS(a, b, c) ((a)<(b) ? (b) : (a)>(c) ? (c) : (a)) + +typedef struct { + int a, b, c, d; +} byte16; +#define COPY_16(a,b) (*((byte16 *)(a))= *((byte16 *)(b))) diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h new file mode 100644 index 00000000000..6138fbc3e3a --- /dev/null +++ b/source/blender/render/intern/include/rendercore.h @@ -0,0 +1,117 @@ +/* + * rendercore_ext.h + * + * $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 ***** + */ + +#ifndef RENDERCORE_H +#define RENDERCORE_H +#include "render_types.h" + +struct HaloRen; + +float mistfactor(float *co); /* dist en hoogte, return alpha */ +/* void sky(char *col); */ +void renderspothalo(unsigned short *col); +void render_lighting_halo(struct HaloRen *har, float *colf); +unsigned int calchalo_z(struct HaloRen *har, unsigned int zz); +float CookTorr(float *n, float *l, float *v, int hard); +void shadelamplus(void); +/* void renderflare(struct HaloRen *har); */ +void add_halo_flare(void); + +/** + * Apply the background (sky). Depending on the active alphamode and + * worldmode, different filling strategies are applied. + * Active alphamode = R.r.alphamode + * Active worldmode = R.wrld.mode + *
  • + * R_ALPHAPREMUL - do not fill sky, but apply alpha to colours + * R_ALPHAKEY - do not fill sky, do not apply alpha to colours + * R_ADDSKY - fill skycolour in the background, blend + * transparent colours with the background + * (there's also a world dependency here? + *
  • + * R.wrld.mode == WO_MIST + * R.r.bufflag == 1, R.flag == R_SEC_FIELD + * R.wrld.skytype == ( WO_SKYBLEND ^ WO_SKYTEX) + * R.wrld.skytype == WO_SKYPAPER + * R.r.mode == R_PANORAMA ) + *
  • + * + * @param rect + * @param y + */ +void scanlinesky(char *rect, int y); + +/** + * Do z buffer stuff. + */ +void zbufshade(void); + +/** + * Insert transparent faces into the z buffer? + */ +void zbufshadeDA(void); /* Delta Accum Pixel Struct */ + +/** + * Also called in: zbuf.c + */ +void shadepixel(float x, float y, int vlaknr); + +/** + * Shade the pixel at xn, yn for halo har, and write the result to col. + * Also called in: previewrender.c + * @param har The halo to be rendered on this location + * @param col [unsigned int 3] The destination colour vector + * @param zz Some kind of distance + * @param dist Square of the distance of this coordinate to the halo's center + * @param x [f] Pixel x relative to center + * @param y [f] Pixel y relative to center + * @param flarec Flare counter? Always har->flarec... + */ +/* void shadehalo(struct HaloRen *har, char *col, unsigned int zz, float dist, float x, float y, short flarec); */ + +/** + * A cryptic but very efficient way of counting the number of bits that + * is set in the unsigned short. + */ +int count_mask(unsigned short mask); + +/* These defines are only used internally :) */ +/* dirty hack: pointers are negative, indices positive */ +/* pointers should be converted to positive numbers */ + +#define IS_A_POINTER_CODE(a) ((a)<0) +#define POINTER_FROM_CODE(a) ((void *)(-(a))) +#define POINTER_TO_CODE(a) (-(long)(a)) + +#endif /* RENDER_EXT_H */ diff --git a/source/blender/render/intern/include/rendercore_int.h b/source/blender/render/intern/include/rendercore_int.h new file mode 100644 index 00000000000..8b1fd0ed759 --- /dev/null +++ b/source/blender/render/intern/include/rendercore_int.h @@ -0,0 +1,55 @@ +/* + * render_int.h + * + * $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 ***** + */ + +#ifndef RENDER_INT_H +#define RENDER_INT_H + +#include "zbuf_types.h" +#include "render_types.h" + +/* float CookTorr(float *n, float *l, float *v, int hard); */ +void do_lamphalo_tex(LampRen *lar, float *p1, float *p2, float *intens); +void spothalo(struct LampRen *lar, float *view, float *intens); +void add_filt_mask(unsigned int mask, unsigned short *col, unsigned int *rb1, unsigned int *rb2, unsigned int *rb3); +void addps(long *rd, int vlak, unsigned int z, short ronde); +PixStr *addpsmain(void); +float count_maskf(unsigned short mask); +void freeps(void); +void halovert(void); +void renderhalo(HaloRen *har); /* postprocess versie */ +void scanlinehaloPS(unsigned int *rectz, long *rectdelta, unsigned int *rectt, short ys); + + +#endif /* RENDER_INT_H */ + diff --git a/source/blender/render/intern/include/shadbuf.h b/source/blender/render/intern/include/shadbuf.h new file mode 100644 index 00000000000..6060edfed95 --- /dev/null +++ b/source/blender/render/intern/include/shadbuf.h @@ -0,0 +1,75 @@ +/* + * shadbuf_ext.h + * + * $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 ***** + */ + +#ifndef SHADBUF_EXT_H +#define SHADBUF_EXT_H + +#include "render_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Init memory for old-style shodow buffers. */ +void initshadowbuf(struct LampRen *lar, float mat[][4]); + + +/** + * Calculates shadowbuffers for a vector of shadow-giving lamps + * @param lar The vector of lamps + */ +void makeshadowbuf(LampRen *lar); + +/** + * Determines the shadow factor for a face and lamp. There is some + * communication with global variables here. + * @returns The shadow factors: 1.0 for no shadow, 0.0 for complete + * shadow. + * @param shb The shadowbuffer to find the shadow factor in. + * @param inp The inproduct between viewvector and ? + * + */ +float testshadowbuf(struct ShadBuf *shb, float inp); + +/** + * Determines the shadow factor for lamp , between + * and . (Which CS?) + */ +float shadow_halo(LampRen *lar, float *p1, float *p2); + +#ifdef __cplusplus +} +#endif + +#endif /* SHADBUF_EXT_H */ diff --git a/source/blender/render/intern/include/shadowBuffer.h b/source/blender/render/intern/include/shadowBuffer.h new file mode 100644 index 00000000000..4df95c20674 --- /dev/null +++ b/source/blender/render/intern/include/shadowBuffer.h @@ -0,0 +1,79 @@ +/** + * $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 ***** + */ + +#ifndef SHADOWBUFFER_H +#define SHADOWBUFFER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef RE_SHADOWBUFFERHANDLE +#define RE_SHADOWBUFFERHANDLE +#define RE_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name +RE_DECLARE_HANDLE(RE_ShadowBufferHandle); +#endif + + struct ShadBuf; + struct LampRen; + +/** + * Calculates shadowbuffers for a vector of shadow-giving lamps + * @param lar The vector of lamps + * @returns a handle to the buffer + */ + extern void RE_buildShadowBuffer(RE_ShadowBufferHandle dsbh, + struct LampRen *lar); + +/** + * Determines the shadow factor for a face and lamp. There is some + * communication with global variables here? Should be made explicit... + * @param shadres The RGB shadow factors: 1.0 for no shadow, 0.0 for complete + * shadow. There must be a float[3] to write the result to. + * @param shb The shadowbuffer to find the shadow factor in. + * @param inp The inproduct between viewvector and ? + * + */ + void RE_testshadowbuf(RE_ShadowBufferHandle dsbh, + struct ShadBuf* shbp, + float inp, + float* shadres); + +/** + * Determines a shadow factor for halo-shadows. + */ + +#ifdef __cplusplus +} +#endif + +#endif /* SHADOWBUFFER_H */ diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h new file mode 100644 index 00000000000..9d033ac26dd --- /dev/null +++ b/source/blender/render/intern/include/texture.h @@ -0,0 +1,86 @@ +/* + * texture_ext.h + * + * $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 ***** + */ + +#ifndef TEXTURE_EXT_H +#define TEXTURE_EXT_H "$Id$" +#define TEXTURE_EXT_H "Copyright (C) 2001 NaN Technologies B.V. + +/* no types!!! */ +/* #include "texture_types.h" */ + +struct Tex; +struct MTex; +struct HaloRen; +struct LampRen; +/** + * Takes uv coordinates (R.uv[], O.dxuv, O.dyuv), find texture colour + * at that spot (using imagewrap()). + * Result is kept in R.vcol (float vector 3) + */ +void render_realtime_texture(void); + +/** + * Do texture mapping for materials. Communicates with R.... variables. + */ +void do_material_tex(void); + +/* unsorted */ +int blend(struct Tex *tex, float *texvec); +int clouds(struct Tex *tex, float *texvec); +int cubemap(struct MTex *mtex, float x, float y, float z, float *adr1, float *adr2); +int cubemap_glob(struct MTex *mtex, float x, float y, float z, float *adr1, float *adr2); +int cubemap_ob(struct MTex *mtex, float x, float y, float z, float *adr1, float *adr2); +void do_2d_mapping(struct MTex *mtex, float *t, float *dxt, float *dyt); +void do_halo_tex(struct HaloRen *har, float xn, float yn, float *colf); +void do_lamp_tex(struct LampRen *la, float *lavec); +void do_sky_tex(void); +int magic(struct Tex *tex, float *texvec); +int marble(struct Tex *tex, float *texvec); +int multitex(struct Tex *tex, float *texvec, float *dxt, float *dyt); +int plugintex(struct Tex *tex, float *texvec, float *dxt, float *dyt); +int stucci(struct Tex *tex, float *texvec); +int texnoise(struct Tex *tex); +int wood(struct Tex *tex, float *texvec); + +#endif /* TEXTURE_EXT_H */ + + + + + + + + + + diff --git a/source/blender/render/intern/include/vanillaRenderPipe.h b/source/blender/render/intern/include/vanillaRenderPipe.h new file mode 100644 index 00000000000..4dfaa41e91d --- /dev/null +++ b/source/blender/render/intern/include/vanillaRenderPipe.h @@ -0,0 +1,49 @@ +/* + * vanillaRenderPipe_ext.h + * + * $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 ***** + */ + +#ifndef VANILLARENDERPIPE_EXT_H +#define VANILLARENDERPIPE_EXT_H + +#include "vanillaRenderPipe_types.h" + +/** + * Render pipeline with all kinds of extras. + * status-------------------------\/ + * - integrated z buffering ok + * - integrated halo rendering ok + */ +void zBufShadeAdvanced(void); + + +#endif /* VANILLARENDERPIPE_EXT_H */ diff --git a/source/blender/render/intern/include/vanillaRenderPipe_int.h b/source/blender/render/intern/include/vanillaRenderPipe_int.h new file mode 100644 index 00000000000..024b82cc812 --- /dev/null +++ b/source/blender/render/intern/include/vanillaRenderPipe_int.h @@ -0,0 +1,191 @@ +/* + * vanillaRenderPipe_int.h + * + * $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 ***** + */ + +#ifndef VANILLARENDERPIPE_INT_H +#define VANILLARENDERPIPE_INT_H + +#include "vanillaRenderPipe_types.h" +#include "zbufferdatastruct_types.h" + +/** + * Z buffer initializer, for new pipeline. + *
  • + * AColourBuffer : colour buffer for one line + * APixbufExt : pixel data buffer for one line, depth RE_ZBUFLEN + *
  • + */ +void initRenderBuffers(int width); +/* void initRenderBuffers(void); */ + +/** + * Z buffer destructor, frees stuff from initZBuffers(). + */ +void freeRenderBuffers(void); + +/** + * Fill the accumulation buffer APixbufExt with face and halo indices. + * Note: Uses globals. + * @param y the line number to set + */ +void calcZBufLine(int y); + +/** + * Shade and render the pixels in this line, into AColourBuffer + * Note: Uses globals. + * @param y the line number to set + */ +void renderZBufLine(int y); + +/** + * Count and sort the list behind ap into buf. Sorts on min. distance. + * Low index <=> high z + */ +int countAndSortPixelFaces(int buf[RE_MAX_FACES_PER_PIXEL][5], + RE_APixstrExt *ap); + +/** + * Compose the conflict and colour stacks + * Note: Uses globals. + */ +int composeStack(int zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE], + struct RE_faceField* stack, int ptr, + int totvlak, float x, float y, int osaNr); +/** + * Integrate conflicting layers. + * Note: Uses globals. + */ +int resolveConflict(struct RE_faceField* stack, int ptr, float x, float y); + +/** + * Integrate the colour stack, defer conflicts. + * Note: Uses globals. + */ +void integrateStack(struct RE_faceField* stack, int ptr, + float x, float y, int osaNr); + +/** + * Calculate the view depth to this object on this location, with + * the current view parameters in R. + */ +int calcDepth(float x, float y, void *data, int type); + + + +/** + * Fills in distances of all faces in a z buffer, for given jitter settings. + */ +int fillZBufDistances(void); + +/** + * Fills in distances of faces in the z buffer. + * + * Halo z buffering ---------------------------------------------- + * + * A halo is treated here as a billboard: no z-extension, always + * oriented perpendicular to the viewer. The rest of the z-buffer + * stores face-numbers first, then calculates colours as the + * final image is rendered. We'll use the same approach here, + * which differs from the original method (which was add halos per + * scan line). This means that the z-buffer now also needs to + * store info about what sort of 'thing' the index refers to. + * + * Halo extension: + * h.maxy --------- + * | h.xs + h.rad + * | h.xs + * | h.xs - h.rad + * h.miny --------- + * + * These coordinates must be clipped to picture size. + * I'm not quite certain about halo numbering. + * + * Halos and jittering ------------------------------------------- + * + * Halos were not jittered previously. Now they are. I wonder + * whether this may have some adverse effects here. + + * @return 1 for succes, 0 if the operation was interrupted. + */ +int zBufferAllFaces(void); + +/** + * Fills in distances of halos in the z buffer. + * @return 1 for succes, 0 if the operation was interrupted. + */ +int zBufferAllHalos(void); + +/** + * New fill function for z buffer, for edge-only rendering. + */ +void zBufferFillEdge(float *vec1, float *vec2); + +/** + * New fill function for z buffer. + */ +void zBufferFillFace(float *v1, float *v2, float *v3); + +/** + * One more filler: fill in halo data in z buffer. + * Empty so far, but may receive content of halo loop. + */ +void zBufferFillHalo(void); + +/** + * Copy the colour buffer output to R.rectot, to line y. + */ +void transferColourBufferToOutput(int y); + +/** + * Set the colour buffer fields to zero. + */ +void eraseColBuf(RE_COLBUFTYPE *buf); + +/** + * Blend source over dest, and leave result in dest. 1 pixel. + */ +void blendOverFloat(int type, float* dest, float* source, void* data); + +/** + * Blend source over dest, and leave result in dest. 1 pixel into + * multiple bins. + */ +void blendOverFloatRow(int type, float* dest, float* source, + void* data, int mask, int osaNr) ; + +/** + * Do a post-process step on a finalized render image. + */ +void std_transFloatColV2CharColV( RE_COLBUFTYPE *buf, char *target); + +#endif /* VANILLARENDERPIPE_INT_H */ diff --git a/source/blender/render/intern/include/vanillaRenderPipe_types.h b/source/blender/render/intern/include/vanillaRenderPipe_types.h new file mode 100644 index 00000000000..90828ff62c3 --- /dev/null +++ b/source/blender/render/intern/include/vanillaRenderPipe_types.h @@ -0,0 +1,90 @@ +/* + * vanillaRenderPipe_types.h + * + * $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 ***** + */ + +#ifndef VANILLARENDERPIPE_TYPES_H +#define VANILLARENDERPIPE_TYPES_H + +/* Render defines */ +#define RE_MAX_OSA_COUNT 16 /* The max. number of possible oversamples */ +#define RE_MAX_FACES_PER_PIXEL 500 /* max. nr of faces rendered behind one */ + /* pixel */ + +enum RE_SkyAlphaBlendingType { + RE_ALPHA_NODEF = 0, + RE_ALPHA_PREMUL, + RE_ALPHA_KEY, + RE_ALPHA_SKY, + RE_ALPHA_MAX +}; + + +/* Render typedefs */ +typedef float RE_COLBUFTYPE; /* datatype for the colour buffer */ + + +/** + * Threshold for add-blending for faces + */ +#define RE_FACE_ADD_THRESHOLD 0.001 + +/** + For oversampling + + New stack: the old stack limits our freedom to do all kinds of + manipulation, so we rewrite it. + + A stacked face needs: + - a face type + - a colour + - a conflict count + - a data pointer (void*) + - a mask + + The stack starts at index 0, with the closest face, and stacks up. + +*/ + +struct RE_faceField { + int faceType; + float colour[4]; + int conflictCount; + void *data; + int mask; +}; + + + +#endif /* VANILLARENDERPIPE_TYPES_H */ + + diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h new file mode 100644 index 00000000000..fdfa5b19abe --- /dev/null +++ b/source/blender/render/intern/include/zbuf.h @@ -0,0 +1,180 @@ +/* + * zbuf_ext.h + * external interface for zbuf.h + * + * $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 ***** + */ + +#ifndef ZBUF_H +#define ZBUF_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct LampRen; +struct VlakRen; + +/*-----------------------------------------------------------*/ +/* Includes */ +/*-----------------------------------------------------------*/ + +#include "zbuf_types.h" +#include "render_types.h" +#include "radio_types.h" /* for RadView */ + +/*-----------------------------------------------------------*/ +/* Function */ +/* (11 so far ) */ +/*-----------------------------------------------------------*/ + +/** + * Fill a 'rectangle' with a fixed value. The rectangle contains x by + * y points. The rows are assumed to be contiguous in memory, and to + * consist of uints. This function is used for initializing the z + * buffer. + * (why is x int and y uint? called in envmap, render, zbuf) + * @param rect Pointer to the data representing the rectangle. + * @param x The width of the rectangle + * @param y The height of the rectangle + * @param val The value used to fill the rectangle. + */ +void fillrect(unsigned int *rect, int x, unsigned int y, unsigned int val); + +/** + * Converts a world coordinate into a homogenous coordinate in view + * coordinates. The transformation matrix is only allowed to have a + * scaling and translation component. + * Also called in: shadbuf.c render.c radfactors.c + * initrender.c envmap.c editmesh.c + * @param v1 [3 floats] the world coordinate + * @param adr [4 floats] the homogenous view coordinate + */ +void projectvert(float *v1,float *adr); + + +/** + * Do a z buffer calculation pass for shadow calculations. + * Also called in: shadbuf.c + * Note: Uses globals. + * @param lar lamp definition data + */ +void zbuffershad(struct LampRen *lar); + + /* to the external interface, temp, I hope... */ +/** + * Tests whether the first three coordinates should be clipped + * wrt. the fourth component. Bits 1 and 2 test on x, 3 and 4 test on + * y, 5 and 6 test on z: + * xyz > test => set first bit (01), + * xyz < -test => set second bit (10), + * xyz == test => reset both bits (00). + * Note: functionality is duplicated from an internal function + * Also called in: initrender.c, radfactors.c + * @param v [4 floats] a coordinate + * @return a vector of bitfields + */ +/* int testclip(float *v); */ + + +/* The following are only used in zbuf.c and render.c ---------------*/ +/** + * Fills the entire in the alpha DA buffer. (All of it!) + * Note: Uses globals. + * Also called in: render.c + * @param y the line number to set + */ +void abufsetrow(int y); + + +/** + * Calculate the z buffer for all faces (or edges when in wireframe + * mode) presently visible. + * Note: Uses globals. + * Also called in: render.c + */ +void zbufferall(void); + + +/** + * Initialize accumulation buffers for alpha z buffering. + * The buffers are global variables. Also resets Accu buffer + * y bounds. + *
  • + * Acolrow : colour buffer for one line + * Arectz : distance buffer for one line, depth ABUFPART + * APixbuf : pixel data buffer for one line, depth ABUFPART + *
  • + * Also called in: render.c (should migrate) + * Note: Uses globals. + */ +void bgnaccumbuf(void); + +/** + * Discard accumulation buffers for alpha z buffering. + * The buffers are global variables. The released buffers are Acolrow, + * Arectz, APixBuf. + * Also called in: render.c (should migrate) + * Note: Uses globals. + */ +void endaccumbuf(void); + +/** + * Z face intersect? + */ +int vergzvlak(const void *x1, const void *x2); + +/** + * Clip and fill vertex into the z buffer. zbuffunc needs to be set + * before entering, to assure that there is a buffer fill function + * that can be called. Zvlnr must be set to the current valid face + * index . + * Note: uses globals + * @param f1 [4 floats] vertex 1 + * @param f2 [4 floats] vertex 2 + * @param f3 [4 floats] vertex 3 + * @param c1 clip conditions? + * @param c2 + * @param c3 + */ +void zbufclip(float *f1, float *f2, float *f3, int c1, int c2, int c3); + +/** + * same, for edges + */ +void zbufclipwire(struct VlakRen *vlr); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/blender/render/intern/include/zbuf_int.h b/source/blender/render/intern/include/zbuf_int.h new file mode 100644 index 00000000000..1ea416a581f --- /dev/null +++ b/source/blender/render/intern/include/zbuf_int.h @@ -0,0 +1,203 @@ +/* + * zbuf_int.h + * internal interface for zbuf.h (ie. functions that are not used + * anywhere else) + * + * $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 ***** + */ + +#ifndef ZBUF_INT_H +#define ZBUF_INT_H + +#include "render_types.h" +#include "zbuf_types.h" + + + +/** + * Convert a homogenous coordinate to a z buffer coordinate. The + * function makes use of Zmulx, Zmuly, the x and y scale factors for + * the screen, and Zjitx, Zjity, the pixel offset. (These are declared + * in render.c) The normalised z coordinate must fall on [0, 1]. + * @param zco [3, 4 floats] pointer to the resulting z buffer coordinate + * @param hoco [4 floats] pointer to the homogenous coordinate of the + * vertex in world space. + */ +void hoco_to_zco(float *zco, float *hoco); + +/** + * Fill the z buffer for alpha? + * + * This is one of the z buffer fill functions called in zbufclip() and + * zbufwireclip(). + * + * @param v1 [4 floats, world coordinates] first vertex + * @param v2 [4 floats, world coordinates] second vertex + * @param v3 [4 floats, world coordinates] third vertex + */ +void zbufinvulAc(float *v1, float *v2, float *v3); + +/** + * Fill the z buffer, but invert z order, and add the face index to + * the corresponing face buffer. + * + * This is one of the z buffer fill functions called in zbufclip() and + * zbufwireclip(). + * + * @param v1 [4 floats, world coordinates] first vertex + * @param v2 [4 floats, world coordinates] second vertex + * @param v3 [4 floats, world coordinates] third vertex + */ +void zbufinvulGLinv(float *v1, float *v2, float *v3); + +/** + * Fill the z buffer, and add the face index to + * the corresponing face buffer. Writes into R.rectz and R.rectot. It + * assumes that Zvlnr is set to the face index of the face under + * consideration. Zvlnr is written into R.rectot. R.rectz + * + * This is one of the z buffer fill functions called in zbufclip() and + * zbufwireclip(). + * + * @param v1 [4 floats, world coordinates] first vertex + * @param v2 [4 floats, world coordinates] second vertex + * @param v3 [4 floats, world coordinates] third vertex + */ +void zbufinvulGL(float *v1, float *v2, float *v3); + +/** + * Fill the z buffer. The face buffer is not operated on! + * + * This is one of the z buffer fill functions called in zbufclip() and + * zbufwireclip(). + * + * @param v1 [4 floats, world coordinates] first vertex + * @param v2 [4 floats, world coordinates] second vertex + * @param v3 [4 floats, world coordinates] third vertex + */ +void zbufinvulGL_onlyZ(float *v1, float *v2, float *v3); + +/** + * Prints 3 unlabelled floating point values to stdout. Used for diagnostics. + * @param v1 any float + * @param v2 any float + * @param v3 any float + */ +void print3floats(float *v1, float *v2, float *v3); + +/** + * Checks labda and uses this to make decision about clipping the line + * segment from v1 to v2. labda is the factor by which the vector is + * cut. ( calculate s + l * ( t - s )). The result is appended to the + * vertex list of this face. + * Note: uses globals. + * (arguments: one int, one pointer to int... why?) + * @param v1 start coordinate s + * @param v2 target coordinate t + * @param b1 + * @param b2 + * @param clve vertex vector. + */ +static void maakvertpira(float *v1, float *v2, int *b1, int b2, int *clve); + +/** + * Sets labda: flag, and parametrize the clipping of vertices in + * viewspace coordinates. labda = -1 means no clipping, labda in [0, + * 1] means a clipping. + * Note: uses globals. + * @param v1 start coordinate s + * @param v2 target coordinate t + * @param b1 + * @param b2 + * @param b3 + * @param a index for coordinate (x, y, or z) + */ +static void clipp(float *v1, float *v2, int b1, int *b2, int *b3, int a); + +/** + * Tests whether this coordinate is 'inside' or 'outside' of the view + * volume? By definition, this is in [0, 1]. + * @param p vertex z difference plus coordinate difference? + * @param q origin z plus r minus some coordinate? + * @param u1 [in/out] clip fraction for ? + * @param u2 [in/out] + * @return 0 if point is outside, or 1 if the point lies on the clip + * boundary + */ +static short cliptestf(float p, float q, float *u1, float *u2); + + +/* not documented yet */ +/* not sure if these should stay static... */ + +static int clipline(float *v1, float *v2); + +/** + * Provide book-keeping for the z buffer data lists. + */ +APixstr *addpsmainA(void); +void freepsA(void); +APixstr *addpsA(void); + +/** + * Fill function for the z buffer (fills lines) + */ +void zbuflineAc(float *vec1, float *vec2); +void zbufline(float *vec1, float *vec2); + + +/** + * Copy results from the solid face z buffering to the transparent + * buffer. + */ +void copyto_abufz(int sample); + +/** + * Do accumulation z buffering. + */ +void zbuffer_abuf(void); + +/** + * Shade this face at this location in SCS. + */ +void shadetrapixel(float x, float y, int vlak); + +/** + * Determine the distance to the camera of this halo, in ZCS. + */ +unsigned int calcHaloDist(HaloRen *har); + +#endif /* ZBUF_INT_H */ + + + + + diff --git a/source/blender/render/intern/include/zbuf_types.h b/source/blender/render/intern/include/zbuf_types.h new file mode 100644 index 00000000000..49960541fa0 --- /dev/null +++ b/source/blender/render/intern/include/zbuf_types.h @@ -0,0 +1,78 @@ +/* + * zbuf_types.h + * type definitions used (and maybe exported) by zbuf.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 ***** + */ + +#ifndef ZBUF_TYPES_H +#define ZBUF_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define ABUFPART 64 + +/** + * Primitive data structure for zbuffering. One struct + * stores data for 4 entries. + */ +typedef struct APixstr { + unsigned short mask[4]; /* jitter mask */ + int z[4]; /* distance */ + int p[4]; /* index */ + struct APixstr *next; +} APixstr; + + +typedef struct APixstrMain +{ + struct APixstr *ps; + struct APixstrMain *next; +} APixstrMain; + + +typedef struct { + float *vert; + float hoco[4]; + int clip; +} VertBucket; + +#ifdef __cplusplus +} +#endif + +#endif /* ZBUF_TYPES_H */ + + + + diff --git a/source/blender/render/intern/include/zbufferdatastruct.h b/source/blender/render/intern/include/zbufferdatastruct.h new file mode 100644 index 00000000000..3e36066100c --- /dev/null +++ b/source/blender/render/intern/include/zbufferdatastruct.h @@ -0,0 +1,99 @@ +/* + * zbufferdatastruct_ext.h + * + * $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 ***** + */ + +#ifndef ZBUFFERDATASTRUCT_EXT_H +#define ZBUFFERDATASTRUCT_EXT_H + +#include "zbufferdatastruct_types.h" + +/** + * Set memory and counters for a fresh z buffer + */ +void initZbuffer(int linewidth); + +/** + * Release memory for the current z buffer + */ +void freeZbuffer(void); + +/** + * Release previous buffer and initialise new buffer. + */ +void resetZbuffer(void); + +/** + * Make a root for a memory block (internal) + */ +RE_APixstrExt *addpsemainA(void); + +/** + * Release a memory chunk + */ +void freepseA(void); + +/** + * Add a structure + */ +RE_APixstrExt *addpseA(void); + +/** + * Add an object to a zbuffer entry. + */ +void insertObject(int teller, +/* int opaque, */ + int obindex, + int obtype, + int dist, + int mask); + +/** + * Add a flat object to a zbuffer entry. + */ +void insertFlatObject(RE_APixstrExt* ap, + int obindex, + int obtype, + int dist, + int mask); + +/** + * Add a flat object to a zbuffer entry, but don't do OSA entry testing. + */ +void insertFlatObjectNoOsa(RE_APixstrExt* ap, + int obindex, + int obtype, + int dist, + int mask); + + +#endif diff --git a/source/blender/render/intern/include/zbufferdatastruct_types.h b/source/blender/render/intern/include/zbufferdatastruct_types.h new file mode 100644 index 00000000000..10e0db8a540 --- /dev/null +++ b/source/blender/render/intern/include/zbufferdatastruct_types.h @@ -0,0 +1,77 @@ +/* + * zbufferdatastruct_types.h + * + * $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 ***** + */ + +#ifndef ZBUFFERDATASTRUCT_TYPES_H +#define ZBUFFERDATASTRUCT_TYPES_H + +#define RE_ZBUFLEN 64 /* number of lines in the accumulation buffer */ + +/** + * Primitive data structure for zbuffering. One struct + * stores data for 4 entries. This struct has been extended + * for the render pipeline overhaul. + */ +typedef struct RE_APixstrExt { + unsigned short mask[4]; /* jitter masks */ + int zmin[4]; /* min. distance of all samples */ + int zmax[4]; /* max. distance of all samples */ + int p[4]; /* index */ + int t[4]; /* entry type: ZB_POLY or ZB_HALO */ + struct RE_APixstrExt *next; +} RE_APixstrExt; + +/* For now I'll stick to the Blender convention of hand made defines */ +/* but this should definitely be done in a better way. An enum may */ +/* be some help, but masking is still a nice feature... */ +/* object types to buffer in the z buffer */ +#define RE_NONE 0 +#define RE_POLY 1 +#define RE_HALO 2 +#define RE_SKY 4 + +/* unique indices for each field */ +#define RE_ZMIN 0 +#define RE_INDEX 1 +#define RE_MASK 2 +#define RE_TYPE 3 +#define RE_ZMAX 4 +#define RE_PIXELFIELDSIZE 5 + +typedef struct RE_APixstrExtMain +{ + struct RE_APixstrExt *ps; + struct RE_APixstrExtMain *next; +} RE_APixstrExtMain; + +#endif diff --git a/source/blender/render/intern/source/Makefile b/source/blender/render/intern/source/Makefile new file mode 100644 index 00000000000..5e3d1b095ad --- /dev/null +++ b/source/blender/render/intern/source/Makefile @@ -0,0 +1,60 @@ +# +# $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 ***** +# +# + +LIBNAME = render +DIR = $(OCGDIR)/blender/$(LIBNAME) + +include nan_compile.mk + +ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows")) + CFLAGS += -funsigned-char + CCFLAGS += -funsigned-char +endif + +CFLAGS += $(LEVEL_2_C_WARNINGS) + +# first /include is my own includes, second is the external interface. +# The external modules follow after. There should be a nicer way to say this. +CPPFLAGS += -I../include +CPPFLAGS += -I../../extern/include +CPPFLAGS += -I../../../radiosity/extern/include +CPPFLAGS += -I../../../misc +CPPFLAGS += -I../../../blenlib +CPPFLAGS += -I../../../imbuf +CPPFLAGS += -I../../../makesdna +CPPFLAGS += -I../../../blenkernel +CPPFLAGS += -I../../../../kernel/gen_messaging +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +# not very neat: the rest of blender.. +CPPFLAGS += -I../../../include + diff --git a/source/blender/render/intern/source/RE_DummyShadowBuffer.cpp b/source/blender/render/intern/source/RE_DummyShadowBuffer.cpp new file mode 100644 index 00000000000..e2adefc05f2 --- /dev/null +++ b/source/blender/render/intern/source/RE_DummyShadowBuffer.cpp @@ -0,0 +1,66 @@ +/** + * $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 ***** + */ + +// #include + +#include "render_intern.h" + +#include "RE_DummyShadowBuffer.h" +struct LampRen; + +RE_DummyShadowBuffer::RE_DummyShadowBuffer(void) +{ + /* empty for now */ +// cout << "Constructing dummy SB\n"; +} + +RE_DummyShadowBuffer::~RE_DummyShadowBuffer(void) +{ + /* empty for now */ +// cout << "Deconstructing dummy SB\n"; +} + +void RE_DummyShadowBuffer::importScene(struct LampRen* lar) +{ + /* empty for now */ +// cout << "Importing scene in dummy SB\n"; +} + +void RE_DummyShadowBuffer::readShadowValue(struct ShadBuf *shb, + float inp, + float* shadowResult) +{ + /* a sort of puple-ish colour */ + shadowResult[0] = 1.0; + shadowResult[1] = 0.0; + shadowResult[2] = 0.5; +} diff --git a/source/blender/render/intern/source/RE_basicShadowBuffer.cpp b/source/blender/render/intern/source/RE_basicShadowBuffer.cpp new file mode 100644 index 00000000000..e126a755c35 --- /dev/null +++ b/source/blender/render/intern/source/RE_basicShadowBuffer.cpp @@ -0,0 +1,734 @@ +/** + * $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 ***** + */ + +#include +#include + +//#include +#include "MEM_guardedalloc.h" +#include "BLI_arithb.h" + +#include "DNA_lamp_types.h" +/* c stuff */ +#include "MTC_matrixops.h" +#include "render.h" +#include "render_intern.h" +#include "renderHelp.h" +#include "jitter.h" +#include "zbuf.h" +#include "shadbuf.h" + +/* own include */ +#include "RE_basicShadowBuffer.h" +/* crud */ +#define MIN2(x,y) ( (x)<(y) ? (x) : (y) ) +/* ------------------------------------------------------------------------- */ +/* The implementation of this one is a bit of a fraud still, as it + * still relies on everything internally to be done in C. Memory is + * allocated on the fly, and deallocated elsewhere... There's not much + * more than a handle for the implementation here. This is an exact + * copy of the old code, retrofitted for integration in the unified + * renderer. + * + * - the shadow values are tripled to make a shadow vector out of a + * single shadow value + */ + +RE_BasicShadowBuffer::RE_BasicShadowBuffer(struct LampRen *lar, float mat[][4]) +{ +// cout << "Constructing basic SB\n"; + bias = 0x00500000; + initshadowbuf(lar, mat); /* a ref to the shb is stored in the lar */ +} + +RE_BasicShadowBuffer::~RE_BasicShadowBuffer(void) +{ + /* clean-up is done when the lar's are deleted */ +// cout << "Destroying basic SB\n"; +} + +void RE_BasicShadowBuffer::lrectreadRectz(int x1, int y1, + int x2, int y2, + char *r1) /* leest deel uit rectz in r1 */ +{ + unsigned int len4, *rz; + + if(x1>=R.rectx || x2>=R.rectx || y1>=R.recty || y2>=R.recty) return; + if(x1>x2 || y1>y2) return; + + len4= 4*(x2- x1+1); + rz= R.rectz+R.rectx*y1+x1; + for(;y1<=y2;y1++) { + memcpy(r1,rz,len4); + rz+= R.rectx; + r1+= len4; + } +} + + +int RE_BasicShadowBuffer::sizeoflampbuf(struct ShadBuf *shb) +{ + int num,count=0; + char *cp; + + cp= shb->cbuf; + num= (shb->size*shb->size)/256; + + while(num--) count+= *(cp++); + + return 256*count; +} + +float* RE_BasicShadowBuffer::give_jitter_tab(int samp) +{ + /* these are all possible jitter tables, takes up some + * 12k, not really bad! + * For soft shadows, it saves memory and render time + */ + static int tab[17]={1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256}; + static float jit[1496][2]; + static char ctab[17]= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int a, offset=0; + + if(samp<2) samp= 2; + else if(samp>16) samp= 16; + + for(a=0; ashb; + float panophi; + float temp, wsize, dist; + int *rz, *rz1, verg, verg1; + unsigned long *ztile; + int a, x, y, minx, miny, byt1, byt2; + short temprx,tempry, square; + char *rc, *rcline, *ctile, *zt; + + panophi = getPanoPhi(); + + /* viewvars onthouden */ + temprx= R.rectx; tempry= R.recty; + R.rectx= R.recty= shb->size; + + shb->jit= give_jitter_tab(shb->samp); + + /* matrices en window: in R.winmat komt transformatie + van obsview naar lampview, inclusief lampwinmat */ + + wsize= shb->pixsize*(shb->size/2.0); + + i_window(-wsize, wsize, -wsize, wsize, shb->d, shb->far, shb->winmat); + + MTC_Mat4MulMat4(shb->persmat, shb->viewmat, shb->winmat); + + /* temp, will be restored */ + MTC_Mat4SwapMat4(shb->persmat, R.winmat); + + /* zbufferen */ + if(R.rectz) MEM_freeN(R.rectz); + R.rectz= (unsigned int *)MEM_mallocN(sizeof(int)*shb->size*shb->size,"makeshadbuf"); + rcline= (char*) MEM_mallocN(256*4+sizeof(int),"makeshadbuf2"); + + /* onthouden: panorama rot */ + temp= panophi; + panophi= 0.0; + pushTempPanoPhi(0.0); + + /* pano interference here? */ + setzbufvlaggen(projectvert); + + popTempPanoPhi(); + panophi= temp; + + zbuffershad(lar); + + /* alle pixels 1 x ingevuld verwijderen (oneven) */ + /* probleem hierbij kan geven dat er abrupte overgangen van zacht gebied + * naar geen zacht gebied is: bijv als eronder een klein vlakje zit + * DAAROM ER WEER UIT + * ook vanwege shadowhalo! + * + a= shb->size*shb->size; + rz= R.rectz; + while(a--) { + if(*rz & 1) *rz= 0x7FFFFFFF; + rz++; + } + */ + + square= lar->mode & LA_SQUARE; + + /* Z tiles aanmaken: dit systeem is 24 bits!!! */ + + ztile= shb->zbuf; + ctile= shb->cbuf; + for(y=0; ysize; y+=16) { + if(y< shb->size/2) miny= y+15-shb->size/2; + else miny= y-shb->size/2; + + for(x=0; xsize; x+=16) { + + /* ligt rechthoek binnen spotbundel? */ + a= shb->size/2; + if(x< a) minx= x+15-a; + else minx= x-a; + + dist= sqrt( (float)(minx*minx+miny*miny) ); + + if(square==0 && dist>(float)(a+12)) { /* 12, tested with a onlyshadow lamp */ + a= 256; verg= 0; /* 0x80000000; */ /* 0x7FFFFFFF; */ + rz1= (&verg)+1; + } + else { + lrectreadRectz(x, y, MIN2(shb->size-1,x+15), MIN2(shb->size-1,y+15), rcline); + rz1= (int *)rcline; + + verg= (*rz1 & 0xFFFFFF00); + + for(a=0;a<256;a++,rz1++) { + if( (*rz1 & 0xFFFFFF00) != verg) break; + } + } + if(a==256) { /* compleet leeg vakje */ + *ctile= 0; + *ztile= *(rz1-1); + } + else { + + /* ACOMP enz. zijn defined L/B endian */ + + rc= rcline; + rz1= (int *)rcline; + verg= rc[ACOMP]; + verg1= rc[BCOMP]; + rc+= 4; + byt1= 1; byt2= 1; + for(a=1;a<256;a++,rc+=4) { + byt1 &= (verg==rc[ACOMP]); + byt2 &= (verg1==rc[BCOMP]); + + if(byt1==0) break; + } + if(byt1 && byt2) { /* alleen byte opslaan */ + *ctile= 1; + *ztile= (unsigned long)MEM_mallocN(256+4, "tile1"); + rz= (int *)*ztile; + *rz= *rz1; + + zt= (char *)(rz+1); + rc= rcline; + for(a=0; a<256; a++, zt++, rc+=4) *zt= rc[GCOMP]; + } + else if(byt1) { /* short opslaan */ + *ctile= 2; + *ztile= (unsigned long)MEM_mallocN(2*256+4,"Tile2"); + rz= (int *)*ztile; + *rz= *rz1; + + zt= (char *)(rz+1); + rc= rcline; + for(a=0; a<256; a++, zt+=2, rc+=4) { + zt[0]= rc[BCOMP]; + zt[1]= rc[GCOMP]; + } + } + else { /* triple opslaan */ + *ctile= 3; + *ztile= (unsigned long)MEM_mallocN(3*256,"Tile3"); + + zt= (char *)*ztile; + rc= rcline; + for(a=0; a<256; a++, zt+=3, rc+=4) { + zt[0]= rc[ACOMP]; + zt[1]= rc[BCOMP]; + zt[2]= rc[GCOMP]; + } + } + } + ztile++; + ctile++; + } + } + + MEM_freeN(rcline); + MEM_freeN(R.rectz); R.rectz= 0; + + R.rectx= temprx; R.recty= tempry; + MTC_Mat4SwapMat4(shb->persmat, R.winmat); + + /* printf("lampbuf %d\n", sizeoflampbuf(shb)); */ +} + +int RE_BasicShadowBuffer::firstreadshadbuf(struct ShadBuf *shb, int xs, int ys, int nr) +{ + /* return 1 als volledig gecomprimeerde shadbuftile && z==const */ + static int *rz; + int ofs; + char *ct; + + /* always test borders of shadowbuffer */ + if(xs<0) xs= 0; else if(xs>=shb->size) xs= shb->size-1; + if(ys<0) ys= 0; else if(ys>=shb->size) ys= shb->size-1; + + /* z berekenen */ + ofs= (ys>>4)*(shb->size>>4) + (xs>>4); + ct= shb->cbuf+ofs; + if(*ct==0) { + if(nr==0) { + rz= *( (int **)(shb->zbuf+ofs) ); + return 1; + } + else if(rz!= *( (int **)(shb->zbuf+ofs) )) return 0; + + return 1; + } + + return 0; +} + +float RE_BasicShadowBuffer::readshadowbuf(struct ShadBuf *shb, + int xs, int ys, int zs) /* return 1.0 : volledig licht */ +{ + float temp; + int *rz, ofs; + int zsamp; + char *ct, *cz; + + /* simpleclip */ + /* if(xs<0 || ys<0) return 1.0; */ + /* if(xs>=shb->size || ys>=shb->size) return 1.0; */ + + /* always test borders of shadowbuffer */ + if(xs<0) xs= 0; else if(xs>=shb->size) xs= shb->size-1; + if(ys<0) ys= 0; else if(ys>=shb->size) ys= shb->size-1; + + /* z berekenen */ + ofs= (ys>>4)*(shb->size>>4) + (xs>>4); + ct= shb->cbuf+ofs; + rz= *( (int **)(shb->zbuf+ofs) ); + + if(*ct==3) { + ct= ((char *)rz)+3*16*(ys & 15)+3*(xs & 15); + cz= (char *)&zsamp; + cz[ACOMP]= ct[0]; + cz[BCOMP]= ct[1]; + cz[GCOMP]= ct[2]; + } + else if(*ct==2) { + ct= ((char *)rz); + ct+= 4+2*16*(ys & 15)+2*(xs & 15); + zsamp= *rz; + + cz= (char *)&zsamp; + cz[BCOMP]= ct[0]; + cz[GCOMP]= ct[1]; + } + else if(*ct==1) { + ct= ((char *)rz); + ct+= 4+16*(ys & 15)+(xs & 15); + zsamp= *rz; + + cz= (char *)&zsamp; + cz[GCOMP]= ct[0]; + + } + else { + /* got warning on this from alpha .... */ + /* but it's working code! (ton) */ + zsamp= (int) rz; + } + + /* if(zsamp >= 0x7FFFFE00) return 1.0; */ /* geen schaduw als op oneindig wordt gesampeld*/ + + if(zsamp > zs) return 1.0; /* absoluut geen schaduw */ + else if( zsamp < zs-bias) return 0.0 ; /* absoluut wel schaduw */ + else { /* zacht gebied */ + + temp= ( (float)(zs- zsamp) )/(float)bias; + return 1.0 - temp*temp; + + } +} + + +void RE_BasicShadowBuffer::readShadowValue(struct ShadBuf *shb, + float inp, + float * shadres) /* return 1.0: geen schaduw */ +{ + float fac, co[4], dx[3], dy[3], aantal=0; + float xs1,ys1, siz, *j, xres, yres; + int xs,ys, zs; + short a,num; + float shadowfactor = 1.0; + +#ifdef RE_NO_SHADOWS + shadres[0] = shadowfactor; + shadres[1] = shadowfactor; + shadres[2] = shadowfactor; + return; +#endif + + /* if(inp <= 0.0) return 1.0; */ + + /* renderco en osaco roteren */ + siz= 0.5*(float)shb->size; + VECCOPY(co, R.co); + co[3]= 1.0; + + MTC_Mat4MulVec4fl(shb->persmat, co); /* rationele hom co */ + + xs1= siz*(1.0+co[0]/co[3]); + ys1= siz*(1.0+co[1]/co[3]); + + /* Clip for z: near and far clip values of the shadow buffer. We + * can test for -1.0/1.0 because of the properties of the + * coordinate transformations. */ + fac= (co[2]/co[3]); + + if(fac>=1.0) { + shadres[0] = 0.0; + shadres[1] = 0.0; + shadres[2] = 0.0; + return; + } else if(fac<= -1.0) { + shadres[0] = 1.0; + shadres[1] = 1.0; + shadres[2] = 1.0; + return; + } + + zs = (int) (((float)0x7FFFFFFF)*fac); + + /* num*num samples nemen, gebied met fac vergroten */ + num= shb->samp*shb->samp; + fac= shb->soft; + + + bias = (int) ((1.1-inp*inp)*shb->bias); + + if(num==1) { + shadowfactor = readshadowbuf(shb,(int)xs1, (int)ys1, zs); + shadres[0] = shadowfactor; + shadres[1] = shadowfactor; + shadres[2] = shadowfactor; + return; + } + + co[0]= R.co[0]+O.dxco[0]; + co[1]= R.co[1]+O.dxco[1]; + co[2]= R.co[2]+O.dxco[2]; + co[3]= 1.0; + MTC_Mat4MulVec4fl(shb->persmat,co); /* rationele hom co */ + dx[0]= xs1- siz*(1.0+co[0]/co[3]); + dx[1]= ys1- siz*(1.0+co[1]/co[3]); + + co[0]= R.co[0]+O.dyco[0]; + co[1]= R.co[1]+O.dyco[1]; + co[2]= R.co[2]+O.dyco[2]; + co[3]= 1.0; + MTC_Mat4MulVec4fl(shb->persmat,co); /* rationele hom co */ + dy[0]= xs1- siz*(1.0+co[0]/co[3]); + dy[1]= ys1- siz*(1.0+co[1]/co[3]); + + xres= fac*( fabs(dx[0])+fabs(dy[0]) ); + yres= fac*( fabs(dx[1])+fabs(dy[1]) ); + + if(xresjit; + + if(xres<16.0 && yres<16.0) { + if(firstreadshadbuf(shb, (int)xs1, (int)ys1, 0)) { + if(firstreadshadbuf(shb, (int)(xs1+xres), (int)ys1, 1)) { + if(firstreadshadbuf(shb, (int)xs1, (int)(ys1+yres), 1)) { + if(firstreadshadbuf(shb, (int)(xs1+xres), (int)(ys1+yres), 1)) { + /* this return should do some renormalization, methinks */ + shadowfactor = readshadowbuf(shb,(int)xs1, (int)ys1, zs); + shadres[0] = shadowfactor; + shadres[1] = shadowfactor; + shadres[2] = shadowfactor; + return; + } + } + } + } + } + + for(a=num;a>0;a--) { + /* i.p.v. jit ook met random geprobeerd: lelijk! */ + xs= (int) (xs1 + xres*j[0]); + ys= (int) (ys1 + yres*j[1]); + j+=2; + + aantal+= readshadowbuf(shb, xs, ys, zs); + } + + /* Renormalizes for the sample number: */ + shadowfactor = aantal/( (float)(num) ); + shadres[0] = shadowfactor; + shadres[1] = shadowfactor; + shadres[2] = shadowfactor; + return; +} + +/* different function... sampling behind clipend can be LIGHT, bias is negative! */ +/* return: light */ +float RE_BasicShadowBuffer::readshadowbuf_halo(struct ShadBuf *shb, int xs, int ys, int zs) +{ + float temp; + int *rz, ofs; + int zbias, zsamp; + char *ct, *cz; + + /* simpleclip */ + if(xs<0 || ys<0) return 0.0; + if(xs>=shb->size || ys>=shb->size) return 0.0; + + /* z berekenen */ + ofs= (ys>>4)*(shb->size>>4) + (xs>>4); + ct= shb->cbuf+ofs; + rz= *( (int **)(shb->zbuf+ofs) ); + + if(*ct==3) { + ct= ((char *)rz)+3*16*(ys & 15)+3*(xs & 15); + cz= (char *)&zsamp; + zsamp= 0; + cz[ACOMP]= ct[0]; + cz[BCOMP]= ct[1]; + cz[GCOMP]= ct[2]; + } + else if(*ct==2) { + ct= ((char *)rz); + ct+= 4+2*16*(ys & 15)+2*(xs & 15); + zsamp= *rz; + + cz= (char *)&zsamp; + cz[BCOMP]= ct[0]; + cz[GCOMP]= ct[1]; + } + else if(*ct==1) { + ct= ((char *)rz); + ct+= 4+16*(ys & 15)+(xs & 15); + zsamp= *rz; + + cz= (char *)&zsamp; + cz[GCOMP]= ct[0]; + + } + else { + /* same as before */ + /* still working code! (ton) */ + zsamp= (int) rz; + } + + /* geen schaduw als op oneindig wordt gesampeld*/ + + if(zsamp >= 0x7FFFFE00) return 1.0; + + if(zsamp > zs) return 1.0; /* absoluut geen schaduw */ + else { + /* bias is negative, so the (zs-bias) can be beyond 0x7fffffff */ + zbias= 0x7fffffff - zs; + if(zbias > -bias) { + if( zsamp < zs-bias) return 0.0 ; /* absoluut wel schaduw */ + } + else return 0.0 ; /* absoluut wel schaduw */ + } + + /* zacht gebied */ + + temp= ( (float)(zs- zsamp) )/(float)bias; + return 1.0 - temp*temp; +} + + +float RE_BasicShadowBuffer::shadow_halo(LampRen *lar, float *p1, float *p2) +{ + /* p1 p2 already are rotated in spot-space */ + ShadBuf *shb= lar->shb; + float co[4], siz; + float labda, labdao, labdax, labday, ldx, ldy; + float zf, xf1, yf1, zf1, xf2, yf2, zf2; + float count, lightcount; + int x, y, z, xs1, ys1; + int dx = 0, dy = 0; + + siz= 0.5*(float)shb->size; + /* negative! The other side is more important */ + bias= -shb->bias; + + co[0]= p1[0]; + co[1]= p1[1]; + co[2]= p1[2]/lar->sh_zfac; + co[3]= 1.0; + MTC_Mat4MulVec4fl(shb->winmat, co); /* rationele hom co */ + xf1= siz*(1.0+co[0]/co[3]); + yf1= siz*(1.0+co[1]/co[3]); + zf1= (co[2]/co[3]); + + + co[0]= p2[0]; + co[1]= p2[1]; + co[2]= p2[2]/lar->sh_zfac; + co[3]= 1.0; + MTC_Mat4MulVec4fl(shb->winmat, co); /* rationele hom co */ + xf2= siz*(1.0+co[0]/co[3]); + yf2= siz*(1.0+co[1]/co[3]); + zf2= (co[2]/co[3]); + + /* de 2dda */ + + xs1= (int)xf1; + ys1= (int)yf1; + + if(xf1 != xf2) { + if(xf2-xf1 > 0.0) { + labdax= (xf1-xs1-1.0)/(xf1-xf2); + ldx= -shb->shadhalostep/(xf1-xf2); + dx= shb->shadhalostep; + } + else { + labdax= (xf1-xs1)/(xf1-xf2); + ldx= shb->shadhalostep/(xf1-xf2); + dx= -shb->shadhalostep; + } + } + else { + labdax= 1.0; + ldx= 0.0; + } + + if(yf1 != yf2) { + if(yf2-yf1 > 0.0) { + labday= (yf1-ys1-1.0)/(yf1-yf2); + ldy= -shb->shadhalostep/(yf1-yf2); + dy= shb->shadhalostep; + } + else { + labday= (yf1-ys1)/(yf1-yf2); + ldy= shb->shadhalostep/(yf1-yf2); + dy= -shb->shadhalostep; + } + } + else { + labday= 1.0; + ldy= 0.0; + } + + x= xs1; + y= ys1; + labda= count= lightcount= 0.0; + +/* printf("start %x %x \n", (int)(0x7FFFFFFF*zf1), (int)(0x7FFFFFFF*zf2)); */ + + while(1) { + labdao= labda; + + if(labdax==labday) { + labdax+= ldx; + x+= dx; + labday+= ldy; + y+= dy; + } + else { + if(labdax=1.0) break; + + zf= zf1 + labda*(zf2-zf1); + count+= 1.0; + + if(zf<= 0.0) lightcount += 1.0; /* close to the spot */ + else { + + /* make sure, behind the clipend we extend halolines. */ + if(zf>=1.0) z= 0x7FFFF000; + else z= (int)(0x7FFFF000*zf); + + lightcount+= readshadowbuf_halo(shb, x, y, z); + + } + } + + if(count!=0.0) return (lightcount/count); + return 0.0; + +} + + + + +/* sampelen met filter + xstart= xs-1; + ystart= ys-1; + if(xstart<0) xstart= 0; + if(ystart<0) ystart= 0; + xend= xstart+2; + yend= ystart+2; + if(xend>=shb->size) { xstart= shb->size-3; xend= shb->size-1;} + if(yend>=shb->size) { ystart= shb->size-3; yend= shb->size-1;} + + fid= filt3; + for(ys=ystart;ys<=yend;ys++) { + rz= shb->buf+ ys*shb->size+ xstart; + for(xs= xstart;xs<=xend;xs++,rz++) { + if( *rz+0x100000 /* for NULL??? */ +#include "render.h" +#include "render_intern.h" +#include "RE_callbacks.h" + +/* + * The callbacks are done in three parts: + * + * - a local static pointer to the eventual function. NULL if not + * defined, or if the behaviour is not required. + * + * - a hook that can be called locally + * + * - a hook that can be called externally, to set an external function + * to provide said functionality. + * + * These might be generated from a spec such as: + * + * callback { + * local = + * external = + * type = (,...) + * } + * + * Should generate: + * - a static var + * - an internal loop, plus decl. + * - an external setter, plus decl. + * + */ + +/* Part 1: ------------------------------------------------------------- */ + +static int (*RE_local_test_break_function)(void) = NULL; + +static void (*RE_local_timecursor_function)(int) = NULL; + +static void (*RE_local_renderdisplay_function)(int i, + int j, + int k, + int l, + unsigned int *m) + = NULL; + +static void (*RE_local_initrenderdisplay_function)(void) = NULL; +static void (*RE_local_clearrenderdisplay_function)(short) = NULL; + +static void (*RE_local_printrenderinfo_function)(double,int) = NULL; + +static void (*RE_local_getrenderdata_function)(void) = NULL; +static void (*RE_local_freerenderdata_function)(void) = NULL; + +/* Part 2: ------------------------------------------------------------- */ + +int RE_local_test_break(void) { + if (RE_local_test_break_function) { + return RE_local_test_break_function(); + } else { + /* transparant behaviour: proceed */ + return 0; + } +} + +void RE_local_timecursor(int i) { + if (RE_local_timecursor_function) RE_local_timecursor_function(i); +} + +void RE_local_render_display(int i, int j, int k, int l, unsigned int* m) { + if (RE_local_renderdisplay_function) RE_local_renderdisplay_function(i, j, k, l, m); +} +void RE_local_init_render_display(void) { + if (RE_local_initrenderdisplay_function) RE_local_initrenderdisplay_function(); +} +void RE_local_clear_render_display(short i) { + if (RE_local_clearrenderdisplay_function) RE_local_clearrenderdisplay_function(i); +} + +void RE_local_printrenderinfo(double time, int i) { + if (RE_local_printrenderinfo_function) RE_local_printrenderinfo_function(time, i); +} + +void RE_local_get_renderdata(void) { + if (RE_local_getrenderdata_function) RE_local_getrenderdata_function(); +} +void RE_local_free_renderdata(void) { + if (RE_local_freerenderdata_function) RE_local_freerenderdata_function(); +} + +/* Part 3: ------------------------------------------------------------- */ + +void RE_set_test_break_callback(int (*f)(void)) { + RE_local_test_break_function = f; +} + +void RE_set_timecursor_callback(void (*f)(int)) { + RE_local_timecursor_function = f; +} + +void RE_set_renderdisplay_callback(void (*f)(int i, + int j, + int k, + int l, + unsigned int *)) +{ + RE_local_renderdisplay_function = f; +} + +void RE_set_initrenderdisplay_callback(void (*f)(void)) { + RE_local_initrenderdisplay_function = f; +} + +void RE_set_clearrenderdisplay_callback(void (*f)(short)) { + RE_local_clearrenderdisplay_function = f; +} + +void RE_set_printrenderinfo_callback(void (*f)(double,int)) { + RE_local_printrenderinfo_function = f; +} + +void RE_set_getrenderdata_callback(void (*f)(void)) { + RE_local_getrenderdata_function = f; +} + +void RE_set_freerenderdata_callback(void (*f)(void)) { + RE_local_freerenderdata_function = f; +} diff --git a/source/blender/render/intern/source/edgeRender.c b/source/blender/render/intern/source/edgeRender.c new file mode 100644 index 00000000000..d3c944efac7 --- /dev/null +++ b/source/blender/render/intern/source/edgeRender.c @@ -0,0 +1,952 @@ +/** + * $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 ***** + * Add enhanced edges on a rendered image (toon shading, edge shading). + */ + +/* + * Edge rendering: use a mask to weigh the depth of neighbouring + * pixels, and do a colour correction. + * + * We need: + * - a buffer to store the depths (ints) + * - a function that alters the colours in R.rectot (copy edge_enhance?) + * The max. z buffer depth is 0x7FFF.FFFF (7 F's) + * + * - We 'ignore' the pixels falling outside the regular buffer (we fill) + * these with the max depth. This causes artefacts when rendering in + * parts. + */ + +/* ------------------------------------------------------------------------- */ + +/* enable extra bounds checking and tracing */ +/* #define RE_EDGERENDERSAFE */ +/* disable the actual edge correction */ +/* #define RE_EDGERENDER_NO_CORRECTION */ + +#include +#include +#include /* INT_MIN,MAX are used here */ +#include + +#include "MEM_guardedalloc.h" +#include "MTC_vectorops.h" + +#include "RE_callbacks.h" +#include "edgeRender.h" +#include "render.h" +#include "render_intern.h" +#include "zbuf.h" /* for zbufclipwire and zbufclip */ +#include "jitter.h" + +#ifdef RE_EDGERENDERSAFE +char edgeRender_h[] = EDGERENDER_H; +char edgeRender_c[] = "$Id$"; +#include "errorHandler.h" +#endif + +/* ------------------------------------------------------------------------- */ +/* the lazy way: */ +#define MIN2(x,y) ( (x)<(y) ? (x) : (y) ) + +/* ------------------------------------------------------------------------- */ + + /* These function pointers are used for z buffer filling. */ +extern void (*zbuffunc)(float *, float *, float *); +extern void (*zbuflinefunc)(float *v1, float *v2); +extern float Zmulx, Zmuly; /* Some kind of scale? */ +extern float Zjitx,Zjity; /* The x,y values for jitter offset */ +extern unsigned int Zvlnr; /* Face rendering pointer and counter: these */ +extern VlakRen *Zvlr; /* are used for 'caching' render results. */ + +/* ------------------------------------------------------------------------- */ + +/* exp: */ +static Material** matBuffer; /* buffer with material indices */ +static Material* mat_cache; /* material of the face being buffered */ + +static char* colBuffer; /* buffer with colour correction */ +static int *edgeBuffer; /* buffer with distances */ +static int bufWidth; /* x-dimension of the buffer */ +static int bufHeight; /* y-dimension of the buffer */ +static int imWidth; /* x-dimension of the image */ +static int imHeight; /* y-dimension of the image */ +static int osaCount; /* oversample count */ +static int maskBorder; /* size of the mask border */ +static short int intensity; /* edge intensity */ +static short int same_mat_redux; /* intensity reduction for boundaries with the same material */ +static int compatible_mode; /* edge positioning compatible with old rederer */ +static int selectmode; /* 0: only solid faces, 1: also transparent f's */ + +static int Aminy; /* y value of first line in the accu buffer */ +static int Amaxy; /* y value of last line in the accu buffer */ + /* -also used to clip when zbuffering */ +static char edgeR; /* Colour for the edges. The edges will receive */ +static char edgeG; /* this tint. The colour is fully used! */ +static char edgeB; +/* static float edgeBlend; */ /* Indicate opaqueness of the edge colour. */ + +/* Local functions --------------------------------------------------------- */ +/** + * Initialise the edge render buffer memory. + */ +void initEdgeRenderBuffer(void); +/** + * Release buffer memory. + */ +void freeEdgeRenderBuffer(void); + +/** + * Set all distances in the distance buffer to the maximum distance. + */ +void resetDistanceBuffer(void); + +/** + * Insert this distance at these pixel coordinates. + */ +void insertInEdgeBuffer(int x, int y, int dist); + +/** + * Renders enhanced edges. Distances from distRect are used to + * determine a correction on colourRect + */ +void renderEdges(char * colourRect); + +/** + * Buffer an edge between these two vertices in the e.r. distance buffer. + */ +void fillEdgeRenderEdge(float *vec1, float *vec2); + +/** + * Buffer a face between these two vertices in the e.r. distance buffer. + */ +void fillEdgeRenderFace(float *v1, float *v2, float *v3); + +/** + * Compose the edge render colour buffer. + */ +void calcEdgeRenderColBuf(char * tarbuf); + +/** + * Loop over all objects that need to be edge rendered. This loop determines + * which objects get to be elected for edge rendering. + */ +int zBufferEdgeRenderObjects(void); + +/** + * Add edge pixels to the original image. It blends over . + */ +void addEdgeOver(char *doel, char *bron); + +/* ------------------------------------------------------------------------- */ + +void addEdges( + char * targetbuf, + int iw, int ih, + int osanr, + short int intens, short int intens_redux, + int compat, int mode, + float r, float g, float b + ) +{ + float rf, gf ,bf; + /* render parameters */ + selectmode = mode; + imWidth = iw; + imHeight = ih; + compatible_mode = compat; + osaCount = osanr; + intensity = intens; + /* Reduction doesn't exceed intensity. */ + same_mat_redux = ((intens_redux < intensity)? intens_redux : intensity); + + rf = r * 255.0; + if (rf > 255) edgeR = 255; else edgeR = rf; + gf = g * 255.0; + if (gf > 255) edgeG = 255; else edgeG = gf; + bf = b * 255.0; + if (bf > 255) edgeB = 255; else edgeB = bf; + + /* Go! */ + initEdgeRenderBuffer(); + calcEdgeRenderColBuf(targetbuf); + freeEdgeRenderBuffer(); + +} /* end of void addEdges(char *, int, int, int, short int , int) */ + +/* ------------------------------------------------------------------------- */ + +void initEdgeRenderBuffer() +{ + char *ptr; + int i; + + maskBorder = 1; /* for 3 by 3 mask*/ + + bufWidth = imWidth + (2 * maskBorder); + bufHeight = imHeight + (2 * maskBorder); + + /* Experimental: store the material indices. */ + if (same_mat_redux) { + matBuffer = MEM_callocN(sizeof(Material*) + * bufWidth * bufHeight, "matBuffer"); + } + + edgeBuffer = MEM_callocN(sizeof(int) * bufWidth * bufHeight, "edgeBuffer"); + colBuffer = MEM_callocN(sizeof(char) * 4 * imWidth * imHeight, "colBuffer"); + + + if ((edgeR != 0) || (edgeG != 0) || (edgeB != 0)) { + /* Set all colbuf pixels to the edge colour. Leave alpha channel */ + /* cleared. Actually, we could blend in any image here... */ + ptr = colBuffer; + for (i = 0; i < imWidth * imHeight; i++, ptr+=4) + { + ptr[0] = edgeR; + ptr[1] = edgeG; + ptr[2] = edgeB; + ptr[3] = 0; + } + } + +#ifdef RE_EDGERENDERSAFE + if (!edgeBuffer || !colBuffer) { + char *fname = "initEdgeRenderBuffer"; + RE_error(RE_CANNOT_ALLOCATE_MEMORY, fname); + } +#endif +} /* end of void initEdgeRenderBuffer(void) */ + +/* ------------------------------------------------------------------------- */ +void freeEdgeRenderBuffer(void) +{ + if(edgeBuffer) MEM_freeN(edgeBuffer); + if(colBuffer) MEM_freeN(colBuffer); + if(matBuffer) MEM_freeN(matBuffer); +} /* end of void freeEdgeRenderBuffer(void) */ + +/* ------------------------------------------------------------------------- */ + +void resetDistanceBuffer(void) +{ + int i; + for(i = 0; i < bufWidth * bufHeight; i++) edgeBuffer[i] = 0x7FFFFFFF; +} /* end of void resetDistanceBuffer(void) */ + +/* ------------------------------------------------------------------------- */ + +void insertInEdgeBuffer(int x, int y, int dist) +{ + int index; +#ifdef RE_EDGERENDERSAFE + char *fname = "insertInEdgeBuffer"; + if ((x < 0) || (x > imWidth ) || + (y < 0) || (y > (imHeight-1) ) ) { + RE_error(RE_EDGERENDER_WRITE_OUTSIDE_BUFFER, fname); + return; + } +#endif + + /* +1? */ + index = (y * bufWidth) + x + maskBorder; + + /*exp: just dump a single index here. Maybe we can do more + * sophisticated things later on. */ + if (same_mat_redux) { + matBuffer[index] = mat_cache; + } + + if (edgeBuffer[index] >dist ) edgeBuffer[index] = dist; + +} /* end of void insertInEdgeBuffer(int x, int y, int dist) */ + +/* ------------------------------------------------------------------------- */ +/* Modelled after rendercore.c/edge_enhance() */ +void renderEdges(char *colourRect) +{ + /* use zbuffer to define edges, add it to the image */ + int val, y, x, col, *rz, *rz1, *rz2, *rz3; + char *cp; + int targetoffset, heightoffset; + int i; + int matdif; /* For now: just a bogus int, 0 when all materials + * under the mask are the same, non-0 otherwise*/ + int *matptr_low = 0, *matptr_cent = 0, *matptr_high = 0; + int matdiffac = 0; + +#ifdef RE_EDGERENDER_NO_CORRECTION + return; /* no edge correction */ +#endif + +#ifdef RE_EDGERENDERSAFE + fprintf(stderr, "\n*** Activated full error trace on " + "edge rendering using:\n\t%s\n\t%s" + "\n*** Rendering edges at %d intensity", + edgeRender_c, edgeRender_h, intensity); +#endif + + + /* Old renderer uses wrong positions! With the compat switch on, the po- */ + /* sitions will be corrected to be offset in the same way. */ + if (compatible_mode) { + targetoffset = 4 * (imWidth - 1); + heightoffset = -1; + } else { + targetoffset = 0; + heightoffset = 0; + } + + /* Fill edges with some default values. We just copy what is in the edge */ + /* This looks messy, but it appears to be ok. */ + edgeBuffer[0] = edgeBuffer[bufWidth + 1]; + edgeBuffer[bufWidth - 1] = edgeBuffer[(2 * bufWidth) - 2]; + edgeBuffer[bufWidth * (bufHeight - 1)] = + edgeBuffer[bufWidth * (bufHeight - 2) + 1]; + edgeBuffer[(bufWidth * bufHeight) - 1] = + edgeBuffer[(bufWidth * (bufHeight - 1)) - 2]; + for (i = 1; i < bufWidth - 1; i++) { /* lieing edges */ + edgeBuffer[i] = edgeBuffer[bufWidth + i]; /* bottom*/ + edgeBuffer[((bufHeight - 1)*bufWidth) + i] + = edgeBuffer[((bufHeight - 2)*bufWidth) + i]; /* top */ + } + for (i = 1; i < bufHeight - 2; i++) { /* standing edges */ + edgeBuffer[i * bufWidth] = edgeBuffer[(i * bufWidth) + 1]; /* left */ + edgeBuffer[((i + 1) * bufWidth) - 1] = + edgeBuffer[((i + 1) * bufWidth) - 2]; /* right */ + } + + /* same hack for the materials: */ + if (same_mat_redux) { + matBuffer[0] = matBuffer[bufWidth + 1]; + matBuffer[bufWidth - 1] = matBuffer[(2 * bufWidth) - 2]; + matBuffer[bufWidth * (bufHeight - 1)] = + matBuffer[bufWidth * (bufHeight - 2) + 1]; + matBuffer[(bufWidth * bufHeight) - 1] = + matBuffer[(bufWidth * (bufHeight - 1)) - 2]; + for (i = 1; i < bufWidth - 1; i++) { /* lieing mats */ + matBuffer[i] = matBuffer[bufWidth + i]; /* bottom*/ + matBuffer[((bufHeight - 1)*bufWidth) + i] + = matBuffer[((bufHeight - 2)*bufWidth) + i]; /* top */ + } + for (i = 1; i < bufHeight - 2; i++) { /* standing mats */ + matBuffer[i * bufWidth] = matBuffer[(i * bufWidth) + 1]; /* left */ + matBuffer[((i + 1) * bufWidth) - 1] = + matBuffer[((i + 1) * bufWidth) - 2]; /* right */ + } + } + + /* alle getallen in zbuffer 3 naar rechts shiften */ + rz = edgeBuffer; + if(rz==0) return; + + for(y=0; y < bufHeight * bufWidth; y++, rz++) { + (*rz)>>= 3; + } + + /* Distance pointers */ + rz1= edgeBuffer; + rz2= rz1 + bufWidth; + rz3= rz2 + bufWidth; + + if (same_mat_redux) { + matptr_low = matBuffer; + matptr_cent = matptr_low + bufWidth; + matptr_high = matptr_cent + bufWidth; + } + + if (osaCount == 1) { + cp = colourRect + targetoffset; + } else { + cp = colBuffer + targetoffset; + } + + i = 0; + + for(y = 0; y < (imHeight + heightoffset) ; y++) { + + + /* All these indices are a bit silly. I need to + * rewrite this, so all buffers use the same + * indexing. */ + for(x = 0; + x < imWidth; + x++, rz1++, rz2++, rz3++, cp+=4, + matptr_low++, + matptr_cent++, + matptr_high++) { + + col= abs( - rz1[0] - 2*rz1[1] - rz1[2] + - 2*rz2[0] + 12*rz2[1] - 2*rz2[2] + - rz3[0] - 2*rz3[1] - rz3[2]) / 3; + + /* Several options for matdif: + * + * - suppress all boundaries with 0 dif + * + * - weaken col dif? Or decrease intensity by + * a factor when non 0 dif?? + */ + + /* exp: matdif is non-0 if the mask-center + * material differs from any of the + * corners. */ + + if (same_mat_redux) { + matdif = abs (matptr_cent[1] - matptr_low[0]) + + abs (matptr_cent[1] - matptr_low[1]) + + abs (matptr_cent[1] - matptr_low[2]) + + abs (matptr_cent[1] - matptr_cent[0]) + + abs (matptr_cent[1] - matptr_low[2]) + + abs (matptr_cent[1] - matptr_high[0]) + + abs (matptr_cent[1] - matptr_high[1]) + + abs (matptr_cent[1] - matptr_high[2]); + + matdiffac = (matdif ? 0 : same_mat_redux); + } + + col= ((intensity - matdiffac) * col)>>14; + if(col>255) col= 255; + + /* Colour edge if + * + * 1. there is an appreciable, non-uniform + * gradient, + * + * 2. there are different materials bordering + * on the center pixel + */ + if( (col>0) + /* && (matdif != 0) */) { + + if(osaCount > 1) { + /* Currently done by tweaking alpha. The colBuffer is */ + /* filled with pixels of the colour appropriate for the */ + /* edges. This colour is alpha-blended over the image. */ + /* This calculation determines how much colour each pixel */ + /* gets. */ + col/= osaCount; + val= cp[3]+col; + if(val>255) cp[3]= 255; else cp[3]= val; + } + else { + /* the pixel is blackened when col is too big */ + val = cp[0] - col; + if(val<=0) { + cp[0]= edgeR; + } else { + cp[0]= val; + } + val = cp[1] - col; + if(val<=0) { + cp[1]= edgeG; + }else { + cp[1]= val; + } + val = cp[2] - col; + if(val<=0) { + cp[2]= edgeB; + } else { + cp[2]= val; + } + } + } + } + rz1+= 2; + rz2+= 2; + rz3+= 2; + if (same_mat_redux) { + matptr_low += 2; + matptr_cent += 2; + matptr_high += 2; + } + + } + +} /* end of void renderEdges() */ + +/* ------------------------------------------------------------------------- */ + +void addEdgeOver(char *doel, char *bron) /* telt bron bij doel */ +{ + float c; + int mul; + + if( bron[3] == 0) return; + if( bron[3] == 255) { /* is getest, scheelt */ + *((unsigned int *)doel)= *((unsigned int *)bron); + return; + } + + /* This must be a special blend-mode, because we get a 'weird' data */ + /* input format now. With edge = (c_e, a_e), picture = (c_p, a_p), we */ + /* get: result = ( c_e*a_e + c_p(1 - a_e), a_p ). */ + + mul = 255 - bron[3]; + + /* Not sure if the conversion to float is really necessary here... I will*/ + /* think about it another day. */ + c = ((mul * doel[0] + bron[0] * bron[3])/255.0); + if(c>255) {doel[0]=255;} else { doel[0]= c;} + c = ((mul * doel[1] + bron[1] * bron[3])/255.0); + if(c>255) {doel[1]=255;} else { doel[1]= c;} + c = ((mul * doel[2] + bron[2] * bron[3])/255.0); + if(c>255) {doel[2]=255;} else { doel[2]= c;} +} + +void calcEdgeRenderColBuf(char* colTargetBuffer) +{ + +/* int part; */ + int keepLooping = 1; + int sample; + + /* zbuffer fix: here? */ + Zmulx= ((float) imWidth)/2.0; + Zmuly= ((float) imHeight)/2.0; + + /* use these buffer fill functions */ + zbuffunc = fillEdgeRenderFace; + zbuflinefunc = fillEdgeRenderEdge; + + /* always buffer the max. extent */ + Aminy = 0; + Amaxy = imHeight; + + sample = 0; /* Zsample is used internally ! */ + while ( (sample < osaCount) && keepLooping ) { + /* jitter */ + Zjitx= -jit[sample][0]; + Zjity= -jit[sample][1]; + + /* should reset dis buffer here */ + resetDistanceBuffer(); + + /* kick all into a z buffer */ + keepLooping = zBufferEdgeRenderObjects(); + + /* do filtering */ + renderEdges(colTargetBuffer); + + if(RE_local_test_break()) keepLooping = 0; + sample++; + } + + /* correction for osa-sampling...*/ + if( osaCount != 1) { + char *rp, *rt; + int a; + + rt= colTargetBuffer; + rp= colBuffer; + for(a = imWidth * imHeight; a>0; a--, rt+=4, rp+=4) { + /* there seem to be rounding errors here... */ + addEdgeOver(rt, rp); + } + } + +} /*End of void calcEdgeRenderZBuf(void) */ + +/* ------------------------------------------------------------------------- */ +/* Clip flags etc. should still be set. When called in the span of 'normal' */ +/* rendering, this should be ok. */ +int zBufferEdgeRenderObjects(void) +{ + int keepLooping; + int faceCounter; /* counter for face number */ + Material *ma; + + keepLooping = 1; + ma = NULL; + faceCounter = 0; + + while ( (faceCounter < R.totvlak) && keepLooping) { + if((faceCounter & 255)==0) { Zvlr= R.blovl[faceCounter>>8]; } + else Zvlr++; + + ma= Zvlr->mat; + + /*exp*/ + mat_cache = ma; + + /* face number is used in the fill functions */ + Zvlnr = faceCounter + 1; + + if(Zvlr->flag & R_VISIBLE) { + + /* here we cull all transparent faces if mode == 0 */ + if (selectmode || !(ma->mode & MA_ZTRA)) { + /* here we can add all kinds of extra selection criteria */ + if(ma->mode & (MA_WIRE)) zbufclipwire(Zvlr); + else { + zbufclip(Zvlr->v1->ho, Zvlr->v2->ho, Zvlr->v3->ho, + Zvlr->v1->clip, Zvlr->v2->clip, Zvlr->v3->clip); + if(Zvlr->v4) { + Zvlnr+= 0x800000; /* in a sense, the 'adjoint' face */ + zbufclip(Zvlr->v1->ho, Zvlr->v3->ho, Zvlr->v4->ho, + Zvlr->v1->clip, Zvlr->v3->clip, Zvlr->v4->clip); + } + } + } + }; + if(RE_local_test_break()) keepLooping = 0; + faceCounter++; + } + return keepLooping; +} /* End of int zBufferEdgeRenderObjects(void) */ + +/* ------------------------------------------------------------------------- */ + +void fillEdgeRenderFace(float *v1, float *v2, float *v3) +{ + /* Coordinates of the vertices are specified in ZCS */ + double z0; /* used as temp var*/ + double xx1; + double zxd,zyd,zy0, tmp; + float *minv,*maxv,*midv; + int zverg,x; + int my0,my2,sn1,sn2,rectx,zd; + int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2/* , mask */; + int linex, liney, xoffset, yoffset; /* pointers to the pixel number */ + + /* These used to be doubles. We may want to change them back if the */ + /* loss of accuracy proves to be a problem? There does not seem to be */ + /* any performance issues here, so I'll just keep the doubles. */ + /* float vec0[3], vec1[3], vec2[3]; */ + double vec0[3], vec1[3], vec2[3]; + + /* MIN MAX */ + /* sort vertices for min mid max y value */ + if(v1[1] Amaxy)) return; + + if(my02.0/65536.0) { + z0= (maxv[0]-minv[0])/xx1; + + tmp= (-65536.0*z0); + dx0= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(my2-minv[1])+minv[0]); + xs0= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx0= 0; + xs0= 65536.0*(MIN2(minv[0],maxv[0])); + } + /* EDGES : DE BOVENSTE */ + xx1= maxv[1]-midv[1]; + if(xx1>2.0/65536.0) { + z0= (maxv[0]-midv[0])/xx1; + + tmp= (-65536.0*z0); + dx1= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(my2-midv[1])+midv[0]); + xs1= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx1= 0; + xs1= 65536.0*(MIN2(midv[0],maxv[0])); + } + /* EDGES : DE ONDERSTE */ + xx1= midv[1]-minv[1]; + if(xx1>2.0/65536.0) { + z0= (midv[0]-minv[0])/xx1; + + tmp= (-65536.0*z0); + dx2= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]); + xs2= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx2= 0; + xs2= 65536.0*(MIN2(minv[0],midv[0])); + } + + /* ZBUF DX DY */ + MTC_diff3DFF(vec1, v1, v2); + MTC_diff3DFF(vec2, v2, v3); + MTC_cross3Double(vec0, vec1, vec2); + + /* cross product of two of the sides is 0 => this face is too small */ + if(vec0[2]==0.0) return; + + if(midv[1] == maxv[1]) omsl= my2; + if(omsl < Aminy) omsl= Aminy-1; /* dan neemt ie de eerste lus helemaal */ + + while (my2 > Amaxy) { /* my2 kan groter zijn */ + xs0+=dx0; + if (my2<=omsl) { + xs2+= dx2; + } + else{ + xs1+= dx1; + } + my2--; + } + + xx1= (vec0[0]*v1[0]+vec0[1]*v1[1])/vec0[2]+v1[2]; + + zxd= -vec0[0]/vec0[2]; + zyd= -vec0[1]/vec0[2]; + zy0= my2*zyd+xx1; + zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX); + + /* start-ofset in rect */ + /* rectx= R.rectx; */ + /* I suspect this var needs very careful setting... When edge rendering */ + /* is on, this is strange */ + rectx = imWidth; + yoffset = my2; + xoffset = 0; + + xs3= 0; /* flag */ + if(dx0>dx1) { + MTC_swapInt(&xs0, &xs1); + MTC_swapInt(&dx0, &dx1); + xs3= 1; /* flag */ + + } + + liney = yoffset; + for(y=my2;y>omsl;y--) { + + sn1= xs0>>16; + xs0+= dx0; + + sn2= xs1>>16; + xs1+= dx1; + + sn1++; + + if(sn2>=rectx) sn2= rectx-1; + if(sn1<0) sn1= 0; + zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX); + + if ((sn1 < 0) || (sn1>imWidth) ) printf("\n sn1 exceeds line"); + linex = xoffset + sn1; + liney = yoffset; + + x= sn2-sn1; + + while(x>=0) { + insertInEdgeBuffer(linex , liney, zverg); /* line y not needed here */ + zverg+= zd; + linex++; + x--; + } + zy0-= zyd; + yoffset--; + } + + if(xs3) { + xs0= xs1; + dx0= dx1; + } + if(xs0>xs2) { + xs3= xs0; + xs0= xs2; + xs2= xs3; + xs3= dx0; + dx0= dx2; + dx2= xs3; + } + + for(; y>=my0; y--) { + + sn1= xs0>>16; + xs0+= dx0; + + sn2= xs2>>16; + xs2+= dx2; + + sn1++; + + if(sn2>=rectx) sn2= rectx-1; + if(sn1<0) sn1= 0; + zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX); + + linex = sn1; + liney = yoffset; + + x= sn2-sn1; + + while(x>=0) { + insertInEdgeBuffer(linex, liney, zverg); /* line y not needed here */ + zverg+= zd; + linex++; + x--; + } + zy0-=zyd; + yoffset--; + } +} /* end of void fillEdgeRenderFace(float *v1, float *v2, float *v3) */ + +/* ------------------------------------------------------------------------- */ + +void fillEdgeRenderEdge(float *vec1, float *vec2) +{ + int start, end, x, y, oldx, oldy, ofs; + int dz, vergz/* , mask */; + float dx, dy; + float v1[3], v2[3]; + int linex, liney; + int xoffset, yoffset; + + + dx= vec2[0]-vec1[0]; + dy= vec2[1]-vec1[1]; + + if(fabs(dx) > fabs(dy)) { + + /* alle lijnen van links naar rechts */ + if(vec1[0]= imWidth) end = imWidth - 1; + + oldy= floor(v1[1]); + dy/= dx; + + vergz= v1[2]; + dz= (v2[2]-v1[2])/dx; + + yoffset = oldy; + xoffset = start; + + if(dy<0) ofs= -imWidth; + else ofs= imWidth; + + liney = yoffset; + linex = xoffset; + + for(x= start; x<=end; x++, xoffset++) { + + y= floor(v1[1]); + if(y!=oldy) { + oldy= y; + liney++; + } + + if(x>=0 && y>=Aminy && y<=Amaxy) { + insertInEdgeBuffer(linex , liney, vergz); + } + + v1[1]+= dy; + vergz+= dz; + } + } + else { + + /* alle lijnen van onder naar boven */ + if(vec1[1]Amaxy || endAmaxy) end= Amaxy; + + oldx= floor(v1[0]); + dx/= dy; + + vergz= v1[2]; + dz= (v2[2]-v1[2])/dy; + + yoffset = start; + xoffset = oldx; + + if(dx<0) ofs= -1; + else ofs= 1; + + linex = xoffset; + liney = yoffset; + + for(y= start; y<=end; y++, liney++) { + + x= floor(v1[0]); + if(x!=oldx) { + oldx= x; + linex += ofs; + } + + if(x>=0 && y>=Aminy && (x < imWidth)) { + insertInEdgeBuffer(linex, liney, vergz); + } + + v1[0]+= dx; + vergz+= dz; + } + } +} /* End of void fillEdgeRenderEdge(float *vec1, float *vec2) */ + +/* ------------------------------------------------------------------------- */ + +/* eof edgeRender.c */ diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c new file mode 100644 index 00000000000..8aebe3670d0 --- /dev/null +++ b/source/blender/render/intern/source/envmap.c @@ -0,0 +1,689 @@ + +/* envmap.c RENDER + * + * ***** 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 ***** + * + * may 1999 + * + * $Id$ + */ + +#include +#include + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +/* external modules: */ +#include "MEM_guardedalloc.h" +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" /* for rectcpy */ + +#include "DNA_texture_types.h" +#include "DNA_image_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_texture_types.h" + +#include "BIF_space.h" +#include "BIF_toolbox.h" + +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_global.h" +#include "BKE_world.h" // init_render_world +#include "BKE_image.h" // BKE_write_ibuf + + +/* this module */ +#include "RE_callbacks.h" +#include "render.h" +#include "render_intern.h" +#include "envmap.h" +#include "mydevice.h" +#include "rendercore.h" /* calls zbufShade(DA).... I want to replace this with my own :)*/ +#include "renderHelp.h" +#include "MTC_matrixops.h" +#include "zbuf.h" + +/* ------------------------------------------------------------------------- */ + +void envmap_split_ima(EnvMap *env); +void envmap_renderdata(EnvMap *env); +void envmap_transmatrix(float mat[][4], int part); +void env_rotate_scene(float mat[][4], int mode); +void env_layerflags(unsigned int notlay); +void env_set_imats(void); +void render_envmap(EnvMap *env); +int envcube_isect(float *vec, float *answ); +static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face); + +/* ------------------------------------------------------------------------- */ + +EnvMap *RE_add_envmap(void) +{ + EnvMap *env; + + env= MEM_callocN(sizeof(EnvMap), "envmap"); + env->type= ENV_CUBE; + env->stype= ENV_STATIC; + env->clipsta= 0.1; + env->clipend= 100.0; + env->cuberes= 100; + + return env; +} /* end of EnvMap *RE_add_envmap() */ + +/* ------------------------------------------------------------------------- */ + +EnvMap *RE_copy_envmap(EnvMap *env) +{ + EnvMap *envn; + int a; + + envn= MEM_dupallocN(env); + envn->ok= 0; + for(a=0; a<6; a++) envn->cube[a]= 0; + if(envn->ima) id_us_plus((ID *)envn->ima); + + return envn; +} + +/* ------------------------------------------------------------------------- */ + +void RE_free_envmapdata(EnvMap *env) +{ + Image *ima; + int a, part; + + for(part=0; part<6; part++) { + ima= env->cube[part]; + if(ima) { + if(ima->ibuf) IMB_freeImBuf(ima->ibuf); + + for(a=0; amipmap); a++) { + if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]); + } + MEM_freeN(ima); + env->cube[part]= 0; + } + } + env->ok= 0; +} + +/* ------------------------------------------------------------------------- */ + +void RE_free_envmap(EnvMap *env) +{ + + RE_free_envmapdata(env); + MEM_freeN(env); + +} + +/* ------------------------------------------------------------------------- */ + +void envmap_split_ima(EnvMap *env) +{ + ImBuf *ibuf; + Image *ima; +/* extern rectcpy(); */ + int dx, part; + + RE_free_envmapdata(env); + + dx= env->ima->ibuf->y; + dx/= 2; + if(3*dx != env->ima->ibuf->x) { + error("Incorrect envmap size"); + env->ok= 0; + env->ima->ok= 0; + } + else { + for(part=0; part<6; part++) { + ibuf= IMB_allocImBuf(dx, dx, 24, IB_rect, 0); + ima= MEM_callocN(sizeof(Image), "image"); + ima->ibuf= ibuf; + ima->ok= 1; + env->cube[part]= ima; + } + IMB_rectop(env->cube[0]->ibuf, env->ima->ibuf, + 0, 0, 0, 0, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[1]->ibuf, env->ima->ibuf, + 0, 0, dx, 0, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[2]->ibuf, env->ima->ibuf, + 0, 0, 2*dx, 0, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[3]->ibuf, env->ima->ibuf, + 0, 0, 0, dx, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[4]->ibuf, env->ima->ibuf, + 0, 0, dx, dx, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[5]->ibuf, env->ima->ibuf, + 0, 0, 2*dx, dx, dx, dx, IMB_rectcpy, 0); + env->ok= 2; + } +} + +/* ------------------------------------------------------------------------- */ +/* ****************** RENDER ********************** */ + +void envmap_renderdata(EnvMap *env) +{ + static RE_Render envR; + static Object *camera; + + if(env) { + envR= R; + camera= G.scene->camera; + + env->cuberes &= 0xFFFC; + R.rectx= R.r.xsch= R.recty= R.r.ysch= env->cuberes; + R.afmx= R.afmy= R.r.xsch/2; + R.xstart= R.ystart= -R.afmx; + R.xend= R.yend= R.xstart+R.rectx-1; + + R.r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR); + R.r.xparts= R.r.yparts= 1; + R.r.bufflag= 0; + R.r.size= 100; + R.ycor= 1.0; + R.r.yasp= R.r.xasp= 1; + + R.near= env->clipsta; + R.far= env->clipend; + + G.scene->camera= env->object; + + } + else { + /* this to make sure init_renderdisplay works */ + envR.winx= R.winx; + envR.winy= R.winy; + envR.winxof= R.winxof; + envR.winyof= R.winyof; + + R= envR; + G.scene->camera= camera; + } + +} + +/* ------------------------------------------------------------------------- */ + +void envmap_transmatrix(float mat[][4], int part) +{ + float tmat[4][4], eul[3], rotmat[4][4]; + + eul[0]= eul[1]= eul[2]= 0.0; + + if(part==0) { /* neg z */ + ; + } else if(part==1) { /* pos z */ + eul[0]= M_PI; + } else if(part==2) { /* pos y */ + eul[0]= M_PI/2.0; + } else if(part==3) { /* neg x */ + eul[0]= M_PI/2.0; + eul[2]= M_PI/2.0; + } else if(part==4) { /* neg y */ + eul[0]= M_PI/2.0; + eul[2]= M_PI; + } else { /* pos x */ + eul[0]= M_PI/2.0; + eul[2]= -M_PI/2.0; + } + + MTC_Mat4CpyMat4(tmat, mat); + EulToMat4(eul, rotmat); + MTC_Mat4MulSerie(mat, tmat, rotmat, + 0, 0, 0, + 0, 0, 0); +} + +/* ------------------------------------------------------------------------- */ + +void env_rotate_scene(float mat[][4], int mode) +{ + VlakRen *vlr = NULL; + VertRen *ver = NULL; + LampRen *lar = NULL; + HaloRen *har = NULL; + float xn, yn, zn, imat[3][3], pmat[4][4], smat[4][4], tmat[4][4]; + int a; + + if(mode==0) { + MTC_Mat4Invert(tmat, mat); + MTC_Mat3CpyMat4(imat, tmat); + } + else { + MTC_Mat4CpyMat4(tmat, mat); + MTC_Mat3CpyMat4(imat, mat); + } + + for(a=0; a>8]; + else ver++; + + MTC_Mat4MulVecfl(tmat, ver->co); + + xn= ver->n[0]; + yn= ver->n[1]; + zn= ver->n[2]; + /* geen transpose ! */ + ver->n[0]= imat[0][0]*xn+imat[1][0]*yn+imat[2][0]*zn; + ver->n[1]= imat[0][1]*xn+imat[1][1]*yn+imat[2][1]*zn; + ver->n[2]= imat[0][2]*xn+imat[1][2]*yn+imat[2][2]*zn; + Normalise(ver->n); + } + + for(a=0; a>8]; + else har++; + + MTC_Mat4MulVecfl(tmat, har->co); + } + + for(a=0; a>8]; + else vlr++; + + xn= vlr->n[0]; + yn= vlr->n[1]; + zn= vlr->n[2]; + /* geen transpose ! */ + vlr->n[0]= imat[0][0]*xn+imat[1][0]*yn+imat[2][0]*zn; + vlr->n[1]= imat[0][1]*xn+imat[1][1]*yn+imat[2][1]*zn; + vlr->n[2]= imat[0][2]*xn+imat[1][2]*yn+imat[2][2]*zn; + Normalise(vlr->n); + } + + set_normalflags(); + + for(a=0; aimat); */ + MTC_Mat4CpyMat3nc(smat, lar->imat); + /* This would be lar->imat = smat * imat, so 3d = 4d * 3d? */ + /* the mat3mulmat3 does a multiply on the wrong elements.... */ +/* Mat3MulMat3(lar->imat, smat, imat); */ + MTC_Mat4MulMat33(lar->imat, smat, imat); + MTC_Mat3MulVecfl(imat, lar->vec); + MTC_Mat4MulVecfl(tmat, lar->co); + + lar->sh_invcampos[0]= -lar->co[0]; + lar->sh_invcampos[1]= -lar->co[1]; + lar->sh_invcampos[2]= -lar->co[2]; + MTC_Mat3MulVecfl(lar->imat, lar->sh_invcampos); + lar->sh_invcampos[2]*= lar->sh_zfac; + + if(lar->shb) { + if(mode==1) { + MTC_Mat4Invert(pmat, mat); + MTC_Mat4MulMat4(smat, pmat, lar->shb->viewmat); + MTC_Mat4MulMat4(lar->shb->persmat, smat, lar->shb->winmat); + } + else MTC_Mat4MulMat4(lar->shb->persmat, lar->shb->viewmat, lar->shb->winmat); + } + } + +} + +/* ------------------------------------------------------------------------- */ + +void env_layerflags(unsigned int notlay) +{ + VlakRen *vlr = NULL; + int a; + + for(a=0; a>8]; + else vlr++; + if(vlr->lay & notlay) vlr->flag &= ~R_VISIBLE; + } +} + +/* ------------------------------------------------------------------------- */ + +void env_set_imats() +{ + Base *base; + float mat[4][4]; + + base= G.scene->base.first; + while(base) { + MTC_Mat4MulMat4(mat, base->object->obmat, R.viewmat); + MTC_Mat4Invert(base->object->imat, mat); + + base= base->next; + } + +} + +/* ------------------------------------------------------------------------- */ + +void render_envmap(EnvMap *env) +{ + /* only the cubemap is implemented */ + ImBuf *ibuf; + Image *ima; + float oldviewinv[4][4], mat[4][4], tmat[4][4]; + short part; + + /* need a recalc: ortho-render has no correct viewinv */ + MTC_Mat4Invert(oldviewinv, R.viewmat); + + /* setup necessary globals */ + envmap_renderdata(env); + + RE_local_init_render_display(); + + R.rectot= MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot"); + R.rectz= MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectz"); + + for(part=0; part<6; part++) { + + RE_local_clear_render_display(R.win); + fillrect(R.rectot, R.rectx, R.recty, 0); + + RE_setwindowclip(1,-1); /* geen jit:(-1) */ + + MTC_Mat4CpyMat4(tmat, G.scene->camera->obmat); + MTC_Mat4Ortho(tmat); + envmap_transmatrix(tmat, part); + MTC_Mat4Invert(mat, tmat); + /* mat now is the camera 'viewmat' */ + + MTC_Mat4CpyMat4(R.viewmat, mat); + MTC_Mat4CpyMat4(R.viewinv, tmat); + + /* we have to correct for the already rotated vertexcoords */ + MTC_Mat4MulMat4(tmat, oldviewinv, R.viewmat); + MTC_Mat4Invert(env->imat, tmat); + + env_rotate_scene(tmat, 1); + init_render_world(); + setzbufvlaggen(RE_projectverto); + env_layerflags(env->notlay); + env_set_imats(); + + if(RE_local_test_break()==0) { + + RE_local_printrenderinfo(0.0, part); + + if(R.r.mode & R_OSA) zbufshadeDA(); + else zbufshade(); + + } + + /* rotate back */ + env_rotate_scene(tmat, 0); + + if(RE_local_test_break()==0) { + ibuf= IMB_allocImBuf(R.rectx, R.recty, 24, IB_rect, 0); + ima= MEM_callocN(sizeof(Image), "image"); + memcpy(ibuf->rect, R.rectot, 4*ibuf->x*ibuf->y); + ima->ibuf= ibuf; + ima->ok= 1; + env->cube[part]= ima; + } + + if(RE_local_test_break()) break; + + } + + if(R.rectz) MEM_freeN(R.rectz); R.rectz= 0; + if(R.rectot) MEM_freeN(R.rectot); R.rectot= 0; + + if(RE_local_test_break()) RE_free_envmapdata(env); + else { + if(R.r.mode & R_OSA) env->ok= ENV_OSA; + else env->ok= ENV_NORMAL; + env->lastframe= G.scene->r.cfra; + } + + /* restore */ + envmap_renderdata(0); + env_set_imats(); + init_render_world(); + +} + +/* ------------------------------------------------------------------------- */ + +void make_envmaps() +{ + Tex *tex; + int do_init= 0; + + tex= G.main->tex.first; + while(tex) { + if(tex->id.us && tex->type==TEX_ENVMAP) { + if(tex->env && tex->env->object) { + if(tex->env->object->lay & G.scene->lay) { + if(tex->env->stype!=ENV_LOAD) { + + if(tex->env->ok==0) { + do_init= 1; + render_envmap(tex->env); + } + else if((R.r.mode & R_OSA) && tex->env->ok==ENV_NORMAL) { + do_init= 1; + RE_free_envmapdata(tex->env); + render_envmap(tex->env); + } + } + } + } + } + tex= tex->id.next; + } + + if(do_init) { + RE_local_init_render_display(); + RE_local_clear_render_display(R.win); + allqueue(REDRAWBUTSTEX, 0); + } +} + +/* ------------------------------------------------------------------------- */ + +int envcube_isect(float *vec, float *answ) +{ + float labda; + int face; + + /* which face */ + if( vec[2]<=-fabs(vec[0]) && vec[2]<=-fabs(vec[1]) ) { + face= 0; + labda= -1.0/vec[2]; + answ[0]= labda*vec[0]; + answ[1]= labda*vec[1]; + } + else if( vec[2]>=fabs(vec[0]) && vec[2]>=fabs(vec[1]) ) { + face= 1; + labda= 1.0/vec[2]; + answ[0]= labda*vec[0]; + answ[1]= -labda*vec[1]; + } + else if( vec[1]>=fabs(vec[0]) ) { + face= 2; + labda= 1.0/vec[1]; + answ[0]= labda*vec[0]; + answ[1]= labda*vec[2]; + } + else if( vec[0]<=-fabs(vec[1]) ) { + face= 3; + labda= -1.0/vec[0]; + answ[0]= labda*vec[1]; + answ[1]= labda*vec[2]; + } + else if( vec[1]<=-fabs(vec[0]) ) { + face= 4; + labda= -1.0/vec[1]; + answ[0]= -labda*vec[0]; + answ[1]= labda*vec[2]; + } + else { + face= 5; + labda= 1.0/vec[0]; + answ[0]= -labda*vec[1]; + answ[1]= labda*vec[2]; + } + answ[0]= 0.5+0.5*answ[0]; + answ[1]= 0.5+0.5*answ[1]; + return face; +} + +/* ------------------------------------------------------------------------- */ + +static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face) +{ + if(face==2 || face==4) { + dxts[0]= dxt[0]; + dyts[0]= dyt[0]; + dxts[1]= dxt[2]; + dyts[1]= dyt[2]; + } + else if(face==3 || face==5) { + dxts[0]= dxt[1]; + dxts[1]= dxt[2]; + dyts[0]= dyt[1]; + dyts[1]= dyt[2]; + } + else { + dxts[0]= dxt[0]; + dyts[0]= dyt[0]; + dxts[1]= dxt[1]; + dyts[1]= dyt[1]; + } +} + +/* ------------------------------------------------------------------------- */ + +extern float Tin, Ta, Tr, Tg, Tb; /* texture.c */ +int RE_envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt) +{ + /* texvec should be the already reflected normal */ + EnvMap *env; + float fac, vec[3], sco[3], col[20], dxts[3], dyts[3]; + int face, face1; + + env= tex->env; + if(env==0 || env->object==0) return 0; + + if(env->stype==ENV_LOAD) { + env->ima= tex->ima; + if(env->ima && env->ima->ok) { + if(env->ima->ibuf==0) ima_ibuf_is_nul(tex); + if(env->ima->ok && env->ok==0) envmap_split_ima(env); + } + } + + if(env->ok==0) { + + Tin= 0.0; + return 0; + } + + /* rotate to envmap space */ + VECCOPY(vec, texvec); + MTC_Mat4Mul3Vecfl(env->object->imat, vec); + + face= envcube_isect(vec, sco); + tex->ima= env->cube[face]; + + if(R.osatex) { + MTC_Mat4Mul3Vecfl(env->object->imat, dxt); + MTC_Mat4Mul3Vecfl(env->object->imat, dyt); + + set_dxtdyt(dxts, dyts, dxt, dyt, face); + imagewraposa(tex, sco, dxts, dyts); + + /* edges? */ + + if(Ta<1.0) { + col[0]= Ta; col[1]= Tr; col[2]= Tg; col[3]= Tb; + + VecAddf(vec, vec, dxt); + face1= envcube_isect(vec, sco); + VecSubf(vec, vec, dxt); + + if(face!=face1) { + tex->ima= env->cube[face1]; + set_dxtdyt(dxts, dyts, dxt, dyt, face1); + imagewraposa(tex, sco, dxts, dyts); + col[4]= Ta; col[5]= Tr; col[6]= Tg; col[7]= Tb; + } + else col[4]= col[5]= col[6]= col[7]= 0.0; + + /* here was the nasty bug! col[5,6,7] were not zero-ed. FPE! */ + + VecAddf(vec, vec, dyt); + face1= envcube_isect(vec, sco); + VecSubf(vec, vec, dyt); + + if(face!=face1) { + tex->ima= env->cube[face1]; + set_dxtdyt(dxts, dyts, dxt, dyt, face1); + imagewraposa(tex, sco, dxts, dyts); + col[8]= Ta; col[9]= Tr; col[10]= Tg; col[11]= Tb; + } + else col[8]= col[9]= col[10]= col[11]= 0.0; + + fac= (col[0]+col[4]+col[8]); + fac= 1.0/fac; + + Tr= fac*(col[0]*col[1] + col[4]*col[5] + col[8]*col[9] ); + Tg= fac*(col[0]*col[2] + col[4]*col[6] + col[8]*col[10] ); + Tb= fac*(col[0]*col[3] + col[4]*col[7] + col[8]*col[11] ); + Ta= 1.0; + + } + } + else { + imagewrap(tex, sco); + } + + tex->ima= env->ima; + + return 1; +} + +/* ------------------------------------------------------------------------- */ + +/* eof */ diff --git a/source/blender/render/intern/source/errorHandler.c b/source/blender/render/intern/source/errorHandler.c new file mode 100644 index 00000000000..fc21ee272c4 --- /dev/null +++ b/source/blender/render/intern/source/errorHandler.c @@ -0,0 +1,99 @@ +/** + * $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 ***** + * Error handler for the rendering code. Maybe also useful elsewhere? + */ + +#include "GEN_messaging.h" +#include "stdio.h" +#include "errorHandler.h" + +#include "render_intern.h" + +/* ------------------------------------------------------------------------- */ + +/* counters for error handling */ +static int lastError; /* code of last encountered error */ +static int errorCount; /* count how many time it occured */ +/* ------------------------------------------------------------------------- */ + +char errorStrings[RE_MAX_ERROR][100] = { + "0: No error", + "1: recalculated depth falls outside original range", + "2: invalid face/halo type", + "3: invalid face index", + "4: invalid data pointer", + "5: generic trace counter", + "6: overflow on z buffer depth", + "7: write outside edgerender buffer", + "8: cannot allocate memory", + "9: write outside colour target buffer", +}; + +/* ------------------------------------------------------------------------- */ + +void RE_errortrace_reset(void) +{ + lastError = RE_NO_ERROR; + errorCount = 0; +} + +void RE_error(int errType, char* fname) +{ + /* + * This memory behaviour should move to the generic stream... + */ + + if (lastError == errType) { + int teller; + errorCount++; + for (teller = 0; teller < 12; teller++) + fprintf(GEN_errorstream, "%c", 0x08); /* backspaces */ + fprintf(GEN_errorstream, "( %8u )", errorCount); + } else { + fprintf(GEN_errorstream, "\n*** %s: %s ", + fname, errorStrings[errType]); + lastError = errType; + errorCount = 1; + } +} /* end of void RE_error(int errType, char* errText) */ + +/* ------------------------------------------------------------------------- */ +/* note: non-repeating */ +void RE_error_int(int errType, char* fname, int value) +{ + fprintf(GEN_errorstream, "\n*** %s: %s : %d", + fname, errorStrings[errType], value); + lastError = RE_NO_ERROR; +} /* end of void RE_error_int(int errType, char* errText, int value) */ + +/* ------------------------------------------------------------------------- */ + +/* eof */ diff --git a/source/blender/render/intern/source/gammaCorrectionTables.c b/source/blender/render/intern/source/gammaCorrectionTables.c new file mode 100644 index 00000000000..b25e7f0cdca --- /dev/null +++ b/source/blender/render/intern/source/gammaCorrectionTables.c @@ -0,0 +1,168 @@ +/** + * Jitter offset table + * + * $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 ***** + */ + +#include "gammaCorrectionTables.h" +#include +#include + +#include "render_intern.h" + +/* There are two parts here: one for the old renderer, one for the unified */ +/* renderer. we start with the latter. */ + +/* Default gamma. For most CRTs, gamma ranges from 2.2 to 2.5 (Foley), so */ +/* 2.35 seems appropriate enough. Experience teaches a different number */ +/* though. Old blender: 2.0. It might be nice to make this a slider */ +#define RE_DEFAULT_GAMMA 2.0 +/* This 400 is sort of based on the number of intensity levels needed for */ +/* the typical dynamic range of a medium, in this case CRTs. (Foley) */ +/* (Actually, it says the number should be between 400 and 535.) */ +#define RE_GAMMA_TABLE_SIZE 400 + +/* These indicate the status of the gamma lookup table --------------------- */ + +static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1]; +static float gamfactor_table[RE_GAMMA_TABLE_SIZE]; +static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1]; +static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE]; +static float colour_domain_table[RE_GAMMA_TABLE_SIZE + 1]; +static float colour_step; +static float inv_colour_step; +static float valid_gamma; +static float valid_inv_gamma; +static int gamma_table_initialised = 0; +static int do_gamma; +/* ------------------------------------------------------------------------- */ + +float gammaCorrect(float c) +{ + int i; + float res = 0.0; + + i = floor(c * inv_colour_step); + /* Clip to range [0,1]: outside, just do the complete calculation. */ + /* We may have some performance problems here. Stretching up the LUT */ + /* may help solve that, by exchanging LUT size for the interpolation. */ + /* Negative colours are explicitly handled. */ + if (i < 0) res = -pow(abs(c), valid_gamma); + else if (i >= RE_GAMMA_TABLE_SIZE ) res = pow(c, valid_gamma); + else res = gamma_range_table[i] + + ( (c - colour_domain_table[i]) * gamfactor_table[i]); + + return res; +} /* end of float gammaCorrect(float col) */ + +/* ------------------------------------------------------------------------- */ + +float invGammaCorrect(float col) +{ + int i; + float res = 0.0; + + i = floor(col*inv_colour_step); + /* Negative colours are explicitly handled. */ + if (i < 0) res = -pow(abs(col), valid_inv_gamma); + else if (i >= RE_GAMMA_TABLE_SIZE) res = pow(col, valid_inv_gamma); + else res = inv_gamma_range_table[i] + + ( (col - colour_domain_table[i]) * inv_gamfactor_table[i]); + + return res; +} /* end of float invGammaCorrect(float col) */ + + +/* ------------------------------------------------------------------------- */ + +void makeGammaTables(float gamma) +{ + /* we need two tables: one forward, one backward */ + int i; + + valid_gamma = gamma; + valid_inv_gamma = 1.0 / gamma; + colour_step = 1.0 / RE_GAMMA_TABLE_SIZE; + inv_colour_step = (float) RE_GAMMA_TABLE_SIZE; + + /* We could squeeze out the two range tables to gain some memory. */ + for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) { + colour_domain_table[i] = i * colour_step; + gamma_range_table[i] = pow(colour_domain_table[i], + valid_gamma); + inv_gamma_range_table[i] = pow(colour_domain_table[i], + valid_inv_gamma); + } + + /* The end of the table should match 1.0 carefully. In order to avoid */ + /* rounding errors, we just set this explicitly. The last segment may */ + /* have a different lenght than the other segments, but our */ + /* interpolation is insensitive to that. */ + colour_domain_table[RE_GAMMA_TABLE_SIZE] = 1.0; + gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0; + inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0; + + /* To speed up calculations, we make these calc factor tables. They are */ + /* multiplication factors used in scaling the interpolation. */ + for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++ ) { + gamfactor_table[i] = inv_colour_step + * (gamma_range_table[i + 1] - gamma_range_table[i]) ; + inv_gamfactor_table[i] = inv_colour_step + * (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]) ; + } + + gamma_table_initialised = 1; +} /* end of void makeGammaTables(float gamma) */ + +/* ------------------------------------------------------------------------- */ + +int gammaTableIsInitialised(void) +{ + return gamma_table_initialised; +} + +/* ------------------------------------------------------------------------- */ +int doGamma() +{ + return do_gamma; +} + +/* ------------------------------------------------------------------------- */ + +/** + * Set/unset performing gamma corrections. + */ +void setDoGamma(int i) +{ + do_gamma = i; +} + +/* eof */ diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c new file mode 100644 index 00000000000..67fddc271e6 --- /dev/null +++ b/source/blender/render/intern/source/initrender.c @@ -0,0 +1,1329 @@ +/** + * $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 ***** + */ + + +/* Global includes */ + +#include +#include +#include +#include + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +#include "MEM_guardedalloc.h" + +#include "PIL_time.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_rand.h" + +#include "MTC_matrixops.h" + +#include "DNA_image_types.h" +#include "DNA_camera_types.h" +#include "DNA_lamp_types.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" + +#include "BKE_utildefines.h" +#include "BKE_global.h" +#include "BKE_material.h" +#include "BKE_object.h" +#include "BKE_image.h" +#include "BKE_ipo.h" +#include "BKE_key.h" +#include "BKE_ika.h" +#include "BKE_action.h" +#include "BKE_writeavi.h" +#include "BKE_scene.h" + +#include "BIF_toolbox.h" +#include "BIF_writeavicodec.h" +#include "BIF_writemovie.h" /* start_movie(), append_movie(), end_movie() */ + +#include "BSE_drawview.h" +#include "BSE_sequence.h" + +/* this module */ +#include "render.h" +#include "render_intern.h" + +#include "RE_callbacks.h" +#include "zbuf.h" +#include "rendercore.h" /* part handler for the old renderer, shading functions */ +#include "renderPreAndPost.h" +#include "outerRenderLoop.h" +#include "renderHelp.h" +#include "jitter.h" + +/* Own includes */ +#include "initrender.h" + +/* Some crud :/ */ +#define ELEM3(a, b, c, d) ( ELEM(a, b, c) || (a)==(d) ) + + +/* uit render.c */ +extern float fmask[256], centLut[16]; +extern unsigned short *mask1[9], *mask2[9], /* *igamtab1, */ *igamtab2/*, *gamtab */; +extern char cmask[256], *centmask; + +Material defmaterial; +short pa; /* pa is globaal part ivm print */ +short allparts[65][4]; +int qscount; + +/* ********************* *********************** */ + + +void init_def_material(void) +{ + Material *ma; + + ma= &defmaterial; + + init_material(&defmaterial); + + init_render_material(ma); +} + +void RE_init_render_data(void) +{ + memset(&R, 0, sizeof(RE_Render)); + memset(&O, 0, sizeof(Osa)); + O.dxwin[0]= 1.0; + O.dywin[1]= 1.0; + + R.blove= (VertRen **)MEM_callocN(sizeof(void *)*(MAXVERT>>8),"Blove"); + R.blovl= (VlakRen **)MEM_callocN(sizeof(void *)*(MAXVLAK>>8),"Blovl"); + R.bloha= (HaloRen **)MEM_callocN(sizeof(void *)*(MAXVERT>>8),"Bloha"); + R.la= (LampRen **)MEM_mallocN(MAXLAMP*sizeof(void *),"renderlamparray"); + + init_def_material(); +} + +void RE_free_render_data() +{ + MEM_freeN(R.blove); + R.blove= 0; + MEM_freeN(R.blovl); + R.blovl= 0; + MEM_freeN(R.bloha); + R.bloha= 0; + MEM_freeN(R.la); + R.la= 0; + if(R.rectot) MEM_freeN(R.rectot); + if(R.rectz) MEM_freeN(R.rectz); + if(R.rectspare) MEM_freeN(R.rectspare); + R.rectot= 0; + R.rectz= 0; + R.rectspare= 0; + + end_render_material(&defmaterial); +} + +/* ****************** GAMMA, MASKERS en LUTS **************** */ + +float calc_weight(float *weight, int i, int j) +{ + float x, y, dist, totw= 0.0; + int a; + + for(a=0; a0; a--) { + val= count_mask(a); + i= (15.9*(fpy1[a & 255]+fpy2[a>>8])/val); + i<<=4; + i+= (15.9*(fpx1[a & 255]+fpx2[a>>8])/val); + centmask[a]= i; + } + + MEM_freeN(fpx1); + MEM_freeN(fpx2); + MEM_freeN(fpy1); + MEM_freeN(fpy2); + +} + +void RE_free_filt_mask() +{ + int a; + + for(a=0; a<9; a++) { + MEM_freeN(mask1[a]); + MEM_freeN(mask2[a]); + } + MEM_freeN(gamtab); + MEM_freeN(igamtab1); + MEM_freeN(igamtab2); + + MEM_freeN(centmask); +} + +/* add stuff */ + + +void defaultlamp() +{ + LampRen *lar; + + lar= (LampRen *)MEM_callocN(sizeof(LampRen),"lampren"); + R.la[R.totlamp++]=lar; + + lar->type= LA_SUN; + lar->vec[0]= -R.viewmat[2][0]; + lar->vec[1]= -R.viewmat[2][1]; + lar->vec[2]= -R.viewmat[2][2]; + Normalise(lar->vec); + lar->r= 1.0; + lar->g= 1.0; + lar->b= 1.0; + lar->lay= 65535; +} + + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void RE_make_existing_file(char *name) +{ + char di[FILE_MAXDIR], fi[FILE_MAXFILE]; + + strcpy(di, name); + BLI_splitdirstring(di, fi); + + /* exist testen */ + if (BLI_exists(di) == 0) { + BLI_recurdir_fileops(di); + } +} + + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +extern float holoofs; /* render.c */ +void RE_setwindowclip(int mode, int jmode) +{ + /* jmode>=0: alleen jitter doen, anders berekenen */ + /* mode==1 zet persmat en grvec */ + Camera *cam=0; + float lens, fac, minx, miny, maxx, maxy; + float xd, yd, afmx, afmy; + + if(G.scene->camera==0) return; + + afmx= R.afmx; + afmy= R.afmy; + + if(mode) { + + if(G.scene->camera->type==OB_LAMP) { + /* fac= cos( PI*((float)(256- la->spsi))/512.0 ); */ + + /* phi= acos(fac); */ + /* lens= 16.0*fac/sin(phi); */ + lens= 35.0; + R.near= 0.1; + R.far= 1000.0; + } + else if(G.scene->camera->type==OB_CAMERA) { + cam= G.scene->camera->data; + + lens= cam->lens; + R.near= cam->clipsta; + R.far= cam->clipend; + } + else { + lens= 16.0; + } + + if( (R.r.xasp*afmx) >= (R.r.yasp*afmy) ) { + R.viewfac= (afmx*lens)/16.0; + } + else { + R.viewfac= R.ycor*(afmy*lens)/16.0; + } + if(R.r.mode & R_ORTHO) { + R.near*= 100.0; /* R.far niet doen */ + R.viewfac*= 100.0; + } + + R.pixsize= R.near/R.viewfac; + + } + + /* I think these offsets are wrong. They do not coincide with shadow */ + /* calculations, btw. */ + minx= R.xstart+.5; + miny= R.ycor*(R.ystart+.5); + maxx= R.xend+.4999; + maxy= R.ycor*(R.yend+.4999); + /* My guess: (or rather, what should be) */ +/* minx= R.xstart - 0.5; */ +/* miny= R.ycor * (R.ystart - 0.5); */ + /* Since the SCS-s map directly to the pixel center coordinates, we need */ + /* to stretch the clip area a bit, not just shift it. However, this gives*/ + /* nasty problems for parts... */ + + if(R.flag & R_SEC_FIELD) { + if(R.r.mode & R_ODDFIELD) { + miny-= .5*R.ycor; + maxy-= .5*R.ycor; + } + else { + miny+= .5*R.ycor; + maxy+= .5*R.ycor; + } + } + + xd= yd= 0.0; + if(jmode!= -1) { + xd= jit[jmode % R.osa][0]; + yd= R.ycor*jit[jmode % R.osa][1]; + + } + + if(G.special1 & G_HOLO) { + if(G.scene->camera->type==OB_CAMERA) { + cam= G.scene->camera->data; + if(cam->flag & CAM_HOLO2) { + + if(cam->netend==0.0) cam->netend= (G.scene->r.efra); + + fac= ((G.scene->r.cfra)-1.0)/(cam->netend)-0.5; + fac*= (R.rectx); + fac*= cam->hololen1; + + holoofs= -fac; + minx-= fac; + maxx-= fac; + } + } + } + + minx= R.pixsize*(minx+xd); + maxx= R.pixsize*(maxx+xd); + miny= R.pixsize*(miny+yd); + maxy= R.pixsize*(maxy+yd); + + if(R.r.mode & R_ORTHO) { + /* hier de near & far vermenigvuldigen is voldoende! */ + + i_window(minx, maxx, miny, maxy, R.near, 100.0*R.far, R.winmat); + } + else i_window(minx, maxx, miny, maxy, R.near, R.far, R.winmat); + +} + + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +void initparts() +{ + short nr, xd, yd, xpart, ypart, xparts, yparts; + short a, xminb, xmaxb, yminb, ymaxb; + + if(R.r.mode & R_BORDER) { + xminb= R.r.border.xmin*R.rectx; + xmaxb= R.r.border.xmax*R.rectx; + + yminb= R.r.border.ymin*R.recty; + ymaxb= R.r.border.ymax*R.recty; + + if(xminb<0) xminb= 0; + if(xmaxb>R.rectx) xmaxb= R.rectx; + if(yminb<0) yminb= 0; + if(ymaxb>R.recty) ymaxb= R.recty; + } + else { + xminb=yminb= 0; + xmaxb= R.rectx; + ymaxb= R.recty; + } + + xparts= R.r.xparts; /* voor border */ + yparts= R.r.yparts; + + for(nr=0;nrrect; + len= (allparts[nr][2]-allparts[nr][0]); + heigth= (allparts[nr][3]-allparts[nr][1]); + + for(y=0;ycamera==0) return; + + if(G.scene->camera->type==OB_CAMERA) { + cam= G.scene->camera->data; + if(cam->flag & (CAM_HOLO1|CAM_HOLO2)) { + fy= G.scene->camera->loc[1]; + fz= G.scene->camera->loc[2]; + dist= cam->hololen*sqrt( fy*fy+ fz*fz ); + + fac= ((G.scene->r.cfra)-(G.scene->r.sfra))/((float)((G.scene->r.efra)-(G.scene->r.sfra))); + + G.scene->camera->loc[0]= -dist+ 2*fac*dist; + } + } +} + +void add_to_blurbuf(int blur) +{ + static unsigned int *blurrect= 0; + int tot, gamval; + short facr, facb; + char *rtr, *rtb; + + if(blur<0) { + if(blurrect) { + if(R.rectot) MEM_freeN(R.rectot); + R.rectot= blurrect; + blurrect= 0; + } + } + else if(blur==R.osa-1) { + /* eerste keer */ + blurrect= MEM_mallocN(R.rectx*R.recty*sizeof(int), "rectblur"); + if(R.rectot) memcpy(blurrect, R.rectot, R.rectx*R.recty*4); + } + else if(blurrect) { + /* accumuleren */ + + facr= 256/(R.osa-blur); + facb= 256-facr; + + if(R.rectot) { + rtr= (char *)R.rectot; + rtb= (char *)blurrect; + tot= R.rectx*R.recty; + while(tot--) { + if( *((unsigned int *)rtb) != *((unsigned int *)rtr) ) { + + if(R.r.mode & R_GAMMA) { + gamval= (facr* igamtab2[ rtr[0]<<8 ] + facb* igamtab2[ rtb[0]<<8 ])>>8; + rtb[0]= gamtab[ gamval ]>>8; + gamval= (facr* igamtab2[ rtr[1]<<8 ] + facb* igamtab2[ rtb[1]<<8 ])>>8; + rtb[1]= gamtab[ gamval ]>>8; + gamval= (facr* igamtab2[ rtr[2]<<8 ] + facb* igamtab2[ rtb[2]<<8 ])>>8; + rtb[2]= gamtab[ gamval ]>>8; + gamval= (facr* igamtab2[ rtr[3]<<8 ] + facb* igamtab2[ rtb[3]<<8 ])>>8; + rtb[3]= gamtab[ gamval ]>>8; + } + else { + rtb[0]= (facr*rtr[0] + facb*rtb[0])>>8; + rtb[1]= (facr*rtr[1] + facb*rtb[1])>>8; + rtb[2]= (facr*rtr[2] + facb*rtb[2])>>8; + rtb[3]= (facr*rtr[3] + facb*rtb[3])>>8; + } + } + rtr+= 4; + rtb+= 4; + } + } + if(blur==0) { + /* laatste keer */ + if(R.rectot) MEM_freeN(R.rectot); + R.rectot= blurrect; + blurrect= 0; + } + } +} + + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +void render() { + /* not too neat... should improve... */ + if(R.r.mode & R_UNIFIED) { + unifiedRenderingLoop(); + } else { + oldRenderLoop(); + } +} + + +void oldRenderLoop(void) /* hierbinnen de PART en FIELD lussen */ +{ + Part *part; + unsigned int *rt, *rt1, *rt2; + int len, y; + short blur, a,fields,fi,parts; /* pa is globaal ivm print */ + unsigned int *border_buf= NULL; + unsigned int border_x= 0; + unsigned int border_y= 0; + + if((R.r.mode & R_BORDER) && !(R.r.mode & R_MOVIECROP)) { + border_buf= R.rectot; + border_x= R.rectx; + border_y= R.recty; + R.rectot= 0; + } + + + if (R.rectz) MEM_freeN(R.rectz); + R.rectz = 0; + + /* FIELDLUS */ + fields= 1; + parts= R.r.xparts*R.r.yparts; + + if(R.r.mode & R_FIELDS) { + fields= 2; + R.rectf1= R.rectf2= 0; /* fieldrecten */ + R.r.ysch/= 2; + R.afmy/= 2; + R.r.yasp*= 2; + R.ycor= ( (float)R.r.yasp)/( (float)R.r.xasp); + + } + + + for(fi=0; fir.cfra)+fi); + + + R.vlaknr= -1; + R.flag|= R_RENDERING; + if(fi==1) R.flag |= R_SEC_FIELD; + + + /* MOTIONBLUR lus */ + if(R.r.mode & R_MBLUR) blur= R.osa; + else blur= 1; + + + while(blur--) { + + /* WINDOW */ + R.rectx= R.r.xsch; + R.recty= R.r.ysch; + R.xstart= -R.afmx; + R.ystart= -R.afmy; + R.xend= R.xstart+R.rectx-1; + R.yend= R.ystart+R.recty-1; + + + if(R.r.mode & R_MBLUR) set_mblur_offs(R.osa-blur); + + initparts(); /* altijd doen ivm border */ + setpart(0); + + RE_local_init_render_display(); + RE_local_clear_render_display(R.win); + RE_local_timecursor((G.scene->r.cfra)); + + prepareScene(); + + /* PARTS */ + R.parts.first= R.parts.last= 0; + for(pa=0; pa1 || (R.r.mode & R_BORDER)) { + + part= MEM_callocN(sizeof(Part), "part"); + BLI_addtail(&R.parts, part); + part->rect= R.rectot; + R.rectot= 0; + + if (R.rectz) { + MEM_freeN(R.rectz); + R.rectz= 0; + } + } + } + } + + /* PARTS SAMENVOEGEN OF BORDER INVOEGEN */ + + /* uitzondering: crop */ + if( (R.r.mode & R_BORDER) && (R.r.mode & R_MOVIECROP)) ; + else { + R.rectx= R.r.xsch; + R.recty= R.r.ysch; + + if(R.r.mode & R_PANORAMA) R.rectx*= R.r.xparts; + + if(parts>1 || (R.r.mode & R_BORDER)) { + if(R.rectot) MEM_freeN(R.rectot); + if(R.r.mode & R_BORDER) { + if(border_xnext; + } + + part= R.parts.first; + while(part) { + MEM_freeN(part->rect); + part= part->next; + } + BLI_freelistN(&R.parts); + } + } + + if( (R.flag & R_HALO)) { + add_halo_flare(); + } + + if(R.r.mode & R_MBLUR) { + add_to_blurbuf(blur); + } + + /* EINDE (blurlus) */ + finalizeScene(); + + if(RE_local_test_break()) break; + } + + /* definitief vrijgeven */ + add_to_blurbuf(-1); + + /* FIELD AFHANDELEN */ + if(R.r.mode & R_FIELDS) { + if(R.flag & R_SEC_FIELD) R.rectf2= R.rectot; + else R.rectf1= R.rectot; + R.rectot= 0; + } + + if(RE_local_test_break()) break; + } + + /* FIELDS SAMENVOEGEN */ + if(R.r.mode & R_FIELDS) { + R.r.ysch*= 2; + R.afmy*= 2; + R.recty*= 2; + R.r.yasp/=2; + + if(R.rectot) MEM_freeN(R.rectot); /* komt voor bij afbreek */ + R.rectot=(unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot"); + + if(RE_local_test_break()==0) { + rt= R.rectot; + + if(R.r.mode & R_ODDFIELD) { + rt2= R.rectf1; + rt1= R.rectf2; + } + else { + rt1= R.rectf1; + rt2= R.rectf2; + } + + len= 4*R.rectx; + + for(a=0; ar; + R.r.postigamma= 1.0/R.r.postgamma; + + /* voor zekerheid: bij voortijdige return */ + R.rectx= R.r.xsch; + R.recty= R.r.ysch; + + /* MAG ER WEL WORDEN GERENDERD */ + + /* verboden combinatie */ + if((R.r.mode & R_BORDER) && (R.r.mode & R_PANORAMA)) { + error("No border allowed for Panorama"); + G.afbreek= 1; + return; + } + + + if(R.r.xparts*R.r.yparts>64) { + error("No more than 64 parts"); + G.afbreek= 1; + return; + } + + if(R.r.yparts>1 && (R.r.mode & R_PANORAMA)) { + error("No Y-Parts allowed for Panorama"); + G.afbreek= 1; + return; + } + + + /* BACKBUF TESTEN */ + /* If an image is specified for use as backdrop, that image is loaded */ + /* here. */ + if((R.r.bufflag & 1) && (G.scene->r.scemode & R_OGL)==0) { + if(R.r.alphamode == R_ADDSKY) { + strcpy(name, R.r.backbuf); + BLI_convertstringcode(name, G.sce, G.scene->r.cfra); + + if(R.backbuf) { + R.backbuf->id.us--; + bima= R.backbuf; + } + else bima= 0; + + R.backbuf= add_image(name); + + if(bima && bima->id.us<1) { + free_image_buffers(bima); + } + if(R.backbuf==0) { + error("No backbuf there!"); + G.afbreek= 1; + return; + } + } + } + + + usegamtab= 0; /* zie hieronder */ + + if(R.r.mode & (R_OSA|R_MBLUR)) { + R.osa= R.r.osa; + if(R.osa>16) R.osa= 16; + + init_render_jit(R.osa); + RE_init_filt_mask(); + + /* wordt af en toe tijdelijk op nul gezet, o.a. in transp zbuf */ + if(R.r.mode & R_GAMMA) { + if((R.r.mode & R_OSA)) usegamtab= 1; + } + } + else R.osa= 0; + + /* WINDOW */ + R.r.xsch= (R.r.size*R.r.xsch)/100; + R.r.ysch= (R.r.size*R.r.ysch)/100; + + R.afmx= R.r.xsch/2; + R.afmy= R.r.ysch/2; + + /* when rendered without camera object */ + /* it has to done here because of envmaps */ + R.near= 0.1; + R.far= 1000.0; + + + if(R.afmx<1 || R.afmy<1) { + error("Image too small"); + return; + } + R.ycor= ( (float)R.r.yasp)/( (float)R.r.xasp); + + start_time= PIL_check_seconds_timer(); + + if(R.r.scemode & R_DOSEQ) { + R.rectx= R.r.xsch; + R.recty= R.r.ysch; + + if(R.rectot) MEM_freeN(R.rectot); + R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot"); + + RE_local_timecursor((G.scene->r.cfra)); + + if(RE_local_test_break()==0) do_render_seq(); + + /* displayen */ + if(R.rectot) RE_local_render_display(0, R.recty-1, + R.rectx, R.recty, + R.rectot); + } + else if(R.r.scemode & R_OGL) { + R.rectx= R.r.xsch; + R.recty= R.r.ysch; + + if(R.rectot) MEM_freeN(R.rectot); + R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot"); + + RE_local_init_render_display(); + drawview3d_render(ogl_render_view3d); + } + else { + if(G.scene->camera==0) { + G.scene->camera= scene_find_camera(G.scene); + } + + if(G.scene->camera==0) { + error("No camera"); + G.afbreek=1; + return; + } + else { + + if(G.scene->camera->type==OB_CAMERA) { + Camera *cam= G.scene->camera->data; + if(cam->type==CAM_ORTHO) R.r.mode |= R_ORTHO; + } + + render(); /* keert terug met complete rect xsch-ysch */ + } + } + + /* nog eens displayen: fields/seq/parts/pano etc */ + if(R.rectot) { + RE_local_init_render_display(); + RE_local_render_display(0, R.recty-1, + R.rectx, R.recty, + R.rectot); + } + else RE_local_clear_render_display(R.win); + + RE_local_printrenderinfo((PIL_check_seconds_timer() - start_time), -1); + + /* variabelen weer goed */ + R.osatex= 0; + R.vlr= 0; /* bij cubemap */ + R.flag= 0; +} + +void RE_animrender(struct View3D *ogl_render_view3d) +{ + int cfrao; + char name[256]; + + if(G.scene==0) return; + + /* scenedata naar R: (voor backbuf, R.rectx enz) */ + R.r= G.scene->r; + + /* START ANIMLUS overal wordt NIET de cfra uit R.r gebruikt: ivm rest blender */ + cfrao= (G.scene->r.cfra); + + if(G.scene->r.scemode & R_OGL) R.r.mode &= ~R_PANORAMA; + + // these calculations apply for + // all movie formats + R.rectx= (R.r.size*R.r.xsch)/100; + R.recty= (R.r.size*R.r.ysch)/100; + if(R.r.mode & R_PANORAMA) { + R.rectx*= R.r.xparts; + R.recty*= R.r.yparts; + } + + if (0) { +#ifdef __sgi + } else if (R.r.imtype==R_MOVIE) { + start_movie(); +#endif +#ifdef _WIN32 + } else if (R.r.imtype == R_AVICODEC) { + start_avi_codec(); +#endif + } else if ELEM4(R.r.imtype, R_AVIRAW, R_AVIJPEG, R_MOVIE, R_AVICODEC) { + if ELEM(R.r.imtype, R_MOVIE, R_AVICODEC) { + printf("Selected movie format not supported on this platform,\nusing RAW AVI instead\n"); + } + start_avi(); + } + + for((G.scene->r.cfra)=(G.scene->r.sfra); (G.scene->r.cfra)<=(G.scene->r.efra); (G.scene->r.cfra)++) { + double starttime= PIL_check_seconds_timer(); + + R.flag= R_ANIMRENDER; + + RE_initrender(ogl_render_view3d); + + /* SCHRIJF PLAATJE */ + if(RE_local_test_break()==0) { + + if (0) { +#ifdef __sgi + } else if (R.r.imtype == R_MOVIE) { + append_movie((G.scene->r.cfra)); +#endif +#ifdef _WIN32 + } else if (R.r.imtype == R_AVICODEC) { + append_avi_codec((G.scene->r.cfra)); +#endif + } else if ELEM4(R.r.imtype, R_AVIRAW, R_AVIJPEG, R_MOVIE, R_AVICODEC) { + append_avi((G.scene->r.cfra)); + } else { + makepicstring(name, (G.scene->r.cfra)); + schrijfplaatje(name); + if(RE_local_test_break()==0) printf("Saved: %s", name); + } + + timestr(PIL_check_seconds_timer()-starttime, name); + printf(" Time: %s\n", name); + fflush(stdout); /* nodig voor renderd !! */ + } + + if(G.afbreek==1) break; + + } + + (G.scene->r.cfra)= cfrao; + + /* restoren tijd */ + if(R.r.mode & (R_FIELDS|R_MBLUR)) { + do_all_ipos(); + do_all_keys(); + do_all_actions(); + do_all_ikas(); + } + + if (0) { +#ifdef __sgi + } else if (R.r.imtype==R_MOVIE) { + end_movie(); +#endif +#ifdef _WIN32 + } else if (R.r.imtype == R_AVICODEC) { + end_avi_codec(); +#endif + } else if ELEM4(R.r.imtype, R_AVIRAW, R_AVIJPEG, R_MOVIE, R_AVICODEC) { + end_avi(); + } +} + +/* *************************************************** */ +/* ******************* Screendumps ******************** */ +/* moved to the windowControl thing */ diff --git a/source/blender/render/intern/source/jitter.c b/source/blender/render/intern/source/jitter.c new file mode 100644 index 00000000000..19311132a7e --- /dev/null +++ b/source/blender/render/intern/source/jitter.c @@ -0,0 +1,192 @@ +/** + * Jitter offset table + * + * $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 ***** + */ + +#include +#include +#include +#include "MEM_guardedalloc.h" + +#include "BLI_arithb.h" +#include "BLI_rand.h" +#include "render.h" +#include "render_intern.h" +#include "jitter.h" + +float jit[64][2]; + +void init_render_jit(int nr); + + +void RE_jitterate1(float *jit1, float *jit2, int num, float rad1) +{ + int i , j , k; + float vecx, vecy, dvecx, dvecy, x, y, len; + + for (i = 2*num-2; i>=0 ; i-=2) { + dvecx = dvecy = 0.0; + x = jit1[i]; + y = jit1[i+1]; + for (j = 2*num-2; j>=0 ; j-=2) { + if (i != j){ + vecx = jit1[j] - x - 1.0; + vecy = jit1[j+1] - y - 1.0; + for (k = 3; k>0 ; k--){ + if( fabs(vecx)0 && len0 && len0 && len= 0 ; i-=2){ + dvecx = dvecy = 0.0; + x = jit1[i]; + y = jit1[i+1]; + for (j =2*num -2; j>= 0 ; j-=2){ + if (i != j){ + vecx = jit1[j] - x - 1.0; + vecy = jit1[j+1] - y - 1.0; + + if( fabs(vecx) +#include + +#include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" +#include "BLI_rand.h" + +#include "BKE_global.h" +#include "BKE_object.h" + +#include "render.h" +#include "render_intern.h" +#include "outerRenderLoop.h" +#include "renderPreAndPost.h" +#include "vanillaRenderPipe.h" +#include "renderHelp.h" +#include "RE_callbacks.h" + +extern short pa; /* can move to inside the outer loop */ +/* should make a gamtab module, just like the jitter... */ +extern unsigned short *mask1[9], *mask2[9], *igamtab2; + + +/* Parts bookkeeping: done on this level, because it seems appropriate to me.*/ +static short partsCoordinates[65][4]; +short setPart(short nr);/* return 0 if this is a bad part. Sets data in R....*/ +void initParts(void); +void addPartToRect(short nr, Part *part); +void addToBlurBuffer(int blur); + +/* ------------------------------------------------------------------------- */ +void addToBlurBuffer(int blur) +{ + static unsigned int *blurrect= 0; + int tot, gamval; + short facr, facb; + char *rtr, *rtb; + + if(blur<0) { + if(blurrect) { + if(R.rectot) MEM_freeN(R.rectot); + R.rectot= blurrect; + blurrect= 0; + } + } + else if(blur==R.osa-1) { + /* eerste keer */ + blurrect= MEM_mallocN(R.rectx*R.recty*sizeof(int), "rectblur"); + if(R.rectot) memcpy(blurrect, R.rectot, R.rectx*R.recty*4); + } + else if(blurrect) { + /* accumuleren */ + + facr= 256/(R.osa-blur); + facb= 256-facr; + + if(R.rectot) { + rtr= (char *)R.rectot; + rtb= (char *)blurrect; + tot= R.rectx*R.recty; + while(tot--) { + if( *((unsigned int *)rtb) != *((unsigned int *)rtr) ) { + + if(R.r.mode & R_GAMMA) { + gamval= (facr* igamtab2[ rtr[0]<<8 ] + facb* igamtab2[ rtb[0]<<8 ])>>8; + rtb[0]= gamtab[ gamval ]>>8; + gamval= (facr* igamtab2[ rtr[1]<<8 ] + facb* igamtab2[ rtb[1]<<8 ])>>8; + rtb[1]= gamtab[ gamval ]>>8; + gamval= (facr* igamtab2[ rtr[2]<<8 ] + facb* igamtab2[ rtb[2]<<8 ])>>8; + rtb[2]= gamtab[ gamval ]>>8; + gamval= (facr* igamtab2[ rtr[3]<<8 ] + facb* igamtab2[ rtb[3]<<8 ])>>8; + rtb[3]= gamtab[ gamval ]>>8; + } + else { + rtb[0]= (facr*rtr[0] + facb*rtb[0])>>8; + rtb[1]= (facr*rtr[1] + facb*rtb[1])>>8; + rtb[2]= (facr*rtr[2] + facb*rtb[2])>>8; + rtb[3]= (facr*rtr[3] + facb*rtb[3])>>8; + } + } + rtr+= 4; + rtb+= 4; + } + } + if(blur==0) { + /* laatste keer */ + if(R.rectot) MEM_freeN(R.rectot); + R.rectot= blurrect; + blurrect= 0; + } + } +} + + +/* ------------------------------------------------------------------------- */ + +void addPartToRect(short nr, Part *part) +{ + unsigned int *rt, *rp; + short y, heigth, len; + + /* de juiste offset in rectot */ + + rt= R.rectot+ (partsCoordinates[nr][1]*R.rectx+ partsCoordinates[nr][0]); + rp= part->rect; + len= (partsCoordinates[nr][2]-partsCoordinates[nr][0]); + heigth= (partsCoordinates[nr][3]-partsCoordinates[nr][1]); + + for(y=0;yR.rectx) xmaxb= R.rectx; + if(yminb<0) yminb= 0; + if(ymaxb>R.recty) ymaxb= R.recty; + } + else { + xminb=yminb= 0; + xmaxb= R.rectx; + ymaxb= R.recty; + } + + xparts= R.r.xparts; /* voor border */ + yparts= R.r.yparts; + + for(nr=0;nrr.cfra)+fi); + + + R.vlaknr= -1; + R.flag|= R_RENDERING; + if(fi==1) R.flag |= R_SEC_FIELD; + + + /* MOTIONBLUR lus */ + if(R.r.mode & R_MBLUR) blur= R.osa; + else blur= 1; + + + while(blur--) { + + /* WINDOW */ + R.rectx= R.r.xsch; + R.recty= R.r.ysch; + R.xstart= -R.afmx; + R.ystart= -R.afmy; + R.xend= R.xstart+R.rectx-1; + R.yend= R.ystart+R.recty-1; + + + if(R.r.mode & R_MBLUR) set_mblur_offs(R.osa-blur); + + initParts(); /* altijd doen ivm border */ + setPart(0); + + RE_local_init_render_display(); + RE_local_clear_render_display(R.win); + RE_local_timecursor((G.scene->r.cfra)); + + prepareScene(); + + /* PARTS */ + R.parts.first= R.parts.last= 0; + for(pa=0; pa1 || (R.r.mode & R_BORDER)) { + + part= MEM_callocN(sizeof(Part), "part"); + BLI_addtail(&R.parts, part); + part->rect= R.rectot; + R.rectot= 0; + + if (R.rectz) { + MEM_freeN(R.rectz); + R.rectz= 0; + } + } + } + } + + /* PARTS SAMENVOEGEN OF BORDER INVOEGEN */ + + /* uitzondering: crop */ + if( (R.r.mode & R_BORDER) && (R.r.mode & R_MOVIECROP)) ; + else { + R.rectx= R.r.xsch; + R.recty= R.r.ysch; + + if(R.r.mode & R_PANORAMA) R.rectx*= R.r.xparts; + + if(parts>1 || (R.r.mode & R_BORDER)) { + if(R.rectot) MEM_freeN(R.rectot); + if(R.r.mode & R_BORDER) { + if(border_xnext; + } + + part= R.parts.first; + while(part) { + MEM_freeN(part->rect); + part= part->next; + } + BLI_freelistN(&R.parts); + } + } + + /* don't do this for unified renderer? */ +/* if( (R.flag & R_HALO) && !G.magic) { */ +/* add_halo_flare(); */ +/* } */ + + if(R.r.mode & R_MBLUR) { + addToBlurBuffer(blur); + } + + /* EINDE (blurlus) */ + finalizeScene(); + + if(RE_local_test_break()) break; + } + + /* definitief vrijgeven */ + addToBlurBuffer(-1); + + /* FIELD AFHANDELEN */ + if(R.r.mode & R_FIELDS) { + if(R.flag & R_SEC_FIELD) R.rectf2= R.rectot; + else R.rectf1= R.rectot; + R.rectot= 0; + } + + if(RE_local_test_break()) break; + } + + /* FIELDS SAMENVOEGEN */ + if(R.r.mode & R_FIELDS) { + R.r.ysch*= 2; + R.afmy*= 2; + R.recty*= 2; + R.r.yasp/=2; + + if(R.rectot) MEM_freeN(R.rectot); /* komt voor bij afbreek */ + R.rectot=(unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot"); + + if(RE_local_test_break()==0) { + rt= R.rectot; + + if(R.r.mode & R_ODDFIELD) { + rt2= R.rectf1; + rt1= R.rectf2; + } + else { + rt1= R.rectf1; + rt2= R.rectf2; + } + + len= 4*R.rectx; + + for(a=0; a + +/* global includes */ +#include "render.h" +#include "render_intern.h" + +/* local includes */ +#include "vanillaRenderPipe_types.h" + +/* own includes */ +#include "pixelblending_types.h" +#include "pixelblending.h" +#include "gammaCorrectionTables.h" + +/* externals */ + +/* ------------------------------------------------------------------------- */ +/* Debug/behaviour defines */ +/* if defined: alpha blending with floats clips colour, as with shorts */ +/* #define RE_FLOAT_COLOUR_CLIPPING */ +/* if defined: alpha values are clipped */ +/* For now, we just keep alpha clipping. We run into thresholding and */ +/* blending difficulties otherwise. Be careful here. */ +#define RE_ALPHA_CLIPPING + +/* functions --------------------------------------------------------------- */ + +/* + One things about key-alpha is that simply dividing by the alpha will + sometimes cause 'overflows' in that the pixel colours will be shot + way over full colour. This should be caught, and subsequently, the + operation will end up modifying the alpha as well. + + Actually, when the starting colour is premul, it shouldn't overflow + ever. Strange thing is that colours keep overflowing... + +*/ +void applyKeyAlphaCharCol(char* target) { + + if ((!(target[3] == 0)) + || (target[3] == 255)) { + /* else: nothing to do */ + /* check whether div-ing is enough */ + float cf[4]; + cf[0] = target[0]/target[3]; + cf[1] = target[1]/target[3]; + cf[2] = target[2]/target[3]; + if ((cf[0] <= 1.0) && (cf[1] <= 1.0) && (cf[2] <= 1.0)) { + /* all colours remain properly scaled? */ + /* scale to alpha */ + cf[0] = (float) target[0] * (255.0/ (float)target[3]); + cf[1] = (float) target[1] * (255.0/ (float)target[3]); + cf[2] = (float) target[2] * (255.0/ (float)target[3]); + + /* Clipping is important. */ + target[0] = (cf[0] > 255.0 ? 255 : (char) cf[0]); + target[1] = (cf[1] > 255.0 ? 255 : (char) cf[1]); + target[2] = (cf[2] > 255.0 ? 255 : (char) cf[2]); + + } else { + /* shouldn't happen! we were premul, remember? */ +/* should go to error handler: printf("Non-premul colour detected\n"); */ + } + } + +} /* end of void applyKeyAlphaCharCol(char* target) */ + +/* ------------------------------------------------------------------------- */ + +void addAddSampColF(float *sampvec, float *source, int mask, int osaNr, + char addfac) +{ + int a; + + for(a=0; a < osaNr; a++) { + if(mask & (1< RE_FULL_COLOUR_FLOAT) retval--; + sampvec+= 4; + } + return retval; +} /* end of int addToSampColF(float, float, int, int) */ + +/* ------------------------------------------------------------------------- */ + +int addToSampCol(unsigned short *sampcol, unsigned short *shortcol, int mask, int osaNr) +{ + int a, retval = osaNr; + + for(a=0; a < osaNr; a++) { + if(mask & (1<0xFFF0) retval--; + sampcol+= 4; + } + return retval; +} /* end of int addToSampCol(unsigned short, uhost, int, int) */ + +/* ------------------------------------------------------------------------- */ + +int addtosampcol(unsigned short *sampcol, unsigned short *shortcol, int mask) +{ + int a, retval = R.osa; + + for(a=0; a < R.osa; a++) { + if(mask & (1<0xFFF0) retval--; + sampcol+= 4; + } + return retval; +} /* end of int addtosampcol(unsigned short *sampcol, unsigned short *shortcol, int mask) */ + +/* ------------------------------------------------------------------------- */ + +void addAlphaOverShort(unsigned short *doel, unsigned short *bron) /* vult bron over doel in met alpha van bron */ +{ + unsigned int c; + unsigned int mul; + + if( doel[3]==0 || bron[3]>=0xFFF0) { /* is getest, scheelt veel */ + *((unsigned int *)doel)= *((unsigned int *)bron); + *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2)); + return; + } + + mul= 0xFFFF-bron[3]; + + c= ((mul*doel[0])>>16)+bron[0]; + if(c>=0xFFF0) doel[0]=0xFFF0; + else doel[0]= c; + c= ((mul*doel[1])>>16)+bron[1]; + if(c>=0xFFF0) doel[1]=0xFFF0; + else doel[1]= c; + c= ((mul*doel[2])>>16)+bron[2]; + if(c>=0xFFF0) doel[2]=0xFFF0; + else doel[2]= c; + c= ((mul*doel[3])>>16)+bron[3]; + if(c>=0xFFF0) doel[3]=0xFFF0; + else doel[3]= c; + +} /* end of void addAlphaOverShort(unsigned short *doel, unsigned short *bron) */ + +/* ------------------------------------------------------------------------- */ + +void addAlphaUnderShort(unsigned short *doel, unsigned short *bron) /* vult bron onder doel in met alpha van doel */ +{ + unsigned int c; + unsigned int mul; + + if(doel[3]>=0xFFF0) return; + if( doel[3]==0 ) { /* is getest, scheelt veel */ + *((unsigned int *)doel)= *((unsigned int *)bron); + *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2)); + return; + } + + mul= 0xFFFF-doel[3]; + + c= ((mul*bron[0])>>16)+doel[0]; + if(c>=0xFFF0) doel[0]=0xFFF0; + else doel[0]= c; + c= ((mul*bron[1])>>16)+doel[1]; + if(c>=0xFFF0) doel[1]=0xFFF0; + else doel[1]= c; + c= ((mul*bron[2])>>16)+doel[2]; + if(c>=0xFFF0) doel[2]=0xFFF0; + else doel[2]= c; + c= ((mul*bron[3])>>16)+doel[3]; + if(c>=0xFFF0) doel[3]=0xFFF0; + else doel[3]= c; + +} /* end of void addAlphaUnderShort(unsigned short *doel, unsigned short *bron) */ + +/* ------------------------------------------------------------------------- */ + +void addAlphaOverFloat(float *dest, float *source) +{ + /* d = s + (1-alpha_s)d*/ + float c; + float mul; + + /* I may want to disable this clipping */ +#ifdef RE_FLOAT_COLOUR_CLIPPING + if( /* (-RE_FULL_COLOUR_FLOAT < source[3]) */ +/* && */ (source[3] > RE_FULL_COLOUR_FLOAT) ) { /* is getest, scheelt veel */ + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; + return; + } +#endif + + mul= 1.0 - source[3]; + + c= (mul*dest[0]) + source[0]; +#ifdef RE_FLOAT_COLOUR_CLIPPING + if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_UNITY_COLOUR_FLOAT; + else +#endif + dest[0]= c; + + c= (mul*dest[1]) + source[1]; +#ifdef RE_FLOAT_COLOUR_CLIPPING + if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_UNITY_COLOUR_FLOAT; + else +#endif + dest[1]= c; + + c= (mul*dest[2]) + source[2]; +#ifdef RE_FLOAT_COLOUR_CLIPPING + if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_UNITY_COLOUR_FLOAT; + else +#endif + dest[2]= c; + + c= (mul*dest[3]) + source[3]; +#ifdef RE_ALPHA_CLIPPING + if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_UNITY_COLOUR_FLOAT; + else +#endif + dest[3]= c; + +} /* end of void addAlphaOverFloat(float *doel, float *bron) */ + + + +/* ------------------------------------------------------------------------- */ + +void addAlphaUnderFloat(float *dest, float *source) +{ + float c; + float mul; + + /* I may want to disable this clipping */ +#ifdef RE_FLOAT_COLOUR_CLIPPING + if( dest[3] >= RE_FULL_COLOUR_FLOAT) return; +#endif + if( (-RE_EMPTY_COLOUR_FLOAT < dest[3]) + && (dest[3] < RE_EMPTY_COLOUR_FLOAT) ) { /* is getest, scheelt veel */ + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; + return; + } + + mul= 1.0 - dest[3]; + + c= (mul*source[0]) + dest[0]; +#ifdef RE_FLOAT_COLOUR_CLIPPING + if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_UNITY_COLOUR_FLOAT; + else +#endif + dest[0]= c; + + c= (mul*source[1]) + dest[1]; +#ifdef RE_FLOAT_COLOUR_CLIPPING + if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_UNITY_COLOUR_FLOAT; + else +#endif + dest[1]= c; + + c= (mul*source[2]) + dest[2]; +#ifdef RE_FLOAT_COLOUR_CLIPPING + if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_UNITY_COLOUR_FLOAT; + else +#endif + dest[2]= c; + + c= (mul*source[3]) + dest[3]; +#ifdef RE_ALPHA_CLIPPING + if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_UNITY_COLOUR_FLOAT; + else +#endif + dest[3]= c; + +} /* end of void addAlphaUnderFloat(float *doel, float *bron) */ + +/* ------------------------------------------------------------------------- */ + +void cpShortColV2CharColV(unsigned short *source, char *dest) +{ + dest[0] = source[0]>>8; + dest[1] = source[1]>>8; + dest[2] = source[2]>>8; + dest[3] = source[3]>>8; +} /* end of void cpShortColV2CharColV(unsigned short *source, char *dest) */ +/* ------------------------------------------------------------------------- */ + +void cpCharColV2ShortColV(char *source, unsigned short *dest) +{ + dest[0] = source[0]<<8; + dest[1] = source[1]<<8; + dest[2] = source[2]<<8; + dest[3] = source[3]<<8; +} /* end of void cpShortColV2CharColV(char *source, unsigned short *dest) */ + +/* ------------------------------------------------------------------------- */ + +void cpIntColV2CharColV(unsigned int *source, char *dest) +{ + dest[0] = source[0]>>24; + dest[1] = source[1]>>24; + dest[2] = source[2]>>24; + dest[3] = source[3]>>24; +} /* end of void cpIntColV2CharColV(unsigned int *source, char *dest) */ + +/* ------------------------------------------------------------------------- */ + +void cpCharColV2FloatColV(char *source, float *dest) +{ + /* What about endianness? Might be caught at this level :) */ + dest[0] = source[0]/255.0; + dest[1] = source[1]/255.0; + dest[2] = source[2]/255.0; + dest[3] = source[3]/255.0; +} /* end of void cpCharColV2FloatColV(char *source, float *dest) */ +/* ------------------------------------------------------------------------- */ + +void cpShortColV2FloatColV(unsigned short *source, float *dest) +{ + dest[0] = source[0]/65535.0; + dest[1] = source[1]/65535.0; + dest[2] = source[2]/65535.0; + dest[3] = source[3]/65535.0; +} /* end of void cpShortColV2FloatColV(char *source, float *dest) */ + +/* ------------------------------------------------------------------------- */ + +void cpFloatColV2CharColV(float* source, char *dest) +{ + /* can't this be done more efficient? hope the conversions are correct... */ + if (source[0] < 0.0) dest[0] = 0; + else if (source[0] > 1.0) dest[0] = 255; + else dest[0] = (char) (source[0] * 255.0); + + if (source[1] < 0.0) dest[1] = 0; + else if (source[1] > 1.0) dest[1] = 255; + else dest[1] = (char) (source[1] * 255.0); + + if (source[2] < 0.0) dest[2] = 0; + else if (source[2] > 1.0) dest[2] = 255; + else dest[2] = (char) (source[2] * 255.0); + + if (source[3] < 0.0) dest[3] = 0; + else if (source[3] > 1.0) dest[3] = 255; + else dest[3] = (char) (source[3] * 255.0); + +} /* end of void cpFloatColV2CharColV(float* source, char *dest) */ + +/* ------------------------------------------------------------------------- */ + +void cpShortColV(unsigned short *source, unsigned short *dest) +{ + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; +} /* end of void cpShortColV(unsigned short *source, unsigned short *dest) */ + +/* ------------------------------------------------------------------------- */ +void cpFloatColV(float *source, float *dest) +{ + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; +} /* end of void cpFloatColV(float *source, float *dest) */ + +/* ------------------------------------------------------------------------- */ + +void cpCharColV(char *source, char *dest) +{ + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; +} /* end of void cpCharColV(char *source, char *dest) */ + +/* ------------------------------------------------------------------------- */ +void addalphaAddfacFloat(float *dest, float *source, char addfac) + /* doel= bron over doel */ +{ + float m; /* weiging factor of destination */ + float c; /* intermediate colour */ + + /* 1. copy source straight away if dest has zero alpha */ + /* 2. copy dest straight away if dest has full alpha */ + /* I am not sure whether (2) is correct. It seems to */ + /* me that this should not happen if float colours */ + /* aren't clipped at 1.0 . */ + /* I'll keep the code, but disabled.... */ + if ( (dest[3] < RE_EMPTY_COLOUR_FLOAT) + /* || source[3] > RE_FULL_COLOUR_FLOAT */ ) { + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; + return; + } + + /* Addfac is a number between 0 and 1: rescale */ + /* final target is to diminish the influence of dest when addfac rises */ + m = 1.0 - ( source[3] * ((255.0 - addfac) / 255.0)); + + /* blend colours*/ + c= (m * dest[0]) + source[0]; +#ifdef RE_FLOAT_COLOUR_CLIPPING + if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_FULL_COLOUR_FLOAT; + else +#endif + dest[0]= c; + + c= (m * dest[1]) + source[1]; +#ifdef RE_FLOAT_COLOUR_CLIPPING + if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_FULL_COLOUR_FLOAT; + else +#endif + dest[1]= c; + + c= (m * dest[2]) + source[2]; +#ifdef RE_FLOAT_COLOUR_CLIPPING + if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_FULL_COLOUR_FLOAT; + else +#endif + dest[2]= c; + + c= dest[3] + source[3]; +#ifdef RE_ALPHA_CLIPPING + if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_FULL_COLOUR_FLOAT; + else +#endif + dest[3]= c; + +} /* end of void addalphaAddfacFloat(unsigned short *doel, unsigned short *bron, char addfac_help) */ + +/* ------------------------------------------------------------------------- */ + +void addalphaAddfacShort(unsigned short *doel, unsigned short *bron, char addfac) + /* doel= bron over doel */ +{ + float m; /* weiging factor of destination */ + float c; /* intermediate colour */ + + /* 1. copy bron straight away if doel has zero alpha */ + if( doel[3] == 0) { + *((unsigned int *)doel) = *((unsigned int *)bron); + *((unsigned int *)(doel+2)) = *((unsigned int *)(bron+2)); + return; + } + + /* Addfac is a number between 0 and 1: rescale */ + /* final target is to diminish the influence of dest when addfac rises */ + m = 1.0 - ( bron[3] * ((255.0 - addfac) / 255.0)); + + /* blend colours*/ + c = (m * doel[0]) + bron[0]; + if( c > 65535.0 ) doel[0]=65535; + else doel[0] = floor(c); + c = (m * doel[1]) + bron[1]; + if( c > 65535.0 ) doel[1]=65535; + else doel[1] = floor(c); + c = (m * doel[2]) + bron[2]; + if( c > 65535.0 ) doel[2]=65535; + else doel[2] = floor(c); + + c = doel[3] + bron[3]; + if(c > 65535.0) doel[3] = 65535; + else doel[3]= floor(c); + +} /* end of void addalphaAddfacShort(unsigned short *doel, unsigned short *bron, char addfac_help) */ + +/* ------------------------------------------------------------------------- */ + +void addHaloToHaloShort(unsigned short *d, unsigned short *s) +{ + /* float m; */ /* weiging factor of destination */ + float c[4]; /* intermediate colour */ + float rescale = 1.0; + + /* 1. copy straight away if has zero alpha */ + if( d[3] == 0) { + *((unsigned int *) d) = *((unsigned int *) s); + *((unsigned int *)(d + 2)) = *((unsigned int *)(s + 2)); + return; + } + + /* 2. halo blending */ + /* no blending, just add */ + c[0] = s[0] + d[0]; + c[1] = s[1] + d[1]; + c[2] = s[2] + d[2]; + c[3] = s[3] + d[3]; + /* One thing that may happen is that this pixel is over-saturated with light - */ + /* i.e. too much light comes out, and the pixel is clipped. Currently, this */ + /* leads to artifacts such as overproportional undersampling of background */ + /* colours. */ + /* Compensating for over-saturation: */ + /* - increase alpha */ + /* - increase alpha and rescale colours */ + + /* let's try alpha increase and clipping */ + + /* calculate how much rescaling we need */ + if( c[0] > 65535.0 ) { + rescale *= c[0] /65535.0; + d[0] = 65535; + } else d[0] = floor(c[0]); + if( c[1] > 65535.0 ) { + rescale *= c[1] /65535.0; + d[1] = 65535; + } else d[1] = floor(c[1]); + if( c[2] > 65535.0 ) { + rescale *= c[2] /65535.0; + d[2] = 65535; + } else d[2] = floor(c[2]); + + /* a bit too hefty I think */ + c[3] *= rescale; + + if( c[3] > 65535.0 ) d[3] = 65535; else d[3]= floor(c[3]); + +} /* end of void addHaloToHaloShort(unsigned short *dest, unsigned short *source, char addfac) */ + +/* ------------------------------------------------------------------------- */ + +void sampleShortColV2ShortColV(unsigned short *sample, unsigned short *dest, int osaNr) +{ + unsigned int intcol[4] = {0}; + unsigned short *scol = sample; + int a = 0; + + for(a=0; a < osaNr; a++, scol+=4) { + intcol[0]+= scol[0]; intcol[1]+= scol[1]; + intcol[2]+= scol[2]; intcol[3]+= scol[3]; + } + + /* Now normalise the integrated colour. It is guaranteed */ + /* to be correctly bounded. */ + dest[0]= intcol[0]/osaNr; + dest[1]= intcol[1]/osaNr; + dest[2]= intcol[2]/osaNr; + dest[3]= intcol[3]/osaNr; + +} /* end of void sampleShortColVToShortColV(unsigned short *sample, unsigned short *dest) */ + + +/* ------------------------------------------------------------------------- */ + +void sampleFloatColV2FloatColV(float *sample, float *dest, int osaNr) +{ + float intcol[4] = {0}; + float *scol = sample; + int a = 0; + + if (doGamma()) { + /* use a LUT and interpolation to do the gamma correction */ + for(a=0; a < osaNr; a++, scol+=4) { + intcol[0] += gammaCorrect(scol[0]); + intcol[1] += gammaCorrect(scol[1]); + intcol[2] += gammaCorrect(scol[2]); + intcol[3] += scol[3]; + } + + /* renormalise */ + intcol[0] /= osaNr; + intcol[1] /= osaNr; + intcol[2] /= osaNr; + intcol[3] /= osaNr; + + /* back to pixel values */ + dest[0] = invGammaCorrect(intcol[0]); + dest[1] = invGammaCorrect(intcol[1]); + dest[2] = invGammaCorrect(intcol[2]); + dest[3] = intcol[3]; + } else { + /* no gamma */ + for(a=0; a < osaNr; a++, scol+=4) { + intcol[0] += scol[0]; intcol[1] += scol[1]; + intcol[2] += scol[2]; intcol[3] += scol[3]; + } + + dest[0]= intcol[0]/osaNr; + dest[1]= intcol[1]/osaNr; + dest[2]= intcol[2]/osaNr; + dest[3]= intcol[3]/osaNr; + } + +} /* end void sampleFloatColVToFloatColV(unsigned short *, unsigned short *) */ + +/* ------------------------------------------------------------------------- */ +/* The following functions are 'old' blending functions: */ + +/* ------------------------------------------------------------------------- */ +void keyalpha(char *doel) /* maakt premul 255 */ +{ + int c; + short div; + div= doel[3]; + if (!div) + { + doel[0] = (doel[0] ? 255 : 0); + doel[1] = (doel[1] ? 255 : 0); + doel[2] = (doel[2] ? 255 : 0); + } else + { + c= (doel[0]<<8)/div; + if(c>255) doel[0]=255; + else doel[0]= c; + c= (doel[1]<<8)/div; + if(c>255) doel[1]=255; + else doel[1]= c; + c= (doel[2]<<8)/div; + if(c>255) doel[2]=255; + else doel[2]= c; + } +} + +/* ------------------------------------------------------------------------- */ +/* vult bron onder doel in met alpha van doel*/ +void addalphaUnder(char *doel, char *bron) +{ + int c; + int mul; + + if(doel[3]==255) return; + if( doel[3]==0) { /* is getest, scheelt */ + *((unsigned int *)doel)= *((unsigned int *)bron); + return; + } + + mul= 255-doel[3]; + + c= doel[0]+ ((mul*bron[0])/255); + if(c>255) doel[0]=255; + else doel[0]= c; + c= doel[1]+ ((mul*bron[1])/255); + if(c>255) doel[1]=255; + else doel[1]= c; + c= doel[2]+ ((mul*bron[2])/255); + if(c>255) doel[2]=255; + else doel[2]= c; + + c= doel[3]+ ((mul*bron[3])/255); + if(c>255) doel[3]=255; + else doel[3]= c; + + /* doel[0]= MAX2(doel[0], bron[0]); */ +} + +/* ------------------------------------------------------------------------- */ +/* gamma-gecorr: vult bron onder doel in met alpha van doel */ +void addalphaUnderGamma(char *doel, char *bron) +{ + unsigned int tot; + int c, doe, bro; + int mul; + + /* hier doel[3]==0 of doel==255 afvangen gebeurt al in skylus */ + mul= 256-doel[3]; + + doe= igamtab1[(int)doel[0]]; + bro= igamtab1[(int)bron[0]]; + tot= (doe+ ((mul*bro)>>8)); + if(tot>65535) tot=65535; + doel[0]= *((gamtab+tot)) >>8; + + doe= igamtab1[(int)doel[1]]; + bro= igamtab1[(int)bron[1]]; + tot= (doe+ ((mul*bro)>>8)); + if(tot>65535) tot=65535; + doel[1]= *((gamtab+tot)) >>8; + + doe= igamtab1[(int)doel[2]]; + bro= igamtab1[(int)bron[2]]; + tot= (doe+ ((mul*bro)>>8)); + if(tot>65535) tot=65535; + doel[2]= *((gamtab+tot)) >>8; + + c= doel[3]+ ((mul*bron[3])/255); + if(c>255) doel[3]=255; + else doel[3]= c; + /* doel[0]= MAX2(doel[0], bron[0]); */ +} + +/* ------------------------------------------------------------------------- */ +/* doel= bron over doel */ +void addalphaOver(char *doel, char *bron) +{ + int c; + int mul; + + if(bron[3]==0) return; + if( bron[3]==255) { /* is getest, scheelt */ + *((unsigned int *)doel)= *((unsigned int *)bron); + return; + } + + mul= 255-bron[3]; + + c= ((mul*doel[0])/255)+bron[0]; + if(c>255) doel[0]=255; + else doel[0]= c; + c= ((mul*doel[1])/255)+bron[1]; + if(c>255) doel[1]=255; + else doel[1]= c; + c= ((mul*doel[2])/255)+bron[2]; + if(c>255) doel[2]=255; + else doel[2]= c; + c= ((mul*doel[3])/255)+bron[3]; + if(c>255) doel[3]=255; + else doel[3]= c; +} + +/* ------------------------------------------------------------------------- */ +void addalphaAdd(char *doel, char *bron) /* telt bron bij doel */ +{ + int c; + + if( doel[3]==0 || bron[3]==255) { /* is getest, scheelt veel */ + *((unsigned int *)doel)= *((unsigned int *)bron); + return; + } + c= doel[0]+bron[0]; + if(c>255) doel[0]=255; + else doel[0]= c; + c= doel[1]+bron[1]; + if(c>255) doel[1]=255; + else doel[1]= c; + c= doel[2]+bron[2]; + if(c>255) doel[2]=255; + else doel[2]= c; + c= doel[3]+bron[3]; + if(c>255) doel[3]=255; + else doel[3]= c; +} +/* ------------------------------------------------------------------------- */ +void addalphaAddshort(unsigned short *doel, unsigned short *bron) /* telt bron bij doel */ +{ + int c; + + if( doel[3]==0) { + *((unsigned int *)doel)= *((unsigned int *)bron); + *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2)); + return; + } + c= doel[0]+bron[0]; + if(c>65535) doel[0]=65535; + else doel[0]= c; + c= doel[1]+bron[1]; + if(c>65535) doel[1]=65535; + else doel[1]= c; + c= doel[2]+bron[2]; + if(c>65535) doel[2]=65535; + else doel[2]= c; + c= doel[3]+bron[3]; + if(c>65535) doel[3]=65535; + else doel[3]= c; +} + +/* ------------------------------------------------------------------------- */ +void addalphaAddFloat(float *dest, float *source) +{ + + /* Makes me wonder whether this is required... */ + if( dest[3] < RE_EMPTY_COLOUR_FLOAT) { + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; + return; + } + + /* no clipping! */ + dest[0] = dest[0]+source[0]; + dest[1] = dest[1]+source[1]; + dest[2] = dest[2]+source[2]; + dest[3] = dest[3]+source[3]; + +} + +/* ALPHADDFAC: + * + * Z= X alphaover Y: + * Zrgb= (1-Xa)*Yrgb + Xrgb + * + * Om ook de add te doen moet (1-Xa) moduleren met 1 via fac + * (1-fac)*(1-Xa) + fac <=> + * 1-Xa-fac+fac*Xa+fac <=> + * Xa*(fac-1)+1 + */ + + +/* ------------------------------------------------------------------------- */ +/* doel= bron over doel */ +void RE_addalphaAddfac(char *doel, char *bron, char addfac) +{ + + int c, mul; + + if( doel[3]==0) { + *((unsigned int *)doel)= *((unsigned int *)bron); + return; + } + + mul= 255 - (bron[3]*(255-addfac))/255; + + c= ((mul*doel[0])/255)+bron[0]; + if(c>255) doel[0]=255; + else doel[0]= c; + c= ((mul*doel[1])/255)+bron[1]; + if(c>255) doel[1]=255; + else doel[1]= c; + c= ((mul*doel[2])/255)+bron[2]; + if(c>255) doel[2]=255; + else doel[2]= c; + + /* c= ((mul*doel[3])/255)+bron[3]; */ + c= doel[3]+bron[3]; + if(c>255) doel[3]=255; + else doel[3]= c; +} + +/* ------------------------------------------------------------------------- */ +/* doel= bron over doel */ +void addalphaAddfacshort(unsigned short *doel, + unsigned short *bron, + short addfac) +{ + int c, mul; + + if( doel[3]==0) { + *((unsigned int *)doel)= *((unsigned int *)bron); + *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2)); + return; + } + + mul= 0xFFFF - (bron[0]*(255-addfac))/255; + + c= ((mul*doel[0])>>16)+bron[0]; + if(c>=0xFFF0) doel[0]=0xFFF0; + else doel[0]= c; + c= ((mul*doel[1])>>16)+bron[1]; + if(c>=0xFFF0) doel[1]=0xFFF0; + else doel[1]= c; + c= ((mul*doel[2])>>16)+bron[2]; + if(c>=0xFFF0) doel[2]=0xFFF0; + else doel[2]= c; + c= ((mul*doel[3])>>16)+bron[3]; + if(c>=0xFFF0) doel[3]=0xFFF0; + else doel[3]= c; + +} + +/* ------------------------------------------------------------------------- */ + +/* eof pixelblending.c */ + + diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c new file mode 100644 index 00000000000..ff69b4226bf --- /dev/null +++ b/source/blender/render/intern/source/pixelshading.c @@ -0,0 +1,1917 @@ +/** + * + * ***** 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 ***** + * Shading of pixels + * + * 11-09-2000 nzc + * + * $Id$ + * + * Shading hierarchy: + * + * (externally visible) + * + * renderPixel---------- + * | renderHaloPixel-- shadeHaloFloat + * | + * | renderFacePixel-- shadeLampLusFloat + * | shadeSpotHaloPixelFloat-- spotHaloFloat + * + * + * renderSpotHaloPixel--(should call shadeSpotHaloPixelFloat, but there's numerical) + * ( issues there... need to iron that out still ) + */ + +#include +#include "BLI_arithb.h" + +/* External modules: */ +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "MTC_matrixops.h" +#include "MTC_vectorops.h" + +#include "DNA_camera_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_image_types.h" +#include "DNA_texture_types.h" +#include "DNA_lamp_types.h" + +#include "BKE_global.h" +#include "BKE_texture.h" +#include "BKE_utildefines.h" + +#include "render.h" +#include "render_intern.h" + +#include "vanillaRenderPipe_types.h" +#include "pixelblending.h" +#include "zbuf.h" +#include "rendercore.h" /* for some shading functions... */ +#include "zbufferdatastruct.h" + +#include "shadbuf.h" +#include "shadowBuffer.h" + +#include "renderHelp.h" + +#include "gammaCorrectionTables.h" +#include "errorHandler.h" +#include "pixelshading.h" + +/* ------------------------------------------------------------------------- */ +/* maybe declare local functions here? */ +/* ------------------------------------------------------------------------- */ + +/* The collector is the communication channel with the render pipe. */ +extern RE_COLBUFTYPE collector[4]; /* used throughout as pixel colour accu */ +/* shortcol was the old collector */ +extern float holoofs, fmask[256]; +extern float Zmulx, Zmuly; /* Some kind of scale? */ + +unsigned int calcHaloZ(HaloRen *har, unsigned int zz); + +/* ------------------------------------------------------------------------- */ +/* if defined: do full error tracing and reporting here */ +/* #define RE_PIXSHADE_FULL_SAFETY */ +/* if defined: use fake (dummy) colours for filling pixels (all is purple) */ +/* #define RE_FAKE_PIXELS */ +/* if defined: use fake (dummy) colours for filling faces (all blue) */ +/* #define RE_FAKE_FACE_PIXELS */ +/* if defined: use fake (dummy) colours for filling halos (all red) */ +/* #define RE_FAKE_HALO_PIXELS */ +/* #define RE_FAKE_HALO_PIXELS_2 */ +/* if defined: use fake (dummy) colours for filling spothalos (green) */ +/* #define RE_FAKE_SPOTHALO_PIXELS */ +/* if defined: use fake (dummy) colours for shading lighting */ +/* #define RE_FAKE_LAMP_SHADE */ +/* if defined: fake colours for sky pixels */ +/* #define RE_FAKE_SKY_PIXELS */ + +/* ------------------------------------------------------------------------- */ + +unsigned int calcHaloZ(HaloRen *har, unsigned int zz) +{ + + if(har->type & HA_ONLYSKY) { + if(zz!=0x7FFFFFFF) zz= 0; + } + else { + zz= (zz>>8); + if(zz<0x800000) zz= (zz+0x7FFFFF); + else zz= (zz-0x800000); + } + return zz; +} + +/* ------------------------------------------------------------------------- */ + +void *renderPixel(float x, float y, int *obdata) +{ + void* data = NULL; +#ifdef RE_PIXSHADE_FULL_SAFETY + char fname[] = "renderPixel"; +#endif +#ifdef RE_FAKE_PIXELS + collector[0] = RE_UNITY_COLOUR_FLOAT; + collector[1] = 0; + collector[2] = RE_UNITY_COLOUR_FLOAT; + collector[3] = RE_UNITY_COLOUR_FLOAT; + return NULL; +#endif + + if (obdata[3] & RE_POLY) { + /* face pixels aren't rendered in floats yet, so we wrap it here */ + data = renderFacePixel(x, y, obdata[1]); + } + else if (obdata[3] & RE_HALO) { + data = renderHaloPixel(x, y, obdata[1]); + } + else if( obdata[1] == 0 ) { + /* for lamphalo, but doesn't seem to be called? Actually it is, and */ + /* it returns NULL pointers. */ + data = renderFacePixel(x, y, obdata[1]); + } +#ifdef RE_PIXSHADE_FULL_SAFETY + else RE_error(RE_BAD_FACE_TYPE, fname); +#endif /* RE_PIXSHADE_FULL_SAFETY */ + return data; + +} /* end of void renderPixel(float x, float y, int *obdata) */ + +/* ------------------------------------------------------------------------- */ + +void *renderFacePixel(float x, float y, int vlaknr) +/* Result goes into */ +{ +#ifdef RE_PIXSHADE_FULL_SAFETY + char fname[]= "renderFacePixelFloat"; +#endif + static VlakRen *vlr; /* static, because we don't want to recalculate vlr */ + /* when we already know it */ + static VertRen *v1, *v2, *v3; + static float t00, t01, t10, t11, dvlak, n1[3], n2[3], n3[3]; + static float s00, s01, s10, s11; + float *o1, *o2, *o3; + float u, v, l, dl, hox, hoy, detsh, fac, deler, alpha; + char *cp1, *cp2, *cp3; + +/* RE_error(RE_TRACE_COUNTER, fname); */ + +#ifdef RE_FAKE_FACE_PIXELS + collector[0] = 0; + collector[1] = 0; + collector[2] = RE_UNITY_COLOUR_FLOAT; + collector[3] = RE_UNITY_COLOUR_FLOAT; + /* try to keep the rest as clean as possible... */ + if( ((vlaknr & 0x7FFFFF) <= R.totvlak) + && ! ((R.vlaknr== -1)||(vlaknr<=0)) ) { + /* a bit superfluous to do this always, but */ + /* when this is switched on, it doesn't matter */ + vlr= RE_findOrAddVlak( (vlaknr-1) & 0x7FFFFF); + } else vlr = NULL; + return vlr; +#endif + + if(R.vlaknr== -1) { /* doet initrender */ + /* also set in the pixelrender loop */ + vlr= R.vlr= 0; + } + + if(vlaknr<=0) { /* sky */ + R.vlaknr= 0; + collector[3] = 0.0; + } + else if( (vlaknr & 0x7FFFFF) <= R.totvlak) { + + /* What follows now is a large bunch of texture coordinate mappings. */ + /* When this face is the same as the previous one, that means all */ + /* the coordinate remapping does not need to be recomputed. */ + if(vlaknr!=R.vlaknr) { + + vlr= RE_findOrAddVlak( (vlaknr-1) & 0x7FFFFF); + + R.mat= vlr->mat; + R.matren= R.mat->ren; + + if(R.matren==0) { /* tijdelijk voor debug */ + collector[3] = RE_UNITY_COLOUR_FLOAT; + collector[2] = 0.0; + collector[1] = RE_UNITY_COLOUR_FLOAT; + collector[0] = RE_UNITY_COLOUR_FLOAT; + return NULL; + } + + R.vlr= vlr; + + R.vno= vlr->n; + R.osatex= (R.matren->texco & TEXCO_OSA); + R.vlaknr= vlaknr; + + v1= vlr->v1; + dvlak= MTC_dot3Float(v1->co, vlr->n); + + if( (vlr->flag & R_SMOOTH) || (R.matren->texco & NEED_UV)) { /* uv nodig */ + if(vlaknr & 0x800000) { + v2= vlr->v3; + v3= vlr->v4; + } + else { + v2= vlr->v2; + v3= vlr->v3; + } + + if(vlr->snproj==0) { + t00= v3->co[0]-v1->co[0]; t01= v3->co[1]-v1->co[1]; + t10= v3->co[0]-v2->co[0]; t11= v3->co[1]-v2->co[1]; + } + else if(vlr->snproj==1) { + t00= v3->co[0]-v1->co[0]; t01= v3->co[2]-v1->co[2]; + t10= v3->co[0]-v2->co[0]; t11= v3->co[2]-v2->co[2]; + } + else { + t00= v3->co[1]-v1->co[1]; t01= v3->co[2]-v1->co[2]; + t10= v3->co[1]-v2->co[1]; t11= v3->co[2]-v2->co[2]; + } + + detsh= t00*t11-t10*t01; + t00/= detsh; t01/=detsh; + t10/=detsh; t11/=detsh; + + if(vlr->flag & R_SMOOTH) { /* puno's goedzetten */ + if(vlr->puno & ME_FLIPV1) MTC_cp3FloatInv(v1->n, n1); + else MTC_cp3Float(v1->n, n1); + + if(vlaknr & 0x800000) { + if(vlr->puno & ME_FLIPV3) MTC_cp3FloatInv(v2->n, n2); + else MTC_cp3Float(v2->n, n2); + + if(vlr->puno & ME_FLIPV4) MTC_cp3FloatInv(v3->n, n3); + else MTC_cp3Float(v3->n, n3); + } + else { + if(vlr->puno & ME_FLIPV2) MTC_cp3FloatInv(v2->n, n2); + else MTC_cp3Float(v2->n, n2); + + if(vlr->puno & ME_FLIPV3) MTC_cp3FloatInv(v3->n, n3); + else MTC_cp3Float(v3->n, n3); + } + } + if(R.matren->texco & TEXCO_STICKY) { + s00= v3->ho[0]/v3->ho[3] - v1->ho[0]/v1->ho[3]; + s01= v3->ho[1]/v3->ho[3] - v1->ho[1]/v1->ho[3]; + s10= v3->ho[0]/v3->ho[3] - v2->ho[0]/v2->ho[3]; + s11= v3->ho[1]/v3->ho[3] - v2->ho[1]/v2->ho[3]; + + detsh= s00*s11-s10*s01; + s00/= detsh; s01/=detsh; + s10/=detsh; s11/=detsh; + } + } + } /* end of if vlaknr*/ + + /* This trafo might be migrated to a separate function. It is used */ + /* quite often. */ + /* COXYZ nieuwe methode */ + if( (G.special1 & G_HOLO) + && (((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) ) { + R.view[0]= (x+(R.xstart)+1.0+holoofs); + } + else { + R.view[0]= (x+(R.xstart)+1.0); + } + + if(R.flag & R_SEC_FIELD) { + if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor; + else R.view[1]= (y+R.ystart+1.5)*R.ycor; + } + else R.view[1]= (y+R.ystart+1.0)*R.ycor; + + R.view[2]= -R.viewfac; + + if(R.r.mode & R_PANORAMA) { + float panoco, panosi; + panoco = getPanovCo(); + panosi = getPanovSi(); + u= R.view[0]; v= R.view[2]; + + R.view[0]= panoco*u + panosi*v; + R.view[2]= -panosi*u + panoco*v; + } + + deler= vlr->n[0]*R.view[0] + vlr->n[1]*R.view[1] + vlr->n[2]*R.view[2]; + if (deler!=0.0) fac= R.zcor= dvlak/deler; + else fac= R.zcor= 0.0; + + R.co[0]= fac*R.view[0]; + R.co[1]= fac*R.view[1]; + R.co[2]= fac*R.view[2]; + + if(R.osatex || (R.r.mode & R_SHADOW) ) { + u= dvlak/(deler-vlr->n[0]); + v= dvlak/(deler- R.ycor*vlr->n[1]); + + O.dxco[0]= R.co[0]- (R.view[0]-1.0)*u; + O.dxco[1]= R.co[1]- (R.view[1])*u; + O.dxco[2]= R.co[2]- (R.view[2])*u; + + O.dyco[0]= R.co[0]- (R.view[0])*v; + O.dyco[1]= R.co[1]- (R.view[1]-1.0*R.ycor)*v; + O.dyco[2]= R.co[2]- (R.view[2])*v; + + } + + fac= Normalise(R.view); + R.zcor*= fac; /* voor mist */ + + if(R.osatex) { + if( (R.matren->texco & TEXCO_REFL) ) { + O.dxview= 1.0/fac; + O.dyview= R.ycor/fac; + } + } + + /* UV en TEX*/ + if( (vlr->flag & R_SMOOTH) || (R.matren->texco & NEED_UV)) { + if(vlr->snproj==0) { + u= (R.co[0]-v3->co[0])*t11-(R.co[1]-v3->co[1])*t10; + v= (R.co[1]-v3->co[1])*t00-(R.co[0]-v3->co[0])*t01; + if(R.osatex) { + O.dxuv[0]= O.dxco[0]*t11- O.dxco[1]*t10; + O.dxuv[1]= O.dxco[1]*t00- O.dxco[0]*t01; + O.dyuv[0]= O.dyco[0]*t11- O.dyco[1]*t10; + O.dyuv[1]= O.dyco[1]*t00- O.dyco[0]*t01; + } + } + else if(vlr->snproj==1) { + u= (R.co[0]-v3->co[0])*t11-(R.co[2]-v3->co[2])*t10; + v= (R.co[2]-v3->co[2])*t00-(R.co[0]-v3->co[0])*t01; + if(R.osatex) { + O.dxuv[0]= O.dxco[0]*t11- O.dxco[2]*t10; + O.dxuv[1]= O.dxco[2]*t00- O.dxco[0]*t01; + O.dyuv[0]= O.dyco[0]*t11- O.dyco[2]*t10; + O.dyuv[1]= O.dyco[2]*t00- O.dyco[0]*t01; + } + } + else { + u= (R.co[1]-v3->co[1])*t11-(R.co[2]-v3->co[2])*t10; + v= (R.co[2]-v3->co[2])*t00-(R.co[1]-v3->co[1])*t01; + if(R.osatex) { + O.dxuv[0]= O.dxco[1]*t11- O.dxco[2]*t10; + O.dxuv[1]= O.dxco[2]*t00- O.dxco[1]*t01; + O.dyuv[0]= O.dyco[1]*t11- O.dyco[2]*t10; + O.dyuv[1]= O.dyco[2]*t00- O.dyco[1]*t01; + } + } + l= 1.0+u+v; + + if(vlr->flag & R_SMOOTH) { + R.vn[0]= l*n3[0]-u*n1[0]-v*n2[0]; + R.vn[1]= l*n3[1]-u*n1[1]-v*n2[1]; + R.vn[2]= l*n3[2]-u*n1[2]-v*n2[2]; + + Normalise(R.vn); + if(R.osatex && (R.matren->texco & (TEXCO_NORM+TEXCO_REFL)) ) { + dl= O.dxuv[0]+O.dxuv[1]; + O.dxno[0]= dl*n3[0]-O.dxuv[0]*n1[0]-O.dxuv[1]*n2[0]; + O.dxno[1]= dl*n3[1]-O.dxuv[0]*n1[1]-O.dxuv[1]*n2[1]; + O.dxno[2]= dl*n3[2]-O.dxuv[0]*n1[2]-O.dxuv[1]*n2[2]; + dl= O.dyuv[0]+O.dyuv[1]; + O.dyno[0]= dl*n3[0]-O.dyuv[0]*n1[0]-O.dyuv[1]*n2[0]; + O.dyno[1]= dl*n3[1]-O.dyuv[0]*n1[1]-O.dyuv[1]*n2[1]; + O.dyno[2]= dl*n3[2]-O.dyuv[0]*n1[2]-O.dyuv[1]*n2[2]; + + } + } + else { + VECCOPY(R.vn, vlr->n); + } + + if(R.matren->mode & MA_ZINV) { /* z invert */ + /* R.vn[0]= -R.vn[0]; */ + /* R.vn[1]= -R.vn[1]; */ + } + + if(R.matren->texco & TEXCO_ORCO) { + if(v2->orco) { + o1= v1->orco; + o2= v2->orco; + o3= v3->orco; + + R.lo[0]= l*o3[0]-u*o1[0]-v*o2[0]; + R.lo[1]= l*o3[1]-u*o1[1]-v*o2[1]; + R.lo[2]= l*o3[2]-u*o1[2]-v*o2[2]; + + if(R.osatex) { + dl= O.dxuv[0]+O.dxuv[1]; + O.dxlo[0]= dl*o3[0]-O.dxuv[0]*o1[0]-O.dxuv[1]*o2[0]; + O.dxlo[1]= dl*o3[1]-O.dxuv[0]*o1[1]-O.dxuv[1]*o2[1]; + O.dxlo[2]= dl*o3[2]-O.dxuv[0]*o1[2]-O.dxuv[1]*o2[2]; + dl= O.dyuv[0]+O.dyuv[1]; + O.dylo[0]= dl*o3[0]-O.dyuv[0]*o1[0]-O.dyuv[1]*o2[0]; + O.dylo[1]= dl*o3[1]-O.dyuv[0]*o1[1]-O.dyuv[1]*o2[1]; + O.dylo[2]= dl*o3[2]-O.dyuv[0]*o1[2]-O.dyuv[1]*o2[2]; + } + } + } + + if(R.matren->texco & TEXCO_GLOB) { + VECCOPY(R.gl, R.co); + MTC_Mat4MulVecfl(R.viewinv, R.gl); + if(R.osatex) { + VECCOPY(O.dxgl, O.dxco); + MTC_Mat3MulVecfl(R.imat, O.dxco); + VECCOPY(O.dygl, O.dyco); + MTC_Mat3MulVecfl(R.imat, O.dyco); + } + } + if((R.matren->texco & TEXCO_UV) || (R.matren->mode & (MA_VERTEXCOL|MA_FACETEXTURE))) { + if(R.vlr->tface) { + float *uv1, *uv2, *uv3; + + uv1= R.vlr->tface->uv[0]; + if( (vlaknr & 0x800000) || (R.vlr->flag & R_FACE_SPLIT) ) { + uv2= R.vlr->tface->uv[2]; + uv3= R.vlr->tface->uv[3]; + } + else { + uv2= R.vlr->tface->uv[1]; + uv3= R.vlr->tface->uv[2]; + } + + R.uv[0]= -1.0 + 2.0*(l*uv3[0]-u*uv1[0]-v*uv2[0]); + R.uv[1]= -1.0 + 2.0*(l*uv3[1]-u*uv1[1]-v*uv2[1]); + + if(R.osatex) { + float duv[2]; + + dl= O.dxuv[0]+O.dxuv[1]; + duv[0]= O.dxuv[0]; + duv[1]= O.dxuv[1]; + + O.dxuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]); + O.dxuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]); + + dl= O.dyuv[0]+O.dyuv[1]; + duv[0]= O.dyuv[0]; + duv[1]= O.dyuv[1]; + + O.dyuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]); + O.dyuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]); + } + } + else { + R.uv[0]= 2.0*(u+.5); + R.uv[1]= 2.0*(v+.5); + } + } + if(R.matren->texco & TEXCO_NORM) { + R.orn[0]= R.vn[0]; + R.orn[1]= -R.vn[1]; + R.orn[2]= R.vn[2]; + } + if(R.matren->mode & MA_VERTEXCOL) { + + /* some colour calculations here */ + cp1= (char *)vlr->vcol; + if(cp1) { + if( (vlaknr & 0x800000) || (R.vlr->flag & R_FACE_SPLIT) ) { + cp2= (char *)(vlr->vcol+2); + cp3= (char *)(vlr->vcol+3); + } + else { + cp2= (char *)(vlr->vcol+1); + cp3= (char *)(vlr->vcol+2); + } + R.vcol[0]= (l*cp3[3]-u*cp1[3]-v*cp2[3])/255.0; + R.vcol[1]= (l*cp3[2]-u*cp1[2]-v*cp2[2])/255.0; + R.vcol[2]= (l*cp3[1]-u*cp1[1]-v*cp2[1])/255.0; + + } + else { + R.vcol[0]= 0.0; + R.vcol[1]= 0.0; + R.vcol[2]= 0.0; + } + } + if(R.matren->mode & MA_FACETEXTURE) { + if((R.matren->mode & MA_VERTEXCOL)==0) { + R.vcol[0]= 1.0; + R.vcol[1]= 1.0; + R.vcol[2]= 1.0; + } + /* shading here */ + if(vlr->tface) render_realtime_texture(); + } + + /* hierna klopt de u en v EN O.dxuv en O.dyuv niet meer */ + if(R.matren->texco & TEXCO_STICKY) { + if(v2->sticky) { + + /* opnieuw u en v berekenen */ + hox= x/Zmulx -1.0; + hoy= y/Zmuly -1.0; + u= (hox - v3->ho[0]/v3->ho[3])*s11 + - (hoy - v3->ho[1]/v3->ho[3])*s10; + v= (hoy - v3->ho[1]/v3->ho[3])*s00 + - (hox - v3->ho[0]/v3->ho[3])*s01; + l= 1.0+u+v; + + o1= v1->sticky; + o2= v2->sticky; + o3= v3->sticky; + + R.sticky[0]= l*o3[0]-u*o1[0]-v*o2[0]; + R.sticky[1]= l*o3[1]-u*o1[1]-v*o2[1]; + + if(R.osatex) { + O.dxuv[0]= s11/Zmulx; + O.dxuv[1]= - s01/Zmulx; + O.dyuv[0]= - s10/Zmuly; + O.dyuv[1]= s00/Zmuly; + + dl= O.dxuv[0]+O.dxuv[1]; + O.dxsticky[0]= dl*o3[0]-O.dxuv[0]*o1[0]-O.dxuv[1]*o2[0]; + O.dxsticky[1]= dl*o3[1]-O.dxuv[0]*o1[1]-O.dxuv[1]*o2[1]; + dl= O.dyuv[0]+O.dyuv[1]; + O.dysticky[0]= dl*o3[0]-O.dyuv[0]*o1[0]-O.dyuv[1]*o2[0]; + O.dysticky[1]= dl*o3[1]-O.dyuv[0]*o1[1]-O.dyuv[1]*o2[1]; + } + } + } + } + else { + VECCOPY(R.vn, vlr->n); + } + if(R.matren->texco & TEXCO_WINDOW) { + R.winco[0]= (x+(R.xstart))/(float)R.afmx; + R.winco[1]= (y+(R.ystart))/(float)R.afmy; + } + + /* After all texture coordinates are set and converted and */ + /* transformed, we need to put some colour on it: */ + shadeLampLusFloat(); + + /* MIST */ + if( (R.wrld.mode & WO_MIST) && (R.matren->mode & MA_NOMIST)==0 ){ + /* alpha returned in float? */ + alpha= mistfactor(R.co); + } + else alpha= 1.0; + + /* RAYTRACE (tijdelijk?) UITGESCHAKELD */ + + if(R.matren->alpha!=1.0 || alpha!=1.0) { + fac= alpha*(R.matren->alpha); + + collector[0] *= fac; /* This applies to transparent faces! Even */ + collector[1] *= fac; /* though it may seem to be a premul op, it */ + collector[2] *= fac; /* isn't. */ + collector[3] = fac; /* doesn't need scaling? */ + } + else { + collector[3] = 1.0; + } + } + else { + collector[0] = 1.0; + collector[1] = 1.0; + collector[2] = 0.0; + collector[3] = 1.0; + } + + /* Spothalos: do this here for covered pixels. It seems messy to place */ + /* it here, structure-wise, but it's more efficient. Also, not having it */ + /* here makes it difficult to do proper overlaying later on. */ + /* It starts off with a coordinate transform again. */ + if(R.flag & R_LAMPHALO) { + if(vlaknr<=0) { /* bereken viewvec en zet R.co op far */ + + /* this view vector stuff should get its own function */ + if( (G.special1 & G_HOLO) && + ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) { + R.view[0]= (x+(R.xstart)+1.0+holoofs); + } else { + R.view[0]= (x+(R.xstart)+1.0); + } + + if(R.flag & R_SEC_FIELD) { + if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor; + else R.view[1]= (y+R.ystart+1.5)*R.ycor; + } else { + R.view[1]= (y+R.ystart+1.0)*R.ycor; + } + + R.view[2]= -R.viewfac; + + if(R.r.mode & R_PANORAMA) { + float panoco, panosi; + panoco = getPanovCo(); + panosi = getPanovSi(); + u= R.view[0]; v= R.view[2]; + + R.view[0]= panoco*u + panosi*v; + R.view[2]= -panosi*u + panoco*v; + } + + R.co[2]= 0.0; + + } + + shadeSpotHaloPixelFloat(collector); +/* renderspothaloFix(collector); */ + + } + +#ifdef RE_PIXSHADE_FULL_SAFETY + if (!vlr) RE_error(RE_BAD_DATA_POINTER, fname); +#endif + + return vlr; + +} /* end of void renderFacePixelFloat(float x, float y, int vlaknr) */ + +/* ------------------------------------------------------------------------- */ +/* + - uses R.view to determine which pixel, I think? + - the spothalo is dumped quite unceremoniously on top of the col vector + This function is also (sort of) implemented in shadespothalofix, but without + all the clipping stuff. Somehow, the clipping here is _quite_ critical. + */ +void shadeSpotHaloPixelFloat(float *col) +{ + LampRen *lar; + float factor = 0.0; + int a; + float rescol[4]; + + + for(a=0; atype==LA_SPOT && (lar->mode & LA_HALO) && lar->haint>0) { + + if(lar->org) { + lar->r= lar->org->r; + lar->g= lar->org->g; + lar->b= lar->org->b; + } + + /* determines how much spothalo we see */ + spotHaloFloat(lar, R.view, &factor); + + if(factor>0.0) { + + /* Why is alpha clipped? */ + if(factor > RE_FULL_COLOUR_FLOAT) rescol[3]= 1.0; + else rescol[3]= factor; + + /* erg vervelend: gammagecorrigeerd renderen EN addalphaADD */ + /* gaat niet goed samen */ + /* eigenlijk moet er een aparte 'optel' gamma komen */ + /* + There is a strange thing here: the spothalo seems to be + calculated in the space you would get when you go from + value space through inverse gamma! So we gamma-transform + to value-space, then integrate, blend, and gamma correct + _again_. + */ + + rescol[0] = factor * lar->r; /* Lampren rgb's are floats */ + rescol[1] = factor * lar->g; + rescol[2] = factor * lar->b; + + /* ---->add values, disregard alpha */ + /* - check for dest. alpha = 0. If so , just copy */ + /* this is a slightly different approach: I do the gamma */ + /* correction BEFORE the addition. What does the other */ + /* approach do? */ + if (col[3]< RE_EMPTY_COLOUR_FLOAT) { + col[0] = gammaCorrect(rescol[0]); + col[1] = gammaCorrect(rescol[1]); + col[2] = gammaCorrect(rescol[2]); + col[3] = rescol[3]; + } else { + col[0] += gammaCorrect(rescol[0]); + col[1] += gammaCorrect(rescol[1]); + col[2] += gammaCorrect(rescol[2]); + col[3] += rescol[3]; + } + + /* this clipping may have to go? Actually, if it's */ + /* done sooner, it may be more efficient */ + if(col[0] > RE_FULL_COLOUR_FLOAT) col[0] = 1.0; + if(col[1] > RE_FULL_COLOUR_FLOAT) col[1] = 1.0; + if(col[2] > RE_FULL_COLOUR_FLOAT) col[2] = 1.0; + if(col[3] > RE_FULL_COLOUR_FLOAT) col[3] = 1.0; + if(col[0] < RE_EMPTY_COLOUR_FLOAT) col[0] = 0.0; + if(col[1] < RE_EMPTY_COLOUR_FLOAT) col[1] = 0.0; + if(col[2] < RE_EMPTY_COLOUR_FLOAT) col[2] = 0.0; + if(col[3] < RE_EMPTY_COLOUR_FLOAT) col[3] = 0.0; + } + } + } + + if(col[0] < RE_EMPTY_COLOUR_FLOAT) col[0] = 0.0; + if(col[1] < RE_EMPTY_COLOUR_FLOAT) col[1] = 0.0; + if(col[2] < RE_EMPTY_COLOUR_FLOAT) col[2] = 0.0; + if(col[3] < RE_EMPTY_COLOUR_FLOAT) col[3] = 0.0; + +} + +/* ------------------------------------------------------------------------- */ + +void spotHaloFloat(struct LampRen *lar, float *view, float *intens) +{ + double a, b, c, disc, nray[3], npos[3]; + float t0, t1 = 0.0, t2= 0.0, t3, haint; + float p1[3], p2[3], ladist, maxz = 0.0, maxy = 0.0; + int snijp, doclip=1, use_yco=0; + int ok1=0, ok2=0; + + *intens= 0.0; + haint= lar->haint; + + VECCOPY(npos, lar->sh_invcampos); /* in initlamp berekend */ + + /* view roteren */ + VECCOPY(nray, view); + MTC_Mat3MulVecd(lar->imat, nray); + + if(R.wrld.mode & WO_MIST) { + /* een beetje patch... */ + R.zcor= -lar->co[2]; + haint *= mistfactor(lar->co); + if(haint==0.0) { + return; + } + } + + + /* maxz roteren */ + if(R.co[2]==0) doclip= 0; /* is als halo op sky */ + else { + p1[0]= R.co[0]-lar->co[0]; + p1[1]= R.co[1]-lar->co[1]; + p1[2]= R.co[2]-lar->co[2]; + + maxz= lar->imat[0][2]*p1[0]+lar->imat[1][2]*p1[1]+lar->imat[2][2]*p1[2]; + maxz*= lar->sh_zfac; + maxy= lar->imat[0][1]*p1[0]+lar->imat[1][1]*p1[1]+lar->imat[2][1]*p1[2]; + + if( fabs(nray[2]) <0.000001 ) use_yco= 1; + } + + /* z scalen zodat het volume genormaliseerd is */ + nray[2]*= lar->sh_zfac; + /* nray hoeft niet genormaliseerd */ + + ladist= lar->sh_zfac*lar->dist; + + /* oplossen */ + a = nray[0] * nray[0] + nray[1] * nray[1] - nray[2]*nray[2]; + b = nray[0] * npos[0] + nray[1] * npos[1] - nray[2]*npos[2]; + c = npos[0] * npos[0] + npos[1] * npos[1] - npos[2]*npos[2]; + + snijp= 0; + if (fabs(a) < 0.00000001) { + /* + * Only one intersection point... + */ + return; + } + else { + disc = b*b - a*c; + + if(disc==0.0) { + t1=t2= (-b)/ a; + snijp= 2; + } + else if (disc > 0.0) { + disc = sqrt(disc); + t1 = (-b + disc) / a; + t2 = (-b - disc) / a; + snijp= 2; + } + } + if(snijp==2) { + /* sorteren */ + if(t1>t2) { + a= t1; t1= t2; t2= a; + } + + /* z van snijpunten met diabolo */ + p1[2]= npos[2] + t1*nray[2]; + p2[2]= npos[2] + t2*nray[2]; + + /* beide punten evalueren */ + if(p1[2]<=0.0) ok1= 1; + if(p2[2]<=0.0 && t1!=t2) ok2= 1; + + /* minstens 1 punt met negatieve z */ + if(ok1==0 && ok2==0) return; + + /* snijpunt met -ladist, de bodem van de kegel */ + if(use_yco==0) { + t3= (-ladist-npos[2])/nray[2]; + + /* moet 1 van de snijpunten worden vervangen? */ + if(ok1) { + if(p1[2]<-ladist) t1= t3; + } + else { + ok1= 1; + t1= t3; + } + if(ok2) { + if(p2[2]<-ladist) t2= t3; + } + else { + ok2= 1; + t2= t3; + } + } + else if(ok1==0 || ok2==0) return; + + /* minstens 1 zichtbaar snijpunt */ + if(t1<0.0 && t2<0.0) return; + + if(t1<0.0) t1= 0.0; + if(t2<0.0) t2= 0.0; + + if(t1==t2) return; + + /* voor zekerheid nog eens sorteren */ + if(t1>t2) { + a= t1; t1= t2; t2= a; + } + + /* t0 berekenen: is de maximale zichtbare z (als halo door vlak */ + /* doorsneden wordt) */ + if(doclip) { + if(use_yco==0) t0= (maxz-npos[2])/nray[2]; + else t0= (maxy-npos[1])/nray[1]; + + if(t0shb && lar->shb->shadhalostep) { + /* from shadbuf.c, returns float */ + *intens *= shadow_halo(lar, p1, p2); + } + /* if(lar->mode & LA_TEXTURE) do_lamphalo_tex(lar, p1, p2, intens); */ + + } +} /* end of void spotHaloFloat(struct LampRen *, float *view, float *intens) */ + +/* ------------------------------------------------------------------------- */ + +void shadeLampLusFloat() +{ + LampRen *lar; + register Material *ma; + float i, inp, inpr, t, lv[3], lampdist, ld = 0; + float ir, ig, ib; + float isr=0,isg=0,isb=0; + float lvrot[3], *vn, *view, shadfac, soft; + int a; + float shadfacvec[3] = {1.0, 1.0, 1.0}; + + vn= R.vn; + view= R.view; + ma= R.matren; + + /* aparte lus */ + if(ma->mode & MA_ONLYSHADOW) { + shadfac= ir= 0.0; + for(a=0; amode & LA_LAYER) if((lar->lay & R.vlr->lay)==0) continue; + + if(lar->shb) { + /* alleen testen binnen spotbundel */ + lv[0]= R.co[0]-lar->co[0]; + lv[1]= R.co[1]-lar->co[1]; + lv[2]= R.co[2]-lar->co[2]; + Normalise(lv); + inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]; + if(inpr>lar->spotsi) { + + inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]; + + RE_testshadowbuf(lar->shadowBufOb, lar->shb, inp, shadfacvec); +/* testshadowbuf(lar->shb, inp, shadfacvec); */ + + i= shadfacvec[0]; + + t= inpr - lar->spotsi; + if(tspotbl && lar->spotbl!=0.0) { + t/= lar->spotbl; + t*= t; + i= t*i+(1.0-t); + } + + shadfac+= i; + ir+= 1.0; + } + else { + shadfac+= 1.0; + ir+= 1.0; + } + } + } + if(ir>0.0) shadfac/= ir; + ma->alpha= (R.mat->alpha)*(1.0-shadfac); + + collector[0] = 0.0; + collector[1] = 0.0; + collector[2] = 0.0; + /* alpha is not set.... why?*/ + return; + } + + if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) { + ma->r= R.vcol[0]; + ma->g= R.vcol[1]; + ma->b= R.vcol[2]; + } + + /* mirror reflection colour */ + R.refcol[0]= R.refcol[1]= R.refcol[2]= R.refcol[3]= 0.0; + + if(ma->texco) { + + if(ma->texco & TEXCO_REFL) { + RE_calc_R_ref(); + } + + if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) { + R.mat->r= R.vcol[0]; + R.mat->g= R.vcol[1]; + R.mat->b= R.vcol[2]; + } + + do_material_tex(); + } + + if(ma->mode & MA_SHLESS) { + if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP+MA_FACETEXTURE) )) { + ir= R.vcol[0]*ma->r; + ig= R.vcol[1]*ma->g; + ib= R.vcol[2]*ma->b; + } + else { + ir= ma->r; /* apparently stored as [0,1]? */ + ig= ma->g; + ib= ma->b; + } + + collector[0] = ir; /* no clipping, no alpha */ + collector[1] = ig; + collector[2] = ib; + return; + } + + if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) { + ir= ma->emit+R.vcol[0]; + ig= ma->emit+R.vcol[1]; + ib= ma->emit+R.vcol[2]; + } + else ir= ig= ib= ma->emit; + + for(a=0; amode & LA_LAYER) if((lar->lay & R.vlr->lay)==0) continue; + + /* lampdist berekening */ + if(lar->type==LA_SUN || lar->type==LA_HEMI) { + VECCOPY(lv, lar->vec); + lampdist= 1.0; + } + else { + lv[0]= R.co[0]-lar->co[0]; + lv[1]= R.co[1]-lar->co[1]; + lv[2]= R.co[2]-lar->co[2]; + ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]); + lv[0]/= ld; + lv[1]/= ld; + lv[2]/= ld; + + /* ld wordt verderop nog gebruikt (texco's) */ + + if(lar->mode & LA_QUAD) { + t= 1.0; + if(lar->ld1>0.0) + t= lar->dist/(lar->dist+lar->ld1*ld); + if(lar->ld2>0.0) + t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld); + + lampdist= t; + } + else { + lampdist= (lar->dist/(lar->dist+ld)); + } + + if(lar->mode & LA_SPHERE) { + t= lar->dist - ld; + if(t<0.0) continue; + + t/= lar->dist; + lampdist*= (t); + } + + } + + if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv); + + if(lar->type==LA_SPOT) { + + /* hier de fie Inp() vertaagt! */ + + if(lar->mode & LA_SQUARE) { + if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) { + float x; + + /* rotate view to lampspace */ + VECCOPY(lvrot, lv); + MTC_Mat3MulVecfl(lar->imat, lvrot); + + x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2])); + /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */ + + inpr= 1.0/(sqrt(1+x*x)); + } + else inpr= 0.0; + } + else { + inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]; + } + + t= lar->spotsi; + if(inprspotbl && lar->spotbl!=0.0) { + /* zachte gebied */ + i= t/lar->spotbl; + t= i*i; + soft= (3.0*t-2.0*t*i); + inpr*= soft; + } + if(lar->mode & LA_ONLYSHADOW && lar->shb) { + if(ma->mode & MA_SHADOW) { + /* inprodukt positief: voorzijde vlak! */ + inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]; + if(inp>0.0) { + + /* testshadowbuf==0.0 : 100% schaduw */ + RE_testshadowbuf(lar->shadowBufOb, lar->shb, inp, shadfacvec); +/* testshadowbuf(lar->shb, inp, shadfacvec); */ + shadfac = 1.0 - shadfacvec[0]; + + if(shadfac>0.0) { + shadfac*= inp*soft*lar->energy; + ir -= shadfac; + ig -= shadfac; + ib -= shadfac; + + continue; + } + } + } + } + lampdist*=inpr; + } + if(lar->mode & LA_ONLYSHADOW) continue; + + if(lar->mode & LA_OSATEX) { + R.osatex= 1; /* signaal voor multitex() */ + + O.dxlv[0]= lv[0] - (R.co[0]-lar->co[0]+O.dxco[0])/ld; + O.dxlv[1]= lv[1] - (R.co[1]-lar->co[1]+O.dxco[1])/ld; + O.dxlv[2]= lv[2] - (R.co[2]-lar->co[2]+O.dxco[2])/ld; + + O.dylv[0]= lv[0] - (R.co[0]-lar->co[0]+O.dyco[0])/ld; + O.dylv[1]= lv[1] - (R.co[1]-lar->co[1]+O.dyco[1])/ld; + O.dylv[2]= lv[2] - (R.co[2]-lar->co[2]+O.dyco[2])/ld; + } + + } + + /* inprodukt en reflectivity*/ + inp=i= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]; + if(lar->type==LA_HEMI) { + i= 0.5*i+0.5; + } + if(i>0.0) { + i*= lampdist*ma->ref; + } + + /* schaduw en spec */ + if(i> -0.41) { /* beetje willekeurig, beetje getest */ + shadfac= 1.0; + if(lar->shb) { + if(ma->mode & MA_SHADOW) { + float shadfacvec[3] = {1.0, 1.0, 1.0}; + RE_testshadowbuf(lar->shadowBufOb, lar->shb, inp, shadfacvec); +/* testshadowbuf(lar->shb, inp, shadfacvec); */ + shadfac = shadfacvec[0]; + +/* shadfac = 1.0; : no shadow */ + if(shadfac==0.0) continue; + i*= shadfac; + } + } + /* specularity */ + + if(ma->spec!=0.0) { + + if(lar->type==LA_SUN || lar->type==LA_HEMI) { + if(lar->type==LA_SUN) { + lv[2]-= 1.0; + } + else { + lv[0]+= view[0]; + lv[1]+= view[1]; + lv[2]+= view[2]; + } + + Normalise(lv); + + t= vn[0]*lv[0]+vn[1]*lv[1]+vn[2]*lv[2]; + + if(lar->type==LA_HEMI) { + t= 0.5*t+0.5; + } + /* let op: shadfac en lampdist uit onderstaande */ + + /* no more speclim */ + + t= ma->spec*RE_Spec(t, ma->har); + isr+= t*(lar->r * ma->specr); + isg+= t*(lar->g * ma->specg); + isb+= t*(lar->b * ma->specb); + } + else { + /* Does specular reflection? This would be the place */ + /* to put BRDFs. */ + t= shadfac*ma->spec*lampdist*CookTorr(vn, lv, view, ma->har); + isr+= t*(lar->r * ma->specr); + isg+= t*(lar->g * ma->specg); + isb+= t*(lar->b * ma->specb); + } + } + } + if(i>0.0) { + ir+= i*lar->r; + ig+= i*lar->g; + ib+= i*lar->b; + } + } + + /* clipping: maybe don't clip? (nzc) */ + /* yes, it shouldn't be done... unfortunately the current + * gammaCorrect implementation doesn't handle negative values + * correctly ( (-1)^2 = 1!!) (ton) + */ +/* if(ir<0.0) ir= 0.0; */ +/* if(ig<0.0) ig= 0.0; */ +/* if(ib<0.0) ib= 0.0; */ +/* if(isr<0.0) isr= 0.0; */ +/* if(isg<0.0) isg= 0.0; */ +/* if(isb<0.0) isb= 0.0; */ + /* Well, it does now. -(1^2) = -1 :) (nzc) */ + + if(ma->mode & MA_ZTRA) { /* ztra shade */ + if(ma->spectra!=0.0) { + + t = MAX3(isr, isb, isg); + t *= ma->spectra; + if(t>1.0) t= 1.0; + if(ma->mapto & MAP_ALPHA) ma->alpha= (1.0-t)*ma->alpha+t; + else ma->alpha= (1.0-t)*R.mat->alpha+t; + } + } + + if(R.refcol[0]==0.0) { + collector[0] = (ma->r * ir) + ma->ambr + isr; + collector[1] = (ma->g * ig) + ma->ambg + isg; + collector[2] = (ma->b * ib) + ma->ambb + isb; + /* clip for >0 ? */ + } + else { + collector[0] = (ma->mirr * R.refcol[1]) + + ((1.0 - (ma->mirr * R.refcol[0])) * ((ma->r * ir) + ma->ambr)) + + isr; + collector[1] = (ma->mirg*R.refcol[2]) + + ((1.0 - (ma->mirg * R.refcol[0])) * ((ma->g * ig) +ma->ambg)) + +isg; + collector[2] = (ma->mirb*R.refcol[3]) + + ((1.0 - (ma->mirb * R.refcol[0])) * ((ma->b * ib) +ma->ambb)) + +isb; + } + +#ifdef RE_FAKE_LAMP_SHADE + collector[0] = 0.5; + collector[1] = 0.5; + collector[2] = 1.0; +#endif + +} + +/* ------------------------------------------------------------------------- */ + +void* renderHaloPixel(float x, float y, int haloNr) { + HaloRen *har = NULL; + float dist = 0.0; + unsigned int zz = 0; + +#ifdef RE_FAKE_HALO_PIXELS + collector[0] = RE_UNITY_COLOUR_FLOAT; + collector[1] = 0; + collector[2] = 0; + collector[3] = RE_UNITY_COLOUR_FLOAT; + har = RE_findOrAddHalo(haloNr); /* crash prevention */ + return (void*) har; +#endif + + /* Find har to go with haloNr */ + har = RE_findOrAddHalo(haloNr); + + /* zz is a strange number... This call should effect that halo's are */ + /* never cut? Seems a bit strange to me now... */ + /* This might be the zbuffer depth */ + zz = calcHaloZ(har, 0x7FFFFFFF); + + /* distance of this point wrt. the halo center. Maybe xcor is also needed? */ + dist = ((x - har->xs) * (x - har->xs)) + + ((y - har->ys) * (y - har->ys) * R.ycor * R.ycor) ; + + collector[0] = RE_ZERO_COLOUR_FLOAT; collector[1] = RE_ZERO_COLOUR_FLOAT; + collector[2] = RE_ZERO_COLOUR_FLOAT; collector[3] = RE_ZERO_COLOUR_FLOAT; + + if (dist < har->radsq) { + shadeHaloFloat(har, collector, zz, dist, + (x - har->xs), (y - har->ys) * R.ycor, har->flarec); + /* make a second fake pixel? */ +#ifdef RE_FAKE_HALO_PIXELS_2 + collector[0] = RE_UNITY_COLOUR_FLOAT; + collector[1] = 0; + collector[2] = 0; + collector[3] = RE_UNITY_COLOUR_FLOAT; +#endif + }; /* else: this pixel is not rendered for this halo: no colour */ + + return (void*) har; + +} /* end of void* renderHaloPixel(float x, float y, int haloNr) */ + +/* ------------------------------------------------------------------------- */ + +extern float hashvectf[]; +void shadeHaloFloat(HaloRen *har, + float *col, unsigned int zz, + float dist, float xn, + float yn, short flarec) +{ + /* in col invullen */ + /* migrate: fill collector */ + float t, zn, radist, ringf=0.0, linef=0.0, alpha, si, co, colf[4]; + int a; + + if(R.wrld.mode & WO_MIST) { + if(har->type & HA_ONLYSKY) { + /* sterren geen mist */ + alpha= har->alfa; + } + else { + /* een beetje patch... */ + R.zcor= -har->co[2]; + alpha= mistfactor(har->co)*har->alfa; + } + } + else alpha= har->alfa; + + if(alpha==0.0) { + col[0] = 0.0; + col[1] = 0.0; + col[2] = 0.0; + col[3] = 0.0; + return; + } + + radist= sqrt(dist); + + /* let op: hiermee wordt gesjoemeld: flarec wordt op nul gezet in de pixstruct */ + if(flarec) har->pixels+= (int)(har->rad-radist); + + if(har->ringc) { + float *rc, fac; + int ofs; + + /* per ring een alicirc */ + ofs= har->seed; + + for(a= har->ringc; a>0; a--, ofs+=2) { + + rc= hashvectf + (ofs % 768); + + fac= fabs( rc[1]*(har->rad*fabs(rc[0]) - radist) ); + + if(fac< 1.0) { + ringf+= (1.0-fac); + } + } + } + + if(har->type & HA_VECT) { + dist= fabs( har->cos*(yn) - har->sin*(xn) )/har->rad; + if(dist>1.0) dist= 1.0; + if(har->tex) { + zn= har->sin*xn - har->cos*yn; + yn= har->cos*xn + har->sin*yn; + xn= zn; + } + } + else dist= dist/har->radsq; + + if(har->type & HA_FLARECIRC) { + + dist= 0.5+fabs(dist-0.5); + + } + + if(har->hard>=30) { + dist= sqrt(dist); + if(har->hard>=40) { + dist= sin(dist*M_PI_2); + if(har->hard>=50) { + dist= sqrt(dist); + } + } + } + else if(har->hard<20) dist*=dist; + + dist=(1.0-dist); + + if(har->linec) { + float *rc, fac; + int ofs; + + /* per starpoint een aliline */ + ofs= har->seed; + + for(a= har->linec; a>0; a--, ofs+=3) { + + rc= hashvectf + (ofs % 768); + + fac= fabs( (xn)*rc[0]+(yn)*rc[1]); + + if(fac< 1.0 ) { + linef+= (1.0-fac); + } + } + + linef*= dist; + + } + + if(har->starpoints) { + float ster, hoek; + /* rotatie */ + hoek= atan2(yn, xn); + hoek*= (1.0+0.25*har->starpoints); + + co= cos(hoek); + si= sin(hoek); + + hoek= (co*xn+si*yn)*(co*yn-si*xn); + + ster= fabs(hoek); + if(ster>1.0) { + ster= (har->rad)/(ster); + + if(ster<1.0) dist*= sqrt(ster); + } + } + + /* halo wordt doorsneden? */ + if(har->zs> zz-har->zd) { + t= ((float)(zz-har->zs))/(float)har->zd; + alpha*= sqrt(sqrt(t)); + } + + dist*= alpha; + ringf*= dist; + linef*= alpha; + + if(dist<0.003) { + col[0] = 0.0; + col[1] = 0.0; + col[2] = 0.0; + col[3] = 0.0; + return; + } + + /* The colour is either the rgb spec-ed by the user, or extracted from */ + /* the texture */ + if(har->tex) { + colf[3]= dist; + do_halo_tex(har, xn, yn, colf); + colf[0]*= colf[3]; + colf[1]*= colf[3]; + colf[2]*= colf[3]; + + } + else { + colf[0]= dist*har->r; + colf[1]= dist*har->g; + colf[2]= dist*har->b; + if(har->type & HA_XALPHA) colf[3]= dist*dist; + else colf[3]= dist; + } + + if(har->mat && har->mat->mode & MA_HALO_SHADE) { + /* we test for lights because of preview... */ + if(R.totlamp) render_lighting_halo(har, colf); + } + + /* Next, we do the line and ring factor modifications. It seems we do */ + /* uchar calculations, but it's basically doing float arith with a 255 */ + /* scale factor. */ + if(linef!=0.0) { + Material *ma= har->mat; + linef *= 255.0; + + colf[0]+= linef * ma->specr; + colf[1]+= linef * ma->specg; + colf[2]+= linef * ma->specb; + + if(har->type & HA_XALPHA) colf[3]+= linef*linef; + else colf[3]+= linef; + } + if(ringf!=0.0) { + Material *ma= har->mat; + ringf *= 255.0; + + colf[0]+= ringf * ma->mirr; + colf[1]+= ringf * ma->mirg; + colf[2]+= ringf * ma->mirb; + + if(har->type & HA_XALPHA) colf[3]+= ringf*ringf; + else colf[3]+= ringf; + } + + /* convert to [0.0; 1.0] range */ + col[0] = colf[0] / 255.0; + col[1] = colf[1] / 255.0; + col[2] = colf[2] / 255.0; + col[3] = colf[3]; + +} /* end of shadeHaloFloat() */ + +/* ------------------------------------------------------------------------- */ + +void renderSpotHaloPixel(float x, float y, float* target) +{ + float u = 0.0, v = 0.0; + +#ifdef RE_FAKE_SPOTHALO_PIXELS + target[0] = 0.0; + target[1] = 1.0; + target[2] = 0.0; + target[3] = 1.0; + return; +#endif + + /* Strange fix? otherwise done inside shadepixel. It's sort */ + /* of like telling this is a 'sky' pixel. */ + R.vlaknr = 0; + target[3] = 0.0; + + /* + Here's the viewvector setting again. + */ + if( (G.special1 & G_HOLO) && ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) { + R.view[0]= (x+(R.xstart)+1.0+holoofs); + } + else { + R.view[0]= (x+(R.xstart)+1.0); + } + + if(R.flag & R_SEC_FIELD) { + if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor; + else R.view[1]= (y+R.ystart+1.5)*R.ycor; + } + else R.view[1]= (y+R.ystart+1.0)*R.ycor; + + R.view[2]= -R.viewfac; + + if(R.r.mode & R_PANORAMA) { + float panoco, panosi; + panoco = getPanovCo(); + panosi = getPanovSi(); + u= R.view[0]; v= R.view[2]; + + R.view[0]= panoco*u + panosi*v; + R.view[2]= -panosi*u + panoco*v; + } + + R.co[2]= 0.0; + + /* This little function is a patch for spothalos on non-covered pixels. */ + renderspothaloFix(target); + +} /* end of void renderSpotHaloPixel(float x, float y, float colbuf[4]) */ + +/* ------------------------------------------------------------------------- */ +/* + This routine is only for sky-pixels. Therefore, no gamma needs to be done. + One strange side-effect is when you have a negative halo lamp. This suddenly + gives loads of colour. That particular case has been explicitly guarded: no + halo for negative halo spots! + + This routine uses the viewvector in R... to determine what to shade. Just + deposit the colour to be blended in col. + + I would like to add colours 'normally', so this routine would be the same + for spothalo on covered pixels, but that doesn't work. Some strange clipping + occurs... + */ +void renderspothaloFix(float *col) +{ + LampRen *lar; + float i; + int a; + + for(a=0; atype==LA_SPOT) + && (lar->mode & LA_HALO) + && !(lar->mode & LA_NEG) + && (lar->haint>0)) { + + if(lar->org) { + lar->r= lar->org->r; + lar->g= lar->org->g; + lar->b= lar->org->b; + } + + /* returns the intensity in i */ + spotHaloFloat(lar, R.view, &i); + + if(i>0.0) { + /* Premul colours here! */ + col[0] = i * lar->r; + col[1] = i * lar->g; + col[2] = i * lar->b; + col[3] = i; + } + } + } +} + +/* ------------------------------------------------------------------------- */ +/* + + There are three different modes for blending sky behind a picture: + 1. sky = blend in sky directly + 2. premul = don't do sky, but apply alpha (so pretend the picture ends + exactly at it's boundaries) + 3. key = don't do anything + Now the stupid thing is that premul means do nothing for us, and key + we have to adjust a bit... + +*/ + +/* Sky vars. */ +enum RE_SkyAlphaBlendingType keyingType = RE_ALPHA_SKY; /* The blending type */ + +void setSkyBlendingMode(enum RE_SkyAlphaBlendingType mode) { + if ((RE_ALPHA_NODEF < mode) && (mode < RE_ALPHA_MAX) ) { + keyingType = mode; + } else { + /* error: false mode received */ + keyingType = RE_ALPHA_SKY; + } +} + +enum RE_SkyAlphaBlendingType getSkyBlendingMode() { + return keyingType; +} + +/* This one renders into collector, as always. */ +void renderSkyPixelFloat(float x, float y) +{ +#ifdef RE_FAKE_SKY_PIXELS + collector[0] = 1.0; + collector[1] = 1.0; + collector[2] = 0.0; + collector[3] = 1.0; + return; +#endif + + switch (keyingType) { + case RE_ALPHA_PREMUL: + /* Premul: don't fill, and don't change the values! */ + case RE_ALPHA_KEY: + /* + Key: Leave pixels fully coloured, but retain alpha data, so you + can composit the picture later on. + - Should operate on the stack outcome! + */ +/* collector[0] = 0.0; */ +/* collector[1] = 0.0; */ +/* collector[2] = 0.0; */ +/* collector[3] = 0.0; */ + collector[3]= 0.0; + collector[0]= R.wrld.horr; + collector[1]= R.wrld.horg; + collector[2]= R.wrld.horb; + break; + case RE_ALPHA_SKY: + /* Fill in the sky as if it were a normal face. */ + shadeSkyPixel(x, y); + break; + default: + ; /* Error: illegal alpha blending state */ + } +} + +/* + Stuff the sky colour into the collector. + */ +void shadeSkyPixel(float fx, float fy) { + + /* + The rules for sky: + 1. Draw an image, if a background image was provided. Stop + 2. get texture and colour blend, and combine these. + */ + + float fac; + + /* 1. Do a backbuffer image: */ + if(R.r.bufflag & 1) { + fillBackgroundImage(fx, fy); + return; + } else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) { + /* + 2. Test for these types of sky. The old renderer always had to check for + coverage, but we don't need that anymore + - SKYBLEND or SKYTEX disabled: fill in a flat colour + - otherwise, do the appropriate mapping (tex or colour blend) + There used to be cached chars here, but they are not useful anymore + */ + collector[0] = R.wrld.horr; + collector[1] = R.wrld.horg; + collector[2] = R.wrld.horb; + collector[3] = RE_UNITY_COLOUR_FLOAT; + } else { + /* + 3. Which type(s) is(are) this (these)? This has to be done when no simple + way of determining the colour exists. + */ + + /* This one true because of the context of this routine */ +/* if(rect[3] < 254) { */ + if(R.wrld.skytype & WO_SKYPAPER) { + R.view[0]= (fx+(R.xstart))/(float)R.afmx; + R.view[1]= (fy+(R.ystart))/(float)R.afmy; + R.view[2]= 0.0; + } + else { + /* Wasn't this some pano stuff? */ + R.view[0]= (fx+(R.xstart)+1.0); + + if(R.flag & R_SEC_FIELD) { + if(R.r.mode & R_ODDFIELD) R.view[1]= (fy+R.ystart+0.5)*R.ycor; + else R.view[1]= (fy+R.ystart+1.5)*R.ycor; + } + else R.view[1]= (fy+R.ystart+1.0)*R.ycor; + + R.view[2]= -R.viewfac; + + fac= Normalise(R.view); + if(R.wrld.skytype & WO_SKYTEX) { + O.dxview= 1.0/fac; + O.dyview= R.ycor/fac; + } + } + + if(R.r.mode & R_PANORAMA) { + float panoco, panosi; + float u, v; + + panoco = getPanovCo(); + panosi = getPanovSi(); + u= R.view[0]; v= R.view[2]; + + R.view[0]= panoco*u + panosi*v; + R.view[2]= -panosi*u + panoco*v; + } + + /* get sky colour in the collector */ + shadeSkyPixelFloat(fy); + } + + +} + +/* Only line number is important here. Result goes to collector[4] */ +void shadeSkyPixelFloat(float y) +{ + + /* Why is this setting forced? Seems silly to me. It is tested in the texture unit. */ + R.wrld.skytype |= WO_ZENUP; + + /* Some view vector stuff. */ + if(R.wrld.skytype & WO_SKYREAL) { + + R.inprz= R.view[0]*R.grvec[0]+ R.view[1]*R.grvec[1]+ R.view[2]*R.grvec[2]; + + if(R.inprz<0.0) R.wrld.skytype-= WO_ZENUP; + R.inprz= fabs(R.inprz); + } + else if(R.wrld.skytype & WO_SKYPAPER) { + R.inprz= 0.5+ 0.5*R.view[1]; + } + else { + /* the fraction of how far we are above the bottom of the screen */ + R.inprz= fabs(0.5+ R.view[1]); + } + + /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If */ + /* SKYBLEND is active, the texture and colour blend are added. */ + if(R.wrld.skytype & WO_SKYTEX) { + VECCOPY(R.lo, R.view); + if(R.wrld.skytype & WO_SKYREAL) { + + MTC_Mat3MulVecfl(R.imat, R.lo); + + SWAP(float, R.lo[1], R.lo[2]); + + } + + R.osatex= 0; + + /* sky texture? I wonder how this manages to work... */ + /* Does this communicate with R.wrld.hor{rgb}? Yes. */ + do_sky_tex(); + /* internally, T{rgb} are used for communicating colours in the */ + /* texture pipe, externally, this particular routine uses the */ + /* R.wrld.hor{rgb} thingies. */ + + } + + /* Why are this R. members? */ + if(R.inprz>1.0) R.inprz= 1.0; + R.inprh= 1.0-R.inprz; + + /* No clipping, no conversion! */ + if(R.wrld.skytype & WO_SKYBLEND) { + collector[0] = (R.inprh*R.wrld.horr + R.inprz*R.wrld.zenr); + collector[1] = (R.inprh*R.wrld.horg + R.inprz*R.wrld.zeng); + collector[2] = (R.inprh*R.wrld.horb + R.inprz*R.wrld.zenb); + } else { + /* Done when a texture was grabbed. */ + collector[0]= R.wrld.horr; + collector[1]= R.wrld.horg; + collector[2]= R.wrld.horb; + } + + collector[3]= RE_UNITY_COLOUR_FLOAT; + /* om verkeerde optimalisatie alphaover van flares te voorkomen */ + /* ??? seems strange to me... This used to be a 1 when the colours */ + /* were chars. might need a separate flag for this... */ +} + + +/* + Render pixel (x,y) from the backbuffer into the collector + + backbuf is type Image, backbuf->ibuf is an ImBuf. ibuf->rect is the + rgba data (32 bit total), in ibuf->x by ibuf->y pixels. Copying + should be really easy. I hope I understand the way ImBuf works + correctly. (nzc) +*/ +void fillBackgroundImage(float x, float y) +{ + + int iy, ix; + unsigned int* imBufPtr; + char *colSource; + + /* This double check is bad... */ + if (!(R.backbuf->ok)) { + /* Something went sour here... bail... */ + collector[0] = 0.0; + collector[1] = 0.0; + collector[2] = 0.0; + collector[3] = 1.0; + return; + } + /* load image if not already done?*/ + if(R.backbuf->ibuf==0) { + R.backbuf->ibuf= IMB_loadiffname(R.backbuf->name, IB_rect); + if(R.backbuf->ibuf==0) { + /* load failed .... keep skipping */ + R.backbuf->ok= 0; + return; + } + } + + /* Now for the real extraction: */ + /* Get the y-coordinate of the scanline? */ + iy= (int) ((y+R.afmy+R.ystart)*R.backbuf->ibuf->y)/(2*R.afmy); + ix= (int) ((x+R.afmx+R.xstart)*R.backbuf->ibuf->x)/(2*R.afmx); + + /* correct in case of fields rendering: */ + if(R.flag & R_SEC_FIELD) { + if((R.r.mode & R_ODDFIELD)==0) { + if( iyibuf->y) iy++; + } + else { + if( iy>0) iy--; + } + } + + /* Offset into the buffer: start of scanline y: */ + imBufPtr = R.backbuf->ibuf->rect + + (iy * R.backbuf->ibuf->x) + + ix; + + colSource = (char*) imBufPtr; + + cpCharColV2FloatColV(colSource, collector); + +} + +/* eof */ diff --git a/source/blender/render/intern/source/renderHelp.c b/source/blender/render/intern/source/renderHelp.c new file mode 100644 index 00000000000..c7294d0feeb --- /dev/null +++ b/source/blender/render/intern/source/renderHelp.c @@ -0,0 +1,294 @@ +/** + * + * ***** 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 ***** + * Some helpful conversions/functions. + * + * $Id$ + */ + +#include +#include +#include + +#include "render.h" +#include "render_intern.h" +#include "renderHelp.h" +#include "zbuf.h" + + + +static float panovco, panovsi; +static float panophi=0.0; +static float tempPanoPhi; + +static int panotestclip(float *v); + +void pushTempPanoPhi(float p) { + tempPanoPhi = panophi; + panophi = p; +} + +void popTempPanoPhi() { + panophi = tempPanoPhi; +} + +float getPanoPhi(){ + return panophi; +} +float getPanovCo(){ + return panovco; +} +float getPanovSi(){ + return panovsi; +} + +void setPanoRot(int part) +{ +/* extern float panovco, panovsi; */ + static float alpha= 1.0; + + /* part==0 alles initialiseren */ + + if(part==0) { + + alpha= ((float)R.r.xsch)/R.viewfac; + alpha= 2.0*atan(alpha/2.0); + } + + + /* we roteren alles om de y-as met phi graden */ + + panophi= -0.5*(R.r.xparts-1)*alpha + part*alpha; + + panovsi= sin(-panophi); + panovco= cos(-panophi); + +} + + + + +static int panotestclip(float *v) +{ + /* gebruiken voor halo's en info's */ + float abs4; + short c=0; + + if((R.r.mode & R_PANORAMA)==0) return RE_testclip(v); + + abs4= fabs(v[3]); + + if(v[2]< -abs4) c=16; /* hier stond vroeger " if(v[2]<0) ", zie clippz() */ + else if(v[2]> abs4) c+= 32; + + if( v[1]>abs4) c+=4; + else if( v[1]< -abs4) c+=8; + + abs4*= R.r.xparts; + if( v[0]>abs4) c+=2; + else if( v[0]< -abs4) c+=1; + + return c; +} + +/* + + This adds the hcs coordinates to vertices. It iterates over all + vertices, halos and faces. After the conversion, we clip in hcs. + + Elsewhere, all primites are converted to vertices. + Called in + - envmapping (envmap.c) + - shadow buffering (shadbuf.c) + - preparation for rendering (renderPreAndPost.c) + +*/ + +/* move to renderer */ +void setzbufvlaggen( void (*projectfunc)(float *, float *) ) +/* ook homoco's */ +{ + VlakRen *vlr = NULL; + VertRen *ver = NULL; + HaloRen *har = NULL; + float zn, vec[3], si, co, hoco[4]; + int a; + float panophi = 0.0; + + panophi = getPanoPhi(); + si= sin(panophi); + co= cos(panophi); + + /* calculate view coordinates (and zbuffer value) */ + for(a=0; a< R.totvert;a++) { + if((a & 255)==0) ver= R.blove[a>>8]; + else ver++; + + if(R.r.mode & R_PANORAMA) { + vec[0]= co*ver->co[0] + si*ver->co[2]; + vec[1]= ver->co[1]; + vec[2]= -si*ver->co[0] + co*ver->co[2]; + } + else { + VECCOPY(vec, ver->co); + } + /* Go from wcs to hcs ... */ + projectfunc(vec, ver->ho); + /* ... and clip in that system. */ + ver->clip = RE_testclip(ver->ho); + /* + Because all other ops are performed in other systems, this is + the only thing that has to be done. + */ + } + + /* calculate view coordinates (and zbuffer value) */ + for(a=0; a>8]; + else har++; + + if(R.r.mode & R_PANORAMA) { + vec[0]= co*har->co[0] + si*har->co[2]; + vec[1]= har->co[1]; + vec[2]= -si*har->co[0] + co*har->co[2]; + } + else { + VECCOPY(vec, har->co); + } + + projectfunc(vec, hoco); + + hoco[3]*= 2.0; + + if( panotestclip(hoco) ) { + har->miny= har->maxy= -10000; /* de render clipt 'm weg */ + } + else if(hoco[3]<0.0) { + har->miny= har->maxy= -10000; /* de render clipt 'm weg */ + } + else /* this seems to be strange code here...*/ + { + zn= hoco[3]/2.0; + har->xs= 0.5*R.rectx*(1.0+hoco[0]/zn); /* the 0.5 negates the previous 2...*/ + har->ys= 0.5*R.recty*(1.0+hoco[1]/zn); + + /* this should be the zbuffer coordinate */ + har->zs= 0x7FFFFF*(1.0+hoco[2]/zn); + /* taking this from the face clip functions? seems ok... */ + har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); + vec[0]+= har->hasize; + projectfunc(vec, hoco); + vec[0]-= har->hasize; + zn= hoco[3]; + har->rad= fabs(har->xs- 0.5*R.rectx*(1.0+hoco[0]/zn)); + + /* deze clip is eigenlijk niet OK */ + if(har->type & HA_ONLYSKY) { + if(har->rad>3.0) har->rad= 3.0; + } + + har->radsq= har->rad*har->rad; + + har->miny= har->ys - har->rad/R.ycor; + har->maxy= har->ys + har->rad/R.ycor; + + /* de Zd is bij pano nog steeds verkeerd: zie testfile in blenderbugs/halo+pano.blend */ + + vec[2]-= har->hasize; /* z is negatief, wordt anders geclipt */ + projectfunc(vec, hoco); + zn= hoco[3]; + zn= fabs(har->zs - 0x7FFFFF*(1.0+hoco[2]/zn)); + har->zd= CLAMPIS(zn, 0, INT_MAX); + + /* if( har->zs < 2*har->zd) { */ + /* PRINT2(d, d, har->zs, har->zd); */ + /* har->alfa= har->mat->alpha * ((float)(har->zs))/(float)(2*har->zd); */ + /* } */ + + } + + } + + /* vlaggen op 0 zetten als eruit geclipt */ + for(a=0; a>8]; + else vlr++; + + vlr->flag |= R_VISIBLE; + if(vlr->v4) { + if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip & vlr->v4->clip) vlr->flag &= ~R_VISIBLE; + } + else if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip) vlr->flag &= ~R_VISIBLE; + + } + +} + +/* ------------------------------------------------------------------------- */ +/* move to renderer */ + +void set_normalflags(void) +{ + VlakRen *vlr = NULL; + float vec[3], xn, yn, zn; + int a1; + + /* KLAP NORMAAL EN SNIJ PROJECTIE */ + for(a1=0; a1>8]; + else vlr++; + + if(vlr->flag & R_NOPUNOFLIP) { + /* render normaal flippen, wel niet zo netjes, maar anders dan moet de render() ook over... */ + vlr->n[0]= -vlr->n[0]; + vlr->n[1]= -vlr->n[1]; + vlr->n[2]= -vlr->n[2]; + } + else { + + vec[0]= vlr->v1->co[0]; + vec[1]= vlr->v1->co[1]; + vec[2]= vlr->v1->co[2]; + + if( (vec[0]*vlr->n[0] +vec[1]*vlr->n[1] +vec[2]*vlr->n[2])<0.0 ) { + vlr->puno= ~(vlr->puno); + vlr->n[0]= -vlr->n[0]; + vlr->n[1]= -vlr->n[1]; + vlr->n[2]= -vlr->n[2]; + } + } + xn= fabs(vlr->n[0]); + yn= fabs(vlr->n[1]); + zn= fabs(vlr->n[2]); + if(zn>=xn && zn>=yn) vlr->snproj= 0; + else if(yn>=xn && yn>=zn) vlr->snproj= 1; + else vlr->snproj= 2; + + } +} diff --git a/source/blender/render/intern/source/renderPreAndPost.c b/source/blender/render/intern/source/renderPreAndPost.c new file mode 100644 index 00000000000..761ac75d430 --- /dev/null +++ b/source/blender/render/intern/source/renderPreAndPost.c @@ -0,0 +1,94 @@ +/** + * + * ***** 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 ***** + * Prepare the scene data for rendering. + * + * $Id$ + */ + +#include "MEM_guardedalloc.h" + +#include "render.h" +#include "render_intern.h" +#include "renderPreAndPost.h" +#include "RE_callbacks.h" + +#include "shadbuf.h" +#include "envmap.h" +#include "renderHelp.h" +#include "shadowBuffer.h" + +/** + * Rotate all objects, make shadowbuffers and environment maps. + */ +void prepareScene() +{ + int a; + + + if(R.rectot) MEM_freeN(R.rectot); + R.rectot= 0; + if(R.rectz) MEM_freeN(R.rectz); + R.rectz= 0; + + RE_local_get_renderdata(); + + /* SCHADUWBUFFER */ + for(a=0; ashadowBufOb) { + RE_buildShadowBuffer(R.la[a]->shadowBufOb, + R.la[a]); + } + } else { + if(R.la[a]->shb) makeshadowbuf(R.la[a]); + } + } + + /* ENVIRONMENT MAPS */ + make_envmaps(); +} + +void finalizeScene(void) +{ + /* Among other things, it releases the shadow buffers. */ + RE_local_free_renderdata(); +} + + +void doClipping( void (*projectfunc)(float *, float *) ) +{ + setzbufvlaggen(projectfunc); +} + +/* eof */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c new file mode 100644 index 00000000000..32db34d7ac6 --- /dev/null +++ b/source/blender/render/intern/source/rendercore.c @@ -0,0 +1,2902 @@ +/** + * $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 ***** + */ + +/* system includes */ +#include +#include +#include + +/* External modules: */ +#include "MEM_guardedalloc.h" +#include "BLI_arithb.h" +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "MTC_matrixops.h" +#include "BKE_utildefines.h" + +#include "DNA_mesh_types.h" +#include "DNA_image_types.h" +#include "DNA_object_types.h" +#include "DNA_camera_types.h" +#include "DNA_lamp_types.h" + +#include "BKE_global.h" +#include "BKE_texture.h" + +/* local include */ +#include "RE_callbacks.h" +#include "old_zbuffer_types.h" +#include "render.h" +#include "render_intern.h" +#include "zbuf.h" /* stuff like bgnaccumbuf, fillrect, ...*/ +#include "pixelblending.h" +#include "shadbuf.h" +#include "renderHelp.h" + +#include "jitter.h" + +/* own include */ +#include "rendercore.h" +#include "rendercore_int.h" + +/* globals for this file */ +/* moved to renderData.c? Not yet... */ +RE_Render R; +Osa O; + +extern float Zjitx,Zjity, Zmulx, Zmuly; +PixStrMain psmfirst; +int psmteller; + +float holoofs= 0.0, fmask[256], centLut[16]; +unsigned short usegamtab=0, shortcol[4], *mask1[9], *mask2[9], *igamtab1, *igamtab2, *gamtab; +char cmask[256], *centmask; + +/* functions */ +/* comes from texture.c (only used here !) */ +/* extern void do_halo_tex(HaloRen *har, float xn, float yn, float *colf); */ + +void gamtabdit(unsigned short *in, char *out); +/* int count_mask(unsigned short ); */ +void scanlinehalo(unsigned int *rectz, unsigned int *rectt, short ys); +/* void add_halo_flare(void); */ +void edge_enhance(void); + +/* Dither with gamma table? */ +void gamtabdit(unsigned short *in, char *out) +/* unsigned short *in; */ +/* char *out; */ +{ + static short rerr=0, gerr=0, berr=0; + unsigned int col; + char *cp; + + cp= (char *)&col; + out[0]= in[0]>>8; + + col= gamtab[in[2]]+berr; + if(col>65535) col= 65535; + out[1]= cp[2]; + berr= cp[3]; + + col= gamtab[in[4]]+gerr; + if(col>65535) col= 65535; + out[2]= cp[2]; + gerr= cp[3]; + + col= gamtab[in[6]]+rerr; + if(col>65535) col= 65535; + out[3]= cp[2]; + rerr= cp[3]; + +} + +float mistfactor(float *co) /* dist en hoogte, return alpha */ +{ + float fac, hi; + + fac= R.zcor - R.wrld.miststa; /* R.zcor wordt per pixel berekend */ + + /* fac= -co[2]-R.wrld.miststa; */ + + if(fac>0.0) { + if(fac< R.wrld.mistdist) { + + fac= (fac/(R.wrld.mistdist)); + + if(R.wrld.mistype==0) fac*= fac; + else if(R.wrld.mistype==1); + else fac= sqrt(fac); + } + else fac= 1.0; + } + else fac= 0.0; + + /* de hoogte schakelt de mist af */ + if(R.wrld.misthi!=0.0 && fac!=0.0) { + /* op hoogte misthi is mist volledig weg */ + + hi= R.viewinv[0][2]*co[0]+R.viewinv[1][2]*co[1]+R.viewinv[2][2]*co[2]+R.viewinv[3][2]; + + if(hi>R.wrld.misthi) fac= 0.0; + else if(hi>0.0) { + hi= (R.wrld.misthi-hi)/R.wrld.misthi; + fac*= hi*hi; + } + } + + return 1.0-fac; +} + +void RE_sky(char *col) +{ + float rf, gf, bf; + + if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) { + *( (unsigned int *)col)= R.wrld.fastcol; + return; + } + + R.wrld.skytype |= WO_ZENUP; + + if(R.wrld.skytype & WO_SKYREAL) { + + R.inprz= R.view[0]*R.grvec[0]+ R.view[1]*R.grvec[1]+ R.view[2]*R.grvec[2]; + + if(R.inprz<0.0) R.wrld.skytype-= WO_ZENUP; + R.inprz= fabs(R.inprz); + } + else if(R.wrld.skytype & WO_SKYPAPER) { + R.inprz= 0.5+ 0.5*R.view[1]; + } + else { + R.inprz= fabs(0.5+ R.view[1]); + } + + if(R.wrld.skytype & WO_SKYTEX) { + VECCOPY(R.lo, R.view); + if(R.wrld.skytype & WO_SKYREAL) { + + MTC_Mat3MulVecfl(R.imat, R.lo); + + SWAP(float, R.lo[1], R.lo[2]); + + } + + R.osatex= 0; + + do_sky_tex(); + + } + + if(R.inprz>1.0) R.inprz= 1.0; + R.inprh= 1.0-R.inprz; + + if(R.wrld.skytype & WO_SKYBLEND) { + rf= 255.0*(R.inprh*R.wrld.horr + R.inprz*R.wrld.zenr); + gf= 255.0*(R.inprh*R.wrld.horg + R.inprz*R.wrld.zeng); + bf= 255.0*(R.inprh*R.wrld.horb + R.inprz*R.wrld.zenb); + + if (rf>255.0) col[0]= 255; + else col[0]= (char)rf; + if (gf>255.0) col[1]= 255; + else col[1]= (char)gf; + if (bf>255.0) col[2]= 255; + else col[2]= (char)bf; + } + else { + col[0]= 255.0*R.wrld.horr; + col[1]= 255.0*R.wrld.horg; + col[2]= 255.0*R.wrld.horb; + } + col[3]= 1; /* om verkeerde optimalisatie alphaover van flares te voorkomen */ +} + +/* ------------------------------------------------------------------------- */ + +void scanlinesky(char *rect, int y) +{ + /* have to type this! set to : addalphaUnder: char*, char* + * addalphaUnderGamma: ditto called with char *, uint* !!! + * unmangle this shit... */ + void (*alphafunc)(); + float fac; + int dx, x, ofs; + unsigned int col=0, *rt; + short *sp; + char *cp, *cp1; + float u, v; + + if(R.r.alphamode & R_ALPHAPREMUL) return; + + if(R.r.alphamode & R_ALPHAKEY) { + + cp= (char *)&col; + cp[3]= 1; + cp[0]= 255.0*R.wrld.horr; + cp[1]= 255.0*R.wrld.horg; + cp[2]= 255.0*R.wrld.horb; + + for(x=0; xok) { + if(R.backbuf->ibuf==0) { + R.backbuf->ibuf= IMB_loadiffname(R.backbuf->name, IB_rect); + if(R.backbuf->ibuf==0) { + R.backbuf->ok= 0; + return; + } + } + /* welke scanline/ */ + y= ((y+R.afmy+R.ystart)*R.backbuf->ibuf->y)/(2*R.afmy); + + if(R.flag & R_SEC_FIELD) { + if((R.r.mode & R_ODDFIELD)==0) { + if( yibuf->y) y++; + } + else { + if( y>0) y--; + } + } + + rt= (R.backbuf->ibuf->rect + y*R.backbuf->ibuf->x); + + /* op welke plek */ + fac= ((float)R.backbuf->ibuf->x)/(float)(2*R.afmx); + ofs= (R.afmx+R.xstart)*fac; + rt+= ofs; + + dx= (int) (65536.0*fac); + sp= (short *)&ofs; + + #ifdef BBIG_ENDIAN + #else + sp++; + #endif + + ofs= 0; + x= R.rectx; + while( x-- ) { + if( rect[3] != 255) { + if(rect[3]==0) *((unsigned int *)rect)= *rt; + else { + alphafunc(rect, rt); + } + } + rect+= 4; + + ofs+= dx; + while( *sp>0 ) { + ofs-= 65536; + rt++; + } + } + + } + return; + } + + if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) { + for(x=0; xsh_zfac; + + VecSubf(vec, p2, p1); + dist= Normalise(vec); + + /* fixed number of steps */ + dist/= (float)steps; + + for(a=0; ahaint; + + VECCOPY(npos, lar->sh_invcampos); /* in initlamp berekend */ + + /* view roteren */ + VECCOPY(nray, view); + MTC_Mat3MulVecd(lar->imat, nray); + + if(R.wrld.mode & WO_MIST) { + /* een beetje patch... */ + R.zcor= -lar->co[2]; + haint *= mistfactor(lar->co); + if(haint==0.0) { + return; + } + } + + + /* maxz roteren */ + if(R.co[2]==0) doclip= 0; /* is als halo op sky */ + else { + p1[0]= R.co[0]-lar->co[0]; + p1[1]= R.co[1]-lar->co[1]; + p1[2]= R.co[2]-lar->co[2]; + + maxz= lar->imat[0][2]*p1[0]+lar->imat[1][2]*p1[1]+lar->imat[2][2]*p1[2]; + maxz*= lar->sh_zfac; + maxy= lar->imat[0][1]*p1[0]+lar->imat[1][1]*p1[1]+lar->imat[2][1]*p1[2]; + + if( fabs(nray[2]) <0.000001 ) use_yco= 1; + } + + /* z scalen zodat het volume genormaliseerd is */ + nray[2]*= lar->sh_zfac; + /* nray hoeft niet genormaliseerd */ + + ladist= lar->sh_zfac*lar->dist; + + /* oplossen */ + a = nray[0] * nray[0] + nray[1] * nray[1] - nray[2]*nray[2]; + b = nray[0] * npos[0] + nray[1] * npos[1] - nray[2]*npos[2]; + c = npos[0] * npos[0] + npos[1] * npos[1] - npos[2]*npos[2]; + + snijp= 0; + if (fabs(a) < 0.00000001) { + /* + * Only one intersection point... + */ + return; + } + else { + disc = b*b - a*c; + + if(disc==0.0) { + t1=t2= (-b)/ a; + snijp= 2; + } + else if (disc > 0.0) { + disc = sqrt(disc); + t1 = (-b + disc) / a; + t2 = (-b - disc) / a; + snijp= 2; + } + } + if(snijp==2) { + /* sorteren */ + if(t1>t2) { + a= t1; t1= t2; t2= a; + } + + /* z van snijpunten met diabolo */ + p1[2]= npos[2] + t1*nray[2]; + p2[2]= npos[2] + t2*nray[2]; + + /* beide punten evalueren */ + if(p1[2]<=0.0) ok1= 1; + if(p2[2]<=0.0 && t1!=t2) ok2= 1; + + /* minstens 1 punt met negatieve z */ + if(ok1==0 && ok2==0) return; + + /* snijpunt met -ladist, de bodem van de kegel */ + if(use_yco==0) { + t3= (-ladist-npos[2])/nray[2]; + + /* moet 1 van de snijpunten worden vervangen? */ + if(ok1) { + if(p1[2]<-ladist) t1= t3; + } + else { + ok1= 1; + t1= t3; + } + if(ok2) { + if(p2[2]<-ladist) t2= t3; + } + else { + ok2= 1; + t2= t3; + } + } + else if(ok1==0 || ok2==0) return; + + /* minstens 1 zichtbaar snijpunt */ + if(t1<0.0 && t2<0.0) return; + + if(t1<0.0) t1= 0.0; + if(t2<0.0) t2= 0.0; + + if(t1==t2) return; + + /* voor zekerheid nog eens sorteren */ + if(t1>t2) { + a= t1; t1= t2; t2= a; + } + + /* t0 berekenen: is de maximale zichtbare z (als halo door vlak doorsneden wordt) */ + if(doclip) { + if(use_yco==0) t0= (maxz-npos[2])/nray[2]; + else t0= (maxy-npos[1])/nray[1]; + + if(t0shb && lar->shb->shadhalostep) { + *intens *= shadow_halo(lar, p1, p2); + } + /* if(lar->mode & LA_TEXTURE) do_lamphalo_tex(lar, p1, p2, intens); */ + + } +} + +void renderspothalo(unsigned short *col) +{ + LampRen *lar; + float i; + int colt, a; + unsigned short scol[4]; + + + for(a=0; atype==LA_SPOT && (lar->mode & LA_HALO) && lar->haint>0) { + + if(lar->org) { + lar->r= lar->org->r; + lar->g= lar->org->g; + lar->b= lar->org->b; + } + + spothalo(lar, R.view, &i); + + if(i>0.0) { + + i*= 65536.0; + + colt= i; + if(colt>65535) scol[3]= 65535; else scol[3]= colt; + + /* erg vervelend: gammagecorrigeerd renderen EN addalphaADD gaat niet goed samen */ + /* eigenlijk moet er een aparte 'optel' gamma komen */ + + colt= i*lar->r; + if(colt>65535) scol[0]= 65535; else scol[0]= colt; + if(usegamtab) scol[0]= igamtab2[scol[0]]; + colt= i*lar->g; + if(colt>65535) scol[1]= 65535; else scol[1]= colt; + if(usegamtab) scol[1]= igamtab2[scol[1]]; + colt= i*lar->b; + if(colt>65535) scol[2]= 65535; else scol[2]= colt; + if(usegamtab) scol[2]= igamtab2[scol[2]]; + + addalphaAddshort(col, scol); + } + } + } +} + +void render_lighting_halo(HaloRen *har, float *colf) +{ + LampRen *lar; + float i, inp, inpr, lv[3], lampdist, ld, t, *vn; + float ir, ig, ib, shadfac, soft; + int a; + + ir= ig= ib= 0.0; + VECCOPY(R.co, har->co); + vn= har->no; + + O.dxco[0]= har->hasize; + O.dxco[1]= 0.0; + O.dxco[2]= 0.0; + + O.dyco[0]= 0.0; + O.dyco[1]= har->hasize; + O.dyco[2]= 0.0; + + for(a=0; amode & LA_LAYER) if((lar->lay & har->lay)==0) continue; + + /* lampdist berekening */ + if(lar->type==LA_SUN || lar->type==LA_HEMI) { + VECCOPY(lv, lar->vec); + lampdist= 1.0; + } + else { + lv[0]= R.co[0]-lar->co[0]; + lv[1]= R.co[1]-lar->co[1]; + lv[2]= R.co[2]-lar->co[2]; + ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]); + lv[0]/= ld; + lv[1]/= ld; + lv[2]/= ld; + + /* ld wordt verderop nog gebruikt (texco's) */ + + if(lar->mode & LA_QUAD) { + t= 1.0; + if(lar->ld1>0.0) + t= lar->dist/(lar->dist+lar->ld1*ld); + if(lar->ld2>0.0) + t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld); + + lampdist= t; + } + else { + lampdist= (lar->dist/(lar->dist+ld)); + } + + if(lar->mode & LA_SPHERE) { + t= lar->dist - ld; + if(t<0.0) continue; + + t/= lar->dist; + lampdist*= (t); + } + + } + + if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv); + + if(lar->type==LA_SPOT) { + + /* hier de fie Inp() vertaagt! */ + + if(lar->mode & LA_SQUARE) { + if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) { + float x, lvrot[3]; + + /* rotate view to lampspace */ + VECCOPY(lvrot, lv); + MTC_Mat3MulVecfl(lar->imat, lvrot); + + x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2])); + /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */ + + inpr= 1.0/(sqrt(1.0+x*x)); + } + else inpr= 0.0; + } + else { + inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]; + } + + t= lar->spotsi; + if(inprspotbl && lar->spotbl!=0.0) { + /* zachte gebied */ + i= t/lar->spotbl; + t= i*i; + soft= (3.0*t-2.0*t*i); + inpr*= soft; + } + if(lar->mode & LA_ONLYSHADOW) { + /* if(ma->mode & MA_SHADOW) { */ + /* inprodukt positief: voorzijde vlak! */ + inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]; + if(inp>0.0) { + /* testshadowbuf==0.0 : 100% schaduw */ + shadfac = testshadowbuf(lar->shb, inp); + if( shadfac>0.0 ) { + shadfac*= inp*soft*lar->energy; + ir -= shadfac; + ig -= shadfac; + ib -= shadfac; + + continue; + } + } + /* } */ + } + lampdist*=inpr; + } + if(lar->mode & LA_ONLYSHADOW) continue; + + } + + /* inprodukt en reflectivity*/ + + inp= 1.0-fabs(vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]); + + /* inp= cos(0.5*M_PI-acos(inp)); */ + + i= inp; + + if(lar->type==LA_HEMI) { + i= 0.5*i+0.5; + } + if(i>0.0) { + i*= lampdist; + /* i*= lampdist*ma->ref; */ + } + + /* schaduw */ + if(i> -0.41) { /* beetje willekeurig, beetje getest */ + shadfac= 1.0; + if(lar->shb) { + /* if(ma->mode & MA_SHADOW) { */ + shadfac = testshadowbuf(lar->shb, inp); + if(shadfac==0.0) continue; + i*= shadfac; + /* } */ + } + } + + if(i>0.0) { + ir+= i*lar->r; + ig+= i*lar->g; + ib+= i*lar->b; + } + } + + if(ir<0.0) ir= 0.0; + if(ig<0.0) ig= 0.0; + if(ib<0.0) ib= 0.0; + + colf[0]*= ir; + colf[1]*= ig; + colf[2]*= ib; + +} + + +extern float hashvectf[]; +void RE_shadehalo(HaloRen *har, char *col, unsigned int zz, float dist, float xn, float yn, short flarec) +{ + /* in col invullen */ + float t, zn, radist, ringf=0.0, linef=0.0, alpha, si, co, colf[4]; + int colt, a; + + if(R.wrld.mode & WO_MIST) { + if(har->type & HA_ONLYSKY) { + /* sterren geen mist */ + alpha= har->alfa; + } + else { + /* een beetje patch... */ + R.zcor= -har->co[2]; + alpha= mistfactor(har->co)*har->alfa; + } + } + else alpha= har->alfa; + + if(alpha==0.0) { + col[0] = 0; + col[1] = 0; + col[2] = 0; + col[3] = 0; + +/* *( (int *)col )=0; */ + + return; + } + + radist= sqrt(dist); + + /* let op: hiermee wordt gesjoemeld: flarec wordt op nul gezet in de pixstruct */ + if(flarec) har->pixels+= (int)(har->rad-radist); + + if(har->ringc) { + float *rc, fac; + int ofs; + + /* per ring een alicirc */ + ofs= har->seed; + + for(a= har->ringc; a>0; a--, ofs+=2) { + + rc= hashvectf + (ofs % 768); + + fac= fabs( rc[1]*(har->rad*fabs(rc[0]) - radist) ); + + if(fac< 1.0) { + ringf+= (1.0-fac); + } + } + } + + if(har->type & HA_VECT) { + dist= fabs( har->cos*(yn) - har->sin*(xn) )/har->rad; + if(dist>1.0) dist= 1.0; + if(har->tex) { + zn= har->sin*xn - har->cos*yn; + yn= har->cos*xn + har->sin*yn; + xn= zn; + } + } + else dist= dist/har->radsq; + + if(har->type & HA_FLARECIRC) { + + dist= 0.5+fabs(dist-0.5); + + } + + if(har->hard>=30) { + dist= sqrt(dist); + if(har->hard>=40) { + dist= sin(dist*M_PI_2); + if(har->hard>=50) { + dist= sqrt(dist); + } + } + } + else if(har->hard<20) dist*=dist; + + dist=(1.0-dist); + + if(har->linec) { + float *rc, fac; + int ofs; + + /* per starpoint een aliline */ + ofs= har->seed; + + for(a= har->linec; a>0; a--, ofs+=3) { + + rc= hashvectf + (ofs % 768); + + fac= fabs( (xn)*rc[0]+(yn)*rc[1]); + + if(fac< 1.0 ) { + linef+= (1.0-fac); + } + } + + linef*= dist; + + } + + if(har->starpoints) { + float ster, hoek; + /* rotatie */ + hoek= atan2(yn, xn); + hoek*= (1.0+0.25*har->starpoints); + + co= cos(hoek); + si= sin(hoek); + + hoek= (co*xn+si*yn)*(co*yn-si*xn); + + ster= fabs(hoek); + if(ster>1.0) { + ster= (har->rad)/(ster); + + if(ster<1.0) dist*= sqrt(ster); + } + } + + /* halo wordt doorsneden? */ + if(har->zs> zz-har->zd) { + t= ((float)(zz-har->zs))/(float)har->zd; + alpha*= sqrt(sqrt(t)); + } + + dist*= alpha; + ringf*= dist; + linef*= alpha; + + if(dist<0.003) { + *( (int *)col )=0; + return; + } + + /* texture? */ + if(har->tex) { + colf[3]= dist; + do_halo_tex(har, xn, yn, colf); + + /* dist== colf[3]; */ + + colf[0]*= colf[3]; + colf[1]*= colf[3]; + colf[2]*= colf[3]; + + } + else { + colf[0]= dist*har->r; + colf[1]= dist*har->g; + colf[2]= dist*har->b; + + if(har->type & HA_XALPHA) colf[3]= dist*dist; + else colf[3]= dist; + } + + if(har->mat && har->mat->mode & MA_HALO_SHADE) { + /* we test for lights because of preview... */ + if(R.totlamp) render_lighting_halo(har, colf); + } + + if(linef!=0.0) { + Material *ma= har->mat; + + colf[0]+= 255.0*linef*ma->specr; + colf[1]+= 255.0*linef*ma->specg; + colf[2]+= 255.0*linef*ma->specb; + + if(har->type & HA_XALPHA) colf[3]+= linef*linef; + else colf[3]+= linef; + } + if(ringf!=0.0) { + Material *ma= har->mat; + + colf[0]+= 255.0*ringf*ma->mirr; + colf[1]+= 255.0*ringf*ma->mirg; + colf[2]+= 255.0*ringf*ma->mirb; + + if(har->type & HA_XALPHA) colf[3]+= ringf*ringf; + else colf[3]+= ringf; + } + + colt= 255.0*colf[3]; + if(colt>254) col[3]= 255; else col[3]= colt; + + colt= colf[2]; + if(colt>254) col[2]= 255; else col[2]= colt; + + colt= colf[1]; + if(colt>254) col[1]= 255; else col[1]= colt; + + colt= colf[0]; + if(colt>254) col[0]= 255; else col[0]= colt; + +} + + +unsigned int calchalo_z(HaloRen *har, unsigned int zz) +{ + + if(har->type & HA_ONLYSKY) { + if(zz!=0x7FFFFFFF) zz= 0; + } + else { + zz= (zz>>8); + if(zz<0x800000) zz= (zz+0x7FFFFF); + else zz= (zz-0x800000); + } + return zz; +} + +void scanlinehaloPS(unsigned int *rectz, long *rectdelta, unsigned int *rectt, short ys) +{ + HaloRen *har = NULL; + PixStr *ps; + float dist,xsq,ysq,xn,yn; + unsigned int a, *rz, *rt, zz; + long *rd; + int accol[4]; + short minx,maxx,x,aantal, aantalm, behind, flarec; + char col[4]; + + for(a=0;a>8]; + else har++; + + if(RE_local_test_break()) break; + + if(ys>har->maxy); + else if(ysminy); + else { + minx= floor(har->xs-har->rad); + maxx= ceil(har->xs+har->rad); + + if(maxx<0); + else if(R.rectx=R.rectx) maxx= R.rectx-1; + + rt= rectt+minx; + rd= rectdelta+minx; + rz= rectz+minx; + + yn= (ys-har->ys)*R.ycor; + ysq= yn*yn; + for(x=minx; x<=maxx; x++) { + + flarec= har->flarec; /* har->pixels mag maar 1 x geteld worden */ + + if( IS_A_POINTER_CODE(*rd)) { + xn= x-har->xs; + xsq= xn*xn; + dist= xsq+ysq; + if(distradsq) { + ps= (PixStr *) POINTER_FROM_CODE(*rd); + aantal= behind= 0; + accol[0]=accol[1]=accol[2]=accol[3]= 0; + while(ps) { + aantalm= count_mask(ps->mask); + aantal+= aantalm; + + zz= calchalo_z(har, ps->z); + if(zz> har->zs) { + *( (int *)col )= 0; + RE_shadehalo(har, col, zz, dist, xn, yn, flarec); + accol[0]+= aantalm*col[0]; + accol[1]+= aantalm*col[1]; + accol[2]+= aantalm*col[2]; + accol[3]+= aantalm*col[3]; + flarec= 0; + } + + ps= ps->next; + } + ps= (PixStr *) POINTER_FROM_CODE(*rd); + aantal= R.osa-aantal; + + zz= calchalo_z(har, *rz); + if(zz> har->zs) { + *( (int *)col )= 0; + RE_shadehalo(har, col, zz, dist, xn, yn, flarec); + accol[0]+= aantal*col[0]; + accol[1]+= aantal*col[1]; + accol[2]+= aantal*col[2]; + accol[3]+= aantal*col[3]; + } + + + col[0]= accol[0]/R.osa; + col[1]= accol[1]/R.osa; + col[2]= accol[2]/R.osa; + col[3]= accol[3]/R.osa; + + /* if(behind > (R.osa>>1)) addalphaUnder(rt,col); */ + RE_addalphaAddfac((char *)rt, (char *)col, har->add); + } + } + else { + zz= calchalo_z(har, *rz); + if(zz> har->zs) { + xn= x- har->xs; + xsq= xn*xn; + dist= xsq+ysq; + if(distradsq) { + RE_shadehalo(har, col, zz, dist, xn, yn, flarec); + RE_addalphaAddfac((char *)rt, (char *)col, har->add); + } + } + } + rt++; + rz++; + rd++; + } + + } + } + } + +} + +void scanlinehalo(unsigned int *rectz, unsigned int *rectt, short ys) +{ + HaloRen *har = NULL; + float dist,xsq,ysq,xn,yn; + unsigned int a, *rz, *rt, zz; + short minx,maxx, x; + char col[4]; + + for(a=0; a>8]; + else har++; + + if(RE_local_test_break()) break; + + if(ys>har->maxy); + else if(ysminy); + else { + minx= floor(har->xs-har->rad); + maxx= ceil(har->xs+har->rad); + + if(maxx<0); + else if(R.rectx=R.rectx) maxx= R.rectx-1; + + rt= rectt+minx; + rz= rectz+minx; + + yn= (ys-har->ys)*R.ycor; + ysq= yn*yn; + for(x=minx; x<=maxx; x++) { + + zz= calchalo_z(har, *rz); + if(zz> har->zs) { + xn= x- har->xs; + xsq= xn*xn; + dist= xsq+ysq; + if(distradsq) { + RE_shadehalo(har, col, zz, dist, xn, yn, har->flarec); + RE_addalphaAddfac((char *)rt, (char *)col, har->add); + } + } + + rt++; + rz++; + } + } + } + } + +} + +void halovert() +{ + HaloRen *har = NULL; + float dist, xsq, ysq, xn, yn; + unsigned int a, *rectz, *rz, *rectt, *rt, zz; + int minx, maxx, miny, maxy, x, y; + char col[4]; + + + for(a=0;a>8]; + else har++; + + if(RE_local_test_break()) break; + + if(har->maxy<0); + else if(R.rectyminy); + else { + minx= floor(har->xs-har->rad); + maxx= ceil(har->xs+har->rad); + + if(maxx<0); + else if(R.rectxys-har->rad); + maxy= ceil(har->ys+har->rad); + + if(minx<0) minx= 0; + if(maxx>=R.rectx) maxx= R.rectx-1; + if(miny<0) miny= 0; + if(maxy>R.recty) maxy= R.recty; + + rectt= R.rectot+ R.rectx*miny; + rectz= R.rectz+ R.rectx*miny; + + for(y=miny;yys)*R.ycor; + ysq= yn*yn; + for(x=minx;x<=maxx;x++) { + + zz= calchalo_z(har, *rz); + + if(zz> har->zs) { + + xn= x - har->xs; + xsq= xn*xn; + dist= xsq+ysq; + if(distradsq) { + RE_shadehalo(har, col, zz, dist, xn, yn, har->flarec); + + RE_addalphaAddfac((char *)rt, (char *)col, har->add); + + } + } + rt++; + rz++; + } + + rectt+= R.rectx; + rectz+= R.rectx; + + if(RE_local_test_break()) break; + } + + } + } + } +} + +float RE_Spec(float inp, int hard) +{ + float b1; + + if(inp>=1.0) return 1.0; + else if (inp<=0.0) return 0.0; + + b1= inp*inp; + /* avoid FPE */ + if(b1<0.01) b1= 0.01; + + if((hard & 1)==0) inp= 1.0; + if(hard & 2) inp*= b1; + b1*= b1; + if(hard & 4) inp*= b1; + b1*= b1; + if(hard & 8) inp*= b1; + b1*= b1; + if(hard & 16) inp*= b1; + b1*= b1; + + /* avoid FPE */ + if(b1<0.001) b1= 0.0; + + if(hard & 32) inp*= b1; + b1*= b1; + if(hard & 64) inp*=b1; + + if(hard & 128) { + b1*= b1; + inp*=b1; + } + + return inp; +} + + +float CookTorr(float *n, float *l, float *v, int hard) +{ + float i, nh, nv, h[3]; + + h[0]= v[0]+l[0]; + h[1]= v[1]+l[1]; + h[2]= v[2]+l[2]; + Normalise(h); + + nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; + if(nh<0.0) return 0.0; + nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; + if(nv<0.0) nv= 0.0; + i= RE_Spec(nh, hard); + + i= i/(0.1+nv); + return i; +} + +void RE_calc_R_ref() +{ + float i; + + /* R.vn dot R.view */ + i= -2*(R.vn[0]*R.view[0]+R.vn[1]*R.view[1]+R.vn[2]*R.view[2]); + + R.ref[0]= (R.view[0]+i*R.vn[0]); + R.ref[1]= (R.view[1]+i*R.vn[1]); + R.ref[2]= (R.view[2]+i*R.vn[2]); + if(R.osatex) { + if(R.vlr->flag & R_SMOOTH) { + i= -2*( (R.vn[0]+O.dxno[0])*(R.view[0]+O.dxview) + + (R.vn[1]+O.dxno[1])*R.view[1]+ (R.vn[2]+O.dxno[2])*R.view[2] ); + + O.dxref[0]= R.ref[0]- ( R.view[0]+O.dxview+i*(R.vn[0]+O.dxno[0])); + O.dxref[1]= R.ref[1]- (R.view[1]+ i*(R.vn[1]+O.dxno[1])); + O.dxref[2]= R.ref[2]- (R.view[2]+ i*(R.vn[2]+O.dxno[2])); + + i= -2*( (R.vn[0]+O.dyno[0])*R.view[0]+ + (R.vn[1]+O.dyno[1])*(R.view[1]+O.dyview)+ (R.vn[2]+O.dyno[2])*R.view[2] ); + + O.dyref[0]= R.ref[0]- (R.view[0]+ i*(R.vn[0]+O.dyno[0])); + O.dyref[1]= R.ref[1]- (R.view[1]+O.dyview+i*(R.vn[1]+O.dyno[1])); + O.dyref[2]= R.ref[2]- (R.view[2]+ i*(R.vn[2]+O.dyno[2])); + + } + else { + + i= -2*( R.vn[0]*(R.view[0]+O.dxview) + + R.vn[1]*R.view[1]+ R.vn[2]*R.view[2] ); + + O.dxref[0]= R.ref[0]- (R.view[0]+O.dxview+i*R.vn[0]); + O.dxref[1]= R.ref[1]- (R.view[1]+ i*R.vn[1]); + O.dxref[2]= R.ref[2]- (R.view[2]+ i*R.vn[2]); + + i= -2*( R.vn[0]*R.view[0]+ + R.vn[1]*(R.view[1]+O.dyview)+ R.vn[2]*R.view[2] ); + + O.dyref[0]= R.ref[0]- (R.view[0]+ i*R.vn[0]); + O.dyref[1]= R.ref[1]- (R.view[1]+O.dyview+i*R.vn[1]); + O.dyref[2]= R.ref[2]- (R.view[2]+ i*R.vn[2]); + } + } + +} + +void shadelamplus() +{ + LampRen *lar; + Material *ma; + float i, inp, inpr, t, lv[3], lampdist, ld = 0, ir, ig, ib, isr=0,isg=0,isb=0; + float lvrot[3], *vn, *view, shadfac, soft; + int a; + + vn= R.vn; + view= R.view; + ma= R.matren; + + /* aparte lus */ + if(ma->mode & MA_ONLYSHADOW) { + shadfac= ir= 0.0; + for(a=0; amode & LA_LAYER) if((lar->lay & R.vlr->lay)==0) continue; + + if(lar->shb) { + /* alleen testen binnen spotbundel */ + lv[0]= R.co[0]-lar->co[0]; + lv[1]= R.co[1]-lar->co[1]; + lv[2]= R.co[2]-lar->co[2]; + Normalise(lv); + inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]; + if(inpr>lar->spotsi) { + + inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]; + + i = testshadowbuf(lar->shb, inp); + + t= inpr - lar->spotsi; + if(tspotbl && lar->spotbl!=0.0) { + t/= lar->spotbl; + t*= t; + i= t*i+(1.0-t); + } + + shadfac+= i; + ir+= 1.0; + } + else { + shadfac+= 1.0; + ir+= 1.0; + } + } + } + if(ir>0.0) shadfac/= ir; + ma->alpha= (R.mat->alpha)*(1.0-shadfac); + + shortcol[0]=shortcol[1]=shortcol[2]= 0; + + return; + } + + if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) { + ma->r= R.vcol[0]; + ma->g= R.vcol[1]; + ma->b= R.vcol[2]; + } + + /* mirror reflection colour */ + R.refcol[0]= R.refcol[1]= R.refcol[2]= R.refcol[3]= 0.0; + + if(ma->texco) { + + if(ma->texco & TEXCO_REFL) { + RE_calc_R_ref(); + } + + if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) { + R.mat->r= R.vcol[0]; + R.mat->g= R.vcol[1]; + R.mat->b= R.vcol[2]; + } + + do_material_tex(); + } + + if(ma->mode & MA_SHLESS) { + if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP+MA_FACETEXTURE) )) { + ir= R.vcol[0]*ma->r; + ig= R.vcol[1]*ma->g; + ib= R.vcol[2]*ma->b; + } + else { + ir= ma->r; + ig= ma->g; + ib= ma->b; + } + + if(usegamtab) { + a= 65535*ir; + if(a<0) a=0; else if(a>65535) a= 65535; + shortcol[0]= igamtab2[a]; + a= 65535*ig; + if(a<0) a=0; else if(a>65535) a= 65535; + shortcol[1]= igamtab2[a]; + a= 65535*ib; + if(a<0) a=0; else if(a>65535) a= 65535; + shortcol[2]= igamtab2[a]; + } + else { + a= 65535*ir; + if(a<0) shortcol[0]= 0; else if(a>65535) shortcol[0]= 65535; else shortcol[0]= a; + a= 65535*ig; + if(a<0) shortcol[1]= 0; else if(a>65535) shortcol[1]= 65535; else shortcol[1]= a; + a= 65535*ib; + if(a<0) shortcol[2]= 0; else if(a>65535) shortcol[2]= 65535; else shortcol[2]= a; + } + return; + } + + if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) { + ir= ma->emit+R.vcol[0]; + ig= ma->emit+R.vcol[1]; + ib= ma->emit+R.vcol[2]; + } + else ir= ig= ib= ma->emit; + + for(a=0; amode & LA_LAYER) if((lar->lay & R.vlr->lay)==0) continue; + + /* lampdist berekening */ + if(lar->type==LA_SUN || lar->type==LA_HEMI) { + VECCOPY(lv, lar->vec); + lampdist= 1.0; + } + else { + lv[0]= R.co[0]-lar->co[0]; + lv[1]= R.co[1]-lar->co[1]; + lv[2]= R.co[2]-lar->co[2]; + ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]); + lv[0]/= ld; + lv[1]/= ld; + lv[2]/= ld; + + /* ld wordt verderop nog gebruikt (texco's) */ + + if(lar->mode & LA_QUAD) { + t= 1.0; + if(lar->ld1>0.0) + t= lar->dist/(lar->dist+lar->ld1*ld); + if(lar->ld2>0.0) + t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld); + + lampdist= t; + } + else { + lampdist= (lar->dist/(lar->dist+ld)); + } + + if(lar->mode & LA_SPHERE) { + t= lar->dist - ld; + if(t<0.0) continue; + + t/= lar->dist; + lampdist*= (t); + } + + } + + if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv); + + if(lar->type==LA_SPOT) { + + /* hier de fie Inp() vertaagt! */ + + if(lar->mode & LA_SQUARE) { + if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) { + float x; + + /* rotate view to lampspace */ + VECCOPY(lvrot, lv); + MTC_Mat3MulVecfl(lar->imat, lvrot); + + x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2])); + /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */ + + inpr= 1.0/(sqrt(1+x*x)); + } + else inpr= 0.0; + } + else { + inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]; + } + + t= lar->spotsi; + if(inprspotbl && lar->spotbl!=0.0) { + /* zachte gebied */ + i= t/lar->spotbl; + t= i*i; + soft= (3.0*t-2.0*t*i); + inpr*= soft; + } + if(lar->mode & LA_ONLYSHADOW && lar->shb) { + if(ma->mode & MA_SHADOW) { + /* inprodukt positief: voorzijde vlak! */ + inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]; + if(inp>0.0) { + /* testshadowbuf==0.0 : 100% schaduw */ + shadfac = 1.0 - testshadowbuf(lar->shb, inp); + if(shadfac>0.0) { + shadfac*= inp*soft*lar->energy; + ir -= shadfac; + ig -= shadfac; + ib -= shadfac; + + continue; + } + } + } + } + lampdist*=inpr; + } + if(lar->mode & LA_ONLYSHADOW) continue; + + if(lar->mode & LA_OSATEX) { + R.osatex= 1; /* signaal voor multitex() */ + + O.dxlv[0]= lv[0] - (R.co[0]-lar->co[0]+O.dxco[0])/ld; + O.dxlv[1]= lv[1] - (R.co[1]-lar->co[1]+O.dxco[1])/ld; + O.dxlv[2]= lv[2] - (R.co[2]-lar->co[2]+O.dxco[2])/ld; + + O.dylv[0]= lv[0] - (R.co[0]-lar->co[0]+O.dyco[0])/ld; + O.dylv[1]= lv[1] - (R.co[1]-lar->co[1]+O.dyco[1])/ld; + O.dylv[2]= lv[2] - (R.co[2]-lar->co[2]+O.dyco[2])/ld; + } + + } + + /* inprodukt en reflectivity*/ + inp=i= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]; + if(lar->type==LA_HEMI) { + i= 0.5*i+0.5; + } + if(i>0.0) { + i*= lampdist*ma->ref; + } + + /* schaduw en spec */ + if(i> -0.41) { /* beetje willekeurig, beetje getest */ + shadfac= 1.0; + if(lar->shb) { + if(ma->mode & MA_SHADOW) { + shadfac = testshadowbuf(lar->shb, inp); + if(shadfac==0.0) continue; + i*= shadfac; + } + } + /* specularity */ + + if(ma->spec!=0.0) { + + if(lar->type==LA_SUN || lar->type==LA_HEMI) { + if(lar->type==LA_SUN) { + lv[2]-= 1.0; + } + else { + lv[0]+= view[0]; + lv[1]+= view[1]; + lv[2]+= view[2]; + } + + Normalise(lv); + + t= vn[0]*lv[0]+vn[1]*lv[1]+vn[2]*lv[2]; + + if(lar->type==LA_HEMI) { + t= 0.5*t+0.5; + } + /* let op: shadfac en lampdist uit onderstaande */ + + /* no more speclim */ + + t= ma->spec*RE_Spec(t, ma->har); + isr+= t*(lar->r * ma->specr); + isg+= t*(lar->g * ma->specg); + isb+= t*(lar->b * ma->specb); + } + else { + t= shadfac*ma->spec*lampdist*CookTorr(vn, lv, view, ma->har); + isr+= t*(lar->r * ma->specr); + isg+= t*(lar->g * ma->specg); + isb+= t*(lar->b * ma->specb); + } + } + } + if(i>0.0) { + ir+= i*lar->r; + ig+= i*lar->g; + ib+= i*lar->b; + } + } + + if(ir<0.0) ir= 0.0; + if(ig<0.0) ig= 0.0; + if(ib<0.0) ib= 0.0; + if(isr<0.0) isr= 0.0; + if(isg<0.0) isg= 0.0; + if(isb<0.0) isb= 0.0; + + if(ma->mode & MA_ZTRA) { /* ztra shade */ + if(ma->spectra!=0.0) { + + t = MAX3(isr, isb, isg); + t *= ma->spectra; + if(t>1.0) t= 1.0; + if(ma->mapto & MAP_ALPHA) ma->alpha= (1.0-t)*ma->alpha+t; + else ma->alpha= (1.0-t)*R.mat->alpha+t; + } + } + + if(R.refcol[0]==0.0) { + a= 65535.0*( ma->r*ir +ma->ambr +isr); + if(a>65535) a=65535; else if(a<0) a= 0; + shortcol[0]= a; + a= 65535.0*(ma->g*ig +ma->ambg +isg); + if(a>65535) a=65535; else if(a<0) a= 0; + shortcol[1]= a; + a= 65535*(ma->b*ib +ma->ambb +isb); + if(a>65535) a=65535; else if(a<0) a= 0; + shortcol[2]= a; + } + else { + a= 65535.0*( ma->mirr*R.refcol[1] + (1.0 - ma->mirr*R.refcol[0])*(ma->r*ir +ma->ambr) +isr); + if(a>65535) a=65535; else if(a<0) a= 0; + shortcol[0]= a; + a= 65535.0*( ma->mirg*R.refcol[2] + (1.0 - ma->mirg*R.refcol[0])*(ma->g*ig +ma->ambg) +isg); + if(a>65535) a=65535; else if(a<0) a= 0; + shortcol[1]= a; + a= 65535.0*( ma->mirb*R.refcol[3] + (1.0 - ma->mirb*R.refcol[0])*(ma->b*ib +ma->ambb) +isb); + if(a>65535) a=65535; else if(a<0) a= 0; + shortcol[2]= a; + } + + if(usegamtab) { + shortcol[0]= igamtab2[ shortcol[0] ]; + shortcol[1]= igamtab2[ shortcol[1] ]; + shortcol[2]= igamtab2[ shortcol[2] ]; + } +} + + +void shadepixel(float x, float y, int vlaknr) + /* x,y: windowcoordinaat van 0 tot rectx,y */ +{ + static VlakRen *vlr; + static VertRen *v1, *v2, *v3; + static float t00, t01, t10, t11, dvlak, n1[3], n2[3], n3[3]; + static float s00, s01, s10, s11; + float *o1, *o2, *o3; + float u, v, l, dl, hox, hoy, detsh, fac, deler, alpha; + char *cp1, *cp2, *cp3; + + if(R.vlaknr== -1) { /* doet initrender */ + vlr= R.vlr= 0; + } + + if(vlaknr<=0) { /* sky */ + R.vlaknr= 0; + shortcol[3]= 0; + } + else if( (vlaknr & 0x7FFFFF) <= R.totvlak) { + + if(vlaknr!=R.vlaknr) { + vlr= RE_findOrAddVlak( (vlaknr-1) & 0x7FFFFF); + + R.mat= vlr->mat; + R.matren= R.mat->ren; + + if(R.matren==0) { /* tijdelijk voor debug */ + shortcol[3]= 65535; + shortcol[2]= 0; + shortcol[1]= 65535; + shortcol[0]= 65535; + return; + } + + R.vlr= vlr; + + R.vno= vlr->n; + R.osatex= (R.matren->texco & TEXCO_OSA); + R.vlaknr= vlaknr; + + v1= vlr->v1; + dvlak= v1->co[0]*vlr->n[0]+v1->co[1]*vlr->n[1]+v1->co[2]*vlr->n[2]; + + if( (vlr->flag & R_SMOOTH) || (R.matren->texco & NEED_UV)) { /* uv nodig */ + if(vlaknr & 0x800000) { + v2= vlr->v3; + v3= vlr->v4; + } + else { + v2= vlr->v2; + v3= vlr->v3; + } + + if(vlr->snproj==0) { + t00= v3->co[0]-v1->co[0]; t01= v3->co[1]-v1->co[1]; + t10= v3->co[0]-v2->co[0]; t11= v3->co[1]-v2->co[1]; + } + else if(vlr->snproj==1) { + t00= v3->co[0]-v1->co[0]; t01= v3->co[2]-v1->co[2]; + t10= v3->co[0]-v2->co[0]; t11= v3->co[2]-v2->co[2]; + } + else { + t00= v3->co[1]-v1->co[1]; t01= v3->co[2]-v1->co[2]; + t10= v3->co[1]-v2->co[1]; t11= v3->co[2]-v2->co[2]; + } + + detsh= t00*t11-t10*t01; + t00/= detsh; t01/=detsh; + t10/=detsh; t11/=detsh; + + if(vlr->flag & R_SMOOTH) { /* puno's goedzetten */ + if(vlr->puno & ME_FLIPV1) { + n1[0]= -v1->n[0]; n1[1]= -v1->n[1]; n1[2]= -v1->n[2]; + } else { + n1[0]= v1->n[0]; n1[1]= v1->n[1]; n1[2]= v1->n[2]; + } + if(vlaknr & 0x800000) { + if(vlr->puno & ME_FLIPV3) { + n2[0]= -v2->n[0]; n2[1]= -v2->n[1]; n2[2]= -v2->n[2]; + } else { + n2[0]= v2->n[0]; n2[1]= v2->n[1]; n2[2]= v2->n[2]; + } + + if(vlr->puno & ME_FLIPV4) { + n3[0]= -v3->n[0]; n3[1]= -v3->n[1]; n3[2]= -v3->n[2]; + } else { + n3[0]= v3->n[0]; n3[1]= v3->n[1]; n3[2]= v3->n[2]; + } + + } + else { + if(vlr->puno & ME_FLIPV2) { + n2[0]= -v2->n[0]; n2[1]= -v2->n[1]; n2[2]= -v2->n[2]; + } else { + n2[0]= v2->n[0]; n2[1]= v2->n[1]; n2[2]= v2->n[2]; + } + + if(vlr->puno & ME_FLIPV3) { + n3[0]= -v3->n[0]; n3[1]= -v3->n[1]; n3[2]= -v3->n[2]; + } else { + n3[0]= v3->n[0]; n3[1]= v3->n[1]; n3[2]= v3->n[2]; + } + } + } + if(R.matren->texco & TEXCO_STICKY) { + s00= v3->ho[0]/v3->ho[3] - v1->ho[0]/v1->ho[3]; + s01= v3->ho[1]/v3->ho[3] - v1->ho[1]/v1->ho[3]; + s10= v3->ho[0]/v3->ho[3] - v2->ho[0]/v2->ho[3]; + s11= v3->ho[1]/v3->ho[3] - v2->ho[1]/v2->ho[3]; + + detsh= s00*s11-s10*s01; + s00/= detsh; s01/=detsh; + s10/=detsh; s11/=detsh; + } + } + } + + /* COXYZ nieuwe methode */ + if( (G.special1 & G_HOLO) && ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) { + R.view[0]= (x+(R.xstart)+1.0+holoofs); + } + else { + R.view[0]= (x+(R.xstart)+1.0); + } + + if(R.flag & R_SEC_FIELD) { + if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor; + else R.view[1]= (y+R.ystart+1.5)*R.ycor; + } + else R.view[1]= (y+R.ystart+1.0)*R.ycor; + + R.view[2]= -R.viewfac; + + if(R.r.mode & R_PANORAMA) { + float panoco, panosi; + panoco = getPanovCo(); + panosi = getPanovSi(); + + u= R.view[0]; v= R.view[2]; + R.view[0]= panoco*u + panosi*v; + R.view[2]= -panosi*u + panoco*v; + } + + deler= vlr->n[0]*R.view[0] + vlr->n[1]*R.view[1] + vlr->n[2]*R.view[2]; + if (deler!=0.0) fac= R.zcor= dvlak/deler; + else fac= R.zcor= 0.0; + + R.co[0]= fac*R.view[0]; + R.co[1]= fac*R.view[1]; + R.co[2]= fac*R.view[2]; + + if(R.osatex || (R.r.mode & R_SHADOW) ) { + u= dvlak/(deler-vlr->n[0]); + v= dvlak/(deler- R.ycor*vlr->n[1]); + + O.dxco[0]= R.co[0]- (R.view[0]-1.0)*u; + O.dxco[1]= R.co[1]- (R.view[1])*u; + O.dxco[2]= R.co[2]- (R.view[2])*u; + + O.dyco[0]= R.co[0]- (R.view[0])*v; + O.dyco[1]= R.co[1]- (R.view[1]-1.0*R.ycor)*v; + O.dyco[2]= R.co[2]- (R.view[2])*v; + + } + + fac= Normalise(R.view); + R.zcor*= fac; /* voor mist */ + + if(R.osatex) { + if( (R.matren->texco & TEXCO_REFL) ) { + O.dxview= 1.0/fac; + O.dyview= R.ycor/fac; + } + } + + /* UV en TEX*/ + if( (vlr->flag & R_SMOOTH) || (R.matren->texco & NEED_UV)) { + if(vlr->snproj==0) { + u= (R.co[0]-v3->co[0])*t11-(R.co[1]-v3->co[1])*t10; + v= (R.co[1]-v3->co[1])*t00-(R.co[0]-v3->co[0])*t01; + if(R.osatex) { + O.dxuv[0]= O.dxco[0]*t11- O.dxco[1]*t10; + O.dxuv[1]= O.dxco[1]*t00- O.dxco[0]*t01; + O.dyuv[0]= O.dyco[0]*t11- O.dyco[1]*t10; + O.dyuv[1]= O.dyco[1]*t00- O.dyco[0]*t01; + } + } + else if(vlr->snproj==1) { + u= (R.co[0]-v3->co[0])*t11-(R.co[2]-v3->co[2])*t10; + v= (R.co[2]-v3->co[2])*t00-(R.co[0]-v3->co[0])*t01; + if(R.osatex) { + O.dxuv[0]= O.dxco[0]*t11- O.dxco[2]*t10; + O.dxuv[1]= O.dxco[2]*t00- O.dxco[0]*t01; + O.dyuv[0]= O.dyco[0]*t11- O.dyco[2]*t10; + O.dyuv[1]= O.dyco[2]*t00- O.dyco[0]*t01; + } + } + else { + u= (R.co[1]-v3->co[1])*t11-(R.co[2]-v3->co[2])*t10; + v= (R.co[2]-v3->co[2])*t00-(R.co[1]-v3->co[1])*t01; + if(R.osatex) { + O.dxuv[0]= O.dxco[1]*t11- O.dxco[2]*t10; + O.dxuv[1]= O.dxco[2]*t00- O.dxco[1]*t01; + O.dyuv[0]= O.dyco[1]*t11- O.dyco[2]*t10; + O.dyuv[1]= O.dyco[2]*t00- O.dyco[1]*t01; + } + } + l= 1.0+u+v; + + if(vlr->flag & R_SMOOTH) { + R.vn[0]= l*n3[0]-u*n1[0]-v*n2[0]; + R.vn[1]= l*n3[1]-u*n1[1]-v*n2[1]; + R.vn[2]= l*n3[2]-u*n1[2]-v*n2[2]; + + Normalise(R.vn); + if(R.osatex && (R.matren->texco & (TEXCO_NORM+TEXCO_REFL)) ) { + dl= O.dxuv[0]+O.dxuv[1]; + O.dxno[0]= dl*n3[0]-O.dxuv[0]*n1[0]-O.dxuv[1]*n2[0]; + O.dxno[1]= dl*n3[1]-O.dxuv[0]*n1[1]-O.dxuv[1]*n2[1]; + O.dxno[2]= dl*n3[2]-O.dxuv[0]*n1[2]-O.dxuv[1]*n2[2]; + dl= O.dyuv[0]+O.dyuv[1]; + O.dyno[0]= dl*n3[0]-O.dyuv[0]*n1[0]-O.dyuv[1]*n2[0]; + O.dyno[1]= dl*n3[1]-O.dyuv[0]*n1[1]-O.dyuv[1]*n2[1]; + O.dyno[2]= dl*n3[2]-O.dyuv[0]*n1[2]-O.dyuv[1]*n2[2]; + + } + } + else { + VECCOPY(R.vn, vlr->n); + } + + if(R.matren->mode & MA_ZINV) { /* z invert */ + /* R.vn[0]= -R.vn[0]; */ + /* R.vn[1]= -R.vn[1]; */ + } + + if(R.matren->texco & TEXCO_ORCO) { + if(v2->orco) { + o1= v1->orco; + o2= v2->orco; + o3= v3->orco; + + R.lo[0]= l*o3[0]-u*o1[0]-v*o2[0]; + R.lo[1]= l*o3[1]-u*o1[1]-v*o2[1]; + R.lo[2]= l*o3[2]-u*o1[2]-v*o2[2]; + + if(R.osatex) { + dl= O.dxuv[0]+O.dxuv[1]; + O.dxlo[0]= dl*o3[0]-O.dxuv[0]*o1[0]-O.dxuv[1]*o2[0]; + O.dxlo[1]= dl*o3[1]-O.dxuv[0]*o1[1]-O.dxuv[1]*o2[1]; + O.dxlo[2]= dl*o3[2]-O.dxuv[0]*o1[2]-O.dxuv[1]*o2[2]; + dl= O.dyuv[0]+O.dyuv[1]; + O.dylo[0]= dl*o3[0]-O.dyuv[0]*o1[0]-O.dyuv[1]*o2[0]; + O.dylo[1]= dl*o3[1]-O.dyuv[0]*o1[1]-O.dyuv[1]*o2[1]; + O.dylo[2]= dl*o3[2]-O.dyuv[0]*o1[2]-O.dyuv[1]*o2[2]; + } + } + } + + if(R.matren->texco & TEXCO_GLOB) { + VECCOPY(R.gl, R.co); + MTC_Mat4MulVecfl(R.viewinv, R.gl); + if(R.osatex) { + VECCOPY(O.dxgl, O.dxco); + MTC_Mat3MulVecfl(R.imat, O.dxco); + VECCOPY(O.dygl, O.dyco); + MTC_Mat3MulVecfl(R.imat, O.dyco); + } + } + if((R.matren->texco & TEXCO_UV) || (R.matren->mode & (MA_VERTEXCOL|MA_FACETEXTURE))) { + if(R.vlr->tface) { + float *uv1, *uv2, *uv3; + + uv1= R.vlr->tface->uv[0]; + if( (vlaknr & 0x800000) || (R.vlr->flag & R_FACE_SPLIT) ) { + uv2= R.vlr->tface->uv[2]; + uv3= R.vlr->tface->uv[3]; + } + else { + uv2= R.vlr->tface->uv[1]; + uv3= R.vlr->tface->uv[2]; + } + + R.uv[0]= -1.0 + 2.0*(l*uv3[0]-u*uv1[0]-v*uv2[0]); + R.uv[1]= -1.0 + 2.0*(l*uv3[1]-u*uv1[1]-v*uv2[1]); + + if(R.osatex) { + float duv[2]; + + dl= O.dxuv[0]+O.dxuv[1]; + duv[0]= O.dxuv[0]; + duv[1]= O.dxuv[1]; + + O.dxuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]); + O.dxuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]); + + dl= O.dyuv[0]+O.dyuv[1]; + duv[0]= O.dyuv[0]; + duv[1]= O.dyuv[1]; + + O.dyuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]); + O.dyuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]); + } + + } + else { + R.uv[0]= 2.0*(u+.5); + R.uv[1]= 2.0*(v+.5); + } + } + if(R.matren->texco & TEXCO_NORM) { + R.orn[0]= R.vn[0]; + R.orn[1]= -R.vn[1]; + R.orn[2]= R.vn[2]; + } + if(R.matren->mode & MA_VERTEXCOL) { + cp1= (char *)vlr->vcol; + if(cp1) { + if( (vlaknr & 0x800000) || (R.vlr->flag & R_FACE_SPLIT) ) { + cp2= (char *)(vlr->vcol+2); + cp3= (char *)(vlr->vcol+3); + } + else { + cp2= (char *)(vlr->vcol+1); + cp3= (char *)(vlr->vcol+2); + } + R.vcol[0]= (l*cp3[3]-u*cp1[3]-v*cp2[3])/255.0; + R.vcol[1]= (l*cp3[2]-u*cp1[2]-v*cp2[2])/255.0; + R.vcol[2]= (l*cp3[1]-u*cp1[1]-v*cp2[1])/255.0; + + } + else { + R.vcol[0]= 0.0; + R.vcol[1]= 0.0; + R.vcol[2]= 0.0; + } + } + if(R.matren->mode & MA_FACETEXTURE) { + if((R.matren->mode & MA_VERTEXCOL)==0) { + R.vcol[0]= 1.0; + R.vcol[1]= 1.0; + R.vcol[2]= 1.0; + } + if(vlr->tface) render_realtime_texture(); + } + + + /* hierna klopt de u en v EN O.dxuv en O.dyuv niet meer */ + if(R.matren->texco & TEXCO_STICKY) { + if(v2->sticky) { + + /* opnieuw u en v berekenen */ + hox= x/Zmulx -1.0; + hoy= y/Zmuly -1.0; + u= (hox - v3->ho[0]/v3->ho[3])*s11 - (hoy - v3->ho[1]/v3->ho[3])*s10; + v= (hoy - v3->ho[1]/v3->ho[3])*s00 - (hox - v3->ho[0]/v3->ho[3])*s01; + l= 1.0+u+v; + + o1= v1->sticky; + o2= v2->sticky; + o3= v3->sticky; + + R.sticky[0]= l*o3[0]-u*o1[0]-v*o2[0]; + R.sticky[1]= l*o3[1]-u*o1[1]-v*o2[1]; + + if(R.osatex) { + O.dxuv[0]= s11/Zmulx; + O.dxuv[1]= - s01/Zmulx; + O.dyuv[0]= - s10/Zmuly; + O.dyuv[1]= s00/Zmuly; + + dl= O.dxuv[0]+O.dxuv[1]; + O.dxsticky[0]= dl*o3[0]-O.dxuv[0]*o1[0]-O.dxuv[1]*o2[0]; + O.dxsticky[1]= dl*o3[1]-O.dxuv[0]*o1[1]-O.dxuv[1]*o2[1]; + dl= O.dyuv[0]+O.dyuv[1]; + O.dysticky[0]= dl*o3[0]-O.dyuv[0]*o1[0]-O.dyuv[1]*o2[0]; + O.dysticky[1]= dl*o3[1]-O.dyuv[0]*o1[1]-O.dyuv[1]*o2[1]; + } + } + } + } + else { + VECCOPY(R.vn, vlr->n); + } + if(R.matren->texco & TEXCO_WINDOW) { + R.winco[0]= (x+(R.xstart))/(float)R.afmx; + R.winco[1]= (y+(R.ystart))/(float)R.afmy; + } + + + shadelamplus(); + + /* MIST */ + if( (R.wrld.mode & WO_MIST) && (R.matren->mode & MA_NOMIST)==0 ){ + alpha= mistfactor(R.co); + } + else alpha= 1.0; + + /* RAYTRACE (tijdelijk?) UITGESCHAKELD */ + + if(R.matren->alpha!=1.0 || alpha!=1.0) { + fac= alpha*(R.matren->alpha); + + /* gamma */ + if(R.osa && usegamtab) fac*= fac; + + shortcol[3]= 65535.0*fac; + shortcol[0]*= fac; + shortcol[1]*= fac; + shortcol[2]*= fac; + } + else { + shortcol[3]= 65535; + } + } + else { + shortcol[0]= 65535; + shortcol[1]= 65535; + shortcol[2]= 0; + shortcol[3]= 65535; + } + + if(R.flag & R_LAMPHALO) { + if(vlaknr<=0) { /* bereken viewvec en zet R.co op far */ + + if( (G.special1 & G_HOLO) && ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) { + R.view[0]= (x+(R.xstart)+1.0+holoofs); + } + else { + R.view[0]= (x+(R.xstart)+1.0); + } + + if(R.flag & R_SEC_FIELD) { + if(R.r.mode & R_ODDFIELD) R.view[1]= (y+R.ystart+0.5)*R.ycor; + else R.view[1]= (y+R.ystart+1.5)*R.ycor; + } + else R.view[1]= (y+R.ystart+1.0)*R.ycor; + + R.view[2]= -R.viewfac; + + if(R.r.mode & R_PANORAMA) { + float panoco, panosi; + panoco = getPanovCo(); + panosi = getPanovSi(); + + u= R.view[0]; v= R.view[2]; + R.view[0]= panoco*u + panosi*v; + R.view[2]= -panosi*u + panoco*v; + } + + R.co[2]= 0.0; + + } + renderspothalo(shortcol); + } +} + +PixStr *addpsmain() +{ + PixStrMain *psm; + + psm= &psmfirst; + + while(psm->next) { + psm= psm->next; + } + + psm->next= (PixStrMain *)MEM_mallocN(sizeof(PixStrMain),"pixstrMain"); + + psm= psm->next; + psm->next=0; + psm->ps= (PixStr *)MEM_mallocN(4096*sizeof(PixStr),"pixstr"); + psmteller= 0; + + return psm->ps; +} + +void freeps() +{ + PixStrMain *psm,*next; + + psm= &psmfirst; + + while(psm) { + next= psm->next; + if(psm->ps) { + MEM_freeN(psm->ps); + psm->ps= 0; + } + if(psm!= &psmfirst) MEM_freeN(psm); + psm= next; + } + + psmfirst.next= 0; + psmfirst.ps= 0; +} + +void addps(long *rd, int vlak, unsigned int z, short ronde) +{ + static PixStr *prev; + PixStr *ps, *last = NULL; + int vlakand; + + if( IS_A_POINTER_CODE(*rd)) { + ps= (PixStr *) POINTER_FROM_CODE(*rd); + vlakand= (vlak & 0x7FFFFF); + + if( (ps->vlak0 & 0x7FFFFF) == vlakand ) return; + + while(ps) { + if( (ps->vlak & 0x7FFFFF) == vlakand ) { + ps->mask |= (1<next; + } + + if((psmteller & 4095)==0) prev= addpsmain(); + else prev++; + psmteller++; + + last->next= prev; + prev->next= 0; + prev->vlak= vlak; + prev->z= z; + prev->mask = (1<ronde= ronde; + + return; + } + + /* eerste PS maken */ + if((psmteller & 4095)==0) prev= addpsmain(); + else prev++; + psmteller++; + + prev->next= 0; + prev->vlak0= (int) *rd; + prev->vlak= vlak; + prev->z= z; + prev->mask = (1<ronde= ronde; + *rd= POINTER_TO_CODE(prev); +} + + +int count_mask(unsigned short mask) +{ + return (cmask[mask & 255]+cmask[mask>>8]); +} + +float count_maskf(unsigned short mask) +{ + return (fmask[mask & 255]+fmask[mask>>8]); +} + + +void add_filt_mask(unsigned int mask, unsigned short *col, unsigned int *rb1, unsigned int *rb2, unsigned int *rb3) +{ + /* bereken de waarde van mask */ + unsigned int a, maskand, maskshift; + int j; + unsigned short val, r, g, b, al; + + al= col[3]; + r= col[0]; + g= col[1]; + b= col[2]; + + maskand= (mask & 255); + maskshift= (mask >>8); + + for(j=2; j>=0; j--) { + + a= j; + + val= *(mask1[a] +maskand) + *(mask2[a] +maskshift); + if(val) { + rb1[3]+= val*al; + rb1[0]+= val*r; + rb1[1]+= val*g; + rb1[2]+= val*b; + } + a+=3; + + val= *(mask1[a] +maskand) + *(mask2[a] +maskshift); + if(val) { + rb2[3]+= val*al; + rb2[0]+= val*r; + rb2[1]+= val*g; + rb2[2]+= val*b; + } + a+=3; + + val= *(mask1[a] +maskand) + *(mask2[a] +maskshift); + if(val) { + rb3[3]+= val*al; + rb3[0]+= val*r; + rb3[1]+= val*g; + rb3[2]+= val*b; + } + + rb1+= 4; + rb2+= 4; + rb3+= 4; + } +} + +void edge_enhance(void) +{ + /* use zbuffer to define edges, add it to the image */ + int val, y, x, col, *rz, *rz1, *rz2, *rz3; + char *cp; + + /* alle getallen in zbuffer 3 naar rechts shiften */ + rz= (int *)R.rectz; + if(rz==0) return; + + for(y=0; y>= 3; + } + } + + /* eerste order, werkt toch niet goed!: + val= abs(rz1[0]-rz2[1])+ 2*abs(rz1[1]-rz2[1])+ abs(rz1[2]-rz2[1]); + val+= 2*abs(rz2[0]-rz2[1])+ 2*abs(rz1[2]-rz2[1]); + val+= abs(rz3[0]-rz2[1])+ 2*abs(rz3[1]-rz2[1])+ abs(rz3[2]-rz2[1]); + *rz= val; + */ + + rz1= (int *)R.rectz; + rz2= rz1+R.rectx; + rz3= rz2+R.rectx; + rz= (int *)R.rectot+R.rectx; + + if(R.r.mode & R_OSA) { + cp= (char *)(R.rectaccu+R.rectx); + } + else { + cp= (char *)(R.rectot+R.rectx); + } + + /* rz itself does not seem to be used. */ + + for(y=0; y>14; + if(col>255) col= 255; + + if(col>0) { + if(R.r.mode & R_OSA) { + col/= R.osa; + + val= cp[3]+col; + if(val>255) cp[3]= 255; else cp[3]= val; + } + else { + val= cp[0]- col; + if(val<0) cp[0]= 0; else cp[0]= val; + val= cp[1]- col; + if(val<0) cp[1]= 0; else cp[1]= val; + val= cp[2]- col; + if(val<0) cp[2]= 0; else cp[2]= val; + } + } + } + rz++; + rz1+= 2; + rz2+= 2; + rz3+= 2; + cp+= 8; + } + +} + +/* ********************* HOOFDLUSSEN ******************** */ + +extern unsigned short *Acolrow; +/* short zbuffermetdehand(); */ +void zbufshadeDA(void) /* Delta Accum Pixel Struct */ +{ + PixStr *ps; + float xd, yd, xs, ys; + unsigned int *rz, *rp, *rt, mask, fullmask; + unsigned int *rowbuf1, *rowbuf2, *rowbuf3, *rb1, *rb2, *rb3; + int a, b; + long *rd; + unsigned short *colrb, *acol; + short v, x, y; + char *colrt, tempcol[4]; + + R.rectdaps= MEM_callocN(sizeof(long)*R.rectx*R.recty+4,"zbufDArectd"); + if(R.flag & R_ZTRA) bgnaccumbuf(); + + psmteller= 0; + + if(R.r.mode & R_EDGE) { + R.rectaccu= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty,"zbufshadeDA"); + } + + for(v=0; vmask]; + xs= (float)x+centLut[b & 15]; + ys= (float)y+centLut[b>>4]; + + shadepixel(xs, ys, ps->vlak); + + if(shortcol[3]) { + add_filt_mask(ps->mask, shortcol, rb1, rb2, rb3); + } + mask |= ps->mask; + + ps= ps->next; + } + ps= (PixStr *) POINTER_FROM_CODE(*rd); + mask= (~mask) & fullmask; + + b= centmask[mask]; + xs= (float)x+centLut[b & 15]; + ys= (float)y+centLut[b>>4]; + + shadepixel(xs, ys, ps->vlak0); + + if(shortcol[3]) { + add_filt_mask(mask, shortcol, rb1, rb2, rb3); + } + } + else { + shadepixel((float)x, (float)y, (int)*rd); + if(shortcol[3]) { + add_filt_mask(fullmask, shortcol, rb1, rb2, rb3); + } + } + + rb1+=4; + rb2+=4; + rb3+=4; + } + } + if(y>0) { + + colrb= (unsigned short *)(rowbuf3+4); + + /* LET OP: ENDIAN */ + + for(x=0; x>8); + tempcol[1]= (acol[1]>>8); + tempcol[2]= (acol[2]>>8); + tempcol[3]= (acol[3]>>8); + addalphaOver(colrt, tempcol); + } + } + } + + if(R.flag & R_HALO) { + /* van deze pixels zijn de pixstr al 1 scanline oud */ + scanlinehaloPS(rz-R.rectx, rd-2*R.rectx, ((unsigned int *)colrt)-R.rectx, y-1); + + } + scanlinesky(colrt-4*R.rectx, y-1); + + /* scanline begint netjes: halo's gebruiken ook textures! */ + R.vlaknr= -1; + + } + if(y0 && G.background==0) { + if((y & 1)==0) { + RE_local_render_display(y-2, y-1, + R.rectx, R.recty, + R.rectot); + } + } + rz+= R.rectx; + } + if(RE_local_test_break()) break; + } + + if( (R.r.mode & R_EDGE) && RE_local_test_break()==0) { + rt= R.rectot; + rp= R.rectaccu; + for(a= R.rectx*R.recty; a>0; a--, rt++, rp++) { + addalphaOver((char *)rt, (char *)rp); + } + } + + /* hier stond dof */ + + MEM_freeN(R.rectdaps); + freeps(); + MEM_freeN(rowbuf1); + MEM_freeN(rowbuf2); + MEM_freeN(rowbuf3); + R.rectdaps= 0; + + if(R.r.mode & R_EDGE) if(R.rectaccu) MEM_freeN(R.rectaccu); + R.rectaccu= 0; + if(R.flag & R_ZTRA) endaccumbuf(); +} /* end of void zbufshadeDA() */ + +/* ------------------------------------------------------------------------ */ + +void zbufshade(void) +{ + unsigned int *rz,*rp; + float fy; + int x,y; + unsigned short *acol; + char *charcol, *rt; + + Zjitx=Zjity= -.5; + + zbufferall(); + + /* SHADE */ + rp= R.rectot; + rz= R.rectz; + charcol= (char *)shortcol; + + #ifdef BBIG_ENDIAN + #else + charcol++; /* short anders uitlezen */ + #endif + + if(R.flag & R_ZTRA) bgnaccumbuf(); + + for(y=0; yminy= miny= har->ys - har->rad/R.ycor; + har->maxy= maxy= har->ys + har->rad/R.ycor; + + if(maxy<0); + else if(R.rectyxs-har->rad); + maxx= ceil(har->xs+har->rad); + + if(maxx<0); + else if(R.rectx=R.rectx) maxx= R.rectx-1; + if(miny<0) miny= 0; + if(maxy>R.recty) maxy= R.recty; + + rectt= R.rectot+ R.rectx*miny; + + for(y=miny;yys)*R.ycor; + ysq= yn*yn; + + for(x=minx; x<=maxx; x++) { + xn= x - har->xs; + xsq= xn*xn; + dist= xsq+ysq; + if(distradsq) { + RE_shadehalo(har, col, 0, dist, xn, yn, har->flarec); + + RE_addalphaAddfac((char *)rt, col, har->add); + } + rt++; + } + + rectt+= R.rectx; + + if(RE_local_test_break()) break; + } + + } + } +} /* end of void renderhalo(HaloRen *har), postprocess versie */ + +/* ------------------------------------------------------------------------ */ + +/* extern float hashvectf[]; */ +void RE_renderflare(HaloRen *har) +{ + HaloRen fla; + Material *ma; + float *rc, rad, alfa, visifac, vec[3]; + int b, type; + + fla= *har; + fla.linec= fla.ringc= fla.flarec= 0; + + rad= har->rad; + alfa= har->alfa; + + visifac= R.ycor*(har->pixels); + /* alle stralen opgeteld / r^3 == 1.0! */ + visifac /= (har->rad*har->rad*har->rad); + visifac*= visifac; + + ma= har->mat; + + /* eerste halo: gewoon doen */ + + har->rad= rad*ma->flaresize*visifac; + har->radsq= har->rad*har->rad; + har->zs= 0.0; + + har->alfa= alfa*visifac; + + renderhalo(har); + + /* volgende halo's: de flares */ + rc= hashvectf + ma->seed2; + + for(b=1; bflarec; b++) { + + fla.r= fabs(255.0*rc[0]); + fla.g= fabs(255.0*rc[1]); + fla.b= fabs(255.0*rc[2]); + fla.alfa= ma->flareboost*fabs(alfa*visifac*rc[3]); + fla.hard= 20.0 + fabs(70*rc[7]); + fla.tex= 0; + + type= (int)(fabs(3.9*rc[6])); + + fla.rad= ma->subsize*sqrt(fabs(2.0*har->rad*rc[4])); + + if(type==3) { + fla.rad*= 3.0; + fla.rad+= R.rectx/10; + } + + fla.radsq= fla.rad*fla.rad; + + vec[0]= 1.4*rc[5]*(har->xs-R.afmx); + vec[1]= 1.4*rc[5]*(har->ys-R.afmy); + vec[2]= 32.0*sqrt(vec[0]*vec[0] + vec[1]*vec[1] + 1.0); + + fla.xs= R.afmx + vec[0] + (1.2+rc[8])*R.rectx*vec[0]/vec[2]; + fla.ys= R.afmy + vec[1] + (1.2+rc[8])*R.rectx*vec[1]/vec[2]; + + if(R.flag & R_SEC_FIELD) { + if(R.r.mode & R_ODDFIELD) fla.ys += 0.5; + else fla.ys -= 0.5; + } + if(type & 1) fla.type= HA_FLARECIRC; + else fla.type= 0; + renderhalo(&fla); + + fla.alfa*= 0.5; + if(type & 2) fla.type= HA_FLARECIRC; + else fla.type= 0; + renderhalo(&fla); + + rc+= 7; + } +} /* end of void renderflare(HaloRen *har) */ + +void add_halo_flare(void) +{ +/* extern void RE_projectverto(); */ /* uit zbuf.c */ + HaloRen *har = NULL; + int a, mode; + + mode= R.r.mode; + R.r.mode &= ~R_PANORAMA; + R.xstart= -R.afmx; + R.ystart= -R.afmy; + R.xend= R.xstart+R.rectx-1; + R.yend= R.ystart+R.recty-1; + + RE_setwindowclip(1,-1); /* geen jit:(-1) */ + setzbufvlaggen(RE_projectverto); + + for(a=0; a>8]; + else har++; + + if(har->flarec) { + RE_renderflare(har); + } + } + + R.r.mode= mode; +} /* end of void add_halo_flare() */ + + +/* end of render.c */ + + diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c new file mode 100644 index 00000000000..03b9d117e23 --- /dev/null +++ b/source/blender/render/intern/source/renderdatabase.c @@ -0,0 +1,248 @@ +/** + * $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 ***** + * Storage, retrieval and query of render specific data. + */ + +/* + * All data from a Blender scene is converter by the renderconverter/ + * into a special format that is used by the render module to make + * images out of. These functions interface to the render-specific + * database. + * + * The blo{ha/ve/vl} arrays store pointers to blocks of 256 data + * entries each. + * + * The index of an entry is >>8 (the highest 24 * bits), to find an + * offset in a 256-entry block. + * + * - If the 256-entry block entry has an entry in the + * blove/bloha/blovl array of the current block, the i-th entry in + * that block is allocated to this entry. + * + * - If the entry has no block allocated for it yet, memory is + * allocated. + * + * The pointer to the correct entry is returned. Memory is guarateed + * to exist (as long as the malloc does not break). Since guarded + * allocation is used, memory _must_ be available. Otherwise, an + * exit(0) would occur. + * + */ + +#include +#include "MEM_guardedalloc.h" +#include "BLI_arithb.h" + +#include "DNA_texture_types.h" +#include "BKE_texture.h" + +#include "render.h" +#include "render_intern.h" + +/* ------------------------------------------------------------------------- */ + +VertRen *RE_findOrAddVert(int nr) +{ + VertRen *v; + int a; + + if(nr<0 || nr>MAXVERT ) { + printf("error in findOrAddVert: %d\n",nr); + return R.blove[0]; + } + a= nr>>8; + v= R.blove[a]; + if(v==0) { + v= (VertRen *)MEM_callocN(256*sizeof(VertRen),"findOrAddVert"); + R.blove[a]= v; + } + v+= (nr & 255); + return v; +} + +/* ------------------------------------------------------------------------ */ + +HaloRen *RE_findOrAddHalo(int nr) +{ + HaloRen *h; + int a; + + if(nr<0 || nr>MAXVERT ) { + printf("error in findOrAddHalo: %d\n",nr); + return R.bloha[0]; + } + a= nr>>8; + h= R.bloha[a]; + if(h==0) { + h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen),"findOrAdHalo"); + R.bloha[a]= h; + } + h+= (nr & 255); + return h; +} + +/* ------------------------------------------------------------------------ */ + +VlakRen *RE_findOrAddVlak(int nr) +{ + VlakRen *v; + int a; + + if(nr<0 || nr>MAXVLAK ) { + printf("error in findOrAddVlak: %d\n",nr); + return R.blovl[0]; + } + a= nr>>8; + v= R.blovl[a]; + if(v==0) { + v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen),"findOrAddVlak"); + R.blovl[a]= v; + } + v+= (nr & 255); + return v; +} + +/* ------------------------------------------------------------------------- */ + +extern float Tin, Tr, Tg, Tb; +HaloRen *RE_inithalo(Material *ma, + float *vec, + float *vec1, + float *orco, + float hasize, + float vectsize) +{ + HaloRen *har; + MTex *mtex; + float xn, yn, zn, texvec[3], hoco[4], hoco1[4]; + + if(hasize==0) return 0; + + RE_projectverto(vec, hoco); + if(hoco[3]==0.0) return 0; + if(vec1) { + RE_projectverto(vec1, hoco1); + if(hoco1[3]==0.0) return 0; + } + + har= RE_findOrAddHalo(R.tothalo++); + VECCOPY(har->co, vec); + har->hasize= hasize; + + /* projectvert wordt in zbufvlaggen gedaan ivm parts/border/pano */ + + /* halovect */ + if(vec1) { + + har->type |= HA_VECT; + + zn= hoco[3]; + har->xs= 0.5*R.rectx*(hoco[0]/zn); + har->ys= 0.5*R.recty*(hoco[1]/zn); + har->zs= 0x7FFFFF*(1.0+hoco[2]/zn); + + har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); + + xn= har->xs - 0.5*R.rectx*(hoco1[0]/hoco1[3]); + yn= har->ys - 0.5*R.recty*(hoco1[1]/hoco1[3]); + if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0; + else zn= atan2(yn, xn); + + har->sin= sin(zn); + har->cos= cos(zn); + zn= VecLenf(vec1, vec); + + har->hasize= vectsize*zn + (1.0-vectsize)*hasize; + + VecSubf(har->no, vec, vec1); + Normalise(har->no); + } + + if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA; + + har->alfa= ma->alpha; + har->r= 255.0*ma->r; + har->g= 255.0*ma->g; + har->b= 255.0*ma->b; + har->add= 255.0*ma->add; + har->mat= ma->ren; + har->hard= ma->har; + har->seed= ma->ren->seed1 % 256; + + if(ma->mode & MA_STAR) har->starpoints= ma->starc; + if(ma->mode & MA_HALO_LINES) har->linec= ma->linec; + if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc; + if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec; + + + if(ma->mtex[0]) { + + if( (ma->mode & MA_HALOTEX) ) har->tex= 1; + else { + + mtex= ma->mtex[0]; + VECCOPY(texvec, vec); + + if(mtex->texco & TEXCO_NORM) { + ; + } + else if(mtex->texco & TEXCO_OBJECT) { + /* texvec[0]+= imatbase->ivec[0]; */ + /* texvec[1]+= imatbase->ivec[1]; */ + /* texvec[2]+= imatbase->ivec[2]; */ + /* Mat3MulVecfl(imatbase->imat, texvec); */ + } + else { + if(orco) { + VECCOPY(texvec, orco); + } + } + + externtex(mtex, texvec); + + yn= Tin*mtex->colfac; + zn= Tin*mtex->varfac; + + if(mtex->mapto & MAP_COL) { + zn= 1.0-yn; + har->r= 255.0*(yn*Tr+ zn*ma->r); + har->g= 255.0*(yn*Tg+ zn*ma->g); + har->b= 255.0*(yn*Tb+ zn*ma->b); + } + if(mtex->texco & 16) { + har->alfa= 255.0*Tin; + } + } + } + + return har; +} +/* ------------------------------------------------------------------------- */ diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c new file mode 100644 index 00000000000..bd0a844a354 --- /dev/null +++ b/source/blender/render/intern/source/shadbuf.c @@ -0,0 +1,771 @@ +/* shadbuf.c RENDER + * + * ***** 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 ***** + * + * april 95 + * + * $Id$ + * + * 27-Jun-2001 switched the shadow buffer for UR to the object-shadow + * buffers, and removed all references and fixes for UR rendering from + * this one. + * */ + +#include +#include + +#include "MTC_matrixops.h" +#include "MEM_guardedalloc.h" +#include "BLI_arithb.h" + +#include "DNA_lamp_types.h" + +#include "render.h" +#include "render_intern.h" + +#include "shadbuf.h" +#include "renderHelp.h" +#include "jitter.h" +#include "zbuf.h" + +/* if defined: objects don't cast shadows anymore */ +/* #define RE_NO_SHADOWS */ + +/* unused? */ +static int bias= 0x00500000; +/* crud */ +#define MIN2(x,y) ( (x)<(y) ? (x) : (y) ) + +/* ------------------------------------------------------------------------- */ + +void lrectreadRectz(int x1, int y1, int x2, int y2, char *r1); +int sizeoflampbuf(struct ShadBuf *shb); +int firstreadshadbuf(struct ShadBuf *shb, int xs, int ys, int nr); +float readshadowbuf(struct ShadBuf *shb, int xs, int ys, int zs); +float readshadowbuf_halo(struct ShadBuf *shb, int xs, int ys, int zs); +float *give_jitter_tab(int samp); +/* ------------------------------------------------------------------------- */ + + +void initshadowbuf(LampRen *lar, float mat[][4]) +{ + struct ShadBuf *shb; + float hoek, temp, viewinv[4][4]; + + /* if(la->spsi<16) return; */ + + /* geheugen reserveren */ + shb= (struct ShadBuf *)MEM_callocN( sizeof(struct ShadBuf),"initshadbuf"); + lar->shb= shb; + + if(shb==0) return; + + VECCOPY(shb->co, lar->co); + + /* percentage: min en max in de gaten houden */ + shb->size= (lar->bufsize*R.r.size)/100; + if(shb->size<512) shb->size= 512; + else if(shb->size > lar->bufsize) shb->size= lar->bufsize; + + shb->samp= lar->samp; + shb->soft= lar->soft; + shb->shadhalostep= lar->shadhalostep; + + shb->zbuf= (unsigned long *)MEM_mallocN( sizeof(unsigned long)*(shb->size*shb->size)/256, "initshadbuf2"); + shb->cbuf= (char *)MEM_callocN( (shb->size*shb->size)/256, "initshadbuf3"); + + if(shb->zbuf==0 || shb->cbuf==0) { + if(shb->zbuf) MEM_freeN(shb->zbuf); + MEM_freeN(lar->shb); + lar->shb= 0; + return; + } + + MTC_Mat4Ortho(mat); + MTC_Mat4Invert(shb->winmat, mat); /* winmat is hier temp */ + + /* matrix: combinatie van inverse view en lampmat */ + /* opnieuw berekenen: de ortho-render heeft geen correcte viewinv */ + MTC_Mat4Invert(viewinv, R.viewmat); + MTC_Mat4MulMat4(shb->viewmat, viewinv, shb->winmat); + + /* projektie */ + hoek= saacos(lar->spotsi); + temp= 0.5*shb->size*cos(hoek)/sin(hoek); + shb->d= lar->clipsta; + + shb->pixsize= (shb->d)/temp; + + shb->far= lar->clipend; + /* bias is percentage, 2x groter gemaakt ivm invalshoek correctie */ + shb->bias= (0.02*lar->bias)*0x7FFFFFFF; + shb->bias= shb->bias*(100/R.r.size); + +} +/* ------------------------------------------------------------------------- */ + + +void lrectreadRectz(int x1, int y1, int x2, int y2, char *r1) /* leest deel uit rectz in r1 */ +{ + unsigned int len4, *rz; + + if(x1>=R.rectx || x2>=R.rectx || y1>=R.recty || y2>=R.recty) return; + if(x1>x2 || y1>y2) return; + + len4= 4*(x2- x1+1); + rz= R.rectz+R.rectx*y1+x1; + for(;y1<=y2;y1++) { + memcpy(r1,rz,len4); + rz+= R.rectx; + r1+= len4; + } +} + + +int sizeoflampbuf(struct ShadBuf *shb) +{ + int num,count=0; + char *cp; + + cp= shb->cbuf; + num= (shb->size*shb->size)/256; + + while(num--) count+= *(cp++); + + return 256*count; +} + +float *give_jitter_tab(int samp) +{ + /* these are all possible jitter tables, takes up some + * 12k, not really bad! + * For soft shadows, it saves memory and render time + */ + static int tab[17]={1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256}; + static float jit[1496][2]; + static char ctab[17]= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int a, offset=0; + + if(samp<2) samp= 2; + else if(samp>16) samp= 16; + + for(a=0; ashb; + float panophi; + float temp, wsize, dist; + int *rz, *rz1, verg, verg1; + unsigned long *ztile; + int a, x, y, minx, miny, byt1, byt2; + short temprx,tempry, square; + char *rc, *rcline, *ctile, *zt; + + panophi = getPanoPhi(); + + /* viewvars onthouden */ + temprx= R.rectx; tempry= R.recty; + R.rectx= R.recty= shb->size; + + shb->jit= give_jitter_tab(shb->samp); + + /* matrices en window: in R.winmat komt transformatie + van obsview naar lampview, inclusief lampwinmat */ + + wsize= shb->pixsize*(shb->size/2.0); + + i_window(-wsize, wsize, -wsize, wsize, shb->d, shb->far, shb->winmat); + + MTC_Mat4MulMat4(shb->persmat, shb->viewmat, shb->winmat); + + /* temp, will be restored */ + MTC_Mat4SwapMat4(shb->persmat, R.winmat); + + /* zbufferen */ + if(R.rectz) MEM_freeN(R.rectz); + R.rectz= (unsigned int *)MEM_mallocN(sizeof(int)*shb->size*shb->size,"makeshadbuf"); + rcline= MEM_mallocN(256*4+sizeof(int),"makeshadbuf2"); + + /* onthouden: panorama rot */ + temp= panophi; + panophi= 0.0; + pushTempPanoPhi(0.0); + + /* pano interference here? */ + setzbufvlaggen(projectvert); + + popTempPanoPhi(); + panophi= temp; + + zbuffershad(lar); + + /* alle pixels 1 x ingevuld verwijderen (oneven) */ + /* probleem hierbij kan geven dat er abrupte overgangen van zacht gebied + * naar geen zacht gebied is: bijv als eronder een klein vlakje zit + * DAAROM ER WEER UIT + * ook vanwege shadowhalo! + * + a= shb->size*shb->size; + rz= R.rectz; + while(a--) { + if(*rz & 1) *rz= 0x7FFFFFFF; + rz++; + } + */ + + square= lar->mode & LA_SQUARE; + + /* Z tiles aanmaken: dit systeem is 24 bits!!! */ + + ztile= shb->zbuf; + ctile= shb->cbuf; + for(y=0; ysize; y+=16) { + if(y< shb->size/2) miny= y+15-shb->size/2; + else miny= y-shb->size/2; + + for(x=0; xsize; x+=16) { + + /* ligt rechthoek binnen spotbundel? */ + a= shb->size/2; + if(x< a) minx= x+15-a; + else minx= x-a; + + dist= sqrt( (float)(minx*minx+miny*miny) ); + + if(square==0 && dist>(float)(a+12)) { /* 12, tested with a onlyshadow lamp */ + a= 256; verg= 0; /* 0x80000000; */ /* 0x7FFFFFFF; */ + rz1= (&verg)+1; + } + else { + lrectreadRectz(x, y, MIN2(shb->size-1,x+15), MIN2(shb->size-1,y+15), rcline); + rz1= (int *)rcline; + + verg= (*rz1 & 0xFFFFFF00); + + for(a=0;a<256;a++,rz1++) { + if( (*rz1 & 0xFFFFFF00) !=verg) break; + } + } + if(a==256) { /* compleet leeg vakje */ + *ctile= 0; + *ztile= *(rz1-1); + } + else { + + /* ACOMP enz. zijn defined L/B endian */ + + rc= rcline; + rz1= (int *)rcline; + verg= rc[ACOMP]; + verg1= rc[BCOMP]; + rc+= 4; + byt1= 1; byt2= 1; + for(a=1;a<256;a++,rc+=4) { + byt1 &= (verg==rc[ACOMP]); + byt2 &= (verg1==rc[BCOMP]); + + if(byt1==0) break; + } + if(byt1 && byt2) { /* alleen byte opslaan */ + *ctile= 1; + *ztile= (unsigned long)MEM_mallocN(256+4, "tile1"); + rz= (int *)*ztile; + *rz= *rz1; + + zt= (char *)(rz+1); + rc= rcline; + for(a=0; a<256; a++, zt++, rc+=4) *zt= rc[GCOMP]; + } + else if(byt1) { /* short opslaan */ + *ctile= 2; + *ztile= (unsigned long)MEM_mallocN(2*256+4,"Tile2"); + rz= (int *)*ztile; + *rz= *rz1; + + zt= (char *)(rz+1); + rc= rcline; + for(a=0; a<256; a++, zt+=2, rc+=4) { + zt[0]= rc[BCOMP]; + zt[1]= rc[GCOMP]; + } + } + else { /* triple opslaan */ + *ctile= 3; + *ztile= (unsigned long)MEM_mallocN(3*256,"Tile3"); + + zt= (char *)*ztile; + rc= rcline; + for(a=0; a<256; a++, zt+=3, rc+=4) { + zt[0]= rc[ACOMP]; + zt[1]= rc[BCOMP]; + zt[2]= rc[GCOMP]; + } + } + } + ztile++; + ctile++; + } + } + + MEM_freeN(rcline); + MEM_freeN(R.rectz); R.rectz= 0; + + R.rectx= temprx; R.recty= tempry; + MTC_Mat4SwapMat4(shb->persmat, R.winmat); + + /* printf("lampbuf %d\n", sizeoflampbuf(shb)); */ +} + +int firstreadshadbuf(struct ShadBuf *shb, int xs, int ys, int nr) +{ + /* return 1 als volledig gecomprimeerde shadbuftile && z==const */ + static int *rz; + int ofs; + char *ct; + + /* always test borders of shadowbuffer */ + if(xs<0) xs= 0; else if(xs>=shb->size) xs= shb->size-1; + if(ys<0) ys= 0; else if(ys>=shb->size) ys= shb->size-1; + + /* z berekenen */ + ofs= (ys>>4)*(shb->size>>4) + (xs>>4); + ct= shb->cbuf+ofs; + if(*ct==0) { + if(nr==0) { + rz= *( (int **)(shb->zbuf+ofs) ); + return 1; + } + else if(rz!= *( (int **)(shb->zbuf+ofs) )) return 0; + + return 1; + } + + return 0; +} + +float readshadowbuf(struct ShadBuf *shb, int xs, int ys, int zs) /* return 1.0 : volledig licht */ +{ + float temp; + int *rz, ofs; + int zsamp; + char *ct, *cz; + + /* simpleclip */ + /* if(xs<0 || ys<0) return 1.0; */ + /* if(xs>=shb->size || ys>=shb->size) return 1.0; */ + + /* always test borders of shadowbuffer */ + if(xs<0) xs= 0; else if(xs>=shb->size) xs= shb->size-1; + if(ys<0) ys= 0; else if(ys>=shb->size) ys= shb->size-1; + + /* z berekenen */ + ofs= (ys>>4)*(shb->size>>4) + (xs>>4); + ct= shb->cbuf+ofs; + rz= *( (int **)(shb->zbuf+ofs) ); + + if(*ct==3) { + ct= ((char *)rz)+3*16*(ys & 15)+3*(xs & 15); + cz= (char *)&zsamp; + cz[ACOMP]= ct[0]; + cz[BCOMP]= ct[1]; + cz[GCOMP]= ct[2]; + } + else if(*ct==2) { + ct= ((char *)rz); + ct+= 4+2*16*(ys & 15)+2*(xs & 15); + zsamp= *rz; + + cz= (char *)&zsamp; + cz[BCOMP]= ct[0]; + cz[GCOMP]= ct[1]; + } + else if(*ct==1) { + ct= ((char *)rz); + ct+= 4+16*(ys & 15)+(xs & 15); + zsamp= *rz; + + cz= (char *)&zsamp; + cz[GCOMP]= ct[0]; + + } + else { + /* got warning on this from alpha .... */ + /* but it's working code! (ton) */ + zsamp= (int) rz; + } + + /* if(zsamp >= 0x7FFFFE00) return 1.0; */ /* geen schaduw als op oneindig wordt gesampeld*/ + + if(zsamp > zs) return 1.0; /* absoluut geen schaduw */ + else if( zsamp < zs-bias) return 0.0 ; /* absoluut wel schaduw */ + else { /* zacht gebied */ + + temp= ( (float)(zs- zsamp) )/(float)bias; + return 1.0 - temp*temp; + + } +} + + +float testshadowbuf(struct ShadBuf *shb, float inp) /* return 1.0: geen schaduw */ +{ + float fac, co[4], dx[3], dy[3], aantal=0; + float xs1,ys1, siz, *j, xres, yres; + int xs,ys, zs; + short a,num; + +#ifdef RE_NO_SHADOWS + return 1.0; +#endif + + /* if(inp <= 0.0) return 1.0; */ + + /* renderco en osaco roteren */ + siz= 0.5*(float)shb->size; + VECCOPY(co, R.co); + co[3]= 1.0; + + MTC_Mat4MulVec4fl(shb->persmat, co); /* rationele hom co */ + + xs1= siz*(1.0+co[0]/co[3]); + ys1= siz*(1.0+co[1]/co[3]); + + /* Clip for z: near and far clip values of the shadow buffer. We + * can test for -1.0/1.0 because of the properties of the + * coordinate transformations. */ + fac= (co[2]/co[3]); + + if(fac>=1.0) { + return 0.0; + } else if(fac<= -1.0) { + return 1.0; + } + + zs= ((float)0x7FFFFFFF)*fac; + + /* num*num samples nemen, gebied met fac vergroten */ + num= shb->samp*shb->samp; + fac= shb->soft; + + + bias= (1.1-inp*inp)*shb->bias; + + if(num==1) { + return readshadowbuf(shb,(int)xs1, (int)ys1, zs); + } + + co[0]= R.co[0]+O.dxco[0]; + co[1]= R.co[1]+O.dxco[1]; + co[2]= R.co[2]+O.dxco[2]; + co[3]= 1.0; + MTC_Mat4MulVec4fl(shb->persmat,co); /* rationele hom co */ + dx[0]= xs1- siz*(1.0+co[0]/co[3]); + dx[1]= ys1- siz*(1.0+co[1]/co[3]); + + co[0]= R.co[0]+O.dyco[0]; + co[1]= R.co[1]+O.dyco[1]; + co[2]= R.co[2]+O.dyco[2]; + co[3]= 1.0; + MTC_Mat4MulVec4fl(shb->persmat,co); /* rationele hom co */ + dy[0]= xs1- siz*(1.0+co[0]/co[3]); + dy[1]= ys1- siz*(1.0+co[1]/co[3]); + + xres= fac*( fabs(dx[0])+fabs(dy[0]) ); + yres= fac*( fabs(dx[1])+fabs(dy[1]) ); + + if(xresjit; + + if(xres<16.0 && yres<16.0) { + if(firstreadshadbuf(shb, (int)xs1, (int)ys1, 0)) { + if(firstreadshadbuf(shb, (int)(xs1+xres), (int)ys1, 1)) { + if(firstreadshadbuf(shb, (int)xs1, (int)(ys1+yres), 1)) { + if(firstreadshadbuf(shb, (int)(xs1+xres), (int)(ys1+yres), 1)) { + return readshadowbuf(shb,(int)xs1, (int)ys1, zs); + } + } + } + } + } + + for(a=num;a>0;a--) { + /* i.p.v. jit ook met random geprobeerd: lelijk! */ + xs= xs1 + xres*j[0]; + ys= ys1 + yres*j[1]; + j+=2; + + aantal+= readshadowbuf(shb, xs, ys, zs); + } + + /* Renormalizes for the sample number: */ + return aantal/( (float)(num) ); +} + +/* different function... sampling behind clipend can be LIGHT, bias is negative! */ +/* return: light */ +float readshadowbuf_halo(struct ShadBuf *shb, int xs, int ys, int zs) +{ + float temp; + int *rz, ofs; + int zbias, zsamp; + char *ct, *cz; + + /* simpleclip */ + if(xs<0 || ys<0) return 0.0; + if(xs>=shb->size || ys>=shb->size) return 0.0; + + /* z berekenen */ + ofs= (ys>>4)*(shb->size>>4) + (xs>>4); + ct= shb->cbuf+ofs; + rz= *( (int **)(shb->zbuf+ofs) ); + + if(*ct==3) { + ct= ((char *)rz)+3*16*(ys & 15)+3*(xs & 15); + cz= (char *)&zsamp; + zsamp= 0; + cz[ACOMP]= ct[0]; + cz[BCOMP]= ct[1]; + cz[GCOMP]= ct[2]; + } + else if(*ct==2) { + ct= ((char *)rz); + ct+= 4+2*16*(ys & 15)+2*(xs & 15); + zsamp= *rz; + + cz= (char *)&zsamp; + cz[BCOMP]= ct[0]; + cz[GCOMP]= ct[1]; + } + else if(*ct==1) { + ct= ((char *)rz); + ct+= 4+16*(ys & 15)+(xs & 15); + zsamp= *rz; + + cz= (char *)&zsamp; + cz[GCOMP]= ct[0]; + + } + else { + /* same as before */ + /* still working code! (ton) */ + zsamp= (int) rz; + } + + /* geen schaduw als op oneindig wordt gesampeld*/ + + if(zsamp >= 0x7FFFFE00) return 1.0; + + if(zsamp > zs) return 1.0; /* absoluut geen schaduw */ + else { + /* bias is negative, so the (zs-bias) can be beyond 0x7fffffff */ + zbias= 0x7fffffff - zs; + if(zbias > -bias) { + if( zsamp < zs-bias) return 0.0 ; /* absoluut wel schaduw */ + } + else return 0.0 ; /* absoluut wel schaduw */ + } + + /* zacht gebied */ + + temp= ( (float)(zs- zsamp) )/(float)bias; + return 1.0 - temp*temp; +} + + +float shadow_halo(LampRen *lar, float *p1, float *p2) +{ + /* p1 p2 already are rotated in spot-space */ + ShadBuf *shb= lar->shb; + float co[4], siz; + float labda, labdao, labdax, labday, ldx, ldy; + float zf, xf1, yf1, zf1, xf2, yf2, zf2; + float count, lightcount; + int x, y, z, xs1, ys1; + int dx = 0, dy = 0; + + siz= 0.5*(float)shb->size; + /* negative! The other side is more important */ + bias= -shb->bias; + + co[0]= p1[0]; + co[1]= p1[1]; + co[2]= p1[2]/lar->sh_zfac; + co[3]= 1.0; + MTC_Mat4MulVec4fl(shb->winmat, co); /* rationele hom co */ + xf1= siz*(1.0+co[0]/co[3]); + yf1= siz*(1.0+co[1]/co[3]); + zf1= (co[2]/co[3]); + + + co[0]= p2[0]; + co[1]= p2[1]; + co[2]= p2[2]/lar->sh_zfac; + co[3]= 1.0; + MTC_Mat4MulVec4fl(shb->winmat, co); /* rationele hom co */ + xf2= siz*(1.0+co[0]/co[3]); + yf2= siz*(1.0+co[1]/co[3]); + zf2= (co[2]/co[3]); + + /* de 2dda */ + + xs1= (int)xf1; + ys1= (int)yf1; + + if(xf1 != xf2) { + if(xf2-xf1 > 0.0) { + labdax= (xf1-xs1-1.0)/(xf1-xf2); + ldx= -shb->shadhalostep/(xf1-xf2); + dx= shb->shadhalostep; + } + else { + labdax= (xf1-xs1)/(xf1-xf2); + ldx= shb->shadhalostep/(xf1-xf2); + dx= -shb->shadhalostep; + } + } + else { + labdax= 1.0; + ldx= 0.0; + } + + if(yf1 != yf2) { + if(yf2-yf1 > 0.0) { + labday= (yf1-ys1-1.0)/(yf1-yf2); + ldy= -shb->shadhalostep/(yf1-yf2); + dy= shb->shadhalostep; + } + else { + labday= (yf1-ys1)/(yf1-yf2); + ldy= shb->shadhalostep/(yf1-yf2); + dy= -shb->shadhalostep; + } + } + else { + labday= 1.0; + ldy= 0.0; + } + + x= xs1; + y= ys1; + labda= count= lightcount= 0.0; + +/* printf("start %x %x \n", (int)(0x7FFFFFFF*zf1), (int)(0x7FFFFFFF*zf2)); */ + + while(1) { + labdao= labda; + + if(labdax==labday) { + labdax+= ldx; + x+= dx; + labday+= ldy; + y+= dy; + } + else { + if(labdax=1.0) break; + + zf= zf1 + labda*(zf2-zf1); + count+= 1.0; + + if(zf<= 0.0) lightcount += 1.0; /* close to the spot */ + else { + + /* make sure, behind the clipend we extend halolines. */ + if(zf>=1.0) z= 0x7FFFF000; + else z= (int)(0x7FFFF000*zf); + + lightcount+= readshadowbuf_halo(shb, x, y, z); + + } + } + + if(count!=0.0) return (lightcount/count); + return 0.0; + +} + + + + +/* sampelen met filter + xstart= xs-1; + ystart= ys-1; + if(xstart<0) xstart= 0; + if(ystart<0) ystart= 0; + xend= xstart+2; + yend= ystart+2; + if(xend>=shb->size) { xstart= shb->size-3; xend= shb->size-1;} + if(yend>=shb->size) { ystart= shb->size-3; yend= shb->size-1;} + + fid= filt3; + for(ys=ystart;ys<=yend;ys++) { + rz= shb->buf+ ys*shb->size+ xstart; + for(xs= xstart;xs<=xend;xs++,rz++) { + if( *rz+0x100000 +//#include + +#include "render.h" +#include "render_intern.h" +#include "shadbuf.h" +#include "shadowBuffer.h" /* the C header */ +#include "RE_ShadowBuffer.h" /* the base buffer */ +#include "RE_DummyShadowBuffer.h" /* A dummy shadow buffer */ +#include "RE_basicShadowBuffer.h" /* the 'old' shadow buffer */ + +struct ShadBuf; +struct LampRen; +struct Lamp; +/* + * Creates a shadow buffer of a certain type + */ +RE_ShadowBufferHandle RE_createShadowBuffer(struct LampRen *lar, + float mat[][4], + int mode) +{ + /* make a dummy: this always returns a fixed value */ + RE_ShadowBuffer* buf = NULL; + switch (mode) { + case 0: + buf = new RE_DummyShadowBuffer(); + break; + case 1: + /* loop to the old c-based buffer */ + /* memory release is done implicitly! */ + initshadowbuf(lar, mat); + break; + case 2: + buf = new RE_BasicShadowBuffer(lar, mat); + break; + case 3: +// cout << "Deep shadow buffer requested\n"; + break; + default: +// cerr << "Bad shadow buffer type specified\n"; + ; /* nada */ + } + return (RE_ShadowBufferHandle) buf; +} + +void RE_deleteShadowBuffer(RE_ShadowBufferHandle buf) +{ +// cout << "requesting buffer delete\n"; + assert(buf); + delete (RE_ShadowBuffer*) buf; +} + +void RE_buildShadowBuffer(RE_ShadowBufferHandle buf, + struct LampRen *lar) +{ + assert(buf); + ((RE_ShadowBuffer*) buf)->importScene(lar); +} + + +void RE_testshadowbuf(RE_ShadowBufferHandle buf, + struct ShadBuf* shbp, + float inp, + float* shadres) +{ + assert(buf); + ((RE_ShadowBuffer*) buf)->readShadowValue(shbp, inp, shadres); +} diff --git a/source/blender/render/intern/source/vanillaRenderPipe.c b/source/blender/render/intern/source/vanillaRenderPipe.c new file mode 100644 index 00000000000..5f78e1b25c9 --- /dev/null +++ b/source/blender/render/intern/source/vanillaRenderPipe.c @@ -0,0 +1,1654 @@ +/** + * + * ***** 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 ***** + * vanillaRenderPipe.c + * + * 28-06-2000 nzc + * + * $Id$ + * + */ + +/* + The render pipe + --------------- + + The overall results of the render pass should end up in R.rectot. This + buffer already exists, and although its contents may change, its location + may not. A lot of other routines depend on it! + +*/ + +/* global includes */ +#include +#include /* INT_MIN,MAX are used here */ +#include +#include "MTC_vectorops.h" +#include "MTC_matrixops.h" +#include "MEM_guardedalloc.h" + +#include "DNA_camera_types.h" +#include "DNA_object_types.h" +#include "BKE_global.h" + +/* local includes (from the render module) */ +#include "RE_callbacks.h" +#include "render.h" /* all kinds of stuff */ +#include "render_intern.h" +#include "zbuf.h" /* for vergzvlak, zbufclip, zbufclipwire */ +#include "edgeRender.h" /* all edge rendering stuff */ +#include "pixelshading.h" /* painting the pixels */ +#include "rendercore.h" + +/* general calculus and data manipulation, also local */ +#include "gammaCorrectionTables.h" +#include "jitter.h" +#include "pixelblending.h" +#include "zbufferdatastruct.h" + +/* own includes */ +#include "vanillaRenderPipe.h" +#include "vanillaRenderPipe_int.h" + +/* crud */ +#define MIN2(x,y) ( (x)<(y) ? (x) : (y) ) + +/* ------------------------------------------------------------------------- */ +/* Debug defines: disable all for production level code. */ +/* These variables control faking of rendered colours, extra tracing, */ +/* extra error checking and such. */ +/* ------------------------------------------------------------------------- */ + +/* if defined: _very_ explicit tracing and checking enabled */ +/* #define RE_FULL_SAFETY */ +/* if defined: use 'simple' alpha thresholding on oversampling */ +/* #define RE_SIMPLE_ALPHA_THRESHOLD */ + +/* ------------------------------------------------------------------------- */ + +#ifdef RE_FULL_SAFETY +/* Full safety does the following: */ +/* - add extra bounds checking */ +/* - add extra type checking */ +/* - do a little performance analysis */ +/* - trace the original sources */ + +/* trace the version of the source */ +char vanillaRenderPipe_ext_h[] = VANILLARENDERPIPE_EXT_H; +char vanillaRenderPipe_int_h[] = VANILLARENDERPIPE_INT_H; +char vanillaRenderPipe_types_h[] = VANILLARENDERPIPE_TYPES_H; +char vanillaRenderPipe_c[] = +"$Id$"; +/* counters for error handling */ +static int conflictsresolved; /* number of conflicts in one frame */ + +#include "errorHandler.h" +#endif /* RE_FULL_SAFETY stuff */ + +/* ------------------------------------------------------------------------- */ + +/* External : -------------------------------------------------------------- */ + +extern float centLut[16]; /* Lookup for jitter offsets. */ +extern unsigned int Zsample; /* Nr. of the currently active oversample. This */ + /* counter must be set explicitly by the */ + /* function that builds the z-buffer. */ + /* The buffer-filling functions use it. */ +extern float Zjitx,Zjity; /* The x,y values for jitter offset */ + +extern float Zmulx, Zmuly; /* Some kind of scale? */ + +extern unsigned int Zvlnr; /* Face rendering pointer and counter: these */ +extern VlakRen *Zvlr; /* are used for 'caching' render results. */ + + /* These function pointers are used for z buffer filling. */ +extern void (*zbuffunc)(float *, float *, float *); +extern void (*zbuflinefunc)(float *, float *); + +extern char cmask[256]; /* When a pixel is supersampled, we must */ +extern char *centmask; /* compute its colour on a point _on_ the face. */ + /* These two are used to compute an offset to */ + /* guarantee we use valid coordinates. */ + +/* unsorted */ +extern float holoofs, fmask[256]; +extern unsigned short usegamtab, shortcol[4], + *mask1[9], *mask2[9],/* *igamtab1, */ *igamtab2/*, *gamtab */; + +extern RE_APixstrExt *APixbufExt;/*Zbuffer: linked list of face, halo indices*/ + +/* Globals : --------------------------------------------------------------- */ + +RE_COLBUFTYPE *AColourBuffer; /* Buffer for colours of 1 line of pixels */ +static int Aminy; /* y value of first line in the accu buffer */ +static int Amaxy; /* y value of last line in the accu buffer */ + /* -also used to clip when zbuffering */ + +/* Buffer width refers to the size of the buffers we build. Image size is */ +/* the same as R.rectx, R.recty. */ +static int imageHeight; /* image size in pixels in y direction */ +static int imageWidth; /* image size in pixels in x direction */ +static int bufferHeight; /* image size in pixels in y direction */ +static int bufferWidth; /* image size in pixels in x direction */ +static int zBufferWidth; /* special width because zbuffer needs to be */ + /* wider */ + +static int Azvoordeel; /* A small offset for transparent rendering. */ +int alphaLUT[32]; /* alpha lookuptable, for oversampling */ + /* Its function has been superceded because */ + /* pixels are always integrated. This */ + /* performs the same normalization. */ +int osaNr; /* The oversample number. I keep it */ + /* separately here, because I treat no OSA */ + /* as if it were osa=1. */ +RE_COLBUFTYPE collector[4]; /* used throughout as pixel colour accu */ +RE_COLBUFTYPE sampcol[RE_MAX_OSA_COUNT * 4]; /* subpixel accu buffer */ + +/* ------------------------------------------------------------------------- */ +/* Local (for now) */ +/* void integrateStack(struct RE_faceField* stack, */ +/* int ptr, */ +/* float x, */ +/* float y, */ +/* int osaNr); */ +void integratePerSubStack(struct RE_faceField* stack, + int ptr, + float x, + float y, + int osaNr); + +/* ------------------------------------------------------------------------- */ + +void zBufShadeAdvanced() +{ + int y, keepLooping = 1; + float xjit = 0.0, yjit = 0.0; + +#ifdef RE_FULL_SAFETY + /* reset trace */ + RE_errortrace_reset(); + conflictsresolved = 0; + fprintf(stderr, "\n*** Activated full error trace on " + "unified renderer using:\n\t%s\n\t%s\n\t%s\n\t%s", + vanillaRenderPipe_c, vanillaRenderPipe_ext_h, + vanillaRenderPipe_int_h, vanillaRenderPipe_types_h); +#endif + + Zjitx=Zjity= -0.5; /* jitter preset: 0.5 pixel */ + + /* EDGE: for edge rendering we should compute a larger buffer, but this */ + /* may require modifications at a deeper level. For now, we just */ + /* 'ignore' edge pixels. */ + imageHeight = R.recty; + imageWidth = R.rectx; + bufferHeight = R.recty; + bufferWidth = R.rectx; + + /* Set osaNr. Treat 'no osa' as 'osa = 1' */ + if(R.r.mode & R_OSA) { + osaNr = R.osa; + if(osaNr > 16) { /* check was moved from calcZBufLine */ + printf("zBufShadeAdvanced> osa too large (internal error)\n"); + G.afbreek= 1; + return; + } + } else { + /* little hack */ + osaNr = 1; + xjit = jit[0][0]; + yjit = jit[0][1]; + jit[0][0] = 0.45; + jit[0][1] = 0.45; + } + + RE_setwindowclip(0, -1); /* just to be sure, reset the view matrix */ + + initRenderBuffers(bufferWidth); + + /* ugh! should be converted sooner!! */ + switch (R.r.alphamode) { + case R_ALPHAKEY: + setSkyBlendingMode(RE_ALPHA_KEY); + break; + case R_ALPHAPREMUL: + setSkyBlendingMode(RE_ALPHA_PREMUL); + break; +/* not there... this is the default case */ +/* case R_ALPHASKY: */ +/* setSkyBlendingMode(RE_ALPHA_SKY); */ +/* break; */ + default: + setSkyBlendingMode(RE_ALPHA_SKY); + } + + y = 0; + while ( (y < bufferHeight) && keepLooping) { + calcZBufLine(y); + R.vlaknr= -1; /* huh? why reset this counter? for shadePixel! */ + renderZBufLine(y); + transferColourBufferToOutput(y); + + if((y & 1) && G.background!=1) RE_local_render_display(y-1, y, + imageWidth, + imageHeight, + R.rectot); + + if(RE_local_test_break()) keepLooping = 0; + y++; + } + freeRenderBuffers(); + + /* Edge rendering is done purely as a post-effect */ + if(R.r.mode & R_EDGE) { + addEdges((char*)R.rectot, imageWidth, imageHeight, + osaNr, + R.r.edgeint, R.r.same_mat_redux, + G.compat, G.notonlysolid, + R.r.edgeR, R.r.edgeG, R.r.edgeB); + } + + add_halo_flare(); /* from rendercore */ + +#ifdef RE_FULL_SAFETY + fprintf(stderr, "\n--- resolved %d conflicts", conflictsresolved); + fflush(stderr); +#endif + + if (!(R.r.mode & R_OSA)) { + jit[0][0] = xjit; + jit[0][1] = yjit; + } + +} /* end of void zbufshadeAdvanced() */ + +/* ------------------------------------------------------------------------- */ + +void initRenderBuffers(int bwidth) +{ + + /* The +1 is needed because the fill-functions use a +1 offset when */ + /* filling in pixels. Mind that also the buffer-clearing function needs */ + /* this offset (done in calcZBufLine). */ + /* The offset is wrong: it shouldn't be there. I need to fix this still. */ + AColourBuffer = MEM_callocN(4 * sizeof(RE_COLBUFTYPE) * bwidth, + "Acolrow"); + zBufferWidth = bwidth + 1; + initZbuffer(bwidth + 1); + + Aminy= -1000; /* indices of lines in the z buffer: no lines buffered */ + Amaxy= -1000; + + /* Use slider when the gamma button is pressed. */ + if (R.r.mode & R_GAMMA) { + makeGammaTables(R.r.gamma); + setDoGamma(1); + } else { + /* + Needed for spotlights! Maybe a separate gammatable would be + required here + */ + makeGammaTables(1.0); + setDoGamma(0); + } + +} /* End of void initZBuffers(void) */ + +/* ------------------------------------------------------------------------- */ + +void freeRenderBuffers(void) { + if (AColourBuffer) MEM_freeN(AColourBuffer); + freeZbuffer(); +} /* End of void freeZBuffers(void) */ + +/* ------------------------------------------------------------------------- */ + +void calcZBufLine(int y) +{ + + int part; + int keepLooping = 1; + + if(y<0) return; + + /* zbuffer fix: here? */ + Zmulx= ((float) bufferWidth)/2.0; + Zmuly= ((float) bufferHeight)/2.0; + + + /* use these buffer fill functions */ + zbuffunc = zBufferFillFace; + zbuflinefunc = zBufferFillEdge; + + /* (FORALL y: Aminy =< y =< Amaxy: y is buffered) */ + if( (y < Aminy) || (y > Amaxy)) { + /* prepare buffer */ + part = (y/RE_ZBUFLEN); /* These two lines are mystifying me... */ + Aminy = part * RE_ZBUFLEN; /* Possibly for rounding things? */ + Amaxy = Aminy + RE_ZBUFLEN - 1; +/* if(Amaxy >= R.recty) Amaxy = R.recty-1; */ + if(Amaxy >= bufferHeight) Amaxy = bufferHeight - 1; + resetZbuffer(); + + Zsample = 0; /* Zsample is used internally ! */ + while ( (Zsample < osaNr) && keepLooping ) { + /* Apply jitter to this pixel. The jitter offsets are globals. */ + /* They are added in zbufclip() */ + /* Negative: these offsets are added to the vertex coordinates */ + /* so it equals translating viewpoint over the positive vector. */ + Zjitx= -jit[Zsample][0]; + Zjity= -jit[Zsample][1]; + + keepLooping = fillZBufDistances(); + + if(RE_local_test_break()) keepLooping = 0; + Zsample++; + } + }; + +} /*End of void calcZBufLine(int y) */ + +/* ------------------------------------------------------------------------- */ + +int countAndSortPixelFaces(int zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE], + RE_APixstrExt *ap) +{ +#ifdef RE_FULL_SAFETY + char fname[] = "countAndSortPixelFaces"; +#endif + int totvlak; /* face counter */ + int i; /* generic counter */ + + totvlak= 0; + while(ap) { + for(i=0; i<4; i++) { + if(ap->t[i]) { + zrow[totvlak][0] = ap->zmin[i]; + zrow[totvlak][1] = ap->p[i]; + zrow[totvlak][2] = ap->mask[i]; + zrow[totvlak][3] = ap->t[i]; + zrow[totvlak][4] = ap->zmax[i]; + totvlak++; + if(totvlak > (RE_MAX_FACES_PER_PIXEL - 1)) + { + totvlak = (RE_MAX_FACES_PER_PIXEL - 1); +#ifdef RE_FULL_SAFETY + RE_error(RE_TOO_MANY_FACES, fname); +#endif + } + } else break; + }; + ap= ap->next; + } + + if(totvlak==2) { /* Sort faces ----------------------------- */ + if(zrow[0][0] < zrow[1][0]) { + i= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= i; + i= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= i; + i= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= i; + i= zrow[0][3]; zrow[0][3]= zrow[1][3]; zrow[1][3]= i; + i= zrow[0][4]; zrow[0][4]= zrow[1][4]; zrow[1][4]= i; + } /* else: two faces, and ordering is ok */ + } else if (totvlak != 1) qsort(zrow, totvlak, + sizeof(int)*RE_PIXELFIELDSIZE, vergzvlak); + return totvlak; +} /* end of int countAndSortPixelFaces(int* zrow,RE_APixstrExt *ap ) */ + +/* ------------------------------------------------------------------------- */ +/* Oversampler v3 - check CVS for older versions */ +/* */ +/* In this version, I have split up the rendering into several parts, so I */ +/* can generate better profiles. */ +/* */ +/* - multiple blend functions ? */ +/* - x-rays? */ +/* - volumetric stuff ? */ +/* - maybe the oversampling should move to the shading part */ +/* */ +/* ------------------------------------------------------------------------- */ + +/* These variables describe the buffers needed for the oversampling. */ +/* 1. A bit vector with flags to indicate which pixels have received colour. */ +static int VR_covered = 0; +/* 2. The local vector collector, for resolving conflicts only. */ +static int VR_cbuf[RE_MAX_FACES_PER_PIXEL][2]; + +/** + * Analyze the z-buffer, and pre-sample the colours. + */ +int composeStack(int zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE], + struct RE_faceField* stack, int ptr, + int totvlak, float x, float y, int osaNr) { + +#ifdef RE_FULL_SAFETY + char* fname = "composeStack"; +#endif + float xs = 0.0; + float ys = 0.0; /* coordinates for the render-spot */ + + float alphathreshold[RE_MAX_OSA_COUNT]; + int inconflict = 0; + int saturationthreshold = 0; + int saturated = 0; + int i = 0; + int Ccount = 0; + int Cthresh = 0; + int save_totvlak = totvlak; + int fullsubpixelflags = 0; + + VR_covered = 0; + for(i = 0; i < osaNr; i++) alphathreshold[i] = 0.0; + saturationthreshold = ( (1< 0) ) { + totvlak--; + + i= centmask[ zrow[totvlak][RE_MASK] ]; /* recenter sample position - */ + xs= (float)x+centLut[i & 15]; + ys= (float)y+centLut[i >> 4]; + + /* stack face ----------- */ + stack[ptr].data = renderPixel(xs, ys, zrow[totvlak]); + stack[ptr].faceType = zrow[totvlak][RE_TYPE]; + cpFloatColV(collector, stack[ptr].colour); + stack[ptr].mask = zrow[totvlak][RE_MASK]; + + /* This is done so that spothalos are properly overlayed on halos */ + /* maybe we need to check the colour here... */ + if(zrow[totvlak][RE_TYPE] & RE_POLY) VR_covered |= zrow[totvlak][RE_MASK]; + + /* calculate conflict parameters: ---------------------------------- */ + if( zrow[totvlak][RE_ZMIN] < Cthresh ) { + inconflict = 1; + /* Prevent from switching on bad data. This may be done more */ + /* efficiently later on. It is _quite_ important. */ + if (totvlak == save_totvlak - 1) Ccount = 0; + else if(Ccount == 0) Ccount = 2; + else Ccount++; + stack[ptr].conflictCount = Ccount; + if (zrow[totvlak][RE_ZMAX] > Cthresh) + Cthresh = zrow[totvlak][RE_ZMAX]; +#ifdef RE_FULL_SAFETY + if (Ccount == 2) conflictsresolved++; +#endif + } else { + Cthresh = zrow[totvlak][RE_ZMAX]; + Ccount = 0; + stack[ptr].conflictCount = 0; + if (totvlak > 0 ) + inconflict = (zrow[totvlak-1][RE_ZMIN] < Cthresh); + else inconflict = 0; + } + + ptr++; + + /* alpha threshold ------------------------------------------------- */ + /* There are currently two ways of blending: alpha-over, and add. */ + /* Add-blending does strange things, in the sense that alpha is */ + /* simply added, and colour is sort of alpha-over blended. Using the */ + /* same thresholding relation seems to work ok. For less than unity */ + /* add factor, the alpha threshold may rise faster, but currently we */ + /* do not check for this factor. */ + for(i = 0; i < osaNr; i++) { + if ( zrow[totvlak][RE_MASK] & (1< RE_FULL_ALPHA_FLOAT) + fullsubpixelflags |= (1<= saturationthreshold); + + } /* done stacking ----------------------------------------------------- */ + + /* + STACK_SKY Sometimes, a sky pixel is needed. Since there are + some issues with mist/ ztra/ env, I always put the sky here. + */ +/* if (!saturated) { */ + totvlak--; + + xs= (float)x; + ys= (float)y; + + renderSkyPixelFloat(xs, ys); + + stack[ptr].faceType = RE_SKY; + cpFloatColV(collector, stack[ptr].colour); + stack[ptr].data = NULL; + stack[ptr].mask = 0xFFFF; + stack[ptr].conflictCount = 0; + ptr++; +/* } */ + + /* Index of the top of the stack */ + return ptr; +} + +/* + Start resolving the conflict: the stack is primed to the top-most valid + layer on the stack. Call this layer n. Layer n has a conflict count of c. + This means layers [ n - c, ..., n ] + */ +int resolveConflict(struct RE_faceField* stack, int ptr, float x, float y) { +#ifdef RE_FULL_SAFETY + char* fname = "resolveConflicts"; +#endif + int face; + int layer; + float dx, dy; + float xs = 0.0; + float ys = 0.0; /* coordinates for the render-spot */ + int i; + + for(i = 0; i< osaNr; i++) { /* per bin, buffer all faces */ + dx = jit[i][0]; + dy = jit[i][1]; + xs = (float)x + dx; + ys = (float)y + dy; + + face = 0; /* only counts covering faces ------------------- */ + layer = 0; /* counts all faces ----------------------------- */ + + while (layer < stack[ptr].conflictCount) { + if ( (1<= 0) { + if (stack[ptr].conflictCount == 0) { + /* + No conflict: sample one colour into multiple bins + */ + blendOverFloatRow(stack[ptr].faceType, + sampcol, + stack[ptr].colour, + stack[ptr].data, + stack[ptr].mask, + osaNr); + ptr--; + } else { + /* + Recalc all z-values, and integrate per sub-pixel. + */ + ptr -= resolveConflict(stack, ptr, x, y); + } + } + + /* Done sampling. Now we still need to fill in pixels that were not */ + /* covered at all It seems strange that we have to check for empty alpha */ + /* but somehow this is necessary. Check out the cover condition :).... */ + + /* It is important that we find a more efficient algorithm here, because */ + /* this little loop eats _lots_ of cycles. */ + + /* Should be integrated in the rest of the rendering... */ + + if((R.flag & R_LAMPHALO) + /*&& + ( VR_covered < ((1 << osaNr) - 1 ) )*/ + ) { + float halocol[4]; + int i; + renderSpotHaloPixel(x, y, halocol); + /* test seems to be wrong? */ + if (halocol[3] > RE_EMPTY_COLOUR_FLOAT) { + for (i = 0; i < osaNr; i++) { + /* here's a pinch: if the pixel was only covered by a halo, */ + /* we still need to fill spothalo. How do we detect this? */ + if (!(VR_covered & (1 << i))) + /* maybe a copy is enough here... */ + addAlphaOverFloat(sampcol + (4 * i), halocol); + } + } + } +} + +/** + * New approach: sample substacks. Each substack is first copied into + * a stack buffer, and then blended down. + * */ +void integratePerSubStack(struct RE_faceField* stack, + int ptr, + float x, + float y, + int osaNr) { + int i = 0; + int j = 0; + int k = 0; + int l = 0; + int filterMask = 0; + /* next step would be to improve on the substack, I guess */ + int subStack[RE_MAX_FACES_PER_PIXEL + 1]; + float colSubStack[4 * (RE_MAX_FACES_PER_PIXEL + 1)]; + int subStackPtr = 0; + int subStackSize = 0; + float xs, ys; + + + while (i < osaNr) { + xs = x + jit[i][0]; + ys = y + jit[i][1]; + + /* + * 1. Copy all relevant faces. Mind that stack is built from + * low index = low z to high index =high z. The sub-stack is + * exactly the other way around! (low index = high z) + */ + filterMask = (1 << i); + subStackPtr = 0; + j = ptr - 1; /* the topmost valid face */ + while (j >= 0) { + if (stack[j].conflictCount) { + /* Conflict: we sort the faces for distance right + * away. We could adapt conflict count, and adjust the + * stack later on, but that's really doing too much, + * too complicated. This is just fine. + * */ + k = 0; + l = 0; + /* check whether the face intersects, and if so, + * stores depth */ + while (k < stack[j].conflictCount) { + if (stack[j - k].mask & filterMask) { + VR_cbuf[l][0] = calcDepth(xs, ys, + stack[j - k].data, + stack[j - k].faceType); + VR_cbuf[l][1] = j - k; + l++; + } + k++; + } + /* VR_cbuf now contains l pairs (distance, stackindex) */ + qsort(VR_cbuf, l, sizeof(int)*2, vergzvlak); + /* + * Now we put the sorted indices on the + * substack. qsort delivers low index = low z, which + * is the right wrong order for the substack */ + k = 0; + while (k < l) { + subStack[subStackPtr] = VR_cbuf[k][1]; + cpFloatColV(stack[VR_cbuf[k][1]].colour, &colSubStack[4*subStackPtr]); + subStackPtr++; + k++; + } + + j -= stack[j].conflictCount; + } else { + /* no conflict */ + if (stack[j].mask & filterMask) { + subStack[subStackPtr] = j; + cpFloatColV(stack[j].colour, &colSubStack[4*subStackPtr]); + subStackPtr++; + } + j--; + } + } + subStackSize = subStackPtr; + + /* 2. Operations on the faces can go here for now. I might + * want to mix this code with the blending. Currently, I only + * handle env/ztra faces. It's a dirty patch now...*/ + subStackPtr = subStackSize - 1; + while (subStackPtr >= 0) { + /* we can make a general meachanism here for operations */ + if (stack[subStack[subStackPtr]].faceType == RE_POLY){ + VlakRen* vlr = (VlakRen*) stack[subStack[subStackPtr]].data; + if (vlr->mat) { + /* ENV faces */ + if (vlr->mat->mode & MA_ENV) { + int m; + colSubStack[4*subStackPtr] = 0.0; + colSubStack[(4*subStackPtr) + 1] = 0.0; + colSubStack[(4*subStackPtr) + 2] = 0.0; + colSubStack[(4*subStackPtr) + 3] = 0.0; + m = subStackPtr - 1; + while (m >= 0) { + if (stack[subStack[m]].faceType != RE_SKY) { + colSubStack[4*m] = 0.0; + colSubStack[(4*m) + 1] = 0.0; + colSubStack[(4*m) + 2] = 0.0; + colSubStack[(4*m) + 3] = 0.0; + } + m--; + } + } + /* ZTRA faces */ + else if (!(vlr->mat->mode & MA_ZTRA)) { + int m; + m = subStackPtr - 1; + while (m >= 0) { + if (stack[subStack[m]].faceType != RE_SKY) { + colSubStack[4*m] = 0.0; + colSubStack[(4*m) + 1] = 0.0; + colSubStack[(4*m) + 2] = 0.0; + colSubStack[(4*m) + 3] = 0.0; + } + m--; + } + } + } + } + subStackPtr--; + } + + /* 3. blend down */ + subStackPtr = 0; + while( subStackPtr < subStackSize ) { + blendOverFloat(stack[subStack[subStackPtr]].faceType, /* type */ + sampcol + (4 * i), /* dest */ + &colSubStack[4 * subStackPtr], + stack[subStack[subStackPtr]].data); /* data */ + subStackPtr++; + } + + i++; + } +} + + + +/* ------------------------------------------------------------------------- */ +/* Rendering: per line */ +/* */ +/* For each pixel in this line, we render as follows: */ +/* a. Count the number of objects buffered for this pixel, and sort on z */ +/* ------- Result is left in zrow */ +/* b. Shade the pixel: */ +/* 1. From front to back: calculate the colour for this object */ +/* 2. Blend this colour in with the already calculated colour */ +/* Repeat 1. and 2. until no faces remain. */ +/* For each pixel, a face is only rendered once, even if it is */ +/* jittered. All subpixels get the colour of the weighted centre */ +/* of the jitter-positions this face covers. */ +/* ------- Result is left in sampcol[] */ +/* c. Copy the result to the colour buffer */ +/* d. Do gamma-corrected blending */ +/* */ +/* zrow may need some clarification: */ +/* 0 - min. distance */ +/* 1 - face/halo index */ +/* 2 - masks */ +/* 3 - type RE_POLY or RE_HALO */ +/* 4 - max. distance */ +/* It is used to store copies of RE_APixstrExt records. These are sorted for */ +/* distance, and then used for rendering pixels. zrow might be replaced by */ +/* an RE_APixstrExt* array */ +/* - redo the numbering to something more logical */ +void renderZBufLine(int y) { + int zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE]; + RE_APixstrExt *ap; /* iterator for the face-lists */ + int apteller; + int x; /* pixel counter */ + RE_COLBUFTYPE *colbuf; /* pointer into the line buffer */ + RE_COLBUFTYPE *j = NULL; /* generic pixel pointer */ + int i; /* yet another counter */ + int stackDepth; /* faces-behind-this-pixel counter */ + struct RE_faceField RE_OSAstack[RE_MAX_FACES_PER_PIXEL + 1]; + int RE_OSAstack_ptr; /* Points to the lowest empty field. The indexed */ + /* field is NOT readable. */ + + /* Prepare buffers and iterators */ + colbuf = AColourBuffer; + eraseColBuf(AColourBuffer); + ap = APixbufExt + (zBufferWidth * (y - Aminy)); + apteller = (zBufferWidth * (y - Aminy)); + + /* Rendering: give the right colour to this pixel (shade it) */ + for( x = 0; x < bufferWidth; x++, ap++, colbuf+=4) { + if(ap->t[0]) { + /* reset sample collector */ + j = sampcol; + for(i = 0; i < osaNr; i++, j+=4) { + j[0] = RE_ZERO_COLOUR_FLOAT; j[1] = RE_ZERO_COLOUR_FLOAT; + j[2] = RE_ZERO_COLOUR_FLOAT; j[3] = RE_ZERO_COLOUR_FLOAT; + }; + + /* a. count and sort number of faces */ + stackDepth = countAndSortPixelFaces(zrow, ap); + + /* b,c. oversample all subpixels, then integrate */ + RE_OSAstack_ptr = 0; + RE_OSAstack_ptr = composeStack(zrow, + RE_OSAstack, RE_OSAstack_ptr, + stackDepth, x, y, osaNr); +/* #ifdef RE_OLD_INTEGRATION */ +/* printf("Performing old integration\n"); */ +/* integrateStack(RE_OSAstack, RE_OSAstack_ptr, */ +/* x, y, osaNr); */ +/* #endif */ +/* #ifndef RE_OLD_INTEGRATION */ +/* printf("Performing new integration\n"); */ + integratePerSubStack(RE_OSAstack, RE_OSAstack_ptr, + x, y, osaNr); +/* #endif */ + + /* d. Gamma corrected blending */ + sampleFloatColV2FloatColV(sampcol, colbuf, osaNr); + } else { + /* Remember to do things back-to-front! */ + + /* This is a bit dirty. Depending on sky-mode, the pixel is */ + /* blended in differently. */ + renderSkyPixelFloat(x, y); + cpFloatColV(collector, colbuf); + + /* Spothalos are part of the normal pixelshader, so for covered */ + /* pixels they are handled ok. They are 'normally' alpha blended */ + /* onto the existing colour in the collector. */ + if(R.flag & R_LAMPHALO) { + renderSpotHaloPixel(x, y, collector); + } + addAlphaOverFloat(colbuf, collector); + } + } /* End of pixel loop */ + +} /* End of void renderZBufLine(int y) */ + + +/* ------------------------------------------------------------------------- */ + +int fillZBufDistances() +{ + int keepLooping = 1; + + keepLooping = zBufferAllFaces(); /* Solid and transparent faces*/ + keepLooping = zBufferAllHalos() && keepLooping; /* ...and halos*/ + return keepLooping; + +} /* End of void fillZBufDistances() */ + +/* ------------------------------------------------------------------------- */ +/* Transparent faces and the 'Azvoordeel' */ +/* A transparent face can get a z-offset, which is a */ +/* way of pretending the face is a bit closer than it */ +/* actually is. This is used in animations, when faces */ +/* that are used to glue on animated characters, items, */ +/* et. need their shadows to be drawn on top of the */ +/* objects they stand on. The Azvoordeel is added to */ +/* the calculated z-coordinate in the buffer-fill */ +/* procedures. */ + +/* static int RE_treat_face_as_opaque; */ + +int zBufferAllFaces(void) +{ + int keepLooping = 1; + int faceCounter; /* counter for face number */ + float vec[3], hoco[4], mul, zval, fval; + Material *ma=0; + + faceCounter = 0; + +/* printf("Going to buffer faces:\n"); */ +/* printf("\tfirst pass:\n"); */ + +/* RE_treat_face_as_opaque = 1; */ + + while ( (faceCounter < R.totvlak) && keepLooping) { + if((faceCounter & 255)==0) { Zvlr= R.blovl[faceCounter>>8]; } + else Zvlr++; + + ma= Zvlr->mat; + + /* VERY dangerous construction... zoffs is set by a slide in the ui */ + /* so it should be safe... */ + if((ma->mode & (MA_ZTRA)) && (ma->zoffs != 0.0)) { + mul= 0x7FFFFFFF; + zval= mul*(1.0+Zvlr->v1->ho[2]/Zvlr->v1->ho[3]); + + VECCOPY(vec, Zvlr->v1->co); + /* z is negatief, wordt anders geclipt */ + vec[2]-= ma->zoffs; + RE_projectverto(vec, hoco); /* vec onto hoco */ + fval= mul*(1.0+hoco[2]/hoco[3]); + + Azvoordeel= (int) fabs(zval - fval ); + } else { + Azvoordeel= 0; + } + /* face number is used in the fill functions */ + Zvlnr = faceCounter + 1; + + if(Zvlr->flag & R_VISIBLE) { /* might test for this sooner... */ + + if(ma->mode & (MA_WIRE)) zbufclipwire(Zvlr); + else { + zbufclip(Zvlr->v1->ho, Zvlr->v2->ho, Zvlr->v3->ho, + Zvlr->v1->clip, Zvlr->v2->clip, Zvlr->v3->clip); + if(Zvlr->v4) { + Zvlnr+= 0x800000; /* in a sense, the 'adjoint' face */ + zbufclip(Zvlr->v1->ho, Zvlr->v3->ho, Zvlr->v4->ho, + Zvlr->v1->clip, Zvlr->v3->clip, Zvlr->v4->clip); + } + } + } + if(RE_local_test_break()) keepLooping = 0; + faceCounter++; + } + + return keepLooping; +} /* End of int zBufferAllFaces(void) */ + +/* ------------------------------------------------------------------------- */ +/* We cheat a little here: we only fill the halo on the first pass, and we */ +/* set a full complement of mask flags. This can be done because we consider */ +/* halos to be flat (billboards), so we do not have to correct the z range */ +/* every time we insert a halo. Also, halos fall off to zero at the edges, */ +/* so we can safely render them in pixels where they do not exist. */ +int zBufferAllHalos(void) +{ + HaloRen *har = NULL; + unsigned int haloCounter = 0; + int dist = 0; + int keepLooping = 1; + short miny = 0, maxy = 0, minx = 0, maxx = 0; + short ycount = 0, xcount = 0; + RE_APixstrExt *ap, *apoffset; + int mask; /* jitter mask */ + + if (!Zsample) + { + mask = (1 << osaNr) - 1 ; /* Fill all samples together */ + + while ( (haloCounter < R.tothalo) && keepLooping) { + if((haloCounter & 255)==0) har= R.bloha[haloCounter>>8]; + else har++; + + /* Halos are sometimes wrongly kicked out of the box they belong */ + /* in... */ + + /* Only buffer the current alpha buffer contents!!! The line */ + /* indices have already been clipped to picture size. */ + minx = floor(har->xs - har->rad) - 1; /* assume min =< max is true*/ + if (minx < 0 ) minx = 0; + maxx = ceil(har->xs + har->rad ) + 1; + /* Do the extra -1 because of the +1 later on. I guess halos might */ + /* have to start one pixel sooner? Or maybe the lower clip should */ + /* be adjusted */ + if (maxx >= zBufferWidth - 1) maxx = zBufferWidth - 2; + + miny = har->miny; + if (miny < Aminy) miny = Aminy; + maxy = har->maxy; + if (maxy > Amaxy) maxy = Amaxy; + + if ( (minx <= maxx) && (miny <= maxy)) { + /* distance to this halo? */ + dist = har->zBufDist /* * R.ycor */; + /* strange that the ycor influences the z coordinate ..*/ + ycount = miny; + while (ycount <= maxy) { + apoffset = APixbufExt + (zBufferWidth * (ycount - Aminy)); + ap = apoffset + minx; + xcount = minx; + while (xcount <= maxx) { + insertFlatObjectNoOsa(ap, haloCounter, RE_HALO, dist, mask); + xcount++; + ap++; + } + ycount++; + } + } + if(RE_local_test_break()) keepLooping = 0; + haloCounter++; + } + } + + return keepLooping; +} /* end of int zbufferAllHalos(void) */ + +/* ------------------------------------------------------------------------- */ +void zBufferFillHalo(void) +{ + /* so far, intentionally empty */ +} /* end of void zBufferFillHalo(void) */ + +/* ------------------------------------------------------------------------- */ +void zBufferFillFace(float *v1, float *v2, float *v3) +{ + /* Coordinates of the vertices are specified in ZCS */ + int apteller, apoffsetteller; + double z0; /* used as temp var*/ + double xx1; + double zxd,zyd,zy0, tmp; + float *minv,*maxv,*midv; + register int zverg,zvlak,x; + int my0,my2,sn1,sn2,rectx,zd; + int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2, mask; + + /* These used to be doubles. We may want to change them back if the */ + /* loss of accuracy proves to be a problem? There does not seem to be */ + /* any performance issues here, so I'll just keep the doubles. */ + /* float vec0[3], vec1[3], vec2[3]; */ + double vec0[3], vec1[3], vec2[3]; + + /* MIN MAX */ + /* sort vertices for min mid max y value */ + if(v1[1] Amaxy)) return; + + if(my02.0/65536.0) { + z0= (maxv[0]-minv[0])/xx1; + + tmp= (-65536.0*z0); + dx0= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(my2-minv[1])+minv[0]); + xs0= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx0= 0; + xs0= 65536.0*(MIN2(minv[0],maxv[0])); + } + /* EDGES : DE BOVENSTE */ + xx1= maxv[1]-midv[1]; + if(xx1>2.0/65536.0) { + z0= (maxv[0]-midv[0])/xx1; + + tmp= (-65536.0*z0); + dx1= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(my2-midv[1])+midv[0]); + xs1= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx1= 0; + xs1= 65536.0*(MIN2(midv[0],maxv[0])); + } + /* EDGES : DE ONDERSTE */ + xx1= midv[1]-minv[1]; + if(xx1>2.0/65536.0) { + z0= (midv[0]-minv[0])/xx1; + + tmp= (-65536.0*z0); + dx2= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]); + xs2= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx2= 0; + xs2= 65536.0*(MIN2(minv[0],midv[0])); + } + + /* ZBUF DX DY */ + /* xyz_1 = v_1 - v_2 */ + MTC_diff3DFF(vec1, v1, v2); + /* xyz_2 = v_2 - v_3 */ + MTC_diff3DFF(vec2, v2, v3); + /* xyz_0 = xyz_1 cross xyz_2 */ + MTC_cross3Double(vec0, vec1, vec2); + + /* cross product of two of the sides is 0 => this face is too small */ + if(vec0[2]==0.0) return; + + if(midv[1] == maxv[1]) omsl= my2; + if(omsl < Aminy) omsl= Aminy-1; /* dan neemt ie de eerste lus helemaal */ + + while (my2 > Amaxy) { /* my2 kan groter zijn */ + xs0+=dx0; + if (my2<=omsl) { + xs2+= dx2; + } + else{ + xs1+= dx1; + } + my2--; + } + + xx1= (vec0[0]*v1[0]+vec0[1]*v1[1])/vec0[2]+v1[2]; + + zxd= -vec0[0]/vec0[2]; + zyd= -vec0[1]/vec0[2]; + zy0= my2*zyd+xx1; + zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX); + + /* start-ofset in rect */ + /* rectx= R.rectx; */ + /* I suspect this var needs very careful setting... When edge rendering */ + /* is on, this is strange */ + rectx = zBufferWidth; + apoffsetteller = rectx*(my2-Aminy); + + mask= 1<dx1) { + MTC_swapInt(&xs0, &xs1); + MTC_swapInt(&dx0, &dx1); + xs3= 1; /* flag */ + + } + + for(y=my2;y>omsl;y--) { + + sn1= xs0>>16; + xs0+= dx0; + + sn2= xs1>>16; + xs1+= dx1; + + sn1++; + + if(sn2>=rectx) sn2= rectx-1; + if(sn1<0) sn1= 0; + zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX); + apteller = apoffsetteller + sn1; + x= sn2-sn1; + + zverg-= Azvoordeel; + + while(x>=0) { + insertObject(apteller, /* RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, zverg, mask); + zverg+= zd; + apteller++; + x--; + } + zy0-= zyd; + apoffsetteller -= rectx; + } + + if(xs3) { + xs0= xs1; + dx0= dx1; + } + if(xs0>xs2) { + xs3= xs0; + xs0= xs2; + xs2= xs3; + xs3= dx0; + dx0= dx2; + dx2= xs3; + } + + for(; y>=my0; y--) { + + sn1= xs0>>16; + xs0+= dx0; + + sn2= xs2>>16; + xs2+= dx2; + + sn1++; + + if(sn2>=rectx) sn2= rectx-1; + if(sn1<0) sn1= 0; + zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX); + apteller = apoffsetteller + sn1; + x= sn2-sn1; + + zverg-= Azvoordeel; + + while(x>=0) { + insertObject(apteller, /* RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, zverg, mask); + zverg+= zd; + apteller++; + x--; + } + + zy0-=zyd; + apoffsetteller -= rectx; + } +} /* end of void zBufferFillFace(float *v1, float *v2, float *v3) */ + +/* ------------------------------------------------------------------------- */ + +void zBufferFillEdge(float *vec1, float *vec2) +{ + int apteller; + int start, end, x, y, oldx, oldy, ofs; + int dz, vergz, mask; + float dx, dy; + float v1[3], v2[3]; + + dx= vec2[0]-vec1[0]; + dy= vec2[1]-vec1[1]; + + if(fabs(dx) > fabs(dy)) { + + /* alle lijnen van links naar rechts */ + if(vec1[0]= zBufferWidth) end = zBufferWidth - 1; + + oldy= floor(v1[1]); + dy/= dx; + + vergz= v1[2]; + vergz-= Azvoordeel; + dz= (v2[2]-v1[2])/dx; + + apteller = zBufferWidth*(oldy-Aminy) +start; + mask = 1<=0 && y>=Aminy && y<=Amaxy) { + insertObject(apteller, /* RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, vergz, mask); + } + + v1[1]+= dy; + vergz+= dz; + } + } + else { + + /* alle lijnen van onder naar boven */ + if(vec1[1]Amaxy || endAmaxy) end= Amaxy; + + oldx= floor(v1[0]); + dx/= dy; + + vergz= v1[2]; + vergz-= Azvoordeel; + dz= (v2[2]-v1[2])/dy; + + apteller = zBufferWidth*(start-Aminy) +oldx; + + mask= 1<=0 && y>=Aminy && (x < zBufferWidth)) { + insertObject(apteller, /* RE_treat_face_as_opaque, */ Zvlnr, RE_POLY, vergz, mask); + } + + v1[0]+= dx; + vergz+= dz; + } + } +} /* End of void zBufferFillEdge(float *vec1, float *vec2) */ + + +/* ------------------------------------------------------------------------- */ +/* Colour buffer related: */ +/* This transforms the 4 inputvalues RE_COLBUFTYPE to a new value */ +/* It expects the values R.r.postigamma, R.r.postmul and R.r.postadd. */ +/* This is the standard transformation, more elaborate tools are for later. */ +/* ------------------------------------------------------------------------- */ +void std_transFloatColV2CharColV( RE_COLBUFTYPE *buf, char *target) +{ + float fval; + + /* alpha */ + if(buf[3]<=0.0) target[3]= 0; + else if(buf[3]>1.0) target[3]= 255; + else target[3]= 255.0*buf[3]; + + if(R.r.postgamma==1.0) { + /* r */ + fval= R.r.postmul*buf[0] + R.r.postadd; + if(fval<=0.0) target[0]= 0; + else if(fval>1.0) target[0]= 255; + else target[0]= 255.0*fval; + + /* g */ + fval= R.r.postmul*buf[1] + R.r.postadd; + if(fval<=0.0) target[1]= 0; + else if(fval>1.0) target[1]= 255; + else target[1]= 255.0*fval; + + /* b */ + fval= R.r.postmul*buf[2] + R.r.postadd; + if(fval<=0.0) target[2]= 0; + else if(fval>1.0) target[2]= 255; + else target[2]= 255.0*fval; + + } + else { + /* putting the postmul within the pow() gives an + * easier control for the user, values from 1.0-2.0 + * are relevant then + */ + + + /* r */ + fval= pow(R.r.postmul*buf[0], R.r.postigamma) + R.r.postadd; + if(fval<=0.0) target[0]= 0; + else if(fval>1.0) target[0]= 255; + else target[0]= 255.0*fval; + + /* g */ + fval=pow( R.r.postmul*buf[1], R.r.postigamma) + R.r.postadd; + if(fval<=0.0) target[1]= 0; + else if(fval>1.0) target[1]= 255; + else target[1]= 255.0*fval; + + /* b */ + fval= pow(R.r.postmul*buf[2], R.r.postigamma) + R.r.postadd; + if(fval<=0.0) target[2]= 0; + else if(fval>1.0) target[2]= 255; + else target[2]= 255.0*fval; + } + +} /* end of void std_transFloatColV2CharColV( RE_COLBUFTYPE *buf, uchar *target) */ + + +/* ---------------------------------------------------------------------------- + + Colour buffer related: + + The colour buffer is a buffer of a single screen line. It contains + four fields of type RE_COLBUFTYPE per pixel. + + We can do several post-process steps. I would prefer to move them outside + the render module later on, but it's ok to leave it here for now. For the + time being, we have: + - post-process function + Does some operations with the colours. + - Multiply with some factor + - Add constant offset + - Apply extra gamma correction (seems weird...) + - key-alpha correction + Key alpha means 'un-applying' the alpha. For fully covered pixels, this + operation has no effect. + +---------------------------------------------------------------------------- */ +void transferColourBufferToOutput(int y) +{ + /* Copy the contents of AColourBuffer to R.rectot + y * R.rectx */ + int x = 0; + RE_COLBUFTYPE *buf = AColourBuffer; + char *target = (char*) (R.rectot + (y * imageWidth)); + +#ifdef RE_FULL_SAFETY + /* since the R.rectot always has size imageWidth * imageHeight, this */ + /* check is possible. I may want to check this per assignment later on. */ + if ( (y < 0) || ((y > (imageHeight - 1) ))) { + char fname[] = "transferColourBufferToOutput"; + RE_error_int(RE_WRITE_OUTSIDE_COLOUR_BUFFER, fname, y); + return; + } +#endif + + /* Copy the first pixels. We can do some more clipping on */ + /* the z buffer, I think. */ + while (x < imageWidth) { + + std_transFloatColV2CharColV(buf, target); + + /* old function was: leave it for test */ +/* cpFloatColV2CharColV(buf, target); */ + + /* + Key-alpha mode: + Need to un-apply alpha if alpha is non-full. For full alpha, + the operation doesn't have effect. Do this after the post- + processing, so we can still use the benefits of that. + + */ + + if (getSkyBlendingMode() == RE_ALPHA_KEY) { + applyKeyAlphaCharCol(target); + } + + target+=4; + buf+=4; + x++; + } +} /* end of void transferColourBufferToOutput(int y) */ + +/* ------------------------------------------------------------------------- */ + +void eraseColBuf(RE_COLBUFTYPE *buf) { + /* By definition, the buffer's length is 4 * R.rectx items */ + int i = 0; +/* while (i < 4 * R.rectx) { */ + while (i < 4 * bufferWidth) { + *buf = RE_ZERO_COLOUR_FLOAT; + buf++; i++; + } +} /* End of void eraseColBuf(RE_COLBUFTYPE *buf) */ + +/* ------------------------------------------------------------------------- */ + +int calcDepth(float x, float y, void* data, int type) +{ +#ifdef RE_FULL_SAFETY + char fname[] = "calcDepth"; + if (data == NULL) { + RE_error(RE_BAD_DATA_POINTER, fname); + return 0; + } +#endif + + if (type & RE_POLY) { + VlakRen* vlr = (VlakRen*) data; + VertRen* v1; + float dvlak, deler, fac, hoco_z, hoco_w; + int zbuf_co; + + v1 = vlr->v1; + + /* vertex dot face normal: WCS */ + dvlak= v1->co[0]*vlr->n[0]+v1->co[1]*vlr->n[1]+v1->co[2]*vlr->n[2]; + + /* jitter has been added to x, y ! */ + /* view vector R.view: screen coords */ + if( (G.special1 & G_HOLO) && + ((Camera *)G.scene->camera->data)->flag & CAM_HOLO2) { + R.view[0]= (x+(R.xstart) + 0.5 +holoofs); + } else R.view[0]= (x+(R.xstart) + 0.5 ); + + if(R.flag & R_SEC_FIELD) { + if(R.r.mode & R_ODDFIELD) R.view[1]= (y + R.ystart)*R.ycor; + else R.view[1]= (y+R.ystart + 1.0)*R.ycor; + } else R.view[1]= (y+R.ystart + 0.5 )*R.ycor; + + + /* for pano, another rotation in the xz plane is needed.... */ + + /* this is ok, in WCS */ + R.view[2]= -R.viewfac; /* distance to viewplane */ + + /* face normal dot view vector: but how can this work? */ + deler = MTC_dot3Float(vlr->n, R.view); + if (deler!=0.0) fac = dvlak/deler; + else fac = 0.0; + + /* indices are wrong.... but gives almost the right value? */ + hoco_z = (fac*R.view[2]) * R.winmat[2][2] + R.winmat[3][2]; + hoco_w = (fac*R.view[2]) * R.winmat[2][3] + R.winmat[3][3]; + + zbuf_co = 0x7FFFFFFF*(hoco_z/hoco_w); + + return zbuf_co; /* z component of R.co */ + } else if (type & RE_HALO) { + HaloRen* har = (HaloRen*) data; + return har->zBufDist; + } +#ifdef RE_FULL_SAFETY + else RE_error(RE_BAD_FACE_TYPE, fname); +#endif /* RE_FULL_SAFETY */ + return 0; +} /* end of int calcDepth(float x, float y, void* data, int type) */ + +/* Maybe these two should be in pixelblendeing.c---------------------------- */ + +void blendOverFloat(int type, float* dest, float* source, void* data) +{ +#ifdef RE_FULL_SAFETY + char fname[] = "blendOverFloat"; + if (data == NULL){ + RE_error(RE_BAD_DATA_POINTER, fname); + return; + } +#endif + + if (type & RE_POLY) { + VlakRen *ver = (VlakRen*) data; + if ((ver->mat != NULL) && (ver->mat->add > RE_FACE_ADD_THRESHOLD)) { + char addf = (char) (ver->mat->add * 255.0); + addalphaAddfacFloat(dest, source, addf); + } + else + addAlphaOverFloat(dest, source); + } else if (type & RE_HALO) { + HaloRen *har= (HaloRen*) data; + addalphaAddfacFloat(dest, source, har->add); + } else if (type & RE_SKY) { + addAlphaOverFloat(dest, source); + } +#ifdef RE_FULL_SAFETY + else RE_error(RE_BAD_FACE_TYPE, fname); +#endif + +} /* end of void blendOverFloat(int , float*, float*, void*) */ + +/* ------------------------------------------------------------------------- */ +void blendOverFloatRow(int type, float* dest, float* source, + void* data, int mask, int osaNr) +{ +#ifdef RE_FULL_SAFETY + char* fname = "blendOverFloatRow"; + if ((data == NULL) && ((type & RE_POLY) || (type & RE_HALO))) { + RE_error(RE_BAD_DATA_POINTER, fname); + return; + } +#endif + + if (type & RE_POLY) { + VlakRen *ver = (VlakRen*) data; + if ((ver->mat != NULL) + && (ver->mat->add > RE_FACE_ADD_THRESHOLD)) { + char addf = (ver->mat->add * 255.0); + addAddSampColF(dest, source, mask, osaNr, addf); + } else { + addOverSampColF(dest, source, mask, osaNr); + } + } else if (type & RE_HALO) { + HaloRen *har = (HaloRen*) data; + addAddSampColF(dest, source, mask, osaNr, har->add); + } else if (type & RE_SKY) { + addOverSampColF(dest, source, mask, osaNr); + } +#ifdef RE_FULL_SAFETY + else RE_error(RE_BAD_FACE_TYPE, fname); +#endif +} /* end of void blendOverFloatRow(int, float*, float*, void*) */ + +/* ------------------------------------------------------------------------- */ + +/* eof vanillaRenderPipe.c */ diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c new file mode 100644 index 00000000000..295e13b8d5f --- /dev/null +++ b/source/blender/render/intern/source/zbuf.c @@ -0,0 +1,2329 @@ +/** + * $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 ***** + */ + +/*---------------------------------------------------------------------------*/ +/* Common includes */ +/*---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include "MTC_matrixops.h" +#include "MEM_guardedalloc.h" + +#include "BKE_global.h" + +#include "DNA_lamp_types.h" +#include "DNA_mesh_types.h" + +#include "radio_types.h" +#include "radio.h" /* needs RG, some root data for radiosity */ + +#include "render.h" +#include "render_intern.h" +#include "RE_callbacks.h" +#include "old_zbuffer_types.h" +/* local includes */ +/* can be removed when the old renderer disappears */ +#include "rendercore.h" /* shade_pixel and count_mask */ +#include "pixelblending.h" +#include "jitter.h" + +/* own includes */ +#include "zbuf.h" +#include "zbuf_int.h" + +/* crud */ +#define MIN2(x,y) ( (x)<(y) ? (x) : (y) ) +/*-----------------------------------------------------------*/ +/* Globals for this file */ +/*-----------------------------------------------------------*/ + +extern float centLut[16]; +extern char *centmask; + +float *vlzp[32][3], labda[3][2], vez[400], *p[40]; + +float Zmulx; /* Half the screenwidth, in pixels. (used in render.c, */ + /* zbuf.c) */ +float Zmuly; /* Half the screenheight, in pixels. (used in render.c,*/ + /* zbuf.c) */ +float Zjitx; /* Jitter offset in x. When jitter is disabled, this */ + /* should be 0.5. (used in render.c, zbuf.c) */ +float Zjity; /* Jitter offset in y. When jitter is disabled, this */ + /* should be 0.5. (used in render.c, zbuf.c) */ + +unsigned int Zvlnr, Zsample; +VlakRen *Zvlr; +void (*zbuffunc)(float *, float *, float *); +void (*zbuflinefunc)(float *, float *); + +APixstr *APixbuf; /* Zbuffer: linked list of face indices */ +unsigned short *Acolrow; /* Zbuffer: colour buffer, one line high */ +int *Arectz; /* Zbuffer: distance buffer, almost obsolete */ +int Aminy; /* y value of first line in the accu buffer */ +int Amaxy; /* y value of last line in the accu buffer */ +int Azvoordeel = 0; +APixstrMain apsmfirst; +short apsmteller = 0; + +/*-----------------------------------------------------------*/ +/* Functions */ +/*-----------------------------------------------------------*/ + +void fillrect(unsigned int *rect, int x, unsigned int y, unsigned int val) +{ + unsigned int len,*drect; + + len= x*y; + drect= rect; + while(len>0) { + len--; + *drect= val; + drect++; + } +} + +/* ************* ACCU ZBUF ************ */ + +/*-APixstr---------------------------------------------------*/ + +APixstr *addpsmainA() +{ + APixstrMain *psm; + + psm= &apsmfirst; + + while(psm->next) { + psm= psm->next; + } + + psm->next= MEM_mallocN(sizeof(APixstrMain), "addpsmainA"); + + psm= psm->next; + psm->next=0; + psm->ps= MEM_callocN(4096*sizeof(APixstr),"pixstr"); + apsmteller= 0; + + return psm->ps; +} + +void freepsA() +{ + APixstrMain *psm, *next; + + psm= &apsmfirst; + + while(psm) { + next= psm->next; + if(psm->ps) { + MEM_freeN(psm->ps); + psm->ps= 0; + } + if(psm!= &apsmfirst) MEM_freeN(psm); + psm= next; + } + + apsmfirst.next= 0; + apsmfirst.ps= 0; + apsmteller= 0; +} + +APixstr *addpsA(void) +{ + static APixstr *prev; + + /* eerste PS maken */ + if((apsmteller & 4095)==0) prev= addpsmainA(); + else prev++; + apsmteller++; + + return prev; +} + +/* vult kleur in, met windowcoordinaat, van Aminy->Amaxy */ +void zbufinvulAc(float *v1, float *v2, float *v3) +{ + APixstr *ap, *apofs, *apn; + double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1; + double zxd,zyd,zy0, tmp; + float *minv,*maxv,*midv; + int *rz,zverg,x; + int my0,my2,sn1,sn2,rectx,zd,*rectzofs; + int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2, mask; + + /* MIN MAX */ + if(v1[1] Amaxy) return; + + if(my02.0/65536.0) { + z0= (maxv[0]-minv[0])/xx1; + + tmp= (-65536.0*z0); + dx0= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(my2-minv[1])+minv[0]); + xs0= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx0= 0; + xs0= 65536.0*(MIN2(minv[0],maxv[0])); + } + /* EDGES : DE BOVENSTE */ + xx1= maxv[1]-midv[1]; + if(xx1>2.0/65536.0) { + z0= (maxv[0]-midv[0])/xx1; + + tmp= (-65536.0*z0); + dx1= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(my2-midv[1])+midv[0]); + xs1= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx1= 0; + xs1= 65536.0*(MIN2(midv[0],maxv[0])); + } + /* EDGES : DE ONDERSTE */ + xx1= midv[1]-minv[1]; + if(xx1>2.0/65536.0) { + z0= (midv[0]-minv[0])/xx1; + + tmp= (-65536.0*z0); + dx2= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]); + xs2= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx2= 0; + xs2= 65536.0*(MIN2(minv[0],midv[0])); + } + + /* ZBUF DX DY */ + x1= v1[0]- v2[0]; + x2= v2[0]- v3[0]; + y1= v1[1]- v2[1]; + y2= v2[1]- v3[1]; + z1= v1[2]- v2[2]; + z2= v2[2]- v3[2]; + x0= y1*z2-z1*y2; + y0= z1*x2-x1*z2; + z0= x1*y2-y1*x2; + if(z0==0.0) return; + + if(midv[1]==maxv[1]) omsl= my2; + if(omsl Amaxy) { /* my2 kan groter zijn */ + xs0+=dx0; + if (my2<=omsl) { + xs2+= dx2; + } + else{ + xs1+= dx1; + } + my2--; + } + + xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2]; + + zxd= -x0/z0; + zyd= -y0/z0; + zy0= my2*zyd+xx1; + zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX); + + /* start-ofset in rect */ + rectx= R.rectx; + rectzofs= (int *)(Arectz+rectx*(my2-Aminy)); + apofs= (APixbuf+ rectx*(my2-Aminy)); + mask= 1<dx1) { + xs3= xs0; + xs0= xs1; + xs1= xs3; + xs3= dx0; + dx0= dx1; + dx1= xs3; + xs3= 1; /* flag */ + + } + + for(y=my2;y>omsl;y--) { + + sn1= xs0>>16; + xs0+= dx0; + + sn2= xs1>>16; + xs1+= dx1; + + sn1++; + + if(sn2>=rectx) sn2= rectx-1; + if(sn1<0) sn1= 0; + zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX); + rz= rectzofs+sn1; + ap= apofs+sn1; + x= sn2-sn1; + + zverg-= Azvoordeel; + + while(x>=0) { + if(zverg< *rz) { + apn= ap; + while(apn) { /* loopunrolled */ + if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; } + if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; } + if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; } + if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; } + if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; } + if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; } + if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; } + if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; } + if(apn->next==0) apn->next= addpsA(); + apn= apn->next; + } + } + zverg+= zd; + rz++; + ap++; + x--; + } + zy0-= zyd; + rectzofs-= rectx; + apofs-= rectx; + } + + if(xs3) { + xs0= xs1; + dx0= dx1; + } + if(xs0>xs2) { + xs3= xs0; + xs0= xs2; + xs2= xs3; + xs3= dx0; + dx0= dx2; + dx2= xs3; + } + + for(; y>=my0; y--) { + + sn1= xs0>>16; + xs0+= dx0; + + sn2= xs2>>16; + xs2+= dx2; + + sn1++; + + if(sn2>=rectx) sn2= rectx-1; + if(sn1<0) sn1= 0; + zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX); + rz= rectzofs+sn1; + ap= apofs+sn1; + x= sn2-sn1; + + zverg-= Azvoordeel; + + while(x>=0) { + if(zverg< *rz) { + apn= ap; + while(apn) { /* loopunrolled */ + if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; } + if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; } + if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; } + if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; } + if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; } + if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; } + if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; } + if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; } + if(apn->next==0) apn->next= addpsA(); + apn= apn->next; + } + } + zverg+= zd; + rz++; + ap++; + x--; + } + + zy0-=zyd; + rectzofs-= rectx; + apofs-= rectx; + } +} + +void zbuflineAc(float *vec1, float *vec2) +{ + APixstr *ap, *apn; + unsigned int *rectz; + int start, end, x, y, oldx, oldy, ofs; + int dz, vergz, mask; + float dx, dy; + float v1[3], v2[3]; + + dx= vec2[0]-vec1[0]; + dy= vec2[1]-vec1[1]; + + if(fabs(dx) > fabs(dy)) { + + /* alle lijnen van links naar rechts */ + if(vec1[0]=R.rectx) end= R.rectx-1; + + oldy= floor(v1[1]); + dy/= dx; + + vergz= v1[2]; + vergz-= Azvoordeel; + dz= (v2[2]-v1[2])/dx; + + rectz= (unsigned int *)(Arectz+R.rectx*(oldy-Aminy) +start); + ap= (APixbuf+ R.rectx*(oldy-Aminy) +start); + mask= 1<=0 && y>=Aminy && y<=Amaxy) { + if(vergz<*rectz) { + + apn= ap; + while(apn) { /* loopunrolled */ + if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; } + if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; } + if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; } + if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; } + if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; } + if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; } + if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; } + if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; } + if(apn->next==0) apn->next= addpsA(); + apn= apn->next; + } + + } + } + + v1[1]+= dy; + vergz+= dz; + } + } + else { + + /* alle lijnen van onder naar boven */ + if(vec1[1]Amaxy || endAmaxy) end= Amaxy; + + oldx= floor(v1[0]); + dx/= dy; + + vergz= v1[2]; + vergz-= Azvoordeel; + dz= (v2[2]-v1[2])/dy; + + rectz= (unsigned int *)( Arectz+ (start-Aminy)*R.rectx+ oldx ); + ap= (APixbuf+ R.rectx*(start-Aminy) +oldx); + mask= 1<=0 && y>=Aminy && xp[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; } + if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; } + if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; } + if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; } + if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; } + if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; } + if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; } + if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; } + if(apn->next==0) apn->next= addpsA(); + apn= apn->next; + } + + } + } + + v1[0]+= dx; + vergz+= dz; + } + } +} + + + +/* ************* NORMAL ZBUFFER ************ */ + +void hoco_to_zco(float *zco, float *hoco) +{ + float deler; + + deler= hoco[3]; + zco[0]= Zmulx*(1.0+hoco[0]/deler)+ Zjitx; + zco[1]= Zmuly*(1.0+hoco[1]/deler)+ Zjity; + zco[2]= 0x7FFFFFFF *(hoco[2]/deler); +} + +void zbufline(vec1, vec2) +float *vec1, *vec2; +{ + unsigned int *rectz, *rectp; + int start, end, x, y, oldx, oldy, ofs; + int dz, vergz; + float dx, dy; + float v1[3], v2[3]; + + dx= vec2[0]-vec1[0]; + dy= vec2[1]-vec1[1]; + + if(fabs(dx) > fabs(dy)) { + + /* alle lijnen van links naar rechts */ + if(vec1[0]=R.rectx) end= R.rectx-1; + + oldy= floor(v1[1]); + dy/= dx; + + vergz= v1[2]; + dz= (v2[2]-v1[2])/dx; + + rectz= R.rectz+ oldy*R.rectx+ start; + rectp= R.rectot+ oldy*R.rectx+ start; + + if(dy<0) ofs= -R.rectx; + else ofs= R.rectx; + + for(x= start; x<=end; x++, rectz++, rectp++) { + + y= floor(v1[1]); + if(y!=oldy) { + oldy= y; + rectz+= ofs; + rectp+= ofs; + } + + if(x>=0 && y>=0 && y=R.recty) end= R.recty-1; + + oldx= floor(v1[0]); + dx/= dy; + + vergz= v1[2]; + dz= (v2[2]-v1[2])/dy; + + rectz= R.rectz+ start*R.rectx+ oldx; + rectp= R.rectot+ start*R.rectx+ oldx; + + if(dx<0) ofs= -1; + else ofs= 1; + + for(y= start; y<=end; y++, rectz+=R.rectx, rectp+=R.rectx) { + + x= floor(v1[0]); + if(x!=oldx) { + oldx= x; + rectz+= ofs; + rectp+= ofs; + } + + if(x>=0 && y>=0 && xec; + if(ec==0) return; + + c1= vlr->v1->clip; + c2= vlr->v2->clip; + c3= vlr->v3->clip; + f1= vlr->v1->ho; + f2= vlr->v2->ho; + f3= vlr->v3->ho; + + if(vlr->v4) { + f4= vlr->v4->ho; + c4= vlr->v4->clip; + + and= (c1 & c2 & c3 & c4); + or= (c1 | c2 | c3 | c4); + } + else { + and= (c1 & c2 & c3); + or= (c1 | c2 | c3); + } + + if(or) { /* niet in midden */ + if(and) { /* helemaal eruit */ + return; + } + else { /* clippen */ + + if(ec & ME_V1V2) { + QUATCOPY(vez, f1); + QUATCOPY(vez+4, f2); + if( clipline(vez, vez+4)) { + hoco_to_zco(vez, vez); + hoco_to_zco(vez+4, vez+4); + zbuflinefunc(vez, vez+4); + } + } + if(ec & ME_V2V3) { + QUATCOPY(vez, f2); + QUATCOPY(vez+4, f3); + if( clipline(vez, vez+4)) { + hoco_to_zco(vez, vez); + hoco_to_zco(vez+4, vez+4); + zbuflinefunc(vez, vez+4); + } + } + if(vlr->v4) { + if(ec & ME_V3V4) { + QUATCOPY(vez, f3); + QUATCOPY(vez+4, f4); + if( clipline(vez, vez+4)) { + hoco_to_zco(vez, vez); + hoco_to_zco(vez+4, vez+4); + zbuflinefunc(vez, vez+4); + } + } + if(ec & ME_V4V1) { + QUATCOPY(vez, f4); + QUATCOPY(vez+4, f1); + if( clipline(vez, vez+4)) { + hoco_to_zco(vez, vez); + hoco_to_zco(vez+4, vez+4); + zbuflinefunc(vez, vez+4); + } + } + } + else { + if(ec & ME_V3V1) { + QUATCOPY(vez, f3); + QUATCOPY(vez+4, f1); + if( clipline(vez, vez+4)) { + hoco_to_zco(vez, vez); + hoco_to_zco(vez+4, vez+4); + zbuflinefunc(vez, vez+4); + } + } + } + + return; + } + } + + deler= f1[3]; + vez[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx; + vez[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity; + vez[2]= 0x7FFFFFFF *(f1[2]/deler); + + deler= f2[3]; + vez[4]= Zmulx*(1.0+f2[0]/deler)+ Zjitx; + vez[5]= Zmuly*(1.0+f2[1]/deler)+ Zjity; + vez[6]= 0x7FFFFFFF *(f2[2]/deler); + + deler= f3[3]; + vez[8]= Zmulx*(1.0+f3[0]/deler)+ Zjitx; + vez[9]= Zmuly*(1.0+f3[1]/deler)+ Zjity; + vez[10]= 0x7FFFFFFF *(f3[2]/deler); + + if(vlr->v4) { + deler= f4[3]; + vez[12]= Zmulx*(1.0+f4[0]/deler)+ Zjitx; + vez[13]= Zmuly*(1.0+f4[1]/deler)+ Zjity; + vez[14]= 0x7FFFFFFF *(f4[2]/deler); + + if(ec & ME_V3V4) zbuflinefunc(vez+8, vez+12); + if(ec & ME_V4V1) zbuflinefunc(vez+12, vez); + } + else { + if(ec & ME_V3V1) zbuflinefunc(vez+8, vez); + } + + if(ec & ME_V1V2) zbuflinefunc(vez, vez+4); + if(ec & ME_V2V3) zbuflinefunc(vez+4, vez+8); + + + +} + +void zbufinvulGLinv(v1,v2,v3) +float *v1,*v2,*v3; +/* vult in R.rectot de waarde Zvlnr in met R.rectz */ +/* KEERT Z-VERGELIJKING OM: ALLES ACHTER IS ZICHTBAAR */ +{ + double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1; + double zxd,zyd,zy0,tmp; + float *minv,*maxv,*midv; + unsigned int *rectpofs,*rp; + int *rz,zverg,zvlak,x; + int my0,my2,sn1,sn2,rectx,zd,*rectzofs; + int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2; + + /* MIN MAX */ + if(v1[1] R.recty) return; + + if(my0<0) my0=0; + + /* EDGES : DE LANGSTE */ + xx1= maxv[1]-minv[1]; + if(xx1>2.0/65536.0) { + z0= (maxv[0]-minv[0])/xx1; + + tmp= (-65536.0*z0); + dx0= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(my2-minv[1])+minv[0]); + xs0= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx0= 0; + xs0= 65536.0*(MIN2(minv[0],maxv[0])); + } + /* EDGES : DE BOVENSTE */ + xx1= maxv[1]-midv[1]; + if(xx1>2.0/65536.0) { + z0= (maxv[0]-midv[0])/xx1; + + tmp= (-65536.0*z0); + dx1= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(my2-midv[1])+midv[0]); + xs1= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx1= 0; + xs1= 65536.0*(MIN2(midv[0],maxv[0])); + } + /* EDGES : DE ONDERSTE */ + xx1= midv[1]-minv[1]; + if(xx1>2.0/65536.0) { + z0= (midv[0]-minv[0])/xx1; + + tmp= (-65536.0*z0); + dx2= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]); + xs2= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx2= 0; + xs2= 65536.0*(MIN2(minv[0],midv[0])); + } + + /* ZBUF DX DY */ + x1= v1[0]- v2[0]; + x2= v2[0]- v3[0]; + y1= v1[1]- v2[1]; + y2= v2[1]- v3[1]; + z1= v1[2]- v2[2]; + z2= v2[2]- v3[2]; + x0= y1*z2-z1*y2; + y0= z1*x2-x1*z2; + z0= x1*y2-y1*x2; + + if(z0==0.0) return; + + if(midv[1]==maxv[1]) omsl= my2; + if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */ + + while (my2 >= R.recty) { /* my2 kan groter zijn */ + xs0+=dx0; + if (my2<=omsl) { + xs2+= dx2; + } + else{ + xs1+= dx1; + } + my2--; + } + + xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2]; + + zxd= -x0/z0; + zyd= -y0/z0; + zy0= my2*zyd+xx1; + zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX); + + /* start-ofset in rect */ + rectx= R.rectx; + rectzofs= (int *)(R.rectz+rectx*my2); + rectpofs= (R.rectot+rectx*my2); + zvlak= Zvlnr; + + xs3= 0; /* flag */ + if(dx0>dx1) { + xs3= xs0; + xs0= xs1; + xs1= xs3; + xs3= dx0; + dx0= dx1; + dx1= xs3; + xs3= 1; /* flag */ + + } + + for(y=my2;y>omsl;y--) { + + sn1= xs0>>16; + xs0+= dx0; + + sn2= xs1>>16; + xs1+= dx1; + + sn1++; + + if(sn2>=rectx) sn2= rectx-1; + if(sn1<0) sn1= 0; + zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX); + rz= rectzofs+sn1; + rp= rectpofs+sn1; + x= sn2-sn1; + while(x>=0) { + if(zverg> *rz || *rz==0x7FFFFFFF) { + *rz= zverg; + *rp= zvlak; + } + zverg+= zd; + rz++; + rp++; + x--; + } + zy0-=zyd; + rectzofs-= rectx; + rectpofs-= rectx; + } + + if(xs3) { + xs0= xs1; + dx0= dx1; + } + if(xs0>xs2) { + xs3= xs0; + xs0= xs2; + xs2= xs3; + xs3= dx0; + dx0= dx2; + dx2= xs3; + } + + for(;y>=my0;y--) { + + sn1= xs0>>16; + xs0+= dx0; + + sn2= xs2>>16; + xs2+= dx2; + + sn1++; + + if(sn2>=rectx) sn2= rectx-1; + if(sn1<0) sn1= 0; + zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX); + rz= rectzofs+sn1; + rp= rectpofs+sn1; + x= sn2-sn1; + while(x>=0) { + if(zverg> *rz || *rz==0x7FFFFFFF) { + *rz= zverg; + *rp= zvlak; + } + zverg+= zd; + rz++; + rp++; + x--; + } + + zy0-=zyd; + rectzofs-= rectx; + rectpofs-= rectx; + } +} + +void zbufinvulGL(float *v1, float *v2, float *v3) /* vult in R.rectot de waarde Zvlnr in met R.rectz */ +{ + double x0,y0,z0; + double x1,y1,z1,x2,y2,z2,xx1; + double zxd,zyd,zy0,tmp; + float *minv,*maxv,*midv; + unsigned int *rectpofs,*rp; + int *rz,zverg,zvlak,x; + int my0,my2,sn1,sn2,rectx,zd,*rectzofs; + int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2; + + /* MIN MAX */ + if(v1[1] R.recty) return; + + if(my0<0) my0= 0; + + /* EDGES : DE LANGSTE */ + xx1= maxv[1]-minv[1]; + if(xx1!=0.0) { + z0= (maxv[0]-minv[0])/xx1; + + tmp= -65536.0*z0; + dx0= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(my2-minv[1]) + minv[0]); + xs0= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx0= 0; + xs0= 65536.0*(MIN2(minv[0],maxv[0])); + } + /* EDGES : DE BOVENSTE */ + xx1= maxv[1]-midv[1]; + if(xx1!=0.0) { + z0= (maxv[0]-midv[0])/xx1; + + tmp= -65536.0*z0; + dx1= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(my2-midv[1])+midv[0]); + xs1= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx1= 0; + xs1= 65536.0*(MIN2(midv[0],maxv[0])); + } + /* EDGES : DE ONDERSTE */ + xx1= midv[1]-minv[1]; + if(xx1!=0.0) { + z0= (midv[0]-minv[0])/xx1; + + tmp= -65536.0*z0; + dx2= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]); + xs2= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx2= 0; + xs2= 65536.0*(MIN2(minv[0],midv[0])); + } + + /* ZBUF DX DY */ + x1= v1[0]- v2[0]; + x2= v2[0]- v3[0]; + y1= v1[1]- v2[1]; + y2= v2[1]- v3[1]; + z1= v1[2]- v2[2]; + z2= v2[2]- v3[2]; + x0= y1*z2-z1*y2; + y0= z1*x2-x1*z2; + z0= x1*y2-y1*x2; + + if(z0==0.0) return; + + if(midv[1]==maxv[1]) omsl= my2; + if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */ + + while (my2 >= R.recty) { /* my2 kan groter zijn */ + xs0+=dx0; + if (my2<=omsl) { + xs2+= dx2; + } + else{ + xs1+= dx1; + } + my2--; + } + + xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2]; + + zxd= -x0/z0; + zyd= -y0/z0; + zy0= my2*zyd+xx1; + zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX); + + /* start-ofset in rect */ + rectx= R.rectx; + rectzofs= (int *)(R.rectz+rectx*my2); + rectpofs= (R.rectot+rectx*my2); + zvlak= Zvlnr; + + xs3= 0; /* flag */ + if(dx0>dx1) { + xs3= xs0; + xs0= xs1; + xs1= xs3; + xs3= dx0; + dx0= dx1; + dx1= xs3; + xs3= 1; /* flag */ + + } + + for(y=my2;y>omsl;y--) { + + /* dit is ongevoelig voor endians */ + sn1= xs0>>16; + xs0+= dx0; + + sn2= xs1>>16; + xs1+= dx1; + + sn1++; + + if(sn2>=rectx) sn2= rectx-1; + if(sn1<0) sn1= 0; + zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX); + rz= rectzofs+sn1; + rp= rectpofs+sn1; + x= sn2-sn1; + + while(x>=0) { + if(zverg< *rz) { + *rz= zverg; + *rp= zvlak; + } + zverg+= zd; + rz++; + rp++; + x--; + } + zy0-=zyd; + rectzofs-= rectx; + rectpofs-= rectx; + } + + if(xs3) { + xs0= xs1; + dx0= dx1; + } + if(xs0>xs2) { + xs3= xs0; + xs0= xs2; + xs2= xs3; + xs3= dx0; + dx0= dx2; + dx2= xs3; + } + + for(;y>=my0;y--) { + + sn1= xs0>>16; + xs0+= dx0; + + sn2= xs2>>16; + xs2+= dx2; + + sn1++; + + if(sn2>=rectx) sn2= rectx-1; + if(sn1<0) sn1= 0; + zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX); + rz= rectzofs+sn1; + rp= rectpofs+sn1; + x= sn2-sn1; + while(x>=0) { + if(zverg< *rz) { + *rz= zverg; + *rp= zvlak; + } + zverg+= zd; + rz++; + rp++; + x--; + } + + zy0-=zyd; + rectzofs-= rectx; + rectpofs-= rectx; + } +} + + +void zbufinvulGL_onlyZ(float *v1, float *v2, float *v3) /* vult alleen R.rectz. oneven z= 1x ingevuld */ +{ + double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1; + double zxd,zyd,zy0,tmp; + float *minv,*maxv,*midv; + int *rz,zverg,x; + int my0,my2,sn1,sn2,rectx,zd,*rectzofs; + int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2; + + /* MIN MAX */ + if(v1[1] R.recty) return; + + if(my0<0) my0=0; + + /* EDGES : DE LANGSTE */ + xx1= maxv[1]-minv[1]; + if(xx1!=0.0) { + z0= (maxv[0]-minv[0])/xx1; + + tmp= (-65536.0*z0); + dx0= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(my2-minv[1])+minv[0]); + xs0= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx0= 0; + xs0= 65536.0*(MIN2(minv[0],maxv[0])); + } + /* EDGES : DE BOVENSTE */ + xx1= maxv[1]-midv[1]; + if(xx1!=0.0) { + z0= (maxv[0]-midv[0])/xx1; + + tmp= (-65536.0*z0); + dx1= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(my2-midv[1])+midv[0]); + xs1= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx1= 0; + xs1= 65536.0*(MIN2(midv[0],maxv[0])); + } + /* EDGES : DE ONDERSTE */ + xx1= midv[1]-minv[1]; + if(xx1!=0.0) { + z0= (midv[0]-minv[0])/xx1; + + tmp= (-65536.0*z0); + dx2= CLAMPIS(tmp, INT_MIN, INT_MAX); + + tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]); + xs2= CLAMPIS(tmp, INT_MIN, INT_MAX); + } + else { + dx2= 0; + xs2= 65536.0*(MIN2(minv[0],midv[0])); + } + + /* ZBUF DX DY */ + x1= v1[0]- v2[0]; + x2= v2[0]- v3[0]; + y1= v1[1]- v2[1]; + y2= v2[1]- v3[1]; + z1= v1[2]- v2[2]; + z2= v2[2]- v3[2]; + x0= y1*z2-z1*y2; + y0= z1*x2-x1*z2; + z0= x1*y2-y1*x2; + + if(z0==0.0) return; + + if(midv[1]==maxv[1]) omsl= my2; + if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */ + + while (my2 >= R.recty) { /* my2 kan groter zijn */ + xs0+=dx0; + if (my2<=omsl) { + xs2+= dx2; + } + else{ + xs1+= dx1; + } + my2--; + } + + xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2]; + + zxd= -x0/z0; + zyd= -y0/z0; + zy0= my2*zyd+xx1; + zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX); + + /* start-ofset in rect */ + rectx= R.rectx; + rectzofs= (int *)(R.rectz+rectx*my2); + + xs3= 0; /* flag */ + if(dx0>dx1) { + xs3= xs0; + xs0= xs1; + xs1= xs3; + xs3= dx0; + dx0= dx1; + dx1= xs3; + xs3= 1; /* flag */ + + } + + for(y=my2;y>omsl;y--) { + + sn1= xs0>>16; + xs0+= dx0; + + sn2= xs1>>16; + xs1+= dx1; + + sn1++; + + if(sn2>=rectx) sn2= rectx-1; + if(sn1<0) sn1= 0; + zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX); + rz= rectzofs+sn1; + + x= sn2-sn1; + while(x>=0) { + if(zverg< *rz) { + *rz= zverg; + } + zverg+= zd; + rz++; + x--; + } + zy0-=zyd; + rectzofs-= rectx; + } + + if(xs3) { + xs0= xs1; + dx0= dx1; + } + if(xs0>xs2) { + xs3= xs0; + xs0= xs2; + xs2= xs3; + xs3= dx0; + dx0= dx2; + dx2= xs3; + } + + for(;y>=my0;y--) { + + sn1= xs0>>16; + xs0+= dx0; + + sn2= xs2>>16; + xs2+= dx2; + + sn1++; + + if(sn2>=rectx) sn2= rectx-1; + if(sn1<0) sn1= 0; + zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX); + rz= rectzofs+sn1; + + x= sn2-sn1; + while(x>=0) { + if(zverg< *rz) { + *rz= zverg; + } + zverg+= zd; + rz++; + x--; + } + + zy0-=zyd; + rectzofs-= rectx; + } +} + +void print3floats(float *v1, float *v2, float *v3) +{ + printf("1 %f %f %f %f\n", v1[0], v1[1], v1[2], v1[3]); + printf("2 %f %f %f %f\n", v2[0], v2[1], v2[2], v2[3]); + printf("3 %f %f %f %f\n", v3[0], v3[1], v3[2], v3[3]); +} + +static short cliptestf(float p, float q, float *u1, float *u2) +{ + float r; + + if(p<0.0) { + if(q*u2) return 0; + else if(r>*u1) *u1=r; + } + } + else { + if(p>0.0) { + if(q<0.0) return 0; + else if(q abs4) c+= 32; + + if( v[0]>abs4) c+=2; + else if( v[0]< -abs4) c+=1; + + if( v[1]>abs4) c+=4; + else if( v[1]< -abs4) c+=8; + + return c; +} + + +static void clipp(float *v1, float *v2, int b1, int *b2, int *b3, int a) +{ + float da,db,u1=0.0,u2=1.0; + + labda[b1][0]= -1.0; + labda[b1][1]= -1.0; + + da= v2[a]-v1[a]; + db= v2[3]-v1[3]; + + /* volgens het oorspronkelijke artikel van Liang&Barsky, wordt bij het clippen van + * hoco's met het viewplane, het getal "0" gebruikt ipv "-w" . + * Dit wijkt af van de andere clipping (links en onder) en vond ik ook niet erg + * 'homogeen'. Het is dus een fout, wie had dat gedacht van L&B! + */ + + if(cliptestf(-da-db, v1[3]+v1[a], &u1,&u2)) { + if(cliptestf(da-db, v1[3]-v1[a], &u1,&u2)) { + *b3=1; + if(u2<1.0) { + labda[b1][1]= u2; + *b2=1; + } + else labda[b1][1]=1.0; /* u2 */ + if(u1>0.0) { + labda[b1][0]= u1; + *b2=1; + } else labda[b1][0]=0.0; + } + } +} + +static int clipline(float *v1, float *v2) /* return 0: niet tekenen */ +{ + float dz,dw, u1=0.0, u2=1.0; + float dx, dy; + + dz= v2[2]-v1[2]; + dw= v2[3]-v1[3]; + + if(cliptestf(-dz-dw, v1[3]+v1[2], &u1,&u2)) { + if(cliptestf(dz-dw, v1[3]-v1[2], &u1,&u2)) { + + dx= v2[0]-v1[0]; + dz= v2[3]-v1[3]; + + if(cliptestf(-dx-dz, v1[0]+v1[3], &u1,&u2)) { + if(cliptestf(dx-dz, v1[3]-v1[0], &u1,&u2)) { + + dy= v2[1]-v1[1]; + + if(cliptestf(-dy-dz,v1[1]+v1[3],&u1,&u2)) { + if(cliptestf(dy-dz,v1[3]-v1[1],&u1,&u2)) { + + if(u2<1.0) { + v2[0]= v1[0]+u2*dx; + v2[1]= v1[1]+u2*dy; + v2[2]= v1[2]+u2*dz; + v2[3]= v1[3]+u2*dw; + } + if(u1>0.0) { + v1[0]= v1[0]+u1*dx; + v1[1]= v1[1]+u1*dy; + v1[2]= v1[2]+u1*dz; + v1[3]= v1[3]+u1*dw; + } + return 1; + } + } + } + } + } + } + + return 0; +} + + +static void maakvertpira(float *v1, float *v2, int *b1, int b2, int *clve) +{ + float l1,l2,*adr; + + l1= labda[b2][0]; + l2= labda[b2][1]; + + if(l1!= -1.0) { + if(l1!= 0.0) { + adr= vez+4*(*clve); + p[*b1]=adr; + (*clve)++; + adr[0]= v1[0]+l1*(v2[0]-v1[0]); + adr[1]= v1[1]+l1*(v2[1]-v1[1]); + adr[2]= v1[2]+l1*(v2[2]-v1[2]); + adr[3]= v1[3]+l1*(v2[3]-v1[3]); + } else p[*b1]= v1; + (*b1)++; + } + if(l2!= -1.0) { + if(l2!= 1.0) { + adr= vez+4*(*clve); + p[*b1]=adr; + (*clve)++; + adr[0]= v1[0]+l2*(v2[0]-v1[0]); + adr[1]= v1[1]+l2*(v2[1]-v1[1]); + adr[2]= v1[2]+l2*(v2[2]-v1[2]); + adr[3]= v1[3]+l2*(v2[3]-v1[3]); + (*b1)++; + } + } +} + +/* ------------------------------------------------------------------------- */ + +void RE_projectverto(float *v1, float *adr) +{ + /* berekent homogene co van vertex v1 */ + float x,y,z; + + x= v1[0]; + y= v1[1]; + z= v1[2]; + adr[0]= x*R.winmat[0][0] + z*R.winmat[2][0]; + adr[1]= y*R.winmat[1][1]+ z*R.winmat[2][1]; + adr[2]= z*R.winmat[2][2] + R.winmat[3][2]; + adr[3]= z*R.winmat[2][3] + R.winmat[3][3]; + +} /* end of void RE_projectverto(float *v1, float *adr) */ + +/* ------------------------------------------------------------------------- */ + +void projectvert(float *v1, float *adr) +{ + /* berekent homogene co van vertex v1 */ + float x,y,z; + + x= v1[0]; + y= v1[1]; + z= v1[2]; + adr[0]= x*R.winmat[0][0]+ y*R.winmat[1][0]+ z*R.winmat[2][0]+ R.winmat[3][0]; + adr[1]= x*R.winmat[0][1]+ y*R.winmat[1][1]+ z*R.winmat[2][1]+ R.winmat[3][1]; + adr[2]= x*R.winmat[0][2]+ y*R.winmat[1][2]+ z*R.winmat[2][2]+ R.winmat[3][2]; + adr[3]= x*R.winmat[0][3]+ y*R.winmat[1][3]+ z*R.winmat[2][3]+ R.winmat[3][3]; +} + + +void zbufclip(float *f1, float *f2, float *f3, int c1, int c2, int c3) +{ + float deler; + + if(c1 | c2 | c3) { /* niet in midden */ + if(c1 & c2 & c3) { /* helemaal eruit */ + return; + } else { /* clippen */ + int arg, v, b, clipflag[3], b1, b2, b3, c4, clve=3, clvlo, clvl=1; + + vez[0]= f1[0]; vez[1]= f1[1]; vez[2]= f1[2]; vez[3]= f1[3]; + vez[4]= f2[0]; vez[5]= f2[1]; vez[6]= f2[2]; vez[7]= f2[3]; + vez[8]= f3[0]; vez[9]= f3[1]; vez[10]= f3[2];vez[11]= f3[3]; + + vlzp[0][0]= vez; + vlzp[0][1]= vez+4; + vlzp[0][2]= vez+8; + + clipflag[0]= ( (c1 & 48) | (c2 & 48) | (c3 & 48) ); + if(clipflag[0]==0) { /* anders opnieuw berekend verderop, na de eerste (z) clip */ + clipflag[1]= ( (c1 & 3) | (c2 & 3) | (c3 & 3) ); + clipflag[2]= ( (c1 & 12) | (c2 & 12) | (c3 & 12) ); + } + + for(b=0;b<3;b++) { + + if(clipflag[b]) { + + clvlo= clvl; + + for(v=0; v2) { + for(b3=3; b3<=b1; b3++) { + vlzp[clvl][0]= p[0]; + vlzp[clvl][1]= p[b3-2]; + vlzp[clvl][2]= p[b3-1]; + clvl++; + } + } + } + } + } + } + } + + /* persp deling */ + /* valt hier nog te optimaliseren door alleen te gebruiken vertices te doen? */ + if(clve>38) printf("clip overflow: clve clvl %d %d\n",clve,clvl); + f1=vez; + for(c1=0;c1>8]; + else vlr++; + + if(vlr->flag & R_VISIBLE) { + if(vlr->mat!=ma) { + ma= vlr->mat; + transp= ma->mode & MA_ZTRA; + env= (ma->mode & MA_ENV); + wire= (ma->mode & MA_WIRE); + + if(ma->mode & MA_ZINV) zbuffunc= zbufinvulGLinv; + else zbuffunc= zbufinvulGL; + } + + if(transp==0) { + if(env) Zvlnr= 0; + else Zvlnr= v+1; + + if(wire) zbufclipwire(vlr); + else { + zbufclip(vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip); + if(vlr->v4) { + if(Zvlnr) Zvlnr+= 0x800000; + zbufclip(vlr->v1->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v3->clip, vlr->v4->clip); + } + } + } + } + } +} + +static int hashlist_projectvert(float *v1, float *hoco) +{ + static VertBucket bucket[256], *buck; + + if(v1==0) { + memset(bucket, 0, 256*sizeof(VertBucket)); + return 0; + } + + buck= &bucket[ (((long)v1)/16) & 255 ]; + if(buck->vert==v1) { + COPY_16(hoco, buck->hoco); + return buck->clip; + } + + projectvert(v1, hoco); + buck->clip = RE_testclip(hoco); + buck->vert= v1; + COPY_16(buck->hoco, hoco); + return buck->clip; +} + + +void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem) +{ + RNode **re, *rn; + float hoco[4][4]; + int a; + int c1, c2, c3, c4= 0; + unsigned int *rectoto, *rectzo; + int rectxo, rectyo; + + if(rg_totelem==0) return; + + hashlist_projectvert(0, 0); + + rectxo= R.rectx; + rectyo= R.recty; + rectoto= R.rectot; + rectzo= R.rectz; + + R.rectx= vw->rectx; + R.recty= vw->recty; + R.rectot= vw->rect; + R.rectz= vw->rectz; + + Zmulx= ((float)R.rectx)/2.0; + Zmuly= ((float)R.recty)/2.0; + + /* needed for projectvert */ + MTC_Mat4MulMat4(R.winmat, vw->viewmat, vw->winmat); + + fillrect(R.rectz, R.rectx, R.recty, 0x7FFFFFFF); + fillrect(R.rectot, R.rectx, R.recty, 0xFFFFFF); + + zbuffunc= zbufinvulGL; + + re= rg_elem; + re+= (rg_totelem-1); + for(a= rg_totelem-1; a>=0; a--, re--) { + rn= *re; + if( (rn->f & RAD_SHOOT)==0 ) { /* no shootelement */ + + if( rn->f & RAD_BACKFACE) Zvlnr= 0xFFFFFF; + else Zvlnr= a; + + c1= hashlist_projectvert(rn->v1, hoco[0]); + c2= hashlist_projectvert(rn->v2, hoco[1]); + c3= hashlist_projectvert(rn->v3, hoco[2]); + + if(rn->v4) { + c4= hashlist_projectvert(rn->v4, hoco[3]); + } + + zbufclip(hoco[0], hoco[1], hoco[2], c1, c2, c3); + if(rn->v4) { + zbufclip(hoco[0], hoco[2], hoco[3], c1, c3, c4); + } + } + } + + /* restore */ + R.rectx= rectxo; + R.recty= rectyo; + R.rectot= rectoto; + R.rectz= rectzo; + +} + +void zbuffershad(LampRen *lar) +{ + VlakRen *vlr= NULL; + Material *ma=0; + int a, ok=1, lay= -1; + + if(lar->mode & LA_LAYER) lay= lar->lay; + + Zmulx= ((float)R.rectx)/2.0; + Zmuly= ((float)R.recty)/2.0; + Zjitx= Zjity= -.5; + + fillrect(R.rectz,R.rectx,R.recty,0x7FFFFFFE); + + zbuffunc= zbufinvulGL_onlyZ; + + for(a=0;a>8]; + else vlr++; + + if(vlr->mat!= ma) { + ma= vlr->mat; + ok= 1; + if((ma->mode & MA_TRACEBLE)==0) ok= 0; + } + /* traceble er weer in: automatische verwijdering niet geweldig */ + + if(ok && (vlr->flag & R_VISIBLE) && (vlr->lay & lay)) { + zbufclip(vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip); + if(vlr->v4) zbufclip(vlr->v1->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v3->clip, vlr->v4->clip); + } + } +} + + + +/* ******************** ABUF ************************* */ + + +void bgnaccumbuf(void) +{ + + Acolrow= MEM_mallocN(4*sizeof(short)*R.rectx, "Acolrow"); + Arectz= MEM_mallocN(sizeof(int)*ABUFPART*R.rectx, "Arectz"); + APixbuf= MEM_mallocN(ABUFPART*R.rectx*sizeof(APixstr), "APixbuf"); + + Aminy= -1000; + Amaxy= -1000; + + apsmteller= 0; + apsmfirst.next= 0; + apsmfirst.ps= 0; +} /* End of void bgnaccumbuf(void) */ + +/* ------------------------------------------------------------------------ */ + +void endaccumbuf(void) +{ + + MEM_freeN(Acolrow); + MEM_freeN(Arectz); + MEM_freeN(APixbuf); + freepsA(); +} /* End of void endaccumbuf(void) */ + +/* ------------------------------------------------------------------------ */ + +void copyto_abufz(int sample) +{ + PixStr *ps; + int x, y, *rza; + long *rd; + + memcpy(Arectz, R.rectz+ R.rectx*Aminy, 4*R.rectx*(Amaxy-Aminy+1)); + + if( (R.r.mode & R_OSA)==0 || sample==0) return; + + rza= Arectz; + rd= (R.rectdaps+ R.rectx*Aminy); + + sample= (1<mask) { + *rza= ps->z; + break; + } + ps= ps->next; + } + } + + rd++; rza++; + } + } +} /* end of void copyto_abufz(int sample) */ + + +/* ------------------------------------------------------------------------ */ + +void zbuffer_abuf() +{ + float vec[3], hoco[4], mul, zval, fval; + Material *ma=0; + int v, len; + + Zjitx= Zjity= -.5; + Zmulx= ((float)R.rectx)/2.0; + Zmuly= ((float)R.recty)/2.0; + + /* clear APixstructen */ + len= sizeof(APixstr)*R.rectx*ABUFPART; + memset(APixbuf, 0, len); + + zbuffunc= zbufinvulAc; + zbuflinefunc= zbuflineAc; + + for(Zsample=0; Zsample>8]; + } + else Zvlr++; + + ma= Zvlr->mat; + +/* printf("Face %d :%x at %f\n", v, ma, Zvlr->v1->ho[3]); */ + + + if(ma->mode & (MA_ZTRA)) { + + /* voordeeltje voor transp renderen */ + if( ma->zoffs != 0.0) { + mul= 0x7FFFFFFF; + zval= mul*(1.0+Zvlr->v1->ho[2]/Zvlr->v1->ho[3]); + + VECCOPY(vec, Zvlr->v1->co); + /* z is negatief, wordt anders geclipt */ + vec[2]-= ma->zoffs; + RE_projectverto(vec, hoco); + fval= mul*(1.0+hoco[2]/hoco[3]); + + Azvoordeel= (int) fabs(zval - fval ); + + /* PATCH: als transp en niet transp dicht op elkaar liggen: Zbuf aliasing: eruit! */ + /* Azvoordeel= 0xFFFF; */ + } + else Azvoordeel= 0; + /* else Azvoordeel= 0xFFFF; */ + + Zvlnr= v+1; + + if(Zvlr->flag & R_VISIBLE) { + + if(ma->mode & (MA_WIRE)) zbufclipwire(Zvlr); + else { + zbufclip(Zvlr->v1->ho, Zvlr->v2->ho, Zvlr->v3->ho, Zvlr->v1->clip, Zvlr->v2->clip, Zvlr->v3->clip); + if(Zvlr->v4) { + Zvlnr+= 0x800000; + zbufclip(Zvlr->v1->ho, Zvlr->v3->ho, Zvlr->v4->ho, Zvlr->v1->clip, Zvlr->v3->clip, Zvlr->v4->clip); + } + } + } + } + if(RE_local_test_break()) break; + } + + if((R.r.mode & R_OSA)==0) break; + if(RE_local_test_break()) break; + } + +} /* end of void zbuffer_abuf() */ + + +int vergzvlak(const void *a1, const void *a2) +{ + const int *x1=a1, *x2=a2; + + if( x1[0] < x2[0] ) return 1; + else if( x1[0] > x2[0]) return -1; + return 0; +} + +void shadetrapixel(float x, float y, int vlak) +{ + if( (vlak & 0x7FFFFF) > R.totvlak) { + printf("error in shadetrapixel nr: %d\n", (vlak & 0x7FFFFF)); + return; + } + + shadepixel(x, y, vlak); +} + +extern unsigned short usegamtab; +extern unsigned short shortcol[4]; +void abufsetrow(int y) +{ + APixstr *ap, *apn; + float xs, ys; + int x, part, a, b, zrow[100][3], totvlak, alpha[32], tempgam, nr, intcol[4]; + int sval, tempRf; + unsigned short *col, tempcol[4], sampcol[16*4], *scol; + + if(y<0) return; + if(R.osa>16) { + printf("abufsetrow: osa too large\n"); + G.afbreek= 1; + return; + } + + tempRf= R.flag; + R.flag &= ~R_LAMPHALO; + + /* alpha LUT */ + if(R.r.mode & R_OSA ) { + x= (65536/R.osa); + for(a=0; a<=R.osa; a++) { + alpha[a]= a*x; + } + } + /* moet pixbuf worden gemaakt? */ + if(yAmaxy) { + part= (y/ABUFPART); + Aminy= part*ABUFPART; + Amaxy= Aminy+ABUFPART-1; + if(Amaxy>=R.recty) Amaxy= R.recty-1; + freepsA(); + zbuffer_abuf(); + } + + /* render rij */ + col= Acolrow; + memset(col, 0, 2*4*R.rectx); + ap= APixbuf+R.rectx*(y-Aminy); + ys= y; + tempgam= usegamtab; + usegamtab= 0; + + for(x=0; xp[0]) { + /* sorteer op z */ + totvlak= 0; + apn= ap; + while(apn) { + for(a=0; a<4; a++) { + if(apn->p[a]) { + zrow[totvlak][0]= apn->z[a]; + zrow[totvlak][1]= apn->p[a]; + zrow[totvlak][2]= apn->mask[a]; + totvlak++; + if(totvlak>99) totvlak= 99; + } + else break; + } + apn= apn->next; + } + if(totvlak==1) { + + if(R.r.mode & R_OSA ) { + b= centmask[ ap->mask[0] ]; + xs= (float)x+centLut[b & 15]; + ys= (float)y+centLut[b>>4]; + } + else { + xs= x; ys= y; + } + shadetrapixel(xs, ys, ap->p[0]); + + nr= count_mask(ap->mask[0]); + if( (R.r.mode & R_OSA) && nr>16; + col[1]= (shortcol[1]*a)>>16; + col[2]= (shortcol[2]*a)>>16; + col[3]= (shortcol[3]*a)>>16; + } + else { + col[0]= shortcol[0]; + col[1]= shortcol[1]; + col[2]= shortcol[2]; + col[3]= shortcol[3]; + } + } + else { + + if(totvlak==2) { + if(zrow[0][0] < zrow[1][0]) { + a= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= a; + a= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= a; + a= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= a; + } + + } + else { /* totvlak>2 */ + qsort(zrow, totvlak, sizeof(int)*3, vergzvlak); + } + + /* samenvoegen als pixels aanvullen */ + + while(totvlak>0) { + totvlak--; + + if(R.r.mode & R_OSA) { + b= centmask[ zrow[totvlak][2] ]; + xs= (float)x+centLut[b & 15]; + ys= (float)y+centLut[b>>4]; + } + else { + xs= x; ys= y; + } + shadetrapixel(xs, ys, zrow[totvlak][1]); + + a= count_mask(zrow[totvlak][2]); + if( (R.r.mode & R_OSA ) && a0) { + memset(sampcol, 0, 4*2*R.osa); + sval= addtosampcol(sampcol, shortcol, zrow[totvlak][2]); + + /* sval==0: aplha helemaal vol */ + while( (sval != 0) && (totvlak>0) ) { + a= count_mask(zrow[totvlak-1][2]); + if(a==R.osa) break; + totvlak--; + + b= centmask[ zrow[totvlak][2] ]; + + xs= (float)x+centLut[b & 15]; + ys= (float)y+centLut[b>>4]; + + shadetrapixel(xs, ys, zrow[totvlak][1]); + sval= addtosampcol(sampcol, shortcol, zrow[totvlak][2]); + } + scol= sampcol; + intcol[0]= scol[0]; intcol[1]= scol[1]; + intcol[2]= scol[2]; intcol[3]= scol[3]; + scol+= 4; + for(a=1; a>16; + shortcol[1]= (shortcol[1]*a)>>16; + shortcol[2]= (shortcol[2]*a)>>16; + shortcol[3]= (shortcol[3]*a)>>16; + addAlphaUnderShort(col, shortcol); + } + } + else addAlphaUnderShort(col, shortcol); + + if(col[3]>=0xFFF0) break; + } + } + } + } + + usegamtab= tempgam; + R.flag= tempRf; +} + +/* end of zbuf.c */ + + + + diff --git a/source/blender/render/intern/source/zbufferdatastruct.c b/source/blender/render/intern/source/zbufferdatastruct.c new file mode 100644 index 00000000000..f8e683d46bd --- /dev/null +++ b/source/blender/render/intern/source/zbufferdatastruct.c @@ -0,0 +1,342 @@ +/** + * 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 + +#include "MEM_guardedalloc.h" +#include "zbufferdatastruct.h" +#include "render.h" +#include "render_intern.h" +/* 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 opaque, */ + int obindex, + int obtype, + int dist, + int mask) +{ + /* Guard the insertion if needed? */ + RE_APixstrExt* apn = &APixbufExt[apteller]; + + 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; + } +#ifndef RE_INDIVIDUAL_SUBPIXELS + 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; + } +#endif + 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; + } +#ifndef RE_INDIVIDUAL_SUBPIXELS + 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; + } +#endif + 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; + } +#ifndef RE_INDIVIDUAL_SUBPIXELS + 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; + } +#endif + 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; + } +#ifndef RE_INDIVIDUAL_SUBPIXELS + 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; + } +#endif + if(apn->next==0) apn->next= addpseA(); + apn= apn->next; + } +} /* end of insertObject(RE_APixstrExt*, int, int, int, int) */ + +/* ------------------------------------------------------------------------- */ + +void insertFlatObject(RE_APixstrExt *apn, int obindex, int obtype, int dist, int mask) +{ + while(apn) { + if(apn->t[0] == RE_NONE) { + apn->p[0] = obindex; apn->zmin[0] = dist; + apn->zmax[0] = dist; apn->mask[0] = mask; + apn->t[0] = obtype; + break; + } +#ifndef RE_INDIVIDUAL_SUBPIXELS + if( (apn->t[0] & obtype) && (apn->p[0] == obindex)) { + apn->mask[0]|= mask; break; + } +#endif + if(apn->t[1] == RE_NONE) { + apn->p[1] = obindex; apn->zmin[1] = dist; + apn->zmax[1] = dist; apn->mask[1] = mask; + apn->t[1] = obtype; + break; + } +#ifndef RE_INDIVIDUAL_SUBPIXELS + if( (apn->t[1] & obtype) && (apn->p[1] == obindex)) { + apn->mask[1]|= mask; break; + } +#endif + if(apn->t[2] == RE_NONE) { + apn->p[2] = obindex; apn->zmin[2] = dist; + apn->zmax[2] = dist; apn->mask[2] = mask; + apn->t[2] = obtype; + break; + } +#ifndef RE_INDIVIDUAL_SUBPIXELS + if( (apn->t[2] & obtype) && (apn->p[2] == obindex)) { + apn->mask[2]|= mask; break; + } +#endif + if(apn->t[3] == RE_NONE) { + apn->p[3] = obindex; apn->zmin[3] = dist; + apn->zmax[3] = dist; apn->mask[3] = mask; + apn->t[3] = obtype; + break; + } +#ifndef RE_INDIVIDUAL_SUBPIXELS + if( (apn->t[3] & obtype) && (apn->p[3] == obindex)) { + apn->mask[3]|= mask; break; + } +#endif + if(apn->next==0) apn->next= addpseA(); + apn= apn->next; + }; +} /* end of void insertFlatObject(RE_APixstrExt, int, int, int, int)*/ + +/* ------------------------------------------------------------------------- */ +/* This function might be helped by an end-of-list marker */ +void insertFlatObjectNoOsa(RE_APixstrExt *ap, + int obindex, + int obtype, + int dist, + int mask) +{ + 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; + } + + 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; + } + + 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; + } + + 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; + } + + if(ap->next==0) ap->next= addpseA(); + ap= ap->next; + }; +} /* end of void insertFlatObjectNoOsa(RE_APixstrExt, int, int, int, int)*/ + +/* ------------------------------------------------------------------------- */ + +/* EOF */ -- cgit v1.2.3