public ShadingMethod(IRayIntersectable geometry, Scene scene, Instance instance) { Enabled = true; this.geometry = geometry; this.scene = scene; this.instance = instance; }
/// <summary> /// /// </summary> /// <param name="geometry"></param> /// <param name="staticShadows"></param> /// <param name="resolution">The resolution of the 3D texture for static shadows. /// A power-of-two size might make indexing into the 3D texture quicker.</param> /// <param name="instanceKey">A text value unique to the current 3D model.</param> /// <remarks>Not thread safe</remarks> public ShadowMethod(IRayIntersectable geometry, Scene scene, bool staticShadows, byte resolution, string instanceKey, /*int randomSeed,*/ RenderContext context) { Contract.Requires(resolution > 0); Enabled = true; this.geometry = geometry; this.scene = scene; // generate random offsets to area light, for soft shadows var random = context.RNG; // var random = new Random(randomSeed); areaLightOffsets = new Vector[softShadowQuality]; for (int i = 0; i < softShadowQuality; i++) { // generate points on the surface of a sphere, representing the area light source var offset = new Vector(random.NextDouble() * 2 - 1, random.NextDouble() * 2 - 1, random.NextDouble() * 2 - 1); offset.Normalise(); offset *= 0.2; areaLightOffsets[i] = offset; } if (staticShadows) { // Create static soft shadow cache, and optionally load from disk. // TODO: power-of-two size/resolution might make 3D array indexing quicker // TODO: does this capture a fixed or varying currSurfaceNormal? If fixed, this could cause the cross-image-test pollution! softShadowCache = new Texture3DCache <byte>(resolution, instanceKey, default(byte), default(byte) + 1, (pos) => { return((byte)(TraceRaysForSoftShadows(pos, currSurfaceNormal, geometry, context) * 254 + 1)); } ); } }
public PathTracingMethod(IRayIntersectable geometry, Scene scene, Instance instance, int randomSeed) { Enabled = true; this.geometry = geometry; // This single Random object is reused by multiple threads leading to non-deterministic rendering output. // TODO: somehow pass in a thread-local Random object. Add some sort of context object to IntersectRay? // random = new Random(randomSeed); }
/// <summary> /// /// </summary> /// <param name="geometry"></param> /// <param name="resolution">The resolution of the 3D texture for caching ambient occlusion. /// A power-of-two size might make indexing into the 3D texture quicker.</param> /// <param name="instanceKey">A text value unique to the current 3D model.</param> /// <remarks>Not thread safe</remarks> public AmbientOcclusionMethod(IRayIntersectable geometry, int resolution, string instanceKey, string cachePath) { Contract.Requires(resolution > 0); Enabled = true; this.geometry = geometry; this.resolution = resolution; this.instanceKey = instanceKey; this.cachePath = cachePath; }
/// <summary> /// Create structure to generate and store 4D lightfield data for a single 3D model (that fits within the unit cube). /// </summary> /// <param name="resolution">The resolution of the 4D lightfield. Lightfield has size 2N x N x 2N x N (yaw covers 360 degrees; pitch covers 180 degrees). /// A power-of-two size might make indexing into the 4D array quicker.</param> /// <param name="instanceKey">A text value unique to the current 3D model.</param> /// <param name="backgroundColor"></param> public LightFieldColorMethod(IRayIntersectable geometry, byte resolution, string instanceKey, uint backgroundColor, string cachePath) { Contract.Requires(resolution > 0); Enabled = true; Interpolate = false; // TODO: was true this.geometry = geometry; this.backgroundColor = backgroundColor; this.resolution = resolution; this.instanceKey = instanceKey; this.cachePath = cachePath; }
/// <summary> /// Create structure to generate and store 4D lightfield data for a single 3D model (that fits within the unit cube). /// </summary> /// <param name="geometry">abstract interface to collection of triangles</param> /// <param name="triList">collection of triangles</param> /// <param name="subdividedTris">spatial subdivision of collection of triangles</param> /// <param name="resolution">The resolution of the 4D lightfield. Lightfield has size 2N x N x 2N x N (yaw covers 360 degrees; pitch covers 180 degrees). /// A power-of-two size might make indexing into the 4D array quicker.</param> /// <param name="instanceKey">A text value unique to the current 3D model.</param> public LightFieldTriMethod(IRayIntersectable geometry, GeometryCollection triList, SpatialSubdivision subdividedTris, byte resolution, string instanceKey, string cachePath, int randomSeed) { Contract.Requires(triList != null); Contract.Requires(subdividedTris != null); Contract.Requires(resolution > 0); Enabled = true; this.geometry = geometry; this.geometry_simple = triList; this.geometry_subdivided = subdividedTris; this.resolution = resolution; this.instanceKey = instanceKey; this.cachePath = cachePath; this.random = new Random(randomSeed); }
/// <summary> /// Calculates soft shadows at a point on a surface. /// Multithread safe? /// </summary> /// <param name="surfacePos">Position of surface point to be shadowed</param> /// <param name="surfaceNormal">Normal to surface at surface point</param> /// <param name="geometry">The geometry to be raytraced (both shadow caster and shadow receiver)</param> /// <returns>Fraction of light reaching the surface point (between 0 and 1): 0 = surface point fully shadowed; 1 = surface point not shadowed at all</returns> private double TraceRaysForSoftShadows(Vector surfacePos, Vector surfaceNormal, IRayIntersectable geometry, RenderContext context) { int rayEscapeCount = 0; for (int i = 0; i < softShadowQuality; i++) { // Check for shadow. Calculate direction and distance from light to surface point. Vector dirLightToSurface; Vector shadowRayStart; Vector shadowRayEnd = surfacePos + surfaceNormal * shadowProbeOffset; if (scene.pointLighting) { // generate points on the surface of a unit sphere (representing the light source) var lightSource = scene.positionalLightPos_Model + areaLightOffsets[i]; dirLightToSurface = shadowRayEnd - lightSource; shadowRayStart = lightSource; } else { // Directional lighting. // TODO: soft shadows might make no sense for a directional light! dirLightToSurface = scene.directionalLightDir_Model; shadowRayStart = shadowRayEnd + dirLightToSurface * 1000.0 + areaLightOffsets[i]; } // Fire off shadow ray through underlying geometry IntersectionInfo shadowInfo = geometry.IntersectRay(shadowRayStart, dirLightToSurface, context); // Did the shadow ray hit an occluder before reaching the light? if (shadowInfo == null || shadowInfo.rayFrac > 1.0) { // No, so this light ray reaches the surface point rayEscapeCount++; } } return((double)rayEscapeCount / (double)softShadowQuality); }
public void Add(IRayIntersectable geometry) { _geomList.Add(geometry); }