Todo list for snogray				-*- mode:org; coding:utf-8 -*-


* TODO Restructure current "Trace" datatype

     Currently this serves two purposes:
       1. It provides a path upwards which can be used to do things like
	  finding the proper index of refraction when existing a glass
	  surface.
       2. It provides a place to hang caches which persist beyond the
	  current ray; this is a "downward" operation.

     The first use, might be better served by a simple linked list
     of current Intersect objects.  The second, by an explicit
     "IsecCache" datatype, which would only be "downwards" (and which
     would hang off Intersect objects during tracing).


* TODO Add system for sharing sample generation info among different levels of sampling

     For instance, if using 3x3 eye-rays and 25 light samples, the final
     stratification of light samples should be done using 225 (3 x 3 x 25)
     total samples, and the light-sample stratification state maintained
     across multiple eye-rays.  This should allow better stratification
     even when using a high eye-ray:light-sample ratio (e.g. for DOF).


* TODO Add alternative types of sample generation

     E.g., quasi Monte Carlo.


* Global Illumination.

** TODO Photon mapping, as described by Henrik Wann Jensen

     See http://graphics.ucsd.edu/~henrik/papers/ewr7/

** TODO Instant radiosity

** TODO Irradiance Caching


* TODO Clean up environment-map region-splitting code.

     Instead of weird iterative searching for the best split point for
     splitting regions, just add a LightMap method to return a split
     point (the current code ends up more or less just splitting as
     evenly as possible taking mapping distortion into account).


* TODO Implement system for generating (and preserving, in snogcvt) image meta-data

     Simple EXIF support is added by exif-20061030-1.patch, but probably
     it's better to use a more general abstraction (e.g., just keep
     meta-data in a ValTable until output time), so that other meta-data
     formats like XMP and IPTC can be supported.


* TODO Write a C extension to Lua for quickly parsing large vertex/triangle arrays

     This allow the caller to specify a very simplistic grammar --
     essentially requiring they being arrays of float/int constants in
     the same order, but with a little flexibility as to the strings
     separating the values.  This should vastly speed up some Lua
     parsers (which can take a lot of time to read in large meshes).


* Add scene loaders:

** TODO RenderMan/PBRT

** TODO Cinema 4D

   There is a published spec for version 5 of the C4D format, which is
   not current, but apparently designated as a sort of "exchange format"
   for C4D.  This is a binary format, but maybe parseable using
   Lua/lpeg/struct.

** TODO 3DS MAX

   Note this is different from 3DS format, which is already supported.

** TODO Povray


* Maybe separate the notion of "Shape" from Surface

  This would allow multiple surfaces with different materials [etc.]
  sharing a single shape (only really important when the shape consumes
  a lot of memory, for instance a large mesh).  Probably not worth it.


* Implement "Lightcuts" algorithm for optimizing (quite dramatically)
   _huge_ numbers of lights:

     http://www.cs.cornell.edu/~kb/publications/SIG05lightcuts.pdf

** Also implement "Reconstruction cuts" (further optimizes lightcuts algorithm)


* TODO Better light management to handle huge numbers of lights.

     + Keep list of lights ordered in terms of "apparent strength"
       (e.g. intensity * solid angle); this varies per pixel, but is a
       good candidate for caching as it will change slowly for nearby
       points.

     + Use the "apparent strength" of lights to influence sample allocation

     + The cached ordered list of lights can have two categories: nearby
       lights and far-away lights (based on given point/bounding-box).
       When moving to a new point, we (1) see if any far-away lights
       have become "nearby", in which case we recalculate the whole
       list, and otherwise (2) reorder lights in the "nearby" list
       according to their current apparent strengths.

       Note that "nearby" lights are _not_ necessarily stronger than
       faraway lights, merely more likely to change in strength (the sun
       for instance, is probably always at the front of the "apparent
       strength" list, yet always in the faraway list).  For typical
       scenes, the number of nearby lights is probably much smaller than
       faraway lights.


* Octree improvements

** Make octree smarter

     See "voxtree-hacks-20050928-0.patch"

     Have different types of octree node for different situations:

       * Normal octree nodes

       * Leaf nodes (no children nodes, just objects)

       * Bounding-box-sub-nodes nodes:  instead of a simple octree,
	 children nodes can have an arbitrary bounding box -- this is
	 good for the case where the child(ren) has a dramatically
	 different scale, as degenerate long single chains of octree
	 nodes can be avoided (the "teapot in a stadium" problem)

** Make octree searching directional

     Currently it will find object in random order; typically it would be
     much better to find closer objects first.

     For octree, put children node pointers in a length-8 array, where
     the 3 bits in the array index correspond to x-hi/lo, y-hi/lo,
     z-hi/lo respectively.  Then when starting the search at the
     top-level, we compute a quick "first check" index according to the
     rough direction of the ray we're searching for.  When iterating
     over sub-nodes in the octree, we can simply do:

	for (index_mask = 0; index_mask < 8; index_mask)
	  search_subnode (subnodes[ray_start_index ^ index_mask]);

** Maybe try to use ray-marching instead of tree-searching


* Implement alternative acceleration structures

** TODO Bounding-Interval Hierarchy

** TODO KD-trees


* Implement new BRDFs

** DONE Cook-Torrance
** TODO Ashikhmin
** TODO Ward
** TODO Schick
** TODO LaFortune
** TODO Oren-Nayar


* Implement more elegant material framework

     Pbrt has a nice system:

       * A generalization of the BRDF, the BxDF ("Bidirectional
       	 reflection/transmission Distribution Function") handles either
       	 hemisphere (ordinary BRDFs only handle the reflection hemisphere).

       * BxDFs are separable, and a container, the BSDF ("Bidirectional
         Sphere Distribution Function") can hold a set of them, which are
         combined to form the entire lighting calculation for a point.
         [This seems to be done dynamically, at intersection time?!?]

	 For instance, instead of every BRDF calculating its own diffuse
	 term, one can just add a standard Lambertian BRDF to whatever more
	 specialized BxDFs are being used for a material.

       * Ideal specular reflection/transmission are defined as BxDFs (in
         terms of the Dirac delta function), not special materials.


* Get rid of seams at corners of cube-maps.

   This is caused by the fact that the face textures run from edge to
   edge, and there is no interpolation at the edge of two adjoining
   faces.

   A simple fix is to simply add a 1-pixel border to each face image,
   and fill them with pixels from the adjacent face.  Then, the mapping
   from cube coordinates into texture coordinate can be slightly
   perturbed such that the face parameter range [-1, 1] maps into the
   texture parameter range [PIXW/2, 1 - PIXW/2], where "PIXW" is the
   width of one pixel in the texture's source image.

   Maybe to maintain the texture abstraction, a texture "adjoin" method
   can take care of filling in the pixels and tweaking the texture's own
   scaling factors so that the texture input parameters are still in the
   range [0, 1].


* Use a better scheme for specifying test-image parameters.



----------------------------------------------------------------

Completed items:


* DONE Texture support

     Add a "TextureMap" data type which maps between a surface point and
     texture coordinates.

     New class TexCoords to hold two texture coordinates?

     Add a "Pigment" data type, which contains a Color and a Texture
     pointer; most places where Color is now used in materials, should
     use Pigment instead (have constructors so that it can be
     initialized just like a color, resulting in a 0 Texture pointer).

     Pigment has a "color(...)" method, which takes an a texture-map and
     a location, and returns a color by using the texture-map to map the
     location into texture coordinates, and looking them in the texture
     (if the pigment's texture is 0 of course, return its color).

     Surface class gets a "texture_coords" method that returns Texture
     coordinates for a given point on the surface.  PrimarySurface gets
     a new field to explicitly store a texture map, and uses that to
     implement texture_coords; mesh triangles use something else, e.g.,
     explicit per-vertex texture-coordinate tables with interpolation.

     Intersect constructor should look up and cache texture-coordinates
     for the intersection point.

     Anyplace where a Color has been replaced by a Pigment should now
     call `pigment.color (isec.tex_coords)' instead of just returning
     the color directly (when the pigment's texture pointers is 0, this
     will be almost as fast).

     Similar techniques are needed for looking up normals; shared
     superclass with textures?
 
 [DONE, more generally, by rewriting illumination to use the IllumMgr
  and subclasses of Illum]


* DONE Split illumination into DirectIllum and IndirIllum superclasses

     The current SampleIllum class should probably just be renamed to
     DirectIllum.  IndirIllum would be a superclass for photon-mapping
     or hemisphere-sampling indirect illumination algorithms.


* DONE Make mirror reflections use light-model

     Importance sampling + indirect illumination


* DONE Implement instancing


* DONE Encapsulate space/octree abstraction inside a surface interface

   ... so that there can be multiple nested search spaces.  This might
   help speed (or hurt it...) by consolidating logically related
   surfaces into their own search spaces, but more importantly, it
   allows easy object instancing by allowing us to wrap a search-space
   with a coordinate transform.


* DONE Use single-precision floating-point uniformly

     Currently double-precision is used widely (e.g. the Vec and Pos
     classes).  Just switching completely to single-precision mostly
     works fine, but causes problems with reflected/transmitted rays
     after sphere-intersection -- so debug those errors, and make sphere
     intersection work with single-precision floating point.  Probably
     just needs some kind of error margin when tracing recursive rays.


* DONE Add a real scene definition language


* DONE Importance sampling

     Add method to Material class to supply a jittered set of rays
     (given a desired number of rays as input) corresponding to the
     Material's BRDF.  The output should be efficient for large number
     of rays (e.g. ~1000) so it can be re-sampled to combine it with
     another importance function, so each element in the set should just
     be something like <reflectance, direction> (the origin is implied). 


* DONE Lighting from environment map

     Use importance resampling to combine the BRDF importance function
     with an importance function for the whole environment map (one
     hemisphere?).

     See "Bidirectional Importance Sampling for Direct Illumination",
     http://www.cs.ubc.ca/~dburke/downloads/EGSR05-Bidir_Importance.pdf


* DONE Switch to proper filtering for anti-aliasing, taking jitter etc into account:

     Add a Filter class, which takes a simple x,y offset and returns a
     filter value at that point (relative to origin).  Add a "SampleGen"
     class will will generate a series of samples (stratified etc) in a
     unit square.  For each output pixel, generate samples, render them,
     and then get the filter value for the samples offset from the pixel
     center, and combine them using the formula

        Sum(filt(samp) light(samp)) / Sum(filt(samp))

     Get rid of wacky scan-line-based filtering I guess.

     For the problem of doing post-processing of HDR images, an idea is:

	When converting from an HDR representation to a limited-gamut
	representation, use filtering even if the image resolution is
	the same; make sure the filter support is wide enough so that a
	high-intensity pixel adjacent to a low-intensity pixel will
	"bleed" into it via the tail of the filter (but make the tail
	amplitude small enough so that the bleeding in normal cases is
	negligible).


* DONE Get rid of weird error handling in image code and just use exceptions


* DONE Get rid of "Image{Source,Sink}Params" classes and instead just pass
   user-supplied  "parameter strings" to image backends.

     The parameter strings can be appended to the "image type" command-line
     options, separated by ":", with "=" mean assign value.  So for
     instance, for jpeg, the user could specify "-Ojpeg:quality=98" (as the
     user will usually specify the image type indirectly via the output
     file extension, it could assume a "=" before the first ":" meant that
     the first element was a parameter rather than a type).


* DONE Use Fresnel equations to calculate reflectance/transmittance

     http://scienceworld.wolfram.com/physics/FresnelEquations.html


* DONE Abstract octree into a more generic "space division" data-type

     Allow experimenting with different implementations, e.g., KD-trees.
     [This might fit well with the octree generalization below.]


* DONE Soft shadows

     RectLight, FarLight.


* DONE Optimize triangle intersection calculation.

     (Accounts for a huge proportion of tracing time)


* DONE Simple support for shadows of transparent/translucent objects

     Real support (bending of light rays) is too hard, but for a simple
     straight light ray, it should be easy and better than nothing.
     [For real support, caustics etc., use photon transport]



;; arch-tag: 87fcbf10-c76f-43d6-9b09-469aba284b80
