1 /******************************************************************************* 2 * radiosity.h 3 * 4 * This file contains radiosity computation classes and types. 5 * 6 * --------------------------------------------------------------------------- 7 * Persistence of Vision Ray Tracer ('POV-Ray') version 3.7. 8 * Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd. 9 * 10 * POV-Ray is free software: you can redistribute it and/or modify 11 * it under the terms of the GNU Affero General Public License as 12 * published by the Free Software Foundation, either version 3 of the 13 * License, or (at your option) any later version. 14 * 15 * POV-Ray is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Affero General Public License for more details. 19 * 20 * You should have received a copy of the GNU Affero General Public License 21 * along with this program. If not, see <http://www.gnu.org/licenses/>. 22 * --------------------------------------------------------------------------- 23 * POV-Ray is based on the popular DKB raytracer version 2.12. 24 * DKBTrace was originally written by David K. Buck. 25 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. 26 * --------------------------------------------------------------------------- 27 * $File: //depot/public/povray/3.x/source/backend/lighting/radiosity.h $ 28 * $Revision: #1 $ 29 * $Change: 6069 $ 30 * $DateTime: 2013/11/06 11:59:40 $ 31 * $Author: chrisc $ 32 *******************************************************************************/ 33 34 #ifndef POVRAY_BACKEND_RADIOSITY_H 35 #define POVRAY_BACKEND_RADIOSITY_H 36 37 #include "backend/frame.h" 38 #include "backend/povray.h" 39 #include "backend/scene/view.h" 40 #include "backend/scene/scene.h" 41 #include "backend/render/tracepixel.h" 42 #include "backend/render/rendertask.h" 43 #include "backend/support/octree.h" 44 #include "backend/support/randomsequences.h" 45 #include "backend/lighting/photons.h" 46 #include "backend/interior/media.h" 47 48 #include "povrayold.h" // TODO FIXME 49 50 #include <vector> 51 52 namespace pov 53 { 54 55 class ViewData; 56 57 #define RADIOSITY_CACHE_EXTENSION ".rca" 58 59 static const unsigned int RADIOSITY_MAX_SAMPLE_DIRECTIONS = 1600; 60 // to get some more pseudo-randomness and make use of the full range of all the precomputed sample directions, 61 // we start each sample direction sequence at a different index than the previous one; 663 has some nice properties for this: 62 // - it is fairly large stride, only giving "overlap" of consecutive samples at high sample counts 63 // - it has no divisors in common with 1600, so that any consecutive 1600 samples will start at a different index 64 // - it gives the highest possible number of "secondary strides", those being -274, 115, -44, -17, -7 and 3 65 66 class SceneRadiositySettings; 67 68 // settings as effective for a particular bounce depth during a particuar trace step 69 struct RadiosityRecursionSettings 70 { 71 // true "tweakables" 72 unsigned int raysPerSample; // number of sample rays to shoot per sample 73 unsigned int reuseCount; // number of samples required for re-use 74 double errorBoundFactor; // factor governing spacing of samples in general 75 double minReuseFactor; // factor governing minimum spacing of samples in creases 76 double maxReuseFactor; // factor governing maximum spacing of samples in open areas 77 double octreeOverfillFactor; // factor governing octree lookup performance 78 unsigned int traceLevel; // base trace level to use for secondary rays 79 double weight; // base weight to use for secondary rays 80 81 // precomputed values 82 double maxErrorBound; // maximum error bound to be expected for sample lookup 83 double octreeAddressFactor; // effective radius factor for filing samples in the octree 84 }; 85 86 // settings as specified in the scene file; 87 // naming conventions are as per the respective scene file parameter 88 class SceneRadiositySettings 89 { 90 public: 91 92 // primary settings from the scene file 93 94 bool radiosityEnabled; 95 96 double brightness; 97 long count; 98 long directionPoolSize; 99 double errorBound; 100 double grayThreshold; 101 double lowErrorFactor; 102 double minimumReuse; 103 bool minimumReuseSet; 104 double maximumReuse; 105 bool maximumReuseSet; 106 long nearestCount; 107 long nearestCountAPT; 108 int recursionLimit; 109 double maxSample; 110 double adcBailout; 111 bool normal; 112 bool media; 113 double pretraceStart; 114 double pretraceEnd; 115 bool alwaysSample; 116 bool vainPretrace; // whether to use full quality during pretrace even where it doesn't matter, to give the user a nice show 117 float defaultImportance; 118 bool subsurface; // whether to use subsurface scattering for radiosity sampling rays 119 SceneRadiositySettings()120 SceneRadiositySettings() { 121 radiosityEnabled = false; 122 brightness = 1.0; 123 count = 35; 124 directionPoolSize = RADIOSITY_MAX_SAMPLE_DIRECTIONS; 125 errorBound = 1.8; 126 grayThreshold = 0.0; 127 lowErrorFactor = 0.5; 128 minimumReuse = 0.015; 129 minimumReuseSet = false; 130 maximumReuse = 0.2; 131 maximumReuseSet = false; 132 nearestCount = 5; // TODO FIXME - let's get rid of this completely 133 nearestCountAPT = 0; // second nearest_count parameter, governing adaptive pretrace 134 recursionLimit = 2; 135 maxSample = -1.0; // default max brightness allows any 136 adcBailout = 0.01; 137 normal = false; 138 media = false; 139 pretraceStart = 0.08; 140 pretraceEnd = 0.04; 141 alwaysSample = false; 142 vainPretrace = false; 143 defaultImportance = 1.0; 144 subsurface = false; 145 } 146 147 RadiosityRecursionSettings* GetRecursionSettings (bool final) const; 148 }; 149 150 class RadiosityCache 151 { 152 private: 153 154 static const unsigned int BLOCK_POOL_UNIT_SIZE = 32; 155 156 public: 157 158 class BlockPool 159 { 160 friend class RadiosityCache; 161 public: 162 BlockPool(); 163 ~BlockPool(); 164 protected: 165 OT_BLOCK* NewBlock(); 166 void Save(OStream *fd); 167 private: 168 struct PoolUnit 169 { 170 PoolUnit *next; 171 OT_BLOCK blocks[BLOCK_POOL_UNIT_SIZE]; PoolUnitPoolUnit172 PoolUnit(PoolUnit *n) : next(n) { } 173 }; 174 PoolUnit *head; // newest pool unit 175 PoolUnit *savedHead; // newest block that has been saved completely 176 unsigned int nextFreeBlock; // next free block (in *head) 177 unsigned int nextUnsavedBlock; // next unsaved block (in *savedHead predecessor) 178 }; 179 180 int firstRadiosityPass; 181 182 long ra_reuse_count; 183 long ra_gather_count; 184 185 RGBColour Gather_Total; 186 long Gather_Total_Count; 187 188 #ifdef RADSTATS 189 extern long ot_blockcount; 190 long ot_seenodecount; 191 long ot_seeblockcount; 192 long ot_doblockcount; 193 long ot_dotokcount; 194 long ot_lastcount; 195 long ot_lowerrorcount; 196 #endif 197 198 RadiosityCache(const SceneRadiositySettings& radset); 199 ~RadiosityCache(); 200 201 bool Load(const Path& inputFile); 202 void InitAutosave(const Path& outputFile, bool append); 203 204 DBL FindReusableBlock(RenderStatistics& stats, DBL errorbound, const Vector3d& ipoint, const Vector3d& snormal, RGBColour& illuminance, int recursionDepth, int pretraceStep, int tileId); 205 BlockPool* AcquireBlockPool(); 206 void AddBlock(BlockPool* pool, RenderStatistics* stats, const Vector3d& Point, const Vector3d& S_Normal, const Vector3d& To_Nearest_Surface, 207 const RGBColour& dx, const RGBColour& dy, const RGBColour& dz, const RGBColour& Illuminance, 208 DBL Harmonic_Mean_Distance, DBL Nearest_Distance, DBL Quality, int Bounce_Depth, int pretraceStep, int tileId); 209 void ReleaseBlockPool(BlockPool* pool); 210 211 private: 212 213 struct Octree 214 { 215 OT_NODE *root; 216 boost::mutex treeMutex; // lock this when adding nodes to the tree 217 boost::mutex blockMutex; // lock this when adding blocks to any node of the tree 218 OctreeOctree219 Octree() : root(NULL) {} 220 }; 221 222 vector<BlockPool*> blockPools; // block pools ready to be re-used 223 boost::mutex blockPoolsMutex; // lock this when accessing blockPools 224 225 Octree octree; 226 227 OStream *ot_fd; 228 boost::mutex fileMutex; // lock this when accessing ot_fd 229 230 RadiosityRecursionSettings* recursionSettings; // dynamically allocated array; use recursion depth as index 231 232 void InsertBlock(OT_NODE* node, OT_BLOCK *block); 233 OT_NODE *GetNode(RenderStatistics* stats, const OT_ID& id); 234 235 static bool AverageNearBlock(OT_BLOCK *block, void *void_info); 236 }; 237 238 class RadiosityFunction : public Trace::RadiosityFunctor 239 { 240 public: 241 242 static const unsigned int TILE_MAX = OT_TILE_MAX; 243 static const unsigned int PRETRACE_INVALID = OT_PASS_INVALID; 244 static const unsigned int PRETRACE_FIRST = OT_PASS_FIRST; 245 static const unsigned int PRETRACE_MAX = OT_PASS_MAX; 246 static const unsigned int FINAL_TRACE = OT_PASS_FINAL; 247 static const unsigned int DEPTH_MAX = (OT_DEPTH_MAX < 20 ? OT_DEPTH_MAX : 20); 248 static const unsigned int MAX_NEAREST_COUNT = 20; 249 250 // initializes radiosity module from: 251 // sd - pointer to the scene data 252 // td - pointer to the thread-specific data 253 // rs - the radiosity settings as parsed from the scene file 254 // rc - the radiosity cache to retrieve previously computed samples from, and store newly computed samples in 255 // cf - the cooperate functor (whatever that is - some thing that handles inter-thread communication?) 256 // pts - number of the current pretrace step (PRETRACE_FIRST to PRETRACE_MAX, or FINAL_TRACE for main render) 257 // camera - position of the camera 258 RadiosityFunction(shared_ptr<SceneData> sd, TraceThreadData *td, 259 const SceneRadiositySettings& rs, RadiosityCache& rc, Trace::CooperateFunctor& cf, bool ft, const Vector3d& camera); 260 virtual ~RadiosityFunction(); 261 262 // looks up the ambient value for a certain point 263 // ipoint - point on the surface 264 // raw_normal - the geometry raw norml at this pont 265 // layer_normal - texture-pertubed normal 266 // ambient_colour - (output) the ambient color at this point 267 // weight - the base "weight" of the traced ray (used to compare againgst ADC bailout) 268 virtual void ComputeAmbient(const Vector3d& ipoint, const Vector3d& raw_normal, const Vector3d& layer_normal, RGBColour& ambient_colour, DBL weight, Trace::TraceTicket& ticket); 269 270 // checks whether the specified recursion depth is still within the configured limits 271 virtual bool CheckRadiosityTraceLevel(const Trace::TraceTicket& ticket); 272 273 // retrieves top level statistics information to drive pretrace re-iteration 274 virtual void GetTopLevelStats(long& queryCount, float& reuse); 275 virtual void ResetTopLevelStats(); 276 virtual void BeforeTile(int id, unsigned int pts = FINAL_TRACE); 277 virtual void AfterTile(); 278 279 private: 280 281 class SampleDirectionGenerator 282 { 283 public: 284 /// constructor 285 SampleDirectionGenerator(); 286 /// Called before each tile 287 void Reset(unsigned int samplePoolCount); 288 /// Called before each sample 289 void InitSequence(unsigned int& sample_count, const Vector3d& raw_normal, const Vector3d& layer_normal, bool use_raw_normal); 290 /// Called to get the next sampling ray direction 291 bool GetDirection(Vector3d& direction); 292 protected: 293 /// number of remaining directions to try 294 size_t remainingDirections; 295 /// whether we're using the raw surface normal instead of the pertubed normal 296 bool rawNormalMode; 297 /// the raw surface normal // TODO FIXME - for smooth triangles etc. this *should* be *really* raw, but it isn't! 298 Vector3d rawNormal; 299 /// direction we'll map the precomputed sample directions' X axis to 300 Vector3d frameX; 301 /// direction we'll map the precomputed sample directions' Y axis to (the effective normal vector) 302 Vector3d frameY; 303 /// direction we'll map the precomputed sample directions' Z axis to 304 Vector3d frameZ; 305 /// Generator for sampling directions 306 SequentialVectorGeneratorPtr sampleDirections; 307 }; 308 309 // structure to store precomputed effective parameters for each recursion depth 310 struct RecursionParameters 311 { 312 SampleDirectionGenerator directionGenerator; // sample generator for this recursion depth 313 IntStatsIndex statsId; // statistics id for per-pass per-recursion statistics 314 IntStatsIndex queryCountStatsId; // statistics id for per-recursion statistics 315 FPStatsIndex weightStatsId; // statistics id for per-recursion statistics 316 }; 317 318 // The modules that do the actual computing 319 // (we use our own instances for the sake of thread-safety) 320 321 Trace trace; // does the main raytracing 322 MediaFunction media; // computes media effects 323 PhotonGatherer photonGatherer; // computes photon-based illumination 324 325 // Local data 326 327 TraceThreadData *threadData; 328 RadiosityCache& radiosityCache; // this is where we retrieve previously computed samples from, and store newly computed samples in 329 RadiosityCache::BlockPool* cacheBlockPool; 330 DBL errorBound; // the error_bound setting 331 bool isFinalTrace; 332 unsigned int pretraceStep; 333 Vector3d cameraPosition; 334 const SceneRadiositySettings& settings; 335 const RadiosityRecursionSettings* recursionSettings; // dynamically allocated array; use recursion depth as index 336 RecursionParameters* recursionParameters; // dynamically allocated array; use recursion depth as index 337 long topLevelQueryCount; 338 float topLevelReuse; 339 int tileId; 340 341 double GatherLight(const Vector3d& IPoint, const Vector3d& Raw_Normal, const Vector3d& LayNormal, RGBColour& Illuminance, Trace::TraceTicket& ticket); 342 }; 343 344 } // end of namespace 345 346 #endif // POVRAY_BACKEND_RADIOSITY_H 347