├── Atmos ├── shapes │ ├── a3Rect.cpp │ ├── a3Rect.h │ ├── a3Sphere.cpp │ ├── a3Triangle.h │ ├── a3Triangle.cpp │ ├── a3Disk.h │ ├── a3InfinitePlane.h │ ├── a3Sphere.h │ ├── a3InfinitePlane.cpp │ ├── a3Shape.h │ ├── a3Disk.cpp │ └── a3Shape.cpp ├── core │ ├── a3Spectrum.cpp │ ├── a3Utils.h │ ├── a3Utils.cpp │ ├── log │ │ ├── a3Log.h │ │ ├── a3LogFile.cpp │ │ ├── a3LogHTML.h │ │ └── a3LogFile.h │ ├── image │ │ ├── a3Film.cpp │ │ ├── a3ImageDecoder.h │ │ ├── a3ImageEncoder.h │ │ ├── a3ImageDecoder.cpp │ │ ├── a3ImageEncoder.cpp │ │ ├── a3NormalMap.h │ │ ├── a3Film.h │ │ └── a3NormalMap.cpp │ ├── a3Dimension.h │ ├── messageQueue │ │ ├── a3Message.h │ │ ├── a3MessageQueueIPC.cpp │ │ ├── a3MessageQueue.h │ │ ├── a3MessageQueueIPC.h │ │ └── a3MessageQueue.cpp │ ├── random │ │ ├── a3Distribution1D.h │ │ ├── a3Distribution2D.h │ │ ├── a3Distribution1D.cpp │ │ ├── a3Distribution2D.cpp │ │ ├── a3Random.h │ │ └── a3Random.cpp │ ├── a3Spectrum.h │ ├── a3BilinearInterpolation.h │ ├── a3BilinearInterpolation.cpp │ ├── a3ModelImporter.h │ ├── a3AABB.inl │ ├── a3Settings.cpp │ ├── a3AABB.h │ ├── a3Scene.h │ ├── a3Record.cpp │ ├── a3Ray.h │ ├── a3Scene.cpp │ ├── a3AABB.cpp │ └── a3Record.h ├── samples │ ├── a3CameraSample.cpp │ ├── a3LightSample.h │ ├── a3Sampler.cpp │ ├── a3LightSample.cpp │ ├── a3CameraSample.h │ ├── a3Sampler.h │ ├── a3RandomSampler.h │ └── a3RandomSampler.cpp ├── textures │ ├── a3Texture.cpp │ ├── a3CheckerBoard.h │ ├── a3CheckerBoard.h~RF4a7dd3.TMP │ ├── a3Texture.h │ ├── a3ConstantTexture.h │ └── a3ImageTexture.h ├── accelerators │ ├── a3BVH.h │ ├── a3PrimitiveSet.h │ ├── a3Exhaustive.h.cpp │ ├── a3PrimitiveSet.cpp │ └── a3Exhaustive.h ├── renderers │ ├── a3IPCRenderer.h │ ├── a3IPCRenderer.cpp │ ├── a3NormalMapRenderer.cpp │ ├── a3NormalMapRenderer.h │ ├── a3SingleRayRenderer.h │ ├── a3Renderer.cpp │ ├── a3Renderer.h │ ├── a3FresnelRenderer.h │ ├── a3SamplerRenderer.h │ ├── a3GridRenderer.h │ ├── a3SingleRayRenderer.cpp │ └── a3FresnelRenderer.cpp ├── bsdf │ ├── a3BSDF.cpp │ ├── a3Diffuse.h │ ├── a3Conductor.h │ ├── a3Dielectric.h │ ├── a3BSDF.h │ ├── a3RoughConductor.h │ ├── a3Microfacet.h │ ├── a3Conductor.cpp │ ├── a3Diffuse.cpp │ ├── a3RoughConductor.cpp │ └── a3Dielectric.cpp ├── integrator │ ├── a3Integrator.cpp │ ├── a3PathTracer.h │ ├── a3Integrator.h │ ├── a3DirectLighting.h │ └── a3DirectLighting.cpp ├── lights │ ├── a3EnvironmentLight.cpp~RF366de814.TMP │ ├── a3Light.cpp │ ├── a3EnvironmentLight.h │ ├── a3Light.h │ ├── a3AreaLight.h │ ├── a3EnvironmentLight.cpp │ └── a3AreaLight.cpp ├── sensors │ ├── a3PerspectiveSensor.h │ ├── a3Sensor.h │ ├── a3Sensor.cpp │ └── a3PerspectiveSensor.cpp └── Atmos.h ├── dependency ├── t3DataStructures │ ├── include │ │ ├── LinearList │ │ │ ├── t3Stack.cpp │ │ │ ├── t3Queue.cpp │ │ │ ├── t3Maze.h │ │ │ ├── t3Expression.h │ │ │ ├── t3Stack.h │ │ │ ├── t3Queue.h │ │ │ └── t3Expression.cpp │ │ ├── LinkList │ │ │ ├── t3TypeList.cpp │ │ │ ├── t3LinkList.cpp │ │ │ ├── t3TypeList.h │ │ │ └── t3LinkList.h │ │ ├── main.cpp │ │ ├── Common │ │ │ ├── t3Timer.h │ │ │ ├── t3Test.h │ │ │ ├── t3Test.cpp │ │ │ ├── t3DataStructuresSettings.h │ │ │ └── t3Timer.cpp │ │ ├── Test │ │ │ ├── t3MazeTest.h │ │ │ ├── t3ExpressionTest.h │ │ │ ├── StringADTTest.h │ │ │ ├── t3RegexTest.h │ │ │ ├── t3LinkListTest.h │ │ │ ├── SparseMatrixTest.h │ │ │ ├── t3BinaryTreeTest.h │ │ │ ├── t3LinearListTest.h │ │ │ └── t3EquivalenceTest.h │ │ ├── Tree │ │ │ ├── t3Heap.h │ │ │ ├── t3ThreadedBinaryTree.h │ │ │ ├── t3Heap.cpp │ │ │ ├── t3ThreadedBinaryTree.cpp │ │ │ └── t3BinaryTree.cpp │ │ ├── String │ │ │ ├── t3StringADT.h │ │ │ └── t3StringADT.cpp │ │ └── SparseMatrix │ │ │ ├── t3SparseMatrixADT.h │ │ │ └── t3SparseMatrixADT.cpp │ └── lib │ │ ├── x64 │ │ ├── t3DataStructures.vs2013.x64.lib │ │ ├── t3DataStructures.vs2015.x64.lib │ │ ├── t3DataStructuresd.vs2013.x64.lib │ │ └── t3DataStructuresd.vs2015.x64.lib │ │ └── x86 │ │ ├── t3DataStructures.vs2013.x86.lib │ │ ├── t3DataStructures.vs2015.x86.lib │ │ ├── t3DataStructuresd.vs2013.x86.lib │ │ └── t3DataStructuresd.vs2015.x86.lib ├── tinyexr │ └── include │ │ └── tinyexr.cc ├── tinyobjloader │ └── include │ │ └── tiny_obj_loader.cc ├── lodepng │ └── lib │ │ ├── x64 │ │ ├── loadpng.vs2013.x64.lib │ │ ├── loadpng.vs2015.x64.lib │ │ ├── loadpngd.vs2013.x64.lib │ │ └── loadpngd.vs2015.x64.lib │ │ └── x86 │ │ ├── loadpng.vs2013.x86.lib │ │ ├── loadpng.vs2015.x86.lib │ │ ├── loadpngd.vs2013.x86.lib │ │ └── loadpngd.vs2015.x86.lib └── t3Math │ ├── lib │ ├── x64 │ │ ├── t3Math.vs2015.x64.lib │ │ └── t3Mathd.vs2015.x64.lib │ └── x86 │ │ ├── t3Math.vs2013.x86.lib │ │ ├── t3Math.vs2015.x86.lib │ │ ├── t3Mathd.vs2013.x86.lib │ │ └── t3Mathd.vs2015.x86.lib │ └── include │ └── t3Math │ └── core │ ├── t3Vector2.inl │ ├── t3Vector3.inl │ ├── t3MathSettings.h │ └── t3Vector2.h ├── test ├── ipc.h ├── editor.h ├── coordinate.h ├── main.cpp ├── png.h ├── aabb.h ├── util.h ├── grid.h ├── ray.h └── exr.h ├── .gitignore ├── .gitattributes └── README.md /Atmos/shapes/a3Rect.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Atmos/core/a3Spectrum.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Atmos/samples/a3CameraSample.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Atmos/shapes/a3Rect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | -------------------------------------------------------------------------------- /Atmos/textures/a3Texture.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/LinearList/t3Stack.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /test/ipc.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/test/ipc.h -------------------------------------------------------------------------------- /test/editor.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/test/editor.h -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/LinkList/t3TypeList.cpp: -------------------------------------------------------------------------------- 1 | #include "t3TypeList.h" 2 | -------------------------------------------------------------------------------- /test/coordinate.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/test/coordinate.h -------------------------------------------------------------------------------- /Atmos/core/a3Utils.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/a3Utils.h -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/LinearList/t3Queue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/LinkList/t3LinkList.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /dependency/tinyexr/include/tinyexr.cc: -------------------------------------------------------------------------------- 1 | #define TINYEXR_IMPLEMENTATION 2 | #include "tinyexr.h" 3 | -------------------------------------------------------------------------------- /Atmos/core/a3Utils.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/a3Utils.cpp -------------------------------------------------------------------------------- /Atmos/core/log/a3Log.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/log/a3Log.h -------------------------------------------------------------------------------- /Atmos/accelerators/a3BVH.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/accelerators/a3BVH.h -------------------------------------------------------------------------------- /Atmos/shapes/a3Sphere.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/shapes/a3Sphere.cpp -------------------------------------------------------------------------------- /Atmos/shapes/a3Triangle.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/shapes/a3Triangle.h -------------------------------------------------------------------------------- /Atmos/core/image/a3Film.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/image/a3Film.cpp -------------------------------------------------------------------------------- /Atmos/core/log/a3LogFile.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/log/a3LogFile.cpp -------------------------------------------------------------------------------- /Atmos/shapes/a3Triangle.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/shapes/a3Triangle.cpp -------------------------------------------------------------------------------- /Atmos/renderers/a3IPCRenderer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/renderers/a3IPCRenderer.h -------------------------------------------------------------------------------- /Atmos/textures/a3CheckerBoard.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/textures/a3CheckerBoard.h -------------------------------------------------------------------------------- /Atmos/core/a3Dimension.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef t3Vector2f a3Dimention; -------------------------------------------------------------------------------- /Atmos/core/image/a3ImageDecoder.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/image/a3ImageDecoder.h -------------------------------------------------------------------------------- /Atmos/core/image/a3ImageEncoder.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/image/a3ImageEncoder.h -------------------------------------------------------------------------------- /Atmos/renderers/a3IPCRenderer.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/renderers/a3IPCRenderer.cpp -------------------------------------------------------------------------------- /Atmos/accelerators/a3PrimitiveSet.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/accelerators/a3PrimitiveSet.h -------------------------------------------------------------------------------- /Atmos/core/image/a3ImageDecoder.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/image/a3ImageDecoder.cpp -------------------------------------------------------------------------------- /Atmos/core/image/a3ImageEncoder.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/image/a3ImageEncoder.cpp -------------------------------------------------------------------------------- /Atmos/core/messageQueue/a3Message.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/messageQueue/a3Message.h -------------------------------------------------------------------------------- /Atmos/core/random/a3Distribution1D.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/random/a3Distribution1D.h -------------------------------------------------------------------------------- /Atmos/core/random/a3Distribution2D.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/random/a3Distribution2D.h -------------------------------------------------------------------------------- /dependency/tinyobjloader/include/tiny_obj_loader.cc: -------------------------------------------------------------------------------- 1 | #define TINYOBJLOADER_IMPLEMENTATION 2 | #include "tiny_obj_loader.h" 3 | -------------------------------------------------------------------------------- /Atmos/accelerators/a3Exhaustive.h.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/accelerators/a3Exhaustive.h.cpp -------------------------------------------------------------------------------- /Atmos/accelerators/a3PrimitiveSet.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/accelerators/a3PrimitiveSet.cpp -------------------------------------------------------------------------------- /Atmos/core/random/a3Distribution1D.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/random/a3Distribution1D.cpp -------------------------------------------------------------------------------- /Atmos/core/random/a3Distribution2D.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/random/a3Distribution2D.cpp -------------------------------------------------------------------------------- /Atmos/renderers/a3NormalMapRenderer.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/renderers/a3NormalMapRenderer.cpp -------------------------------------------------------------------------------- /Atmos/renderers/a3NormalMapRenderer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/renderers/a3NormalMapRenderer.h -------------------------------------------------------------------------------- /Atmos/renderers/a3SingleRayRenderer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/renderers/a3SingleRayRenderer.h -------------------------------------------------------------------------------- /Atmos/textures/a3CheckerBoard.h~RF4a7dd3.TMP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/textures/a3CheckerBoard.h~RF4a7dd3.TMP -------------------------------------------------------------------------------- /Atmos/core/messageQueue/a3MessageQueueIPC.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/Atmos/core/messageQueue/a3MessageQueueIPC.cpp -------------------------------------------------------------------------------- /Atmos/samples/a3LightSample.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class a3LightSample 4 | { 5 | public: 6 | a3LightSample(); 7 | 8 | float uPos[2]; 9 | }; -------------------------------------------------------------------------------- /dependency/lodepng/lib/x64/loadpng.vs2013.x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/lodepng/lib/x64/loadpng.vs2013.x64.lib -------------------------------------------------------------------------------- /dependency/lodepng/lib/x64/loadpng.vs2015.x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/lodepng/lib/x64/loadpng.vs2015.x64.lib -------------------------------------------------------------------------------- /dependency/lodepng/lib/x86/loadpng.vs2013.x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/lodepng/lib/x86/loadpng.vs2013.x86.lib -------------------------------------------------------------------------------- /dependency/lodepng/lib/x86/loadpng.vs2015.x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/lodepng/lib/x86/loadpng.vs2015.x86.lib -------------------------------------------------------------------------------- /dependency/t3Math/lib/x64/t3Math.vs2015.x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3Math/lib/x64/t3Math.vs2015.x64.lib -------------------------------------------------------------------------------- /dependency/t3Math/lib/x64/t3Mathd.vs2015.x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3Math/lib/x64/t3Mathd.vs2015.x64.lib -------------------------------------------------------------------------------- /dependency/t3Math/lib/x86/t3Math.vs2013.x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3Math/lib/x86/t3Math.vs2013.x86.lib -------------------------------------------------------------------------------- /dependency/t3Math/lib/x86/t3Math.vs2015.x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3Math/lib/x86/t3Math.vs2015.x86.lib -------------------------------------------------------------------------------- /dependency/t3Math/lib/x86/t3Mathd.vs2013.x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3Math/lib/x86/t3Mathd.vs2013.x86.lib -------------------------------------------------------------------------------- /dependency/t3Math/lib/x86/t3Mathd.vs2015.x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3Math/lib/x86/t3Mathd.vs2015.x86.lib -------------------------------------------------------------------------------- /dependency/lodepng/lib/x64/loadpngd.vs2013.x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/lodepng/lib/x64/loadpngd.vs2013.x64.lib -------------------------------------------------------------------------------- /dependency/lodepng/lib/x64/loadpngd.vs2015.x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/lodepng/lib/x64/loadpngd.vs2015.x64.lib -------------------------------------------------------------------------------- /dependency/lodepng/lib/x86/loadpngd.vs2013.x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/lodepng/lib/x86/loadpngd.vs2013.x86.lib -------------------------------------------------------------------------------- /dependency/lodepng/lib/x86/loadpngd.vs2015.x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/lodepng/lib/x86/loadpngd.vs2015.x86.lib -------------------------------------------------------------------------------- /dependency/t3Math/include/t3Math/core/t3Vector2.inl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3Math/include/t3Math/core/t3Vector2.inl -------------------------------------------------------------------------------- /dependency/t3Math/include/t3Math/core/t3Vector3.inl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3Math/include/t3Math/core/t3Vector3.inl -------------------------------------------------------------------------------- /Atmos/core/a3Spectrum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef t3Vector3 a3Spectrum; 6 | //#define t3Vector3f a3Spectrum -------------------------------------------------------------------------------- /Atmos/core/a3BilinearInterpolation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // 暂时默认区间为[0, 1] 4 | float a3BilinearInterpolation(float x, float y, float f00, float f01, float f11, float f10); -------------------------------------------------------------------------------- /Atmos/samples/a3Sampler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | a3Sampler::a3Sampler() 5 | { 6 | 7 | } 8 | 9 | 10 | -------------------------------------------------------------------------------- /dependency/t3DataStructures/lib/x64/t3DataStructures.vs2013.x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3DataStructures/lib/x64/t3DataStructures.vs2013.x64.lib -------------------------------------------------------------------------------- /dependency/t3DataStructures/lib/x64/t3DataStructures.vs2015.x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3DataStructures/lib/x64/t3DataStructures.vs2015.x64.lib -------------------------------------------------------------------------------- /dependency/t3DataStructures/lib/x64/t3DataStructuresd.vs2013.x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3DataStructures/lib/x64/t3DataStructuresd.vs2013.x64.lib -------------------------------------------------------------------------------- /dependency/t3DataStructures/lib/x64/t3DataStructuresd.vs2015.x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3DataStructures/lib/x64/t3DataStructuresd.vs2015.x64.lib -------------------------------------------------------------------------------- /dependency/t3DataStructures/lib/x86/t3DataStructures.vs2013.x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3DataStructures/lib/x86/t3DataStructures.vs2013.x86.lib -------------------------------------------------------------------------------- /dependency/t3DataStructures/lib/x86/t3DataStructures.vs2015.x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3DataStructures/lib/x86/t3DataStructures.vs2015.x86.lib -------------------------------------------------------------------------------- /dependency/t3DataStructures/lib/x86/t3DataStructuresd.vs2013.x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3DataStructures/lib/x86/t3DataStructuresd.vs2013.x86.lib -------------------------------------------------------------------------------- /dependency/t3DataStructures/lib/x86/t3DataStructuresd.vs2015.x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BentleyBlanks/Atmos/HEAD/dependency/t3DataStructures/lib/x86/t3DataStructuresd.vs2015.x86.lib -------------------------------------------------------------------------------- /Atmos/textures/a3Texture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | template 4 | class a3Texture 5 | { 6 | public: 7 | virtual ~a3Texture() {} 8 | 9 | virtual T evaluate(float u, float v) const = 0; 10 | }; -------------------------------------------------------------------------------- /Atmos/renderers/a3Renderer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | a3Renderer::a3Renderer() : progress(0.0f) 4 | { 5 | 6 | } 7 | 8 | a3Renderer::~a3Renderer() 9 | { 10 | 11 | } 12 | 13 | void a3Renderer::postEffect() 14 | { 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /Atmos/bsdf/a3BSDF.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | a3BSDF::a3BSDF() : reflectance(NULL) 4 | { 5 | 6 | } 7 | 8 | a3BSDF::a3BSDF(a3Texture* texture): reflectance(texture) 9 | { 10 | 11 | } 12 | 13 | a3BSDF::~a3BSDF() 14 | { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Atmos/samples/a3LightSample.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | a3LightSample::a3LightSample() 5 | { 6 | uPos[0] = a3Random::randomFloat(); 7 | 8 | uPos[1] = a3Random::randomFloat(); 9 | } 10 | -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/LinkList/t3TypeList.h: -------------------------------------------------------------------------------- 1 | #ifndef T3_TYPELIST_H 2 | #define T3_TYPELIST_H 3 | 4 | template 5 | class t3TypeList 6 | { 7 | public: 8 | typedef T head; 9 | typedef U next; 10 | }; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /Atmos/integrator/a3Integrator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | a3Spectrum a3Integrator::Li(const a3Ray & ray, const a3Scene & scene) const 5 | { 6 | a3FuncNotImplementedError("Li"); 7 | 8 | return a3Spectrum(); 9 | } 10 | -------------------------------------------------------------------------------- /Atmos/samples/a3CameraSample.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class a3CameraSample 4 | { 5 | public: 6 | a3CameraSample() :imageX(0), imageY(0) {} 7 | 8 | a3CameraSample(float imageX, float imageY) :imageX(imageX), imageY(imageY) {} 9 | 10 | float imageX, imageY; 11 | }; -------------------------------------------------------------------------------- /Atmos/samples/a3Sampler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3CameraSample; 6 | 7 | class a3Sampler 8 | { 9 | public: 10 | a3Sampler(); 11 | 12 | // 默认均匀采样 13 | virtual int getMoreSamples(int x, int y, a3CameraSample* sample, a3CameraSample* sampleFilter = NULL) = 0; 14 | }; -------------------------------------------------------------------------------- /Atmos/core/a3BilinearInterpolation.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | float a3BilinearInterpolation(float x, float y, float f00, float f01, float f11, float f10) 4 | { 5 | return f00 * (1 - x) * (1 - y) + 6 | f10 * x * (1 - y) + 7 | f11 * x * y + 8 | f01 * (1 - x) * y; 9 | } 10 | 11 | -------------------------------------------------------------------------------- /Atmos/samples/a3RandomSampler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3RandomSampler : public a3Sampler 6 | { 7 | public: 8 | a3RandomSampler(); 9 | 10 | virtual int getMoreSamples(int x, int y, a3CameraSample* sample, a3CameraSample* sampleFilter = NULL); 11 | 12 | // 当前采样点 13 | int x, y; 14 | }; -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/main.cpp: -------------------------------------------------------------------------------- 1 | //#include 2 | //#include 3 | //#include 4 | //#include 5 | //#include 6 | //#include 7 | //#include 8 | //#include 9 | #include -------------------------------------------------------------------------------- /Atmos/textures/a3ConstantTexture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | template 6 | class a3ConstantTexture:public a3Texture 7 | { 8 | public: 9 | a3ConstantTexture(const T value) :value(value) {} 10 | 11 | virtual T evaluate(float u, float v) const override 12 | { 13 | return value; 14 | } 15 | 16 | T value; 17 | }; -------------------------------------------------------------------------------- /Atmos/accelerators/a3Exhaustive.h: -------------------------------------------------------------------------------- 1 | #ifndef A3_EXHAUSTIVE_H 2 | #define A3_EXHAUSTIVE_H 3 | 4 | #include 5 | 6 | class a3Exhaustive :public a3PrimitiveSet 7 | { 8 | public: 9 | virtual bool intersect(const a3Ray& ray, a3IntersectRecord* intersection) const override; 10 | 11 | virtual bool intersect(const a3Ray& ray) const override; 12 | }; 13 | 14 | #endif -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Common/t3Timer.h: -------------------------------------------------------------------------------- 1 | #ifndef T3_TIMER_H 2 | #define T3_TIMER_H 3 | 4 | class t3Timer 5 | { 6 | public: 7 | t3Timer():startTime(0.0f){} 8 | 9 | // 开始计时 10 | double start(); 11 | 12 | // 结束计时 13 | double end(); 14 | 15 | // 时间差 16 | double difference(); 17 | 18 | double startTime, endTime; 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /Atmos/core/random/a3Random.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // thread-safe random number generator 4 | class a3Random 5 | { 6 | public: 7 | a3Random(); 8 | 9 | static double randomDouble(const double min = 0.0f, const double max = 1.0f); 10 | 11 | static float randomFloat(const float min = 0.0f, const float max = 1.0f); 12 | 13 | static int randomInt(const int min = 0, const int max = 100); 14 | }; 15 | -------------------------------------------------------------------------------- /Atmos/renderers/a3Renderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3Scene; 6 | class a3CameraSample; 7 | class a3Sensor; 8 | class a3Ray; 9 | class a3IntersectRecord; 10 | 11 | class a3Renderer 12 | { 13 | public: 14 | a3Renderer(); 15 | 16 | ~a3Renderer(); 17 | 18 | virtual void render(const a3Scene* scene) = 0; 19 | 20 | virtual void postEffect(); 21 | 22 | float progress; 23 | }; -------------------------------------------------------------------------------- /Atmos/core/a3ModelImporter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3Scene; 6 | class a3Shape; 7 | 8 | class a3ModelImporter 9 | { 10 | public: 11 | a3ModelImporter(); 12 | 13 | ~a3ModelImporter(); 14 | 15 | std::vector load(const char* filePath); 16 | 17 | bool convertHandness; 18 | 19 | private: 20 | class a3Importer; 21 | a3Importer* importer; 22 | 23 | //a3Scene* scene 24 | }; -------------------------------------------------------------------------------- /Atmos/integrator/a3PathTracer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class a3Ray; 7 | class a3Scene; 8 | 9 | class a3PathTracer : public a3Integrator 10 | { 11 | public: 12 | a3PathTracer(); 13 | 14 | virtual ~a3PathTracer(); 15 | 16 | // Sample the incident radiance along a ray. 17 | virtual a3Spectrum Li(const a3Ray& ray, const a3Scene& scene) const; 18 | 19 | // Russian Rulette 20 | int maxDepth; 21 | int rrDepth; 22 | }; 23 | -------------------------------------------------------------------------------- /Atmos/core/image/a3NormalMap.h: -------------------------------------------------------------------------------- 1 | #ifndef A3_NORMALMAP_H 2 | #define A3_NORMALMAP_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class a3NormalMap : public a3Film 9 | { 10 | public: 11 | a3NormalMap(unsigned width, unsigned height, const std::string& fileName); 12 | 13 | a3NormalMap(const a3Film& film); 14 | 15 | ~a3NormalMap(); 16 | 17 | virtual void addSample(const a3CameraSample* sample, const t3Vector3f& normal); 18 | }; 19 | 20 | #endif -------------------------------------------------------------------------------- /Atmos/renderers/a3FresnelRenderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3Sampler; 6 | class a3Film; 7 | 8 | // [Debug] 9 | class a3FresnelRenderer : public a3Renderer 10 | { 11 | public: 12 | void render(const a3Scene* scene); 13 | 14 | bool check(); 15 | 16 | float getFresnel(const a3Scene* scene, a3Ray* ray, const a3CameraSample* sample); 17 | 18 | // 采样器 19 | a3Sampler* sampler; 20 | 21 | // 相机 22 | a3Sensor* camera; 23 | 24 | // 生成的菲涅尔贴图 25 | a3Film* image; 26 | }; -------------------------------------------------------------------------------- /Atmos/integrator/a3Integrator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3Ray; 6 | class a3Scene; 7 | 8 | class a3Integrator 9 | { 10 | public: 11 | a3Integrator() {} 12 | 13 | virtual ~a3Integrator() {} 14 | 15 | // Sample the incident radiance along a ray. 16 | virtual a3Spectrum Li(const a3Ray& ray, const a3Scene& scene) const = 0; 17 | 18 | // Controls the number of light/bsdf samples for direct illumination per camera hit point 19 | int numLightSamples, numBxdfSamples; 20 | }; -------------------------------------------------------------------------------- /Atmos/integrator/a3DirectLighting.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3DirectLighting : public a3Integrator 6 | { 7 | public: 8 | a3DirectLighting(int numBxdfSamples = 1, int numLightSamples = 1); 9 | 10 | ~a3DirectLighting(); 11 | 12 | virtual a3Spectrum Li(const a3Ray& ray, const a3Scene& scene) const; 13 | 14 | // number of samples on light and bsdf 15 | int numLightSamples, numBxdfSamples; 16 | 17 | // MIS 18 | float fracBSDF, fracLight; 19 | float weightBSDF, weightLight; 20 | }; -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Test/t3MazeTest.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char* argv[]) 8 | { 9 | t3Maze maze(7, 6); 10 | 11 | maze << 1, 1, 1, 1, 1, 1, 12 | 13 | 1, 0, 0, 0, 0, 1, 14 | 1, 1, 1, 1, 0, 1, 15 | 1, 0, 0, 1, 0, 1, 16 | 1, 0, 0, 1, 0, 1, 17 | 1, 0, 0, 0, 0, 1, 18 | 19 | 1, 1, 1, 1, 1, 1; 20 | 21 | maze.print(); 22 | 23 | maze.path(3, 1); 24 | 25 | getchar(); 26 | return 0; 27 | } -------------------------------------------------------------------------------- /Atmos/core/a3AABB.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | const t3Vector3f& a3AABB::operator[](int i) const 6 | { 7 | a3Assert(i == 0 || i == 1); 8 | // --!不明觉厉的写法 9 | return (&min)[i]; 10 | } 11 | 12 | t3Vector3f& a3AABB::operator[](int i) 13 | { 14 | a3Assert(i == 0 || i == 1); 15 | // --!不明觉厉的写法 16 | return (&min)[i]; 17 | } 18 | 19 | bool a3AABB::operator==(const a3AABB& bbox) const 20 | { 21 | return bbox.min == min && bbox.max == max; 22 | } 23 | 24 | bool a3AABB::operator!=(const a3AABB& bbox) const 25 | { 26 | return bbox.min != min || bbox.max != max; 27 | } 28 | 29 | 30 | -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/LinearList/t3Maze.h: -------------------------------------------------------------------------------- 1 | #ifndef T3_MAZE_H 2 | #define T3_MAZE_H 3 | 4 | #include 5 | #include 6 | 7 | class t3Maze//:public std::ostream 8 | { 9 | public: 10 | t3Maze(int row, int col); 11 | 12 | ~t3Maze(); 13 | 14 | void print(); 15 | 16 | void add(int value); 17 | 18 | // 给定出口 19 | void path(int exitRow, int exitCol); 20 | 21 | t3Maze& operator,(int value); 22 | 23 | t3Maze& operator<<(int value); 24 | 25 | int col, row; 26 | 27 | int **m; 28 | 29 | int pCol, pRow; 30 | }; 31 | #endif -------------------------------------------------------------------------------- /Atmos/samples/a3RandomSampler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | a3RandomSampler::a3RandomSampler() 6 | { 7 | 8 | } 9 | 10 | int a3RandomSampler::getMoreSamples(int x, int y, a3CameraSample* sample, a3CameraSample *sampleFilter) 11 | { 12 | sample->imageX = x; 13 | sample->imageY = y; 14 | 15 | if(sampleFilter) 16 | { 17 | // 在原有采样位置处[-1, 1]做随机采样 18 | sampleFilter->imageX = x + a3Random::randomFloat() * 2 - 1; 19 | sampleFilter->imageY = y + a3Random::randomFloat() * 2 - 1; 20 | } 21 | return 1; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /Atmos/lights/a3EnvironmentLight.cpp~RF366de814.TMP: -------------------------------------------------------------------------------- 1 | #include "a3EnvironmentLight.h" 2 | 3 | a3EnvironmentLight::a3EnvironmentLight(const std::string & filePath) 4 | { 5 | } 6 | 7 | a3EnvironmentLight::~a3EnvironmentLight() 8 | { 9 | } 10 | 11 | a3Spectrum a3EnvironmentLight::evalEnvironment(const a3Ray & ray) const 12 | { 13 | return a3Spectrum(); 14 | } 15 | 16 | a3Spectrum a3EnvironmentLight::sampleDirect(const a3DirectSamplingRecord & dRec) const 17 | { 18 | return a3Spectrum(); 19 | } 20 | 21 | bool a3EnvironmentLight::isEnvironment() const 22 | { 23 | return false; 24 | } 25 | 26 | bool a3EnvironmentLight::isDeltaDistribution() const 27 | { 28 | return false; 29 | } 30 | -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Test/t3ExpressionTest.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | //#define T3_TEST_POSTFIX 8 | #define T3_TEST_INFIX_TO_POSTFIX 9 | 10 | int main(int argc, char* argv[]) 11 | { 12 | t3Expression exp; 13 | 14 | #ifdef T3_TEST_POSTFIX 15 | exp.create("42/1-12*+22*- "); 16 | 17 | t3Log("Expression evaluate: %d", exp.evaluate()); 18 | #endif 19 | 20 | #ifdef T3_TEST_INFIX_TO_POSTFIX 21 | exp.create("((((4/2)-1)+(1*2))-(2*2)) "); 22 | 23 | exp.toPostfix(); 24 | 25 | t3Log("Expression evaluate: %d", exp.evaluate()); 26 | #endif 27 | getchar(); 28 | return 0; 29 | } -------------------------------------------------------------------------------- /Atmos/core/image/a3Film.h: -------------------------------------------------------------------------------- 1 | #ifndef A3_IMAGE_H 2 | #define A3_IMAGE_H 3 | 4 | #include 5 | #include 6 | 7 | class a3CameraSample; 8 | class a3ImageEncoder; 9 | 10 | class a3Film 11 | { 12 | public: 13 | a3Film(unsigned width, unsigned height, const std::string& fileName); 14 | 15 | ~a3Film(); 16 | 17 | virtual void addColor(int x, int y, const t3Vector3f& color); 18 | 19 | virtual void addSample(const a3CameraSample* sample, const t3Vector3f& L); 20 | 21 | void setFileName(const std::string& fileName); 22 | 23 | void write(); 24 | 25 | int width, height; 26 | 27 | std::string fileName; 28 | 29 | //protected: 30 | a3ImageEncoder* picture; 31 | }; 32 | 33 | #endif -------------------------------------------------------------------------------- /Atmos/lights/a3Light.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | a3Light::a3Light(const t3Matrix4x4& lightToWorld, std::string name) 6 | : lightToWorld(lightToWorld), worldToLight(lightToWorld.getInverse()), name(name) 7 | { 8 | 9 | } 10 | 11 | a3Light::a3Light(std::string name) : name(name) 12 | { 13 | lightToWorld.makeIdentityMatrix(); 14 | worldToLight.makeIdentityMatrix(); 15 | } 16 | 17 | a3Light::~a3Light() 18 | { 19 | 20 | } 21 | 22 | a3Spectrum a3Light::eval(const a3IntersectRecord & its, const t3Vector3f & d) const 23 | { 24 | return a3Spectrum::zero(); 25 | } 26 | 27 | a3Spectrum a3Light::evalEnvironment(const a3Ray & ray) const 28 | { 29 | return a3Spectrum::zero(); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /Atmos/core/image/a3NormalMap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | a3NormalMap::a3NormalMap(unsigned width, unsigned height, const std::string& fileName) : a3Film(width, height, fileName) 6 | { 7 | 8 | } 9 | 10 | a3NormalMap::a3NormalMap(const a3Film& film) : a3Film(film.width, film.height, film.fileName) 11 | { 12 | 13 | } 14 | 15 | a3NormalMap::~a3NormalMap() 16 | { 17 | 18 | } 19 | 20 | void a3NormalMap::addSample(const a3CameraSample* sample, const t3Vector3f& normal) 21 | { 22 | t3Vector3f normalTemp = normal.getNormalized(); 23 | 24 | normalTemp = (normalTemp / 2.0f + t3Vector3f(0.5f, 0.5f, 0.5f)) * 255; 25 | 26 | picture->setColor(sample->imageX, sample->imageY, normalTemp); 27 | } 28 | -------------------------------------------------------------------------------- /Atmos/shapes/a3Disk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3ShapeSamplingRecord; 6 | 7 | class a3Disk :public a3Shape 8 | { 9 | public: 10 | a3Disk(const t3Matrix4x4& shapeToWorld, const float radius); 11 | 12 | virtual ~a3Disk(); 13 | 14 | // ray intersection test for visibility queries 15 | virtual bool intersect(const a3Ray& ray, float* t, float* u, float* v) const; 16 | 17 | // compute the area 18 | virtual float area() const; 19 | 20 | // Sample a point on the surface of this shape instance 21 | virtual void sample(a3ShapeSamplingRecord& sRec) const; 22 | 23 | // return the normal vec from the point be hitted 24 | virtual t3Vector3f getNormal(const t3Vector3f& hitPoint, float u, float v) const; 25 | 26 | float radius; 27 | }; -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Tree/t3Heap.h: -------------------------------------------------------------------------------- 1 | #ifndef T3_HEAP_H 2 | #define T3_HEAP_H 3 | 4 | #include 5 | #include 6 | 7 | class t3HeapElement 8 | { 9 | public: 10 | t3HeapElement():key(0){} 11 | 12 | t3HeapElement(t3HeapElement& e){this->key = e.key;} 13 | 14 | int key; 15 | }; 16 | 17 | // 使用数组完成的最大堆 而非链表形式 18 | class t3HeapADT 19 | { 20 | public: 21 | t3HeapADT(); 22 | 23 | //bool isFull(); 24 | 25 | bool isEmpty(); 26 | 27 | void insert(int data); 28 | 29 | // 删除堆中最大的元素 30 | t3TreeNode* remove(); 31 | 32 | t3HeapElement *elements; 33 | 34 | // 当前堆中数量 35 | int n; 36 | 37 | // 当前可存放最大元素 38 | int length; 39 | private: 40 | // 尽量不要扩建,效率很低 41 | void enlarge(); 42 | }; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /Atmos/bsdf/a3Diffuse.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3Diffuse : public a3BSDF 6 | { 7 | public: 8 | a3Diffuse(); 9 | 10 | // evaluate the BSDF f(wi, wo)(f * cos * R) 11 | virtual a3Spectrum eval(const a3BSDFSamplingRecord& bRec) const; 12 | 13 | // sample the BSDF and return the importance weight 14 | // returned value has divided by the probability density of the sample 15 | virtual a3Spectrum sample(a3BSDFSamplingRecord& bRec) const; 16 | 17 | // compute the probability of sampling wo (given wi, BSDF(wi, wo) * costheta) 18 | virtual float pdf(const a3BSDFSamplingRecord& bRec) const; 19 | 20 | // if delta distribution 21 | virtual bool isDeltaDistribution() const; 22 | 23 | // reflectance of Lambertion 24 | //--!could be replaced by Texture 25 | a3Spectrum R; 26 | }; -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Test/StringADTTest.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]) 6 | { 7 | t3Timer timer; 8 | 9 | t3StringADT s; 10 | s.create("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ababababababababababababababababab aab"); 11 | 12 | s.setPattern("aab"); 13 | 14 | timer.start(); 15 | for(int i=0; i<1000000; i++) 16 | s.find(); 17 | timer.end(); 18 | t3Log("find()花费时间: %lf\n", timer.difference()); 19 | 20 | t3Log("-----------------------\n"); 21 | 22 | timer.start(); 23 | for(int i=0; i<1000000; i++) 24 | s.findFast(); 25 | timer.end(); 26 | 27 | t3Log("findFast()花费时间: %lf\n", timer.difference()); 28 | 29 | //s.findFast("lao"); 30 | getchar(); 31 | return 0; 32 | } -------------------------------------------------------------------------------- /Atmos/bsdf/a3Conductor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3Conductor : public a3BSDF 6 | { 7 | public: 8 | a3Conductor(); 9 | 10 | // evaluate the BSDF f(wi, wo)(f * cos * R) 11 | virtual a3Spectrum eval(const a3BSDFSamplingRecord& bRec) const; 12 | 13 | // sample the BSDF and return the importance weight 14 | // returned value has divided by the probability density of the sample 15 | virtual a3Spectrum sample(a3BSDFSamplingRecord& bRec) const; 16 | 17 | // compute the probability of sampling wo (given wi, BSDF(wi, wo) * costheta) 18 | virtual float pdf(const a3BSDFSamplingRecord& bRec) const; 19 | 20 | // if delta distribution 21 | virtual bool isDeltaDistribution() const; 22 | 23 | // specular refelctance 24 | a3Spectrum R; 25 | 26 | // interior refractive index of refraction, absorbtion 27 | a3Spectrum eta, k; 28 | }; -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/LinearList/t3Expression.h: -------------------------------------------------------------------------------- 1 | #ifndef T3_EXPRESSION_H 2 | #define T3_EXPRESSION_H 3 | 4 | #include 5 | #include 6 | 7 | enum t3Precedence 8 | { 9 | lparen, 10 | rparen, 11 | plus, 12 | minus, 13 | times, 14 | divide, 15 | mod, 16 | eos, 17 | operand 18 | }; 19 | 20 | class t3Expression 21 | { 22 | public: 23 | t3Expression(); 24 | 25 | // 给出中缀表达式 26 | void create(std::string s); 27 | 28 | void toPostfix(); 29 | 30 | int evaluate(); 31 | 32 | t3Precedence getToken(int n); 33 | 34 | const char getChar(int n); 35 | 36 | const char getSymbol(t3Precedence p); 37 | 38 | void printToken(t3Precedence p); 39 | 40 | std::string exp; 41 | 42 | t3Stack postfixStack; 43 | t3Stack valueStack; 44 | }; 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/String/t3StringADT.h: -------------------------------------------------------------------------------- 1 | #ifndef T3_STRINGADT_H 2 | #define T3_STRINGADT_H 3 | 4 | #include 5 | 6 | class t3StringADT 7 | { 8 | public: 9 | t3StringADT(); 10 | t3StringADT(char* c); 11 | 12 | // 可重复构造 13 | void create(char* c); 14 | 15 | void setPattern(char* pattern); 16 | 17 | // 在当前字符串中寻找指定模式 18 | int find(); 19 | 20 | // KMP算法 21 | int findFast(); 22 | 23 | 24 | private: 25 | // enum ERROR_STRING 26 | // { 27 | // T3_PATTERN_NULL = 0, 28 | // T3_STRING_NULL, 29 | // }; 30 | // 31 | // void error(ERROR_STRING errorMessage); 32 | 33 | // 代匹配字符串 34 | char* string; 35 | 36 | char* pattern; 37 | 38 | //失配数组 39 | int *next; 40 | 41 | // 字符串长度 42 | int lengthString; 43 | 44 | int lengthPattern; 45 | }; 46 | 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /test/main.cpp: -------------------------------------------------------------------------------- 1 | // 基本数学库和光线相交检测 2 | //#include "ray.h" 3 | 4 | // 基本渲染管线检测 5 | //#include "render.h" 6 | 7 | // 基本多类场景测试 8 | //#include "scenes.h" 9 | 10 | // png文件导入保存测试 11 | //#include "png.h" 12 | 13 | // 模型导入测试 14 | //#include "model.h" 15 | 16 | // 基本场景渲染队列演示 17 | //#include "renderQueue.h" 18 | 19 | // 局部坐标系与世界坐标系转换测试 20 | //#include "coordinate.h" 21 | 22 | // 基本包围盒与图元加速器测试 23 | //#include "aabb.h" 24 | 25 | // 基本的exr图片导入导出支持 26 | //#include "exr.h" 27 | 28 | // 菲尼尔渲染贴图测试 29 | //#include "fresnel.h" 30 | 31 | // 基本面积光测试 32 | //#include "areaLight.h" 33 | 34 | // Blender to Atmos渲染测试 35 | //#include "blender.h" 36 | 37 | // Grid渲染器测试 38 | //#include "grid.h" 39 | 40 | // Util工具函数测试 41 | //#include "util.h" 42 | 43 | // IPC渲染结果传输测试 44 | //#include "ipc.h" 45 | 46 | // 编辑器IPC完整性测试 47 | //#include "editor.h" 48 | 49 | // 基本积分器测试 50 | #include "integrator.h" 51 | 52 | // 微表面模型MIS场景测试 53 | //#include "microfacet.h" -------------------------------------------------------------------------------- /Atmos/renderers/a3SamplerRenderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class a3Random; 7 | class a3Sampler; 8 | class a3Integrator; 9 | 10 | class a3SamplerRenderer : public a3Renderer 11 | { 12 | public: 13 | a3SamplerRenderer(); 14 | 15 | a3SamplerRenderer(int spp); 16 | 17 | ~a3SamplerRenderer(); 18 | 19 | bool begin(); 20 | 21 | void render(const a3Scene* scene); 22 | 23 | void end(); 24 | 25 | bool check(); 26 | 27 | void postEffect(); 28 | 29 | // 采样器 30 | a3Sampler* sampler; 31 | 32 | // 相机 33 | a3Sensor* camera; 34 | 35 | // 积分器 36 | a3Integrator* integrator; 37 | 38 | // 伽马校正开关 39 | bool enableGammaCorrection; 40 | 41 | // Tone Mapping开关 42 | bool enableToneMapping; 43 | 44 | // Samples Per Pixels 45 | int spp; 46 | 47 | // color list for temp use 48 | a3Spectrum* colorList; 49 | }; -------------------------------------------------------------------------------- /Atmos/bsdf/a3Dielectric.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3Dielectric : public a3BSDF 6 | { 7 | public: 8 | a3Dielectric(); 9 | 10 | // evaluate the BSDF f(wi, wo)(f * cos * R) 11 | virtual a3Spectrum eval(const a3BSDFSamplingRecord& bRec) const; 12 | 13 | // sample the BSDF and return the importance weight 14 | // returned value has divided by the probability density of the sample 15 | virtual a3Spectrum sample(a3BSDFSamplingRecord& bRec) const; 16 | 17 | // compute the probability of sampling wo (given wi, BSDF(wi, wo) * costheta) 18 | virtual float pdf(const a3BSDFSamplingRecord& bRec) const; 19 | 20 | // if delta distribution 21 | virtual bool isDeltaDistribution() const; 22 | 23 | // specular refelctance / transmittance 24 | a3Spectrum specularReflectance, specularTransmittance; 25 | 26 | // inverse interior refractive index of refraction 27 | float eta; 28 | }; -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Test/t3RegexTest.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main(int argc, char** argv) 9 | { 10 | regex pattern("[[:digit:]]", regex_constants::extended); 11 | printf("input strings:\n"); 12 | string buf; 13 | 14 | while(cin >> buf) 15 | { 16 | printf("*******\n%s\n********\n", buf.c_str()); 17 | 18 | if(buf == "quit") 19 | { 20 | printf("quit just now!\n"); 21 | break; 22 | } 23 | 24 | match_results result; 25 | printf("run compare now! '%s'\n", buf.c_str()); 26 | bool valid = regex_match(buf, result, pattern); 27 | printf("compare over now! '%s'\n", buf.c_str()); 28 | 29 | if(!valid) 30 | printf("no match!\n"); 31 | else 32 | printf("ok\n"); 33 | } 34 | 35 | return 0; 36 | } -------------------------------------------------------------------------------- /Atmos/core/a3Settings.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // 隐藏可见范围的全局变量 13 | a3Version atmosVersion; 14 | 15 | // 注意:只能在Debug模式下才能使用 16 | void t2Log(const char* string, ...) 17 | { 18 | #ifdef _DEBUG 19 | va_list args; 20 | va_start(args, string); 21 | vprintf(string, args); 22 | va_end(args); 23 | #endif 24 | } 25 | 26 | std::string a3Version::get() 27 | { 28 | std::ostringstream out; 29 | out << type << major << minor << revision; 30 | return out.str(); 31 | } 32 | 33 | void a3Version::print() 34 | { 35 | std::cout << "Atmos版本:" << type << " " << major << "." << minor << "." << revision << std::endl; 36 | } 37 | 38 | // --!重大革新:小改动:BUG修复 39 | a3Version::a3Version() : major(0), minor(3), revision(1), type("Alpha") 40 | { 41 | 42 | } 43 | -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Common/t3Test.h: -------------------------------------------------------------------------------- 1 | #ifndef A3_TEST_H 2 | #define A3_TEST_H 3 | 4 | #include 5 | #include 6 | 7 | #define t3PrintError(errorMessage) t3PrintError_(std::string(__FUNCTION__), errorMessage) 8 | 9 | #define t3PrintErrorArg(argName, arg, errorMessage) t3PrintError_(std::string(__FUNCTION__), argName, arg, errorMessage) 10 | 11 | 12 | template 13 | void t3PrintError_(std::string functionName, std::string argName, T arg, std::string errorMessage) 14 | { 15 | std::cout << "Error: " << "执行函数: " << functionName << "()时参数:" << argName << " = " << arg << "发生错误:" << errorMessage 16 | << std::endl; 17 | } 18 | 19 | template 20 | void t3PrintError_(std::string functionName, std::string errorMessage) 21 | { 22 | std::cout << "Error: " << "执行函数: " << functionName << "()时发生错误:" << errorMessage << std::endl; 23 | } 24 | 25 | void t3Log(const char* _Format,...); 26 | 27 | //double t3GetRealTime(); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /Atmos/core/messageQueue/a3MessageQueue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct a3MessageEntryHead 6 | { 7 | a3MessageEntryHead() :type(0) {} 8 | 9 | int type; 10 | }; 11 | 12 | typedef std::vector MessageEntryVector; 13 | 14 | struct a3MessageQueueHead 15 | { 16 | a3MessageQueueHead() :head(0), tail(0) {} 17 | int head; 18 | int tail; 19 | }; 20 | 21 | class a3MessageQueue 22 | { 23 | public: 24 | a3MessageQueue(); 25 | ~a3MessageQueue(); 26 | 27 | void init(char* buffer, int buffer_size, int msg_size); 28 | void uninit(); 29 | 30 | bool isEmpty(); 31 | bool isFull(); 32 | int getSize(); 33 | 34 | bool enqueue(const a3MessageEntryHead& msg); 35 | bool dequeue(a3MessageEntryHead& msg); 36 | 37 | private: 38 | MessageEntryVector entries; 39 | a3MessageQueueHead* mqHead; 40 | int messageNum; 41 | int messageSize; 42 | 43 | private: 44 | a3MessageQueue(const a3MessageQueue&); 45 | void operator=(const a3MessageQueue&); 46 | }; -------------------------------------------------------------------------------- /Atmos/textures/a3ImageTexture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | class a3ImageTexture:public a3Texture 10 | { 11 | public: 12 | a3ImageTexture(const char* filePath) 13 | { 14 | decoder = new a3ImageDecoder(); 15 | 16 | if(decoder->load(filePath)) 17 | a3Log::success("Image Texture Created Succeed\n"); 18 | } 19 | 20 | virtual ~a3ImageTexture() 21 | { 22 | A3_SAFE_DELETE(decoder); 23 | } 24 | 25 | virtual T evaluate(float u, float v) const 26 | { 27 | return decoder->lookup(u, v); 28 | } 29 | 30 | a3ImageDecoder* decoder; 31 | }; 32 | 33 | inline a3ImageTexture* a3CreateImageTexture(const char* filePath) 34 | { 35 | a3ImageTexture* texture = new a3ImageTexture(filePath); 36 | 37 | return texture; 38 | } 39 | -------------------------------------------------------------------------------- /Atmos/shapes/a3InfinitePlane.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3ShapeSamplingRecord; 6 | 7 | // For Testing, not as the shape of light 8 | class a3InfinitePlane :public a3Shape 9 | { 10 | public: 11 | a3InfinitePlane(const t3Matrix4x4& shapeToWorld); 12 | 13 | virtual ~a3InfinitePlane(); 14 | 15 | // ray intersection test for visibility queries 16 | virtual bool intersect(const a3Ray& ray, float* t, float* u, float* v) const; 17 | 18 | // compute the area 19 | virtual float area() const; 20 | 21 | // Sample a point on the surface of this shape instance 22 | virtual void sample(a3ShapeSamplingRecord& sRec) const; 23 | 24 | // Query the probability density of sample() for a particular point on the surface. 25 | virtual float pdf(const a3ShapeSamplingRecord& sRec) const; 26 | 27 | // return the normal vec from the point be hitted 28 | virtual t3Vector3f getNormal(const t3Vector3f& hitPoint, float u, float v) const; 29 | }; -------------------------------------------------------------------------------- /Atmos/bsdf/a3BSDF.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class a3BSDFSamplingRecord; 7 | class a3BSDF 8 | { 9 | public: 10 | a3BSDF(); 11 | 12 | a3BSDF(a3Texture* texture); 13 | 14 | virtual ~a3BSDF(); 15 | 16 | // evaluate the BSDF f(wi, wo) 17 | virtual a3Spectrum eval(const a3BSDFSamplingRecord& bRec) const = 0; 18 | 19 | // sample the BSDF and return the importance weight 20 | // returned value has divided by the probability density of the sample 21 | virtual a3Spectrum sample(a3BSDFSamplingRecord& bRec) const = 0; 22 | 23 | // compute the probability of sampling wo (given wi, BSDF(wi, wo) * costheta) 24 | virtual float pdf(const a3BSDFSamplingRecord& bRec) const = 0; 25 | 26 | // if delta distribution 27 | virtual bool isDeltaDistribution() const = 0; 28 | 29 | std::string name; 30 | 31 | // reflectance on texture 32 | a3Texture* reflectance; 33 | }; 34 | -------------------------------------------------------------------------------- /Atmos/shapes/a3Sphere.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3Sphere : public a3Shape 6 | { 7 | public: 8 | a3Sphere(const t3Matrix4x4& shapeToWorld, const float radius); 9 | 10 | virtual ~a3Sphere(); 11 | 12 | // ray intersection test for visibility queries 13 | virtual bool intersect(const a3Ray& ray, float* t, float* u, float* v) const; 14 | 15 | // compute the area 16 | virtual float area() const; 17 | 18 | // Sample a point on the surface of this shape instance 19 | virtual void sample(a3ShapeSamplingRecord& sRec) const; 20 | 21 | // return the normal vec from the point be hitted 22 | virtual t3Vector3f getNormal(const t3Vector3f& hitPoint, float u, float v) const; 23 | 24 | // shading coordinates to world(would be replaced in the future) 25 | virtual t3Matrix4x4 getShadeToWorld(const a3IntersectRecord& its) const; 26 | 27 | float radius; 28 | 29 | // initted by objectToWorld 30 | t3Vector3f center; 31 | }; -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Common/t3Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | //template 10 | //void t3PrintError_(std::string functionName, std::string argName, T arg, std::string errorMessage) 11 | //{ 12 | // std::cout << "Error: " << "执行函数: " << functionName << "()时参数:" << argName << " = " << arg << "发生错误:" << errorMessage << std::endl; 13 | //} 14 | // 15 | //void t3PrintError_(std::string functionName, std::string errorMessage) 16 | //{ 17 | // std::cout << "Error: " << "执行函数: " << functionName << "()时发生错误:" << errorMessage << std::endl; 18 | //} 19 | 20 | void t3Log(const char * _Format,...) 21 | { 22 | va_list args; 23 | va_start(args,_Format); 24 | 25 | FILE* out = stdout; 26 | vfprintf(out, _Format, args); 27 | fprintf(out, "\n"); 28 | 29 | va_end( args ); 30 | } 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | README~ 3 | .gitignore~ 4 | *.out 5 | *.exe 6 | *.tlog 7 | *.obj 8 | *.pdb 9 | *.idb 10 | *.sdf 11 | *.ilk 12 | *.log 13 | *.lastbuildstate 14 | #*.sln 15 | *.suo 16 | #*.vcxproj 17 | #*.filters 18 | #*.user 19 | *.png 20 | *.ppm 21 | *.psess 22 | *.vsp 23 | *.rar 24 | *.psd 25 | *.mp4 26 | *.user 27 | 28 | #Temp file generated by VS2015 29 | *.VC.* 30 | 31 | #dependency/assimp/lib/* 32 | resources/* 33 | 34 | #VS2013 Deprecated 35 | build/Atmos.vs2013/Atmos/Debug/*.* 36 | build/Atmos.vs2013/Atmos/Release/*.* 37 | build/Atmos.vs2013/AtmosTest/Debug/*.* 38 | build/Atmos.vs2013/AtmosTest/Release/*.* 39 | 40 | #VS2015 41 | #x86 42 | build/Atmos.vs2015/Atmos/Win32/Debug/*.* 43 | build/Atmos.vs2015/Atmos/Win32/Release/*.* 44 | build/Atmos.vs2015/AtmosTest/Win32/Debug/*.* 45 | build/Atmos.vs2015/AtmosTest/Win32/Release/*.* 46 | 47 | #x64 48 | build/Atmos.vs2015/Atmos/x64/Debug/*.* 49 | build/Atmos.vs2015/Atmos/x64/Release/*.* 50 | build/Atmos.vs2015/AtmosTest/x64/Debug/*.* 51 | build/Atmos.vs2015/AtmosTest/x64/Release/*.* -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Test/t3LinkListTest.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | //#define T3_TEST_TYPELIST 9 | #define T3_TEST_LINKLIST 10 | 11 | int main(int argc, char* argv[]) 12 | { 13 | #ifdef T3_TEST_LINKLIST 14 | t3SingleLinkList linkList; 15 | 16 | t3Log("-------------------------------\n"); 17 | 18 | linkList.insert(20); 19 | linkList.insert(3); 20 | t3LinkListNode* node = linkList.insert(2); 21 | linkList.insert(60); 22 | linkList.insert(28); 23 | 24 | linkList.print(); 25 | 26 | linkList.deleteNode(node); 27 | 28 | t3Log("-------------------------------\n"); 29 | linkList.print(); 30 | 31 | linkList.invert(); 32 | 33 | t3Log("-------------------------------\n"); 34 | linkList.print(); 35 | 36 | #endif 37 | 38 | #ifdef T3_TEST_TYPELIST 39 | 40 | #endif 41 | getchar(); 42 | return 0; 43 | } -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/SparseMatrix/t3SparseMatrixADT.h: -------------------------------------------------------------------------------- 1 | #ifndef T3_SPARSEMATRIXADT_H 2 | #define T3_SPARSEMATRIXADT_H 3 | 4 | class term 5 | { 6 | public: 7 | term():col(0), row(0), value(0){} 8 | 9 | term(int row, int col, int value):col(col), row(row), value(value){} 10 | 11 | int col, row; 12 | int value; 13 | }; 14 | 15 | // 数组构造成的稀疏矩阵 16 | class t3SparseMatrixADT 17 | { 18 | public: 19 | // 创建一个最大能容纳maxRow x maxCol 非零元素个数count的稀疏矩阵 本质上是一维矩阵 20 | void create(int maxRow, int maxCol, int itemCount); 21 | 22 | // 返回一个堆中分配的稀疏矩阵 23 | t3SparseMatrixADT* transpose(); 24 | 25 | t3SparseMatrixADT* transposeFast(); 26 | 27 | // 在矩阵中添加一项的拷贝 28 | void add(int row, int col, int value); 29 | 30 | void add(term& t); 31 | 32 | void print(); 33 | 34 | void operator+(t3SparseMatrixADT& m); 35 | 36 | void operator*(t3SparseMatrixADT& m); 37 | 38 | term *m; 39 | 40 | // 非零元素个数 41 | int count; 42 | }; 43 | 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /Atmos/bsdf/a3RoughConductor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class a3RoughConductor : public a3BSDF 7 | { 8 | public: 9 | a3RoughConductor(); 10 | 11 | // evaluate the BSDF f(wi, wo)(f * cos * R) 12 | virtual a3Spectrum eval(const a3BSDFSamplingRecord& bRec) const; 13 | 14 | // sample the BSDF and return the importance weight 15 | // returned value has divided by the probability density of the sample 16 | virtual a3Spectrum sample(a3BSDFSamplingRecord& bRec) const; 17 | 18 | // compute the probability of sampling wo (given wi, BSDF(wi, wo) * costheta) 19 | virtual float pdf(const a3BSDFSamplingRecord& bRec) const; 20 | 21 | // if delta distribution 22 | virtual bool isDeltaDistribution() const; 23 | 24 | // specular refelctance 25 | a3Spectrum R; 26 | 27 | // interior refractive index of refraction, absorbtion 28 | a3Spectrum eta, k; 29 | 30 | // microfacets oriented perpendicular to the x axis and y axis, 31 | float alphaX, alphaY; 32 | 33 | a3Microfacet::a3MicrofacetType type; 34 | }; -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Test/SparseMatrixTest.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]) 6 | { 7 | t3SparseMatrixADT m1, *m2 = NULL; 8 | t3Timer timer; 9 | 10 | m1.create(6, 6, 8); 11 | 12 | // 强行默认是按行顺序排列了的 13 | m1.add(0, 0, 15); 14 | m1.add(0, 3, 22); 15 | m1.add(0, 5, -15); 16 | m1.add(1, 1, 11); 17 | m1.add(1, 2, 3); 18 | m1.add(2, 3, -6); 19 | m1.add(4, 0, 91); 20 | m1.add(5, 2, 28); 21 | 22 | m1.print(); 23 | 24 | timer.start(); 25 | for(int i=0; i<500000; i++) 26 | { 27 | m2 = m1.transpose(); 28 | } 29 | timer.end(); 30 | 31 | t3Log("transpose()花费时间: %lf\n", timer.difference()); 32 | 33 | 34 | timer.start(); 35 | for(int i=0; i<500000; i++) 36 | { 37 | m2 = m1.transposeFast(); 38 | } 39 | timer.end(); 40 | 41 | t3Log("transposeFast()花费时间: %lf\n", timer.difference()); 42 | 43 | m2->print(); 44 | 45 | getchar(); 46 | 47 | return 0; 48 | } -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Tree/t3ThreadedBinaryTree.h: -------------------------------------------------------------------------------- 1 | #ifndef T3_THREADED_BINARYTREE_H 2 | #define T3_THREADED_BINARYTREE_H 3 | 4 | #include 5 | 6 | class t3ThreadTreeNode 7 | { 8 | public: 9 | t3ThreadTreeNode(int data):leftThread(false), rightThread(false), leftChild(NULL), rightChild(NULL), data(data){} 10 | // 默认线索全为false 11 | t3ThreadTreeNode():leftThread(false), rightThread(false), leftChild(NULL), rightChild(NULL), data(0){} 12 | 13 | int data; 14 | bool leftThread, rightThread; 15 | t3ThreadTreeNode *leftChild, *rightChild; 16 | }; 17 | 18 | class t3ThreadedBinaryTree:public t3BinaryTree 19 | { 20 | public: 21 | t3ThreadedBinaryTree(); 22 | 23 | void inThreading(); 24 | 25 | // 这里只重现中序遍历 其余可自行实现 26 | void inorder(); 27 | 28 | // 不做错误检查 29 | void insertRight(t3ThreadTreeNode *parent, t3ThreadTreeNode *child); 30 | 31 | // 返回中序遍历的后继结点 32 | t3ThreadTreeNode* inSuccessor(t3ThreadTreeNode *root); 33 | 34 | private: 35 | void inThreading(t3ThreadTreeNode *current); 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /Atmos/lights/a3EnvironmentLight.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class a3ImageDecoder; 7 | 8 | class a3EnvironmentLight : public a3Light 9 | { 10 | public: 11 | // optional emmiter to world transform 12 | a3EnvironmentLight(const std::string& filePath, const t3Matrix4x4& lightToWorld = t3Matrix4x4::newIdentityMatrix()); 13 | 14 | ~a3EnvironmentLight(); 15 | 16 | // return the radiant emittance from an environment emitter 17 | virtual a3Spectrum evalEnvironment(const a3Ray& ray) const; 18 | 19 | // given a reference point in the scene, sample an emitter position that contributes towards it. 20 | virtual a3Spectrum sampleDirect(a3LightSamplingRecord& dRec) const; 21 | 22 | // evaluate the probability density of the direct sampling method 23 | virtual float pdf(const a3LightSamplingRecord& dRec) const; 24 | 25 | // is this an environment emitter 26 | virtual bool isEnvironment() const; 27 | 28 | // is this a delta distribution emitter 29 | virtual bool isDeltaDistribution() const; 30 | 31 | // image based lighting 32 | a3ImageDecoder* image; 33 | }; 34 | -------------------------------------------------------------------------------- /dependency/t3Math/include/t3Math/core/t3MathSettings.h: -------------------------------------------------------------------------------- 1 | #define T3_VARARGS __cdecl /* Functions with variable arguments */ 2 | #define T3_CDECL __cdecl /* Standard C function */ 3 | #define T3_STDCALL __stdcall /* Standard calling convention */ 4 | 5 | //#define T3_FORCE_INLINE __forceinline /* Force code to be inline */ 6 | #ifdef _MSC_VER // for MSVC 7 | #define T3_FORCE_INLINE __forceinline 8 | #elif defined __GNUC__ // for gcc on Linux/Apple OS X 9 | #define T3_FORCE_INLINE __inline__ __attribute__((always_inline)) 10 | #else 11 | #define T3_FORCE_INLINE 12 | #endif 13 | 14 | #define T3_FORCE_NOINLINE __declspec(noinline) /* Force code to NOT be inline */ 15 | 16 | #define T3MATH_DEFAULT_EPSILON 0.000001f 17 | #define T3MATH_LARGE_EPSILON 0.00001f 18 | 19 | #define T3MATH_E 2.71828182846f 20 | #define T3MATH_PI 3.14159265358979323f 21 | 22 | #define T3MATH_INV_PI 0.31830988618379067154f 23 | #define T3MATH_INV_TWOPI 0.15915494309189533577f 24 | #define T3MATH_INV_FOURPI 0.07957747154594766788f 25 | 26 | #ifndef T3MATH_INFINITY 27 | #define T3MATH_INFINITY FLT_MAX 28 | #endif 29 | 30 | #define T3MATH_RAD_TO_DEG (180.0f / T3MATH_PI) 31 | 32 | #define T3MATH_DEG_TO_RAD (T3MATH_PI / 180.0f) -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Common/t3DataStructuresSettings.h: -------------------------------------------------------------------------------- 1 | #ifndef T3_DATASTRUCTURESSETTINGS_H 2 | #define T3_DATASTRUCTURESSETTINGS_H 3 | 4 | #if defined( __WIN32__ ) || defined( _WIN32 ) 5 | #define T3_PLATFORM_WIN32 6 | #elif defined( __APPLE_CC__) 7 | #include 8 | 9 | #if (T3_PLATFORM_OS_IPHONE_SIMULATOR) || (T3_PLATFORM_OS_IPHONE) || (T3_PLATFORM_IPHONE) 10 | #define T3_PLATFORM_OF_IPHONE 11 | #define T3_PLATFORM_OF_IOS 12 | #define T3_PLATFORM_OPENGLES 13 | #else 14 | #define T3_PLATFORM_OSX 15 | #endif 16 | 17 | #elif defined (__ANDROID__) 18 | #define T3_PLATFORM_ANDROID 19 | #define T3_PLATFORM_OPENGLES 20 | 21 | #elif defined(__ARMEL__) 22 | #define T3_PLATFORM_LINUX 23 | #define T3_PLATFORM_OPENGLES 24 | 25 | #define T3_PLATFORM_LINUX_ARM 26 | #else 27 | #define T3_PLATFORM_LINUX 28 | #endif 29 | 30 | // 线性表默认长度 31 | #define T3_STACK_DEFAULT_LENGTH 32 32 | #define T3_QUEUE_DEFAULT_LENGTH 32 33 | 34 | // 二叉树默认最大元素存放量 35 | #define T3_BINARTTREE_DEFAULT_LENGTH 16 36 | // 临时变量最大空间长度 37 | #define T3_BINARTTREE_MAPINDEX_LENGTH 64 38 | 39 | // 最大堆的最大容量 40 | #define T3_HEAP_DEFAULT_LENGTH 100 41 | #endif 42 | -------------------------------------------------------------------------------- /Atmos/sensors/a3PerspectiveSensor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3Ray; 6 | class a3CameraSample; 7 | class a3Film; 8 | class a3Random; 9 | 10 | // 暂时与Thinlens合并 11 | class a3PerspectiveSensor : public a3Sensor 12 | { 13 | public: 14 | // fov(度)与屏幕宽高比一致 15 | a3PerspectiveSensor(const t3Vector3f& origin, const t3Vector3f& lookat, const t3Vector3f& up, 16 | float fov, 17 | float focalDistance, float lensRadius, 18 | a3Film* image); 19 | 20 | // fov(度) 21 | a3PerspectiveSensor(const t3Vector3f& origin, const t3Vector3f& lookat, const t3Vector3f& up, 22 | float fovX, float fovY, 23 | float focalDistance, float lensRadius, 24 | a3Film* image); 25 | 26 | a3PerspectiveSensor(const t3Vector3f& origin, const t3Vector3f& lookat, const t3Vector3f& up, 27 | float focalLength, float apretureWidth, float apretureHeight, float canvasDistance, 28 | float focalDistance, float lensRadius, 29 | a3Film* image); 30 | 31 | virtual float castRay(const a3CameraSample* sample, a3Ray* ray) const; 32 | 33 | //a3Random* random; 34 | }; -------------------------------------------------------------------------------- /Atmos/lights/a3Light.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class a3Ray; 8 | class a3LightSamplingRecord; 9 | class a3IntersectRecord; 10 | class a3Light 11 | { 12 | public: 13 | a3Light(std::string name); 14 | 15 | a3Light(const t3Matrix4x4& lightToWorld, std::string name); 16 | 17 | virtual ~a3Light(); 18 | 19 | // return the radiant emittance for the attached shape's surface intersection 20 | virtual a3Spectrum eval(const a3IntersectRecord& its, const t3Vector3f &d) const; 21 | 22 | // return the radiant emittance from an environment emitter 23 | virtual a3Spectrum evalEnvironment(const a3Ray& ray) const; 24 | 25 | // given a reference point in the scene, sample an emitter position that contributes towards it. 26 | virtual a3Spectrum sampleDirect(a3LightSamplingRecord& dRec) const = 0; 27 | 28 | // evaluate the probability density of the direct sampling method 29 | virtual float pdf(const a3LightSamplingRecord& dRec) const = 0; 30 | 31 | // is this an environment emitter 32 | virtual bool isEnvironment() const = 0; 33 | 34 | // is this a delta distribution emitter 35 | virtual bool isDeltaDistribution() const = 0; 36 | 37 | std::string name; 38 | 39 | t3Matrix4x4 lightToWorld, worldToLight; 40 | }; -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Tree/t3Heap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | t3HeapADT::t3HeapADT():n(0), elements(NULL), length(T3_HEAP_DEFAULT_LENGTH) 6 | { 7 | enlarge(); 8 | } 9 | 10 | //bool t3HeapADT::isFull() 11 | //{ 12 | // 13 | //} 14 | 15 | bool t3HeapADT::isEmpty() 16 | { 17 | return !n; 18 | } 19 | 20 | void t3HeapADT::insert(int data) 21 | { 22 | n++; 23 | if(n > length) 24 | enlarge(); 25 | 26 | // 缺省 27 | } 28 | 29 | // 删除堆中最大的元素 30 | t3TreeNode* t3HeapADT::remove() 31 | { 32 | // 缺省 33 | return NULL; 34 | } 35 | 36 | void t3HeapADT::enlarge() 37 | { 38 | if(elements) 39 | { 40 | t3Log("t3HeapADT: enlarge!"); 41 | 42 | int orignalLength = length; 43 | // 扩增两倍 44 | length = 2 * orignalLength; 45 | 46 | t3HeapElement *temp = new t3HeapElement[length](); 47 | 48 | // 数据迁移 49 | for(int i=0; i 5 | 6 | // not support UTF8 log to file 7 | // default file name format [year]-[month]-[day]-Atmos-VertionType.html 8 | // would cover the same name file, be sure to end() when everything is finished 9 | class a3LogHTML 10 | { 11 | public: 12 | static void log(a3LogLevel logLevel, const char* message, ...); 13 | 14 | static void begin(); 15 | 16 | static void end(); 17 | 18 | // log to default name file: [prefix]:Atmos-VerisionType.html 19 | static void fatalError(const char* message, ...); 20 | 21 | static void error(const char* message, ...); 22 | 23 | static void seriousWarning(const char* message, ...); 24 | 25 | static void warning(const char* message, ...); 26 | 27 | static void success(const char* message, ...); 28 | 29 | static void info(const char* message, ...); 30 | 31 | static void dev(const char* message, ...); 32 | 33 | static void debug(const char* message, ...); 34 | 35 | private: 36 | a3LogHTML() {} 37 | a3LogHTML(const a3LogHTML&) {} 38 | ~a3LogHTML() {} 39 | a3LogHTML& operator=(const a3LogHTML& event) const {} 40 | 41 | static void log(a3LogLevel logLevel, const char* message, va_list args); 42 | 43 | static std::ofstream* ofile; 44 | 45 | static bool isBegin; 46 | }; 47 | 48 | 49 | #endif -------------------------------------------------------------------------------- /Atmos/lights/a3AreaLight.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class a3ImageDecoder; 8 | class a3Shape; 9 | class a3AreaLight : public a3Light 10 | { 11 | public: 12 | // optional emmiter to world transform 13 | a3AreaLight(a3Shape* shape, a3Spectrum radiance, const t3Matrix4x4& lightToWorld = t3Matrix4x4::newIdentityMatrix()); 14 | 15 | ~a3AreaLight(); 16 | 17 | // return the radiant emittance for the attached shape's surface intersection 18 | virtual a3Spectrum eval(const a3IntersectRecord& its, const t3Vector3f &d) const; 19 | 20 | // given a reference point in the scene, sample an emitter position that contributes towards it. 21 | // returned value has divided by the probability density of the sample 22 | virtual a3Spectrum sampleDirect(a3LightSamplingRecord& dRec) const; 23 | 24 | // evaluate the probability density of the direct sampling method 25 | virtual float pdf(const a3LightSamplingRecord& dRec) const; 26 | 27 | // is this an environment emitter 28 | virtual bool isEnvironment() const; 29 | 30 | // is this a delta distribution emitter 31 | virtual bool isDeltaDistribution() const; 32 | 33 | // attach to a shape ptr 34 | void setShape(a3Shape* shape); 35 | 36 | const a3Shape* getShape(); 37 | 38 | a3Shape* shape; 39 | 40 | a3Spectrum radiance; 41 | }; 42 | -------------------------------------------------------------------------------- /Atmos/bsdf/a3Microfacet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class a3Microfacet 6 | { 7 | public: 8 | enum a3MicrofacetType 9 | { 10 | Beckmann = 0, 11 | GGX = 1, 12 | Phong = 2 13 | }; 14 | 15 | a3Microfacet(float alphaX, float alphaY, a3MicrofacetType type = Beckmann); 16 | 17 | // evaluate the microfacet distribution function(D(wh)) 18 | float D(const t3Vector3f& m) const; 19 | 20 | // Separable shadow - masking function based on Smith's one - dimensional masking model 21 | float G(const t3Vector3f &wi, const t3Vector3f &wo, const t3Vector3f &m) const; 22 | 23 | // Draw a sample from the microfacet normal distribution and return the associated probability density 24 | t3Vector3f sample(const t3Vector3f& wi, float& pdf) const; 25 | 26 | // Returns the density function associated with the sample function 27 | float pdf(const t3Vector3f& wi, const t3Vector3f& m) const; 28 | 29 | // Smith's shadowing-masking function G1 for each of the supported microfacet distributions 30 | float smithG1(const t3Vector3f &v, const t3Vector3f &m) const; 31 | 32 | // Is this an anisotropic microfacet distribution? 33 | bool isAnisotropic() const; 34 | 35 | // Is this an anisotropic microfacet distribution? 36 | bool isIsotropic() const; 37 | 38 | // Supported distribution types 39 | a3MicrofacetType type; 40 | 41 | float alphaX, alphaY; 42 | }; -------------------------------------------------------------------------------- /Atmos/core/a3AABB.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class a3Ray; 7 | 8 | class a3AABB 9 | { 10 | public: 11 | a3AABB(); 12 | a3AABB(const t3Vector3f& p); 13 | a3AABB(const t3Vector3f& p0, const t3Vector3f& p1); 14 | 15 | void set(const t3Vector3f& p0, const t3Vector3f& p1); 16 | 17 | bool overlaps(const a3AABB& bbox) const; 18 | 19 | bool inside(const t3Vector3f& point) const; 20 | 21 | void expand(float delta); 22 | 23 | float surfaceArea() const; 24 | 25 | float volume() const; 26 | 27 | // 返回当前BBox边长最大的轴的序号 28 | int maxExtentIndex() const; 29 | 30 | // 返回几何体中心 31 | t3Vector3f centroid() const; 32 | 33 | // 线性插值 34 | t3Vector3f interpolate(float tx, float ty, float tz); 35 | 36 | void boundingSphere(t3Vector3f* center, float* radius) const; 37 | 38 | // 与Accelerator中暂不启用 39 | bool intersect(const a3Ray& ray, float *hitT0, float *hitT1) const; 40 | 41 | static a3AABB calUnion(const a3AABB& box, const t3Vector3f& p); 42 | 43 | static a3AABB calUnion(const a3AABB& a, const a3AABB& b); 44 | 45 | // x:0 y:1 z:2 46 | inline t3Vector3f& operator[](int i); 47 | 48 | inline const t3Vector3f& operator[](int i)const; 49 | 50 | inline bool operator==(const a3AABB& bbox) const; 51 | 52 | inline bool operator!=(const a3AABB& bbox) const; 53 | 54 | void print(); 55 | 56 | void print(std::string name); 57 | 58 | t3Vector3f min, max; 59 | }; 60 | 61 | #include 62 | -------------------------------------------------------------------------------- /Atmos/Atmos.h: -------------------------------------------------------------------------------- 1 | // shape 2 | #include 3 | //#include 4 | #include 5 | #include 6 | #include 7 | //#include 8 | 9 | #include 10 | 11 | // light 12 | #include 13 | //#include 14 | //#include 15 | #include 16 | 17 | // renderer 18 | #include 19 | //#include 20 | #include 21 | //#include 22 | //#include 23 | //#include 24 | 25 | // textures 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | //integrator 36 | #include 37 | #include 38 | 39 | // bsdf 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | // core 46 | #include 47 | #include 48 | #include 49 | // core/image 50 | #include 51 | #include 52 | #include -------------------------------------------------------------------------------- /Atmos/core/a3Scene.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class a3IntersectRecord; 7 | class a3LightSamplingRecord; 8 | class a3Shape; 9 | class a3Light; 10 | class a3Ray; 11 | class a3PrimitiveSet; 12 | 13 | class a3Scene 14 | { 15 | public: 16 | a3Scene(); 17 | ~a3Scene(); 18 | 19 | // utility func 20 | bool addShape(a3Shape* shape); 21 | 22 | bool addLight(a3Light* light); 23 | 24 | bool check() const; 25 | 26 | // intersection with hit point detail 27 | bool intersect(const a3Ray& ray, a3IntersectRecord* intersection) const; 28 | 29 | // fast scene intersection test 30 | bool intersect(const a3Ray& ray) const; 31 | 32 | // Return the environment radiance for a ray that did not intersect any of the scene objects 33 | a3Spectrum evalEnvironment(const a3Ray& ray) const; 34 | 35 | // given a reference point in the scene, sample an emitter position that contributes towards it 36 | a3Spectrum sampleDirect(a3LightSamplingRecord& dRec) const; 37 | 38 | // evaluate the probability density of the direct sampling 39 | float pdfLightDirect(const a3LightSamplingRecord& Rec) const; 40 | 41 | // returns radiance emitted into direction d 42 | a3Spectrum Le(const t3Vector3f& d, const a3IntersectRecord& intersection) const; 43 | 44 | // Return the scene's environment emitter (if there is one) 45 | a3Light* getEnvironmentLight() const; 46 | 47 | // all lights in the scene 48 | std::vector lights; 49 | 50 | // all shapes in the scene 51 | a3PrimitiveSet* primitiveSet; 52 | }; -------------------------------------------------------------------------------- /Atmos/sensors/a3Sensor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class a3Ray; 8 | class a3CameraSample; 9 | class a3Film; 10 | 11 | // 远近裁剪面分别为0.01与1000.0 12 | class a3Sensor 13 | { 14 | public: 15 | // focalLength + apreture -> fov 16 | // fov + canvasDistance -> canvasSize 17 | a3Sensor(const t3Vector3f& origin, const t3Vector3f& lookat, const t3Vector3f& up, 18 | float focalLength, float apretureWidth, float apretureHeight, float canvasDistance, 19 | float focalDistance, float lensRadius, 20 | a3Film* image); 21 | 22 | virtual float castRay(const a3CameraSample* sample, a3Ray* ray) const = 0; 23 | 24 | void setCameraToWorld(const t3Vector3f& origin, const t3Vector3f& lookat, const t3Vector3f& up); 25 | 26 | void print(); 27 | 28 | // camera's position / eye's position 29 | t3Vector3f origin; 30 | 31 | // camera coordinate system 32 | t3Vector3f direction, up, right, lookat; 33 | // (同一坐标原点)从相机坐标系转换到世界坐标系 34 | t3Matrix4x4 cameraToWorld, rasterToCamera, cameraToScreen; 35 | 36 | a3Film* image; 37 | 38 | // 光圈用于确定film gate aspect ratio 39 | float focalLength; 40 | t3Vector2f apreture; 41 | 42 | // 弧度单位 43 | t3Vector2f fov; 44 | 45 | // 存储画布的宽高(x: width, y:height) 46 | t3Vector2f canvasSize; 47 | // 一般默认为画布距离摄像机 1.0 48 | float canvasDistance; 49 | 50 | // 摄像机在xy方向上的增量 51 | //t3Vector3f dx, dy; 52 | 53 | // 焦距,透镜半径 用于构造景深 54 | float focalDistance; 55 | float lensRadius; 56 | }; -------------------------------------------------------------------------------- /Atmos/renderers/a3GridRenderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class a3Random; 8 | class a3Sampler; 9 | class a3Integrator; 10 | 11 | class a3GridRenderer : public a3Renderer 12 | { 13 | public: 14 | a3GridRenderer(); 15 | a3GridRenderer(int spp); 16 | a3GridRenderer(int spp, int startX, int startY, int renderWidth, int renderHeight); 17 | ~a3GridRenderer(); 18 | 19 | // 初始化需要分配的信息 20 | void begin(); 21 | 22 | void end(); 23 | 24 | // 初始化划分力度 25 | void setLevel(int levelX = A3_GRID_LEVELX, int levelY = A3_GRID_LEVELY); 26 | 27 | virtual void render(const a3Scene* scene) override; 28 | 29 | void postEffect(); 30 | 31 | bool check(); 32 | 33 | void write(); 34 | 35 | bool isFinished(); 36 | 37 | // 采样器 38 | a3Sampler* sampler; 39 | 40 | // 相机 41 | a3Sensor* camera; 42 | 43 | // 积分器 44 | a3Integrator* integrator; 45 | 46 | // 伽马校正开关 47 | bool enableGammaCorrection; 48 | 49 | // Tone Mapping开关 50 | bool enableToneMapping; 51 | 52 | // Samples Per Pixels 53 | int spp; 54 | 55 | // color list for temp use 56 | a3Spectrum* colorList; 57 | 58 | // 局部区域划分Grid渲染 59 | int startX, startY; 60 | 61 | // 渲染区域宽高 62 | int renderWidth, renderHeight; 63 | 64 | // 划分力度 65 | int levelX, levelY; 66 | 67 | bool finished; 68 | 69 | // [private] 70 | // 当前遍历到的网格序号 71 | int currentGrid; 72 | 73 | // 网格宽高 74 | int gridWidth, gridHeight; 75 | 76 | // 真实图像大小的宽高 77 | int imageWidth, imageHeight; 78 | }; -------------------------------------------------------------------------------- /Atmos/core/a3Record.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // ------------------------------a3IntersectRecord------------------------------ 7 | bool a3IntersectRecord::isValid() const 8 | { 9 | return t != FLT_MAX; 10 | } 11 | 12 | bool a3IntersectRecord::isLight() const 13 | { 14 | return shape->isLight(); 15 | } 16 | 17 | a3Light * a3IntersectRecord::getLight() const 18 | { 19 | if(shape && isLight()) 20 | return shape->getLight(); 21 | else 22 | return NULL; 23 | } 24 | 25 | t3Vector3f a3IntersectRecord::getNormal() const 26 | { 27 | if(shape) 28 | return shape->getNormal(p, u, v); 29 | else 30 | return t3Vector3f::zero(); 31 | } 32 | 33 | const a3BSDF * a3IntersectRecord::getBSDF() const 34 | { 35 | return shape->getBSDF(); 36 | } 37 | 38 | a3Spectrum a3IntersectRecord::Le(const t3Vector3f & d) const 39 | { 40 | a3Light* light = shape->getLight(); 41 | return light ? light->eval(*this, d) : a3Spectrum::zero(); 42 | } 43 | 44 | t3Vector3f a3IntersectRecord::toWorld(const t3Vector3f & localCoord) 45 | { 46 | return t3Matrix4x4::transform3x3(localToWorld, localCoord).getNormalized(); 47 | } 48 | 49 | t3Vector3f a3IntersectRecord::toLocal(const t3Vector3f & worldCoord) 50 | { 51 | return t3Matrix4x4::transform3x3(worldToLocal, worldCoord).getNormalized(); 52 | } 53 | 54 | void a3LightSamplingRecord::set(const t3Vector3f & hitPoint, const t3Vector3f & hitNormal) 55 | { 56 | light = NULL; 57 | this->hitPoint = hitPoint; 58 | this->hitNormal = hitNormal; 59 | pdf = 0.0f; 60 | distance = 0.0f; 61 | } 62 | -------------------------------------------------------------------------------- /Atmos/core/a3Ray.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class a3Ray 8 | { 9 | public: 10 | a3Ray() : minT(A3_RAY_BIAS), maxT(A3_INFINITY), depth(0){} 11 | 12 | a3Ray(const t3Vector3f& origin, const t3Vector3f& direction, float start = A3_RAY_BIAS, float end = A3_INFINITY, int depth = 0) 13 | : origin(origin), direction(direction), minT(start), maxT(end), depth(depth){} 14 | 15 | a3Ray(const t3Vector3f& origin, const t3Vector3f& direction, const a3Ray& parent, float start = A3_RAY_BIAS, float end = A3_INFINITY) 16 | : origin(origin), direction(direction), minT(start), maxT(end), depth(parent.depth + 1){} 17 | 18 | a3Ray(const a3Ray& ray) 19 | : origin(ray.origin), direction(ray.direction), minT(ray.minT), maxT(ray.maxT), depth(ray.depth), time(ray.time){} 20 | 21 | void set(const t3Vector3f& origin, const t3Vector3f& direction) 22 | { 23 | this->origin = origin; 24 | this->direction = direction; 25 | } 26 | 27 | t3Vector3f operator()(float t) const 28 | { 29 | return origin + direction * t; 30 | } 31 | 32 | void transform(const t3Matrix4x4& m) 33 | { 34 | // point transform 35 | origin = m * origin; 36 | 37 | // special vector transform 38 | direction = t3Matrix4x4::transform3x3(m, direction); 39 | } 40 | 41 | void print() const 42 | { 43 | #ifdef _DEBUG 44 | origin.print("a3Ray.origin"); 45 | direction.print("a3Ray.direction"); 46 | #endif 47 | } 48 | 49 | t3Vector3f origin, direction; 50 | 51 | float minT, maxT; 52 | 53 | int depth; 54 | 55 | float time; 56 | }; -------------------------------------------------------------------------------- /test/png.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | //#define PNG_PP 9 | 10 | #define LOADPNG 11 | 12 | int main() 13 | { 14 | #ifdef PNG_PP 15 | png::image< png::rgb_pixel > image(128, 128); 16 | for(size_t y = 0; y < image.get_height(); ++y) 17 | { 18 | for(size_t x = 0; x < image.get_width(); ++x) 19 | { 20 | image[y][x] = png::rgb_pixel(x, y, x + y); 21 | // non-checking equivalent of image.set_pixel(x, y, ...); 22 | } 23 | } 24 | image.write("rgb.png"); 25 | #endif 26 | 27 | #ifdef LOADPNG 28 | //decode 29 | std::vector image; 30 | unsigned width, height; 31 | 32 | unsigned error = lodepng::decode(image, width, height, "test.png"); 33 | 34 | //if there's an error, display it 35 | if(error) std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl; 36 | 37 | for(int i = 0; i < width; i++) 38 | { 39 | for(int j = 0; j < height; j++) 40 | { 41 | a3Log::print("[%d]", i * 10 + j); 42 | a3Log::print("r: %d, ", image[i * 10 + j + 0]); 43 | a3Log::print("g: %d, ", image[i * 10 + j + 1]); 44 | a3Log::print("b: %d, ", image[i * 10 + j + 2]); 45 | a3Log::print("a: %d\n", image[i * 10 + j + 3]); 46 | } 47 | } 48 | 49 | image[50] = 100; 50 | 51 | // encode 52 | //Encode the image 53 | error = lodepng::encode("test1.png", image, width, height); 54 | 55 | //if there's an error, display it 56 | if(error) std::cout << "encoder error " << error << ": " << lodepng_error_text(error) << std::endl; 57 | #endif 58 | 59 | return 0; 60 | } -------------------------------------------------------------------------------- /Atmos/bsdf/a3Conductor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | a3Conductor::a3Conductor() 7 | { 8 | R = a3Spectrum::one(); 9 | 10 | eta = a3Spectrum::zero(); 11 | k = a3Spectrum::one(); 12 | } 13 | 14 | a3Spectrum a3Conductor::eval(const a3BSDFSamplingRecord & bRec) const 15 | { 16 | // Verify that the provided direction pair matches an ideal specular reflection 17 | float cosThetai = a3CosTheta(bRec.wi); 18 | float cosThetao = a3CosTheta(bRec.wo); 19 | 20 | t3Vector3f reflect = a3GetReflect(bRec.wi); 21 | 22 | if(cosThetai <= 0 || 23 | cosThetao <= 0 || 24 | t3Math::Abs(reflect.dot(bRec.wo) -1) > A3_EPSILON_DELTA) 25 | return a3Spectrum::zero(); 26 | 27 | 28 | return R * a3FresnelConductor(cosThetai, eta, k); 29 | } 30 | 31 | a3Spectrum a3Conductor::sample(a3BSDFSamplingRecord & bRec) const 32 | { 33 | float cosThetai = a3CosTheta(bRec.wi); 34 | if(cosThetai <= 0) 35 | return a3Spectrum::zero(); 36 | 37 | bRec.wo = a3GetReflect(bRec.wi); 38 | bRec.eta = 1.0f; 39 | bRec.pdf = 1.0f; 40 | 41 | return R * a3FresnelConductor(cosThetai, eta, k); 42 | } 43 | 44 | float a3Conductor::pdf(const a3BSDFSamplingRecord & bRec) const 45 | { 46 | // Verify that the provided direction pair matches an ideal specular reflection 47 | float cosThetai = a3CosTheta(bRec.wi); 48 | float cosThetao = a3CosTheta(bRec.wo); 49 | 50 | t3Vector3f reflect = a3GetReflect(bRec.wi); 51 | 52 | if(cosThetai <= 0 || 53 | cosThetao <= 0 || 54 | t3Math::Abs(reflect.dot(bRec.wo) - 1) > A3_EPSILON_DELTA) 55 | return 0.0f; 56 | 57 | return 1.0f; 58 | } 59 | 60 | bool a3Conductor::isDeltaDistribution() const 61 | { 62 | return true; 63 | } 64 | -------------------------------------------------------------------------------- /Atmos/lights/a3EnvironmentLight.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | a3EnvironmentLight::a3EnvironmentLight(const std::string & filePath, const t3Matrix4x4& lightToWorld) 9 | : a3Light(lightToWorld, "a3EnvironmentLight") 10 | { 11 | image = new a3ImageDecoder(filePath); 12 | } 13 | 14 | a3EnvironmentLight::~a3EnvironmentLight() 15 | { 16 | A3_SAFE_DELETE(image); 17 | } 18 | 19 | a3Spectrum a3EnvironmentLight::evalEnvironment(const a3Ray & ray) const 20 | { 21 | t3Vector3f d = t3Matrix4x4::transform3x3(lightToWorld, ray.direction); 22 | 23 | // IS in the future 24 | float u = a3SphericalPhi(d) * T3MATH_INV_TWOPI; 25 | float v = a3SphericalTheta(d) * T3MATH_INV_PI; 26 | 27 | return image->lookup(u, v); 28 | } 29 | 30 | a3Spectrum a3EnvironmentLight::sampleDirect(a3LightSamplingRecord& dRec) const 31 | { 32 | // IS in the future 33 | 34 | dRec.pdf = 1 / (4 * PI); 35 | dRec.distance = A3_INFINITY; 36 | dRec.d = a3UniformSampleSphere(a3Random::randomFloat(), a3Random::randomFloat()); 37 | 38 | // texture 39 | if(image) 40 | { 41 | float u = a3SphericalPhi(dRec.d) * T3MATH_INV_TWOPI; 42 | float v = a3SphericalTheta(dRec.d) * T3MATH_INV_PI; 43 | 44 | return image->lookup(u, v); 45 | } 46 | else 47 | return a3Spectrum::zero(); 48 | } 49 | 50 | float a3EnvironmentLight::pdf(const a3LightSamplingRecord & dRec) const 51 | { 52 | return 0.0f; 53 | } 54 | 55 | bool a3EnvironmentLight::isEnvironment() const 56 | { 57 | return true; 58 | } 59 | 60 | bool a3EnvironmentLight::isDeltaDistribution() const 61 | { 62 | return false; 63 | } 64 | -------------------------------------------------------------------------------- /Atmos/shapes/a3InfinitePlane.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | a3InfinitePlane::a3InfinitePlane(const t3Matrix4x4 & shapeToWorld) 6 | : a3Shape(shapeToWorld) 7 | { 8 | name = "a3InfinitePlane"; 9 | } 10 | 11 | a3InfinitePlane::~a3InfinitePlane() 12 | { 13 | } 14 | 15 | bool a3InfinitePlane::intersect(const a3Ray & _ray, float * t, float * u, float * v) const 16 | { 17 | a3Ray ray = _ray; 18 | ray.transform(worldToShape); 19 | 20 | //--!See https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-plane-and-ray-disk-intersection for detail 21 | t3Vector3f normal(0, 1, 0); 22 | 23 | // paralle or not 24 | double denominator = normal.dot(ray.direction), tHit = 0.0f; 25 | 26 | if(t3Math::Abs(denominator) > A3_EPSILON_FLOAT) 27 | { 28 | tHit = (-ray.origin).dot(normal) / denominator; 29 | 30 | if(tHit < ray.minT || tHit > ray.maxT) 31 | return false; 32 | 33 | *t = tHit; 34 | 35 | return true; 36 | } 37 | 38 | return false; 39 | } 40 | 41 | float a3InfinitePlane::area() const 42 | { 43 | return A3_INFINITY; 44 | } 45 | 46 | void a3InfinitePlane::sample(a3ShapeSamplingRecord & sRec) const 47 | { 48 | // can't be area light 49 | sRec.p = t3Vector3f::zero(); 50 | sRec.pdf = pdf(sRec); 51 | sRec.normal = getNormal(t3Vector3f::zero(), 0, 0); 52 | } 53 | 54 | float a3InfinitePlane::pdf(const a3ShapeSamplingRecord & sRec) const 55 | { 56 | // Not physically based 57 | return 0.0f; 58 | } 59 | 60 | t3Vector3f a3InfinitePlane::getNormal(const t3Vector3f & hitPoint, float u, float v) const 61 | { 62 | return t3Matrix4x4::transform3x3(shapeToWorld, t3Vector3f(0, 1, 0)).getNormalized(); 63 | } 64 | -------------------------------------------------------------------------------- /Atmos/shapes/a3Shape.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class a3Ray; 11 | class a3IntersectRecord; 12 | class a3ShapeSamplingRecord; 13 | class a3Light; 14 | class a3Shape 15 | { 16 | public: 17 | a3Shape(const t3Matrix4x4& shapeToWorld); 18 | 19 | virtual ~a3Shape(); 20 | 21 | // ray intersection test for visibility queries 22 | virtual bool intersect(const a3Ray& ray, float* t, float* u, float* v) const = 0; 23 | 24 | // compute the area 25 | virtual float area() const = 0; 26 | 27 | // Sample a point on the surface of this shape instance 28 | virtual void sample(a3ShapeSamplingRecord& sRec) const = 0; 29 | 30 | // Query the probability density of sample() for a particular point on the surface 31 | virtual float pdf(const a3ShapeSamplingRecord& sRec) const; 32 | 33 | // return the normal vec from the point be hitted 34 | virtual t3Vector3f getNormal(const t3Vector3f& hitPoint, float u, float v) const = 0; 35 | 36 | // shading coordinates to world(would be replaced in the future) 37 | virtual t3Matrix4x4 getShadeToWorld(const a3IntersectRecord& its) const; 38 | 39 | // bsdf set/get 40 | void setBSDF(a3BSDF* bsdf); 41 | 42 | const a3BSDF* getBSDF() const; 43 | 44 | // setted when attach a shape to a light 45 | // manually called not recommended 46 | void setLight(a3Light* light); 47 | 48 | a3Light* getLight() const; 49 | 50 | bool isLight() const; 51 | 52 | t3Matrix4x4 shapeToWorld, worldToShape; 53 | 54 | // Axis-Aligned Bounding Box 55 | a3AABB aabb; 56 | 57 | // RTTI 58 | std::string name; 59 | 60 | a3BSDF* bsdf; 61 | 62 | a3Light* light; 63 | }; -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Test/t3BinaryTreeTest.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | //#define T3_BINARYTREE_TEST 9 | #define T3_THREADEDBINARYTREE_TEST 10 | 11 | int main(int argc, char* argv[]) 12 | { 13 | int preorder[] = {7, 10, 4, 3, 1, 2, 8, 11}; 14 | int inorder[] = {4, 10, 3, 1, 7, 11, 8, 2}; 15 | int length = sizeof(preorder) / sizeof(preorder[0]); 16 | 17 | #ifdef T3_BINARYTREE_TEST 18 | t3BinaryTree tree; 19 | 20 | tree.create(preorder, inorder, length); 21 | 22 | t3Log("---------------------preorder---------------------\n"); 23 | tree.preorder(); 24 | 25 | t3Log("---------------------inorder---------------------\n"); 26 | tree.inorder(); 27 | 28 | t3Log("---------------------postorder---------------------\n"); 29 | tree.postorder(); 30 | 31 | t3Log("---------------------levelorder---------------------\n"); 32 | tree.levelorder(); 33 | 34 | t3BinaryTree *root; 35 | root = tree.copy(); 36 | root->inorder(); 37 | 38 | t3Log("---------------------inorder---------------------\n"); 39 | root->inorder(); 40 | if(tree.equal(root)) 41 | t3Log("equal() -> ==\n"); 42 | else 43 | t3Log("equal() -> !=\n"); 44 | #endif 45 | 46 | #ifdef T3_THREADEDBINARYTREE_TEST 47 | 48 | t3ThreadedBinaryTree tree; 49 | tree.create(preorder, inorder, length); 50 | tree.inThreading(); 51 | t3Log("---------------------inorder---------------------\n"); 52 | tree.inorder(); 53 | t3ThreadTreeNode node(5); 54 | tree.insertRight(tree.tree, &node); 55 | t3Log("---------------------insert inorder---------------------\n"); 56 | tree.inorder(); 57 | #endif 58 | getchar(); 59 | 60 | return 0; 61 | } -------------------------------------------------------------------------------- /Atmos/bsdf/a3Diffuse.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | a3Diffuse::a3Diffuse() 10 | { 11 | R = a3Spectrum::one(); 12 | 13 | name = "a3Diffuse"; 14 | } 15 | 16 | a3Spectrum a3Diffuse::eval(const a3BSDFSamplingRecord & bRec) const 17 | { 18 | // shading coordinates 19 | // guarantee wi, normal, wo in the same side 20 | float cosThetai = bRec.wi.dot(t3Vector3f(0, 1, 0)); 21 | float cosThetao = bRec.wo.dot(t3Vector3f(0, 1, 0)); 22 | 23 | if(cosThetai <= 0 || cosThetao <= 0) 24 | return a3Spectrum::zero(); 25 | 26 | // reflectance * bsdf(wi, wo); 27 | return R * pdf(bRec); 28 | } 29 | 30 | a3Spectrum a3Diffuse::sample(a3BSDFSamplingRecord & bRec) const 31 | { 32 | float cosThetai = bRec.wi.dot(t3Vector3f(0, 1, 0)); 33 | if(cosThetai <= 0) 34 | return a3Spectrum::zero(); 35 | 36 | //bRec.wo = a3UniformSampleHemisphere(a3Random::randomFloat(), a3Random::randomFloat()); 37 | //bRec.pdf = a3UniformHemispherePdf(); 38 | 39 | // local system 40 | // cosine weighted 41 | bRec.wo = a3CosineSampleHemisphere(a3Random::randomFloat(), a3Random::randomFloat()).getNormalized(); 42 | bRec.pdf = a3CosineSampleHemispherePdf(bRec.wo); 43 | bRec.eta = 1.0f; 44 | 45 | //return R * 2 * bRec.wo.y; 46 | return R; 47 | } 48 | 49 | float a3Diffuse::pdf(const a3BSDFSamplingRecord & bRec) const 50 | { 51 | float cosThetai = bRec.wi.dot(t3Vector3f(0, 1, 0)); 52 | float cosThetao = bRec.wo.dot(t3Vector3f(0, 1, 0)); 53 | 54 | if(cosThetai <= 0 || cosThetao <= 0) 55 | return 0.0f; 56 | 57 | // cosine weighted pdf 58 | //return a3UniformHemispherePdf(); 59 | return a3CosineSampleHemispherePdf(bRec.wo); 60 | } 61 | 62 | bool a3Diffuse::isDeltaDistribution() const 63 | { 64 | return false; 65 | } -------------------------------------------------------------------------------- /test/aabb.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | a3AABB box0(t3Vector3f(0), t3Vector3f(10)), 8 | box1(t3Vector3f(11, 0, 0), t3Vector3f(20, 10, 10)), 9 | box2(t3Vector3f(-5, 0, 0), t3Vector3f(5, 10, 10)); 10 | 11 | a3Ray ray(t3Vector3f(0), t3Vector3f(1)); 12 | 13 | t3Vector3f p(-1); 14 | 15 | // overlaps 16 | if(box0.overlaps(box1)) 17 | a3Log::print("box0 overlaps box1\n"); 18 | else 19 | a3Log::print("box0 not overlaps box1\n"); 20 | 21 | if(box0.overlaps(box2)) 22 | a3Log::print("box0 overlaps box2\n"); 23 | else 24 | a3Log::print("box0 not overlaps box2\n"); 25 | 26 | // inside 27 | if(box0.inside(p)) 28 | a3Log::print("p inside box0\n"); 29 | else 30 | a3Log::print("p outside box0\n"); 31 | 32 | // expand 33 | a3AABB aabb0(t3Vector3f(0), t3Vector3f(2)), 34 | aabb1(t3Vector3f(1, 2, 3), t3Vector3f(9, 8, 7)); 35 | aabb0.print("aabb0"); 36 | aabb0.expand(5); 37 | aabb0.print("aabb0"); 38 | 39 | // surface area 40 | a3Log::print("area: %f\n", aabb0.surfaceArea()); 41 | 42 | // volume 43 | a3Log::print("volume: %f\n", aabb0.volume()); 44 | 45 | // maxExtent 46 | a3Log::print("max extent index: %d\n", aabb1.maxExtentIndex()); 47 | 48 | // lerp 49 | box0.interpolate(0.5f, 0.5f, 0.5f).print("interpolate point"); 50 | 51 | // sphere 52 | t3Vector3f center; 53 | float radius = 0; 54 | box0.boundingSphere(¢er, &radius); 55 | center.print("center"); 56 | a3Log::print("radius: %f\n", radius); 57 | 58 | // intersect 59 | float hitT0 = 0, hitT1 = 0; 60 | if(box0.intersect(ray, &hitT0, &hitT1)) 61 | a3Log::print("ray intersect box0 t0: %f, t1: %f\n", hitT0, hitT1); 62 | else 63 | a3Log::print("ray not intersect box0\n"); 64 | 65 | getchar(); 66 | return 0; 67 | } -------------------------------------------------------------------------------- /Atmos/core/messageQueue/a3MessageQueueIPC.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct a3Mutex 8 | { 9 | public: 10 | a3Mutex():mutex(NULL){} 11 | ~a3Mutex() {} 12 | 13 | void create(const wchar_t* name); 14 | void open(const wchar_t* name); 15 | 16 | void destroy(); 17 | 18 | void lock(); 19 | void unlock(); 20 | public: 21 | std::wstring name; 22 | HANDLE mutex = NULL; 23 | 24 | private: 25 | a3Mutex(const a3Mutex&); 26 | void operator=(const a3Mutex&); 27 | }; 28 | 29 | 30 | struct a3MutexGuard 31 | { 32 | public: 33 | a3MutexGuard(a3Mutex& mutex) : mutex(mutex) { 34 | mutex.lock(); 35 | } 36 | 37 | ~a3MutexGuard() { 38 | mutex.unlock(); 39 | } 40 | public: 41 | a3Mutex& mutex; 42 | }; 43 | 44 | 45 | struct MessageQueueBuffer 46 | { 47 | public: 48 | MessageQueueBuffer():fileMapping(0), buffer(NULL), size(0) {} 49 | ~MessageQueueBuffer() {} 50 | 51 | void create(const wchar_t* name, int size); 52 | void open(const wchar_t* name, int size); 53 | 54 | void destroy(); 55 | 56 | char* getBuffer(); 57 | int getBufferSize(); 58 | 59 | public: 60 | std::wstring name; 61 | HANDLE fileMapping; 62 | char* buffer; 63 | int size; 64 | 65 | private: 66 | MessageQueueBuffer(const MessageQueueBuffer&); 67 | void operator=(const MessageQueueBuffer&); 68 | }; 69 | 70 | class a3MessageQueueIPC 71 | { 72 | public: 73 | a3MessageQueueIPC(){} 74 | ~a3MessageQueueIPC(){} 75 | 76 | void init(const wchar_t* name, bool create, int msgMaxNum, int msgMaxSize); 77 | void uninit(); 78 | 79 | bool isEmpty(); 80 | bool isFull(); 81 | int getSize(); 82 | 83 | bool enqueue(const a3MessageEntryHead& msg); 84 | bool dequeue(a3MessageEntryHead& msg); 85 | 86 | private: 87 | std::wstring name; 88 | a3Mutex mutex; 89 | MessageQueueBuffer buffer; 90 | a3MessageQueue queue; 91 | 92 | private: 93 | a3MessageQueueIPC(const a3MessageQueueIPC&); 94 | void operator=(const a3MessageQueueIPC&); 95 | }; -------------------------------------------------------------------------------- /Atmos/shapes/a3Disk.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | a3Disk::a3Disk(const t3Matrix4x4 & shapeToWorld, const float radius) 8 | :radius(radius), a3Shape(shapeToWorld) 9 | { 10 | name = "a3Disk"; 11 | } 12 | 13 | a3Disk::~a3Disk() 14 | { 15 | } 16 | 17 | bool a3Disk::intersect(const a3Ray & _ray, float * t, float * u, float * v) const 18 | { 19 | a3Ray ray = _ray; 20 | ray.transform(worldToShape); 21 | 22 | //--!See https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-plane-and-ray-disk-intersection for detail 23 | t3Vector3f normal(0, 1, 0); 24 | 25 | // paralle or not 26 | float denominator = normal.dot(ray.direction), tHit = 0.0f; 27 | 28 | if(t3Math::Abs(denominator) > A3_EPSILON_FLOAT) 29 | { 30 | tHit = (-ray.origin).dot(normal) / denominator; 31 | 32 | if(tHit < ray.minT || tHit > ray.maxT) 33 | return false; 34 | 35 | // distance between hitpoint and disk center 36 | if(ray(tHit).lengthSquared() <= radius * radius) 37 | { 38 | *t = tHit; 39 | 40 | return true; 41 | } 42 | } 43 | 44 | return false; 45 | } 46 | 47 | void a3Disk::sample(a3ShapeSamplingRecord & sRec) const 48 | { 49 | // uniform sampling the disk 50 | t3Vector2f sampledP = a3UniformSampleDisk(a3Random::randomFloat(), a3Random::randomFloat()); 51 | 52 | sRec.p = shapeToWorld * t3Vector3f(sampledP.x * radius, 0.0f, sampledP.y * radius); 53 | sRec.pdf = 1 / area(); 54 | sRec.normal = getNormal(t3Vector3f::zero(), 0, 0); 55 | } 56 | 57 | t3Vector3f a3Disk::getNormal(const t3Vector3f & hitPoint, float u, float v) const 58 | { 59 | return t3Matrix4x4::transform3x3(shapeToWorld, t3Vector3f(0, 1, 0)).getNormalized(); 60 | } 61 | 62 | float a3Disk::area() const 63 | { 64 | return T3MATH_PI * radius * radius; 65 | } 66 | -------------------------------------------------------------------------------- /Atmos/core/random/a3Random.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // --!See https://stackoverflow.com/questions/21237905/how-do-i-generate-thread-safe-uniform-random-numbers for more detail 4 | 5 | #if (_MSC_VER <= 1800) 6 | #define thread_local __declspec( thread ) 7 | #elif defined (__GCC__) 8 | #define thread_local __thread 9 | #endif 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | /* Thread-safe function that returns a random number between min and max (inclusive). 16 | This function takes ~142% the time that calling rand() would take. For this extra 17 | cost you get a better uniform distribution and thread-safety. */ 18 | 19 | a3Random::a3Random() 20 | { 21 | 22 | } 23 | 24 | double a3Random::randomDouble(const double min, const double max) 25 | { 26 | static thread_local std::mt19937* generator = nullptr; 27 | 28 | if(!generator) 29 | { 30 | std::hash hasher; 31 | generator = new std::mt19937(clock() + hasher(std::this_thread::get_id())); 32 | } 33 | std::uniform_real_distribution distribution(min, max); 34 | return distribution(*generator); 35 | } 36 | 37 | float a3Random::randomFloat(const float min, const float max) 38 | { 39 | static thread_local std::mt19937* generator = nullptr; 40 | 41 | if(!generator) 42 | { 43 | std::hash hasher; 44 | generator = new std::mt19937(clock() + hasher(std::this_thread::get_id())); 45 | } 46 | std::uniform_real_distribution distribution(min, max); 47 | return distribution(*generator); 48 | } 49 | 50 | int a3Random::randomInt(const int min, const int max) 51 | { 52 | static thread_local std::mt19937* generator = nullptr; 53 | 54 | if(!generator) 55 | { 56 | std::hash hasher; 57 | generator = new std::mt19937(clock() + hasher(std::this_thread::get_id())); 58 | } 59 | std::uniform_int_distribution distribution(min, max); 60 | return distribution(*generator); 61 | } 62 | -------------------------------------------------------------------------------- /Atmos/shapes/a3Shape.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | a3Shape::a3Shape(const t3Matrix4x4 & shapeToWorld) 7 | :shapeToWorld(shapeToWorld), light(NULL), bsdf(NULL), worldToShape(shapeToWorld.getInverse()), name("a3Shape") 8 | { 9 | 10 | } 11 | 12 | a3Shape::~a3Shape() 13 | { 14 | } 15 | 16 | bool a3Shape::intersect(const a3Ray & ray, float * t, float * u, float * v) const 17 | { 18 | a3FuncNotImplementedError(); 19 | 20 | return false; 21 | } 22 | 23 | float a3Shape::area() const 24 | { 25 | a3FuncNotImplementedError(); 26 | 27 | return 0.0f; 28 | } 29 | 30 | void a3Shape::sample(a3ShapeSamplingRecord & sRec) const 31 | { 32 | a3FuncNotImplementedError(); 33 | } 34 | 35 | float a3Shape::pdf(const a3ShapeSamplingRecord & sRec) const 36 | { 37 | return 1 / area(); 38 | } 39 | 40 | t3Vector3f a3Shape::getNormal(const t3Vector3f & hitPoint, float u, float v) const 41 | { 42 | a3FuncNotImplementedError(); 43 | 44 | return t3Vector3f::zero(); 45 | } 46 | 47 | t3Matrix4x4 a3Shape::getShadeToWorld(const a3IntersectRecord& its) const 48 | { 49 | t3Matrix4x4 shadeToWorld(shapeToWorld._mat[0][0], shapeToWorld._mat[0][1], shapeToWorld._mat[0][2], 0, 50 | shapeToWorld._mat[1][0], shapeToWorld._mat[1][1], shapeToWorld._mat[1][2], 0, 51 | shapeToWorld._mat[2][0], shapeToWorld._mat[2][1], shapeToWorld._mat[2][2], 0, 52 | 0, 0, 0, 1); 53 | return shadeToWorld; 54 | } 55 | 56 | void a3Shape::setBSDF(a3BSDF* bsdf) 57 | { 58 | if(bsdf) 59 | this->bsdf = bsdf; 60 | else 61 | a3NullPtrWarning("bsdf"); 62 | } 63 | 64 | const a3BSDF* a3Shape::getBSDF() const 65 | { 66 | return bsdf; 67 | } 68 | 69 | void a3Shape::setLight(a3Light * light) 70 | { 71 | if(light) 72 | this->light = light; 73 | else 74 | a3NullPtrWarning("light"); 75 | } 76 | 77 | a3Light * a3Shape::getLight() const 78 | { 79 | return light; 80 | } 81 | 82 | bool a3Shape::isLight() const 83 | { 84 | return light != NULL; 85 | } 86 | -------------------------------------------------------------------------------- /test/util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | using namespace std; 5 | 6 | void main() 7 | { 8 | a3Log::print("-------------------------Lower Upper-------------------------\n"); 9 | string lower = "whosyourdaddy", upper = "WHOSYOURDADDY"; 10 | 11 | a3Log::print("lower to upper: %s\n", a3ToUpper(lower).c_str()); 12 | a3Log::print("upper to lower: %s\n", a3ToLower(upper).c_str()); 13 | 14 | int intValue = 10; 15 | float floatValue = 12.5f; 16 | double doubleValue = 13.5; 17 | vector intList = {10, 20, 30}; 18 | 19 | a3Log::print("-------------------------To String-------------------------\n"); 20 | a3Log::print("%d %s\n", intValue, a3ToString(intValue).c_str()); 21 | a3Log::print("%f %s\n", floatValue, a3ToString(floatValue).c_str()); 22 | a3Log::print("%f %s\n", doubleValue, a3ToString(doubleValue).c_str()); 23 | 24 | for(auto i : intList) 25 | { 26 | a3Log::print("%d ", i); 27 | } 28 | a3Log::print("%s\n", a3ToString(intList).c_str()); 29 | 30 | a3Log::print("-------------------------String To-------------------------\n"); 31 | string sint = "100", sfloat = "1000.0f", sdouble = "123.0", sbool = "false", schar = "abc"; 32 | 33 | a3Log::print("%d\n", a3ToInt(sint)); 34 | 35 | a3Log::print("%f\n", a3ToFloat(sfloat)); 36 | 37 | a3Log::print("%f\n", a3ToDouble(sdouble)); 38 | 39 | a3Log::print("%s\n", a3ToBool(sbool) == false ? "FALSE" : "TRUE"); 40 | 41 | a3Log::print("%c\n", a3ToChar(schar)); 42 | 43 | a3Log::print("-------------------------To Hex-------------------------\n"); 44 | 45 | a3Log::print("%s\n", a3ToHex(intValue).c_str()); 46 | a3Log::print("%s\n", a3ToHex(floatValue).c_str()); 47 | a3Log::print("%s\n", a3ToHex(doubleValue).c_str()); 48 | 49 | a3Log::print("%s\n", a3ToHex("1000").c_str()); 50 | 51 | a3Log::print("-------------------------Hex To-------------------------\n"); 52 | 53 | // Converts a hexadecimal representation of an string 54 | a3Log::print("%s\n", a3HexToString("61626364656667").c_str()); 55 | 56 | a3Log::print("%f\n", a3HexToFloat("43000000")); 57 | 58 | a3Log::print("%d\n", a3HexToInt("0xff")); 59 | 60 | a3Log::print("%c\n", a3HexToChar("61")); 61 | 62 | getchar(); 63 | } -------------------------------------------------------------------------------- /Atmos/core/log/a3LogFile.h: -------------------------------------------------------------------------------- 1 | #ifndef A3_LOGFILE_H 2 | #define A3_LOGFILE_H 3 | 4 | #include 5 | 6 | // not support UTF8 log to file 7 | // file name format [year]-[month]-[day]-[prefix].[suffix] 8 | // file content format [hour]:[minute]:[second] [log level] [message] [...] 9 | class a3LogFile 10 | { 11 | public: 12 | static void log(a3LogLevel logLevel, const char* prefix, const char* suffix, const char* message, ...); 13 | 14 | static void log(a3LogLevel logLevel, const char* message, ...); 15 | 16 | // log to default name file: [prefix]:Atmos-VerisionType [suffix]:log 17 | static void fatalError(const char* message, ...); 18 | 19 | static void error(const char* message, ...); 20 | 21 | static void seriousWarning(const char* message, ...); 22 | 23 | static void warning(const char* message, ...); 24 | 25 | static void success(const char* message, ...); 26 | 27 | static void info(const char* message, ...); 28 | 29 | static void dev(const char* message, ...); 30 | 31 | static void debug(const char* message, ...); 32 | 33 | // log to custom name log file 34 | static void fatalError(const char* prefix, const char* suffix, const char* message ...); 35 | 36 | static void error(const char* prefix, const char* suffix, const char* message ...); 37 | 38 | static void seriousWarning(const char* prefix, const char* suffix, const char* message ...); 39 | 40 | static void warning(const char* prefix, const char* suffix, const char* message ...); 41 | 42 | static void success(const char* prefix, const char* suffix, const char* message ...); 43 | 44 | static void info(const char* prefix, const char* suffix, const char* message ...); 45 | 46 | static void dev(const char* prefix, const char* suffix, const char* message ...); 47 | 48 | static void debug(const char* prefix, const char* suffix, const char* message ...); 49 | 50 | private: 51 | a3LogFile() {} 52 | a3LogFile(const a3LogFile&) {} 53 | ~a3LogFile() {} 54 | a3LogFile& operator=(const a3LogFile& event) const {} 55 | 56 | static void log(a3LogLevel logLevel, const char* prefix, const char* suffix, const char* message, va_list args); 57 | 58 | static void log(a3LogLevel logLevel, const char* message, va_list args); 59 | 60 | static std::ofstream* ofile; 61 | static std::ifstream* ifile; 62 | }; 63 | 64 | #endif -------------------------------------------------------------------------------- /Atmos/renderers/a3SingleRayRenderer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | a3SingleRayRenderer::a3SingleRayRenderer() :singleRayX(0), singleRayY(0) 14 | { 15 | 16 | } 17 | 18 | a3SingleRayRenderer::a3SingleRayRenderer(int singleRayX, int singleRayY) : singleRayX(singleRayX), singleRayY(singleRayY) 19 | { 20 | 21 | } 22 | 23 | a3SingleRayRenderer::~a3SingleRayRenderer() 24 | { 25 | 26 | } 27 | 28 | void a3SingleRayRenderer::render(const a3Scene* scene) 29 | { 30 | if(!check()) return; 31 | 32 | a3CameraSample sample; 33 | 34 | sampler->getMoreSamples(singleRayX, singleRayY, &sample, NULL); 35 | 36 | // memory allocating 37 | a3Ray ray; 38 | 39 | // generate camera rays 40 | camera->castRay(&sample, &ray); 41 | 42 | t3Vector3f color = integrator->Li(ray, *scene); 43 | 44 | color.x = t3Math::clamp(color.x, 0.0f, 255.0f); 45 | color.y = t3Math::clamp(color.y, 0.0f, 255.0f); 46 | color.z = t3Math::clamp(color.z, 0.0f, 255.0f); 47 | 48 | if(enableGammaCorrection) 49 | a3GammaCorrection(color); 50 | 51 | //color.print("SingleRay Color"); 52 | 53 | a3Log::info("SingleRay Pos: %d, %d\n", singleRayX, singleRayY); 54 | 55 | a3Log::info("SingleRay Color: %f, %f, %f\n", color.x, color.y, color.z); 56 | } 57 | 58 | bool a3SingleRayRenderer::check() 59 | { 60 | if(!camera) 61 | { 62 | a3Log::error("Before a3SamplerRenderer::render() was called, camera: %d is not allocated\n", camera); 63 | return false; 64 | } 65 | 66 | if(!sampler) 67 | { 68 | a3Log::error("Before a3SamplerRenderer::render() was called, sampler: %d is not allocated\n", sampler); 69 | return false; 70 | } 71 | 72 | if(!integrator) 73 | { 74 | a3Log::error("Before a3SamplerRenderer::render() was called, integrator: %d is not allocated\n", integrator); 75 | return false; 76 | } 77 | 78 | if(singleRayX < 0 || singleRayY < 0) 79 | { 80 | a3Log::error("Error coordinates:(%d %d) when a3SamplerRenderer::render() was called", singleRayX, singleRayY); 81 | 82 | return false; 83 | } 84 | 85 | return true; 86 | } 87 | -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Test/t3LinearListTest.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | //#define T3_TEST_MAZE 11 | #define T3_TEST_STACK 12 | //#define T3_TEST_QUEUE 13 | 14 | int main(int argc, char* argv[]) 15 | { 16 | t3Timer timer; 17 | 18 | std::string command; 19 | 20 | int i; 21 | 22 | #ifdef T3_TEST_STACK 23 | t3Stack stack; 24 | while(1) 25 | { 26 | std::cout << "Tatty Console:~dataStructure$ "; 27 | // 非直接读入一个单词 而为一整个句子 28 | //std::getline(std::cin, command); 29 | std::cin >> command; 30 | 31 | if(command == "quit") 32 | break; 33 | else if(command == "print") 34 | stack.print(); 35 | else if(command == "push") 36 | { 37 | std::cout << "Input push data: "; 38 | std::cin >> i; 39 | stack.push(i); 40 | } 41 | else if(command == "pop") 42 | std::cout << "Pop Stack: " << stack.pop() << std::endl; 43 | else if(command == "get") 44 | std::cout << "Stack's Top Element: " << stack.get() << std::endl; 45 | else if(command == "Who's Your Daddy?") 46 | // 反正cin这辈子也不可能输出这玩意 47 | std::cout << "I'm Your Father" << std::endl; 48 | else 49 | std::cout << "Error Command." << command << std::endl; 50 | } 51 | #endif 52 | 53 | #ifdef T3_TEST_QUEUE 54 | t3Queue queue; 55 | while(1) 56 | { 57 | std::cout << "Tatty Console:~dataStructure$ "; 58 | // 非直接读入一个单词 而为一整个句子 59 | //std::getline(std::cin, command); 60 | std::cin >> command; 61 | 62 | if(command == "quit") 63 | break; 64 | else if(command == "print") 65 | queue.print(); 66 | else if(command == "push") 67 | { 68 | std::cout << "Input push data: "; 69 | std::cin >> i; 70 | queue.push(i); 71 | } 72 | else if(command == "pop") 73 | std::cout << "Pop Queue: " << queue.pop() << std::endl; 74 | else if(command == "get") 75 | std::cout << "Queue's Top Element: " << queue.get() << std::endl; 76 | else 77 | std::cout << "Error Command." << command << std::endl; 78 | } 79 | #endif 80 | getchar(); 81 | return 0; 82 | } -------------------------------------------------------------------------------- /test/grid.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | enum a3MaterialType 4 | { 5 | NONE = 0, 6 | LAMBERTIAN = 1, 7 | MIRROR = 2, 8 | GLASS = 3 9 | }; 10 | 11 | int main() 12 | { 13 | // alloc 14 | a3Film* image = new a3Film(1024, 768, "../../../../resources/results/grid.png"); 15 | 16 | a3PerspectiveSensor* camera = camera = new a3PerspectiveSensor(t3Vector3f(0, 80, 20), t3Vector3f(0, 0, 0), t3Vector3f(0, 0, 1), 40, 100.0f, 0.0f, image); 17 | 18 | a3PathIntegrator* path = new a3PathIntegrator(); 19 | path->russianRouletteDepth = 3; 20 | path->maxDepth = -1; 21 | 22 | a3BVH* bvh = NULL; 23 | a3Scene* scene = new a3Scene(); 24 | scene->primitiveSet = bvh = new a3BVH(); 25 | 26 | a3GridRenderer* r = new a3GridRenderer(8); 27 | r->setLevel(5, 5); 28 | r->camera = camera; 29 | r->sampler = new a3RandomSampler(); 30 | r->integrator = path; 31 | r->enableGammaCorrection = false; 32 | r->enableToneMapping = false; 33 | //r->startX = 0; 34 | //r->startY = 0; 35 | //r->renderWidth = 700; 36 | //r->renderHeight = 200; 37 | 38 | auto addShape = [&scene](a3Shape* s, a3Spectrum R, a3Spectrum emission, int type, a3Texture* texture)->auto 39 | { 40 | s->emission = emission; 41 | 42 | switch(type) 43 | { 44 | case LAMBERTIAN: 45 | s->bsdf = new a3Diffuse(R); 46 | break; 47 | case MIRROR: 48 | s->bsdf = new a3Conductor(R); 49 | break; 50 | case GLASS: 51 | s->bsdf = new a3Dieletric(R); 52 | break; 53 | default: 54 | break; 55 | } 56 | 57 | s->bsdf->texture = texture; 58 | if(texture) 59 | s->bCalTextureCoordinate = true; 60 | 61 | scene->addShape(s); 62 | 63 | return s->bsdf; 64 | }; 65 | 66 | scene->addLight(new a3InfiniteAreaLight("../../../../resources/images/grace-new_latlong.exr")); 67 | 68 | a3ModelImporter importer; 69 | std::vector* blender = importer.load("../../../../resources/models/blender.obj"); 70 | 71 | for(auto s : *blender) 72 | addShape(s, t3Vector3f(1.0f), t3Vector3f(0, 0, 0), GLASS, NULL); 73 | 74 | bvh->init(); 75 | 76 | // rendering 77 | t3Timer timer; 78 | timer.start(); 79 | 80 | r->begin(); 81 | 82 | for(int i = 0; i < r->levelX * r->levelY; i++) 83 | r->render(scene); 84 | 85 | r->end(); 86 | 87 | timer.end(); 88 | 89 | a3Log::info("Cost time: %f sec", timer.difference()); 90 | 91 | getchar(); 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Atmos/core/messageQueue/a3MessageQueue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | a3MessageQueue::a3MessageQueue() 5 | { 6 | 7 | } 8 | 9 | a3MessageQueue::~a3MessageQueue() 10 | { 11 | 12 | } 13 | 14 | void a3MessageQueue::init(char* buffer, int buffer_size, int msg_size) 15 | { 16 | assert(buffer); 17 | assert(buffer_size > 0); 18 | assert(msg_size > 0); 19 | 20 | int queue_head_size = sizeof(a3MessageQueueHead); 21 | 22 | // at least enough for one message. 23 | assert(buffer_size > (queue_head_size + msg_size)); 24 | 25 | int total_msg_size = buffer_size - queue_head_size; 26 | int total_msg_num = total_msg_size / msg_size; 27 | 28 | mqHead = (a3MessageQueueHead*)buffer; 29 | entries.resize(total_msg_num); 30 | 31 | buffer += queue_head_size; 32 | for (int i = 0; i < total_msg_num; i++) { 33 | a3MessageEntryHead* msg = (a3MessageEntryHead*)buffer; 34 | entries[i] = msg; 35 | buffer += msg_size; 36 | } 37 | 38 | messageNum = total_msg_num; 39 | messageSize = msg_size; 40 | } 41 | 42 | void a3MessageQueue::uninit() 43 | { 44 | entries.clear(); 45 | messageNum = 0; 46 | messageSize = 0; 47 | mqHead = NULL; 48 | } 49 | 50 | bool a3MessageQueue::isEmpty() 51 | { 52 | assert(mqHead); 53 | return mqHead->tail == mqHead->head; 54 | } 55 | 56 | bool a3MessageQueue::isFull() 57 | { 58 | assert(mqHead); 59 | assert(messageNum > 0); 60 | 61 | int tail = mqHead->tail; 62 | int head = mqHead->head; 63 | return (tail + 1) % messageNum == head; 64 | } 65 | 66 | int a3MessageQueue::getSize() 67 | { 68 | assert(mqHead); 69 | assert(messageNum > 0); 70 | 71 | int tail = mqHead->tail; 72 | int head = mqHead->head; 73 | return (tail - head + messageNum) % messageNum; 74 | } 75 | 76 | bool a3MessageQueue::enqueue(const a3MessageEntryHead& msg) 77 | { 78 | assert(mqHead); 79 | assert(messageNum > 0); 80 | 81 | if (isFull()) { 82 | return false; 83 | } 84 | 85 | int tail = mqHead->tail; 86 | a3MessageEntryHead* dst = entries[tail]; 87 | 88 | const char* src_buffer = (const char*)&msg; 89 | char* dst_buffer = (char*)dst; 90 | memcpy(dst_buffer, src_buffer, messageSize); 91 | 92 | tail = (tail + 1) % messageNum; 93 | mqHead->tail = tail; 94 | 95 | return true; 96 | } 97 | 98 | bool a3MessageQueue::dequeue(a3MessageEntryHead& msg) 99 | { 100 | assert(mqHead); 101 | assert(messageNum > 0); 102 | 103 | if (isEmpty()) { 104 | return false; 105 | } 106 | 107 | int head = mqHead->head; 108 | a3MessageEntryHead* src = entries[head]; 109 | 110 | const char* src_buffer = (const char*)src; 111 | char* dst_buffer = (char*)&msg; 112 | memcpy(dst_buffer, src_buffer, messageSize); 113 | 114 | head = (head + 1) % messageNum; 115 | mqHead->head = head; 116 | 117 | return true; 118 | } 119 | -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Tree/t3ThreadedBinaryTree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | t3ThreadTreeNode *previous; 3 | 4 | t3ThreadedBinaryTree::t3ThreadedBinaryTree() 5 | { 6 | 7 | } 8 | 9 | void t3ThreadedBinaryTree::inThreading() 10 | { 11 | previous = NULL; 12 | inThreading(tree); 13 | } 14 | 15 | void t3ThreadedBinaryTree::inThreading(t3ThreadTreeNode *current) 16 | { 17 | if(current) 18 | { 19 | inThreading(current->leftChild); 20 | 21 | // 空 / false 22 | if(!current->leftChild && !current->leftThread) 23 | { 24 | current->leftThread = true; 25 | current->leftChild = previous; 26 | } 27 | 28 | // 空 / 空 / false 29 | if(previous && !previous->rightChild && !previous->rightThread) 30 | { 31 | previous->rightThread = true; 32 | previous->rightChild = current; 33 | } 34 | 35 | previous = current; 36 | 37 | inThreading(current->rightChild); 38 | } 39 | } 40 | 41 | void t3ThreadedBinaryTree::inorder() 42 | { 43 | if(!tree) 44 | return; 45 | 46 | t3ThreadTreeNode *h; 47 | h = tree; 48 | // 找到根的最左端 49 | while(!h->leftThread) 50 | h = h->leftChild; 51 | 52 | t3Log(" %d ", h->data); 53 | 54 | // 直到找到最后一个后继结点 55 | while(h->rightChild) 56 | { 57 | if(h->rightThread) 58 | h = h->rightChild; 59 | else 60 | { 61 | h = h->rightChild; 62 | 63 | // 找到该节点的最左端结点 64 | while(!h->leftThread) 65 | h = h->leftChild; 66 | } 67 | t3Log(" %d ", h->data); 68 | } 69 | } 70 | 71 | t3ThreadTreeNode* t3ThreadedBinaryTree::inSuccessor(t3ThreadTreeNode *root) 72 | { 73 | if(!root) 74 | { 75 | t3PrintError("空指针没有后继结点"); 76 | return NULL; 77 | } 78 | 79 | t3ThreadTreeNode *temp = root->rightChild; 80 | if(!root->rightThread) 81 | // 找到其最左端结点 即root的后继结点 82 | while(!temp->leftThread) 83 | temp = temp->leftChild; 84 | 85 | return temp; 86 | } 87 | 88 | void t3ThreadedBinaryTree::insertRight(t3ThreadTreeNode *parent, t3ThreadTreeNode *child) 89 | { 90 | if(!parent || !child) 91 | { 92 | t3PrintError("插入二叉线索树中的子节点或父节点不能为空"); 93 | return; 94 | } 95 | 96 | child->leftThread = true; 97 | child->leftChild = parent; 98 | child->rightChild = parent->rightChild; 99 | child->rightThread = parent->rightThread; 100 | 101 | parent->rightThread = false; 102 | parent->rightChild = child; 103 | 104 | // 看原父节点右边有无子节点 105 | if(!child->rightThread) 106 | { 107 | t3ThreadTreeNode *temp; 108 | // 找到后继 109 | temp = inSuccessor(child); 110 | temp->leftChild = child; 111 | } 112 | } -------------------------------------------------------------------------------- /Atmos/lights/a3AreaLight.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | a3AreaLight::a3AreaLight(a3Shape* shape, a3Spectrum radiance, const t3Matrix4x4 & lightToWorld) 8 | : radiance(radiance), a3Light(lightToWorld, "a3AreaLight") 9 | { 10 | // attach a shape to a light 11 | this->shape = shape; 12 | shape->setLight(this); 13 | } 14 | 15 | a3AreaLight::~a3AreaLight() 16 | { 17 | } 18 | 19 | a3Spectrum a3AreaLight::eval(const a3IntersectRecord & its, const t3Vector3f & d) const 20 | { 21 | if(its.getNormal().dot(d) >= 0.0f) 22 | return radiance; 23 | else 24 | return a3Spectrum::zero(); 25 | } 26 | 27 | a3Spectrum a3AreaLight::sampleDirect(a3LightSamplingRecord & lRec) const 28 | { 29 | if(!shape) 30 | { 31 | a3NullPtrWarning("shape"); 32 | return a3Spectrum::zero(); 33 | } 34 | 35 | a3ShapeSamplingRecord sRec; 36 | shape->sample(sRec); 37 | 38 | // filling the sampling info 39 | lRec.p = sRec.p; 40 | lRec.normal = sRec.normal; 41 | 42 | lRec.d = lRec.hitPoint - lRec.p; 43 | lRec.distance = lRec.d.length(); 44 | lRec.d /= lRec.distance; 45 | 46 | // light to the hitPoint respect to normal on light 47 | float cosTheta = t3Math::Abs(lRec.normal.dot(lRec.d)); 48 | // pdf area to solid angle 49 | lRec.pdf = cosTheta != 0 ? sRec.pdf * lRec.distance * lRec.distance / cosTheta : 0.0f; 50 | 51 | // light and hitPoint are oriented correctly with respect to each other 52 | if(lRec.normal.dot(lRec.d) >= 0.0f && 53 | lRec.hitNormal.dot(lRec.d) < 0.0f && 54 | lRec.pdf != 0.0f) 55 | return radiance / lRec.pdf; 56 | else 57 | return a3Spectrum::zero(); 58 | } 59 | 60 | float a3AreaLight::pdf(const a3LightSamplingRecord & lRec) const 61 | { 62 | a3ShapeSamplingRecord sRec; 63 | if(shape) 64 | { 65 | float sPdf = shape->pdf(sRec); 66 | 67 | // light to the hitPoint respect to normal on light 68 | float cosTheta = t3Math::Abs(lRec.normal.dot(lRec.d)); 69 | 70 | // pdf area to solid angle 71 | float pdf = cosTheta != 0 ? sPdf * lRec.distance * lRec.distance / cosTheta : 0.0f; 72 | 73 | // Check that the emitter and receiver are oriented correctly with respect to each other 74 | if(lRec.normal.dot(lRec.d) >= 0.0f && 75 | lRec.hitNormal.dot(lRec.d) < 0.0f) 76 | return pdf; 77 | else 78 | return 0.0f; 79 | } 80 | else 81 | return 0.0f; 82 | } 83 | 84 | bool a3AreaLight::isEnvironment() const 85 | { 86 | return false; 87 | } 88 | 89 | bool a3AreaLight::isDeltaDistribution() const 90 | { 91 | return false; 92 | } 93 | 94 | void a3AreaLight::setShape(a3Shape * shape) 95 | { 96 | if(shape) 97 | this->shape = shape; 98 | else 99 | a3NullPtrWarning("shape"); 100 | } 101 | 102 | const a3Shape * a3AreaLight::getShape() 103 | { 104 | return shape; 105 | } 106 | -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/LinkList/t3LinkList.h: -------------------------------------------------------------------------------- 1 | #ifndef T3_LINKLIST_H 2 | #define T3_LINKLIST_H 3 | 4 | #include 5 | #include 6 | 7 | template 8 | class t3LinkListNode 9 | { 10 | public: 11 | t3LinkListNode():next(NULL){} 12 | 13 | void print() 14 | { 15 | std::cout << "t3LinkListNode's data:"<< data << std:: endl; 16 | } 17 | 18 | t3LinkListNode* next; 19 | 20 | T data; 21 | }; 22 | 23 | template 24 | class t3SingleLinkList { 25 | public: 26 | t3SingleLinkList(); 27 | 28 | void insert(t3LinkListNode *front, t3LinkListNode *node); 29 | 30 | t3LinkListNode* insert(const T &data); 31 | 32 | void deleteNode(t3LinkListNode *node); 33 | 34 | //O(n)复杂度的单链表翻转 35 | void invert(); 36 | 37 | void print(); 38 | 39 | // 头指针 40 | t3LinkListNode *head; 41 | }; 42 | 43 | template 44 | t3SingleLinkList::t3SingleLinkList():head(NULL) 45 | { 46 | 47 | } 48 | 49 | //O(n)复杂度的单链表翻转 50 | template 51 | void t3SingleLinkList::invert() 52 | { 53 | t3LinkListNode *middle = NULL, *trail, *now = head; 54 | while(now) 55 | { 56 | trail = middle; 57 | middle = now; 58 | now = now->next; 59 | middle->next = trail; 60 | } 61 | 62 | head = middle; 63 | } 64 | 65 | template 66 | t3LinkListNode* t3SingleLinkList::insert(const T &data) 67 | { 68 | t3LinkListNode *temp = new t3LinkListNode(); 69 | temp->data = data; 70 | 71 | if(head) 72 | { 73 | insert(head, temp); 74 | } 75 | else 76 | { 77 | head = temp; 78 | temp->next = NULL; 79 | } 80 | 81 | return temp; 82 | } 83 | 84 | template 85 | void t3SingleLinkList::insert(t3LinkListNode *front, t3LinkListNode *node) 86 | { 87 | if(!node || !front) 88 | { 89 | t3PrintError("链表待插入结点为空"); 90 | return; 91 | } 92 | 93 | node->next = front->next; 94 | front->next = node; 95 | } 96 | 97 | template 98 | void t3SingleLinkList::deleteNode(t3LinkListNode *node) 99 | { 100 | if(!node) 101 | { 102 | t3PrintError("链表无法删除空节点"); 103 | return; 104 | } 105 | 106 | t3LinkListNode *front = NULL, *now = head; 107 | 108 | while(now && now != node) 109 | { 110 | front = now; 111 | now = now->next; 112 | } 113 | 114 | if(now) 115 | { 116 | if(now == node) 117 | { 118 | front->next = now->next; 119 | // 可选不释放这块内存 继续由node保存 120 | delete now; 121 | now = NULL; 122 | node = NULL; 123 | } 124 | else 125 | t3PrintErrorArg("node", node, "无法在链表中找到指定结点"); 126 | } 127 | else 128 | t3PrintError("链表为空"); 129 | } 130 | 131 | template 132 | void t3SingleLinkList::print() 133 | { 134 | t3LinkListNode *temp = head; 135 | while(temp != NULL) 136 | { 137 | temp->print(); 138 | temp = temp->next; 139 | } 140 | } 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /dependency/t3Math/include/t3Math/core/t3Vector2.h: -------------------------------------------------------------------------------- 1 | #ifndef T3_VECTOR2_H 2 | #define T3_VECTOR2_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | class t3Vector2 10 | { 11 | public: 12 | Type x, y; 13 | 14 | t3Vector2(); 15 | 16 | t3Vector2(Type x, Type y); 17 | 18 | // 复制构造 19 | t3Vector2(const t3Vector2& vector); 20 | 21 | // t3Vector2->t3Vector2 22 | template 23 | explicit t3Vector2(const t3Vector2 &p); 24 | 25 | T3_FORCE_INLINE void clone(const t3Vector2& vector); 26 | 27 | T3_FORCE_INLINE void set(t3Vector2& vector); 28 | 29 | T3_FORCE_INLINE void set(const Type x, const Type y); 30 | 31 | // 重载 = 32 | inline t3Vector2& operator=(const t3Vector2& vector); 33 | // 重载 == != 34 | inline bool operator==(const t3Vector2& vector) const; 35 | inline bool operator!=(const t3Vector2& vector) const; 36 | 37 | // 重载一元 - + 38 | inline t3Vector2 operator-(); 39 | inline t3Vector2 operator+(); 40 | 41 | // 重载 二元 + - 42 | inline t3Vector2 operator+(const t3Vector2& vector) const; 43 | inline t3Vector2 operator-(const t3Vector2& vector) const; 44 | 45 | // 标量 乘除法 * / scale 46 | inline t3Vector2 operator*(const Type scale) const; 47 | // 会对 48 | inline t3Vector2 operator/(const Type scale) const; 49 | 50 | // 重载 += -= *= /= 51 | inline t3Vector2& operator+=(const t3Vector2& vector); 52 | inline t3Vector2& operator-=(const t3Vector2& vector); 53 | inline t3Vector2& operator*=(const Type scale); 54 | inline t3Vector2& operator/=(const Type scale); 55 | 56 | // 向量 * vector(无需inline一个右乘 因为类型相同左右不分) 57 | inline Type operator*(const t3Vector2& vector) const; 58 | 59 | // 置为零向量 60 | T3_FORCE_INLINE void zero(); 61 | 62 | // 将此2D向量标准化 63 | T3_FORCE_INLINE bool normalize(); 64 | 65 | // 求模长 66 | T3_FORCE_INLINE Type getLength() const; 67 | 68 | T3_FORCE_INLINE Type getLengthSquare() const; 69 | 70 | // 叉积 71 | T3_FORCE_INLINE Type cross(const t3Vector2& vector) const; 72 | 73 | // 与一标量叉积的结果为 先求得当前向量的垂直向量(-y, x)再缩放scalar倍 74 | // 叉积 75 | T3_FORCE_INLINE t3Vector2 cross(const float& scalar) const; 76 | 77 | T3_FORCE_INLINE Type dot(const t3Vector2& vector) const; 78 | 79 | // 两点间距离 80 | T3_FORCE_INLINE Type getDistance(const t3Vector2& end) const; 81 | 82 | T3_FORCE_INLINE Type getDistanceSquare(const t3Vector2& end) const; 83 | 84 | // 测试使用的Console Log输出 85 | T3_FORCE_INLINE void print(std::string name); 86 | 87 | T3_FORCE_INLINE void print(); 88 | 89 | }; 90 | 91 | #include 92 | 93 | // 特化 94 | typedef t3Vector2 t3Vector2d; 95 | typedef t3Vector2 t3Vector2f; 96 | typedef t3Vector2 t3Vector2i; 97 | 98 | // t2Point 99 | typedef t3Vector2d t2Point2d; 100 | typedef t3Vector2f t2Point2f; 101 | typedef t3Vector2i t2Point2i; 102 | 103 | //// 零向量 104 | //static t3Vector2f t3Vector2fZero; 105 | //static t3Vector2i t3Vector2iZero; 106 | 107 | 108 | #endif -------------------------------------------------------------------------------- /Atmos/renderers/a3FresnelRenderer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | float a3FrDiel(float cosi, float cost, const float &etai, const float &etat) 17 | { 18 | float Rparl = ((etat * cosi) - (etai * cost)) / 19 | ((etat * cosi) + (etai * cost)); 20 | float Rperp = ((etai * cosi) - (etat * cost)) / 21 | ((etai * cosi) + (etat * cost)); 22 | return (Rparl*Rparl + Rperp*Rperp) / 2.f; 23 | } 24 | 25 | void a3FresnelRenderer::render(const a3Scene* scene) 26 | { 27 | // 渲染法线贴图用于检测法线 28 | #pragma omp parallel for schedule(dynamic) 29 | for(int x = 0; x < camera->image->width; x++) 30 | { 31 | a3Log::info("Fresnel Map Rendering: %8.2f \r", (double) x / camera->image->width * 100); 32 | 33 | for(int y = 0; y < camera->image->height; y++) 34 | { 35 | // 当前采样位置 36 | a3CameraSample sample; 37 | a3Ray ray; 38 | 39 | // 获取下一个采样位置 40 | sampler->getMoreSamples(x, y, &sample); 41 | 42 | camera->castRay(&sample, &ray); 43 | 44 | float fresnel = getFresnel(scene, &ray, &sample); 45 | 46 | image->addSample(&sample, t3Vector3f(fresnel)); 47 | } 48 | } 49 | 50 | a3Log::print("\n"); 51 | // 保存法线图像文件 52 | image->write(); 53 | } 54 | 55 | bool a3FresnelRenderer::check() 56 | { 57 | if(!camera) 58 | { 59 | a3Log::error("a3SamplerRenderer::render()前camera: %d尚未分配指定\n", camera); 60 | return false; 61 | } 62 | 63 | if(!sampler) 64 | { 65 | a3Log::error("a3SamplerRenderer::render()前sampler: %d尚未分配指定\n", sampler); 66 | return false; 67 | } 68 | 69 | if(!image) 70 | { 71 | a3Log::error("a3SamplerRenderer::render()前image: %d尚未分配指定\n", image); 72 | return false; 73 | } 74 | 75 | return true; 76 | } 77 | 78 | float a3FresnelRenderer::getFresnel(const a3Scene* scene, a3Ray* ray, const a3CameraSample* sample) 79 | { 80 | a3IntersectRecord intersection; 81 | 82 | if(!scene->intersect(*ray, &intersection)) 83 | // zero normal 84 | return 0.0f; 85 | 86 | a3Shape* obj = intersection.shape; 87 | 88 | t3Vector3f normal = intersection.getNormal(); 89 | 90 | // future added 91 | ////float n = obj->refractiveIndex; 92 | 93 | ////float R0 = (1.0f - n) / (1.0 + n); 94 | 95 | ////R0 = R0 * R0; 96 | 97 | //float costheta1 = normal.dot(-ray->direction); 98 | 99 | ////float probablity = R0 + (1 - R0) * t3Math::pow((1 - t3Math::Abs(costheta1)), 5); 100 | 101 | //float sint = 1.0f / n * sqrtf(1.f - costheta1 * costheta1); 102 | 103 | //float cost = sqrtf(1.f - sint * sint); 104 | 105 | //float probablity = a3FrDiel(costheta1, cost, 1.0f, n); 106 | 107 | //return 1 - probablity; 108 | return 1; 109 | } 110 | 111 | -------------------------------------------------------------------------------- /Atmos/bsdf/a3RoughConductor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | a3RoughConductor::a3RoughConductor() 9 | { 10 | R = a3Spectrum::one(); 11 | 12 | eta = a3Spectrum::zero(); 13 | k = a3Spectrum::one(); 14 | 15 | type = a3Microfacet::a3MicrofacetType::Beckmann; 16 | alphaX = 0.1f; 17 | alphaY = 0.1f; 18 | } 19 | 20 | a3Spectrum a3RoughConductor::eval(const a3BSDFSamplingRecord & bRec) const 21 | { 22 | /* Stop if this component was not requested */ 23 | if(a3CosTheta(bRec.wi) <= 0 || 24 | a3CosTheta(bRec.wo) <= 0) 25 | return a3Spectrum(0.0f); 26 | 27 | /* Calculate the reflection half-vector */ 28 | t3Vector3f H = (bRec.wo + bRec.wi).getNormalized(); 29 | 30 | /* Construct the microfacet distribution matching the 31 | roughness values at the current surface position. */ 32 | a3Microfacet distr(alphaX, alphaY, type); 33 | 34 | /* Evaluate the microfacet normal distribution */ 35 | const float D = distr.D(H); 36 | if(D == 0) 37 | return a3Spectrum(0.0f); 38 | 39 | /* Fresnel factor */ 40 | const a3Spectrum F = a3FresnelConductor(bRec.wi.dot(H), eta, k) * R; 41 | 42 | /* Smith's shadow-masking function */ 43 | const float G = distr.G(bRec.wi, bRec.wo, H); 44 | 45 | /* Calculate the total amount of reflection */ 46 | return F * D * G / (4.0f * a3CosTheta(bRec.wi)); 47 | } 48 | 49 | a3Spectrum a3RoughConductor::sample(a3BSDFSamplingRecord & bRec) const 50 | { 51 | if(a3CosTheta(bRec.wi) < 0) 52 | return a3Spectrum(0.0f); 53 | 54 | /* Construct the microfacet distribution matching the 55 | roughness values at the current surface position. */ 56 | a3Microfacet distr(alphaX, alphaY, type); 57 | 58 | /* Sample M, the microfacet normal */ 59 | float pdf; 60 | t3Vector3f m = distr.sample(bRec.wi, pdf); 61 | 62 | if(pdf == 0) 63 | return a3Spectrum(0.0f); 64 | 65 | /* Perfect specular reflection based on the microfacet normal */ 66 | bRec.wo = a3GetReflect(bRec.wi, m); 67 | bRec.eta = 1.0f; 68 | 69 | /* Side check */ 70 | if(a3CosTheta(bRec.wo) <= 0) 71 | return a3Spectrum(0.0f); 72 | 73 | a3Spectrum F = a3FresnelConductor(bRec.wi.dot(m), eta, k) * R; 74 | 75 | float weight = distr.D(m) * distr.G(bRec.wi, bRec.wo, m) 76 | * bRec.wi.dot(m) / (pdf * a3CosTheta(bRec.wi)); 77 | 78 | /* Jacobian of the half-direction mapping */ 79 | bRec.pdf = pdf / (4.0f * bRec.wo.dot(m)); 80 | 81 | return F * weight; 82 | } 83 | 84 | float a3RoughConductor::pdf(const a3BSDFSamplingRecord & bRec) const 85 | { 86 | if(a3CosTheta(bRec.wi) <= 0 || 87 | a3CosTheta(bRec.wo) <= 0) 88 | return 0.0f; 89 | 90 | /* Calculate the reflection half-vector */ 91 | t3Vector3f H = (bRec.wo + bRec.wi).getNormalized(); 92 | 93 | /* Construct the microfacet distribution matching the 94 | roughness values at the current surface position. */ 95 | a3Microfacet distr(alphaX, alphaY, type); 96 | 97 | return distr.pdf(bRec.wi, H) / (4 * t3Math::Abs(bRec.wo.dot(H))); 98 | } 99 | 100 | bool a3RoughConductor::isDeltaDistribution() const 101 | { 102 | return false; 103 | } 104 | -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Test/t3EquivalenceTest.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAX_SIZE 24 8 | 9 | class t3Equivalence 10 | { 11 | public: 12 | t3Equivalence(int n):n(n) 13 | { 14 | for(int i=0; i(); 18 | seq[i]->next = NULL; 19 | } 20 | } 21 | 22 | void addPair(int data1, int data2) 23 | { 24 | if(data1 >= n || data1 < 0 || data2 >= n) 25 | { 26 | t3PrintError("给定位置大小有误, 需在[0, MAX_SIZE)范围内"); 27 | return; 28 | } 29 | 30 | t3LinkListNode* x = new t3LinkListNode(); 31 | // 前缀插入 32 | x->data = data1; 33 | x->next = seq[data2]; 34 | seq[data2] = x; 35 | 36 | t3LinkListNode* y = new t3LinkListNode(); 37 | // 前缀插入 38 | y->data = data2; 39 | y->next = seq[data1]; 40 | seq[data1] = y; 41 | } 42 | 43 | void output() 44 | { 45 | for(int i=0; i *x = seq[i]; 55 | 56 | while(1) 57 | { 58 | while(x) 59 | { 60 | // 未被输出 61 | if(!outs[x->data]) 62 | { 63 | t3Log(", %d", x->data); 64 | outs[x->data] = true; 65 | 66 | // 入栈 67 | stack.push(x); 68 | } 69 | 70 | x = x->next; 71 | } 72 | 73 | if(stack.isEmpty()) 74 | break; 75 | 76 | x = seq[stack.pop()->data]; 77 | } 78 | } 79 | } 80 | 81 | void print() 82 | { 83 | for(int i=0; idata); 89 | t3LinkListNode* temp = seq[i]->next; 90 | while(temp) 91 | { 92 | t3Log(", %d", temp->data); 93 | temp = temp->next; 94 | } 95 | //t3Log("\n", seq[i]->data); 96 | } 97 | } 98 | 99 | int n; 100 | bool outs[MAX_SIZE]; 101 | t3LinkListNode* seq[MAX_SIZE]; 102 | t3Stack*> stack; 103 | }; 104 | 105 | // P108页寻找等价类 106 | int main(int argc, char* argv[]) 107 | { 108 | t3Equivalence equ(12); 109 | equ.addPair(0, 4); 110 | equ.addPair(3, 1); 111 | equ.addPair(6, 10); 112 | equ.addPair(8, 9); 113 | equ.addPair(7, 4); 114 | equ.addPair(6, 8); 115 | equ.addPair(3, 5); 116 | equ.addPair(2, 11); 117 | equ.addPair(11, 0); 118 | 119 | equ.print(); 120 | 121 | equ.output(); 122 | 123 | getchar(); 124 | 125 | return 0; 126 | } -------------------------------------------------------------------------------- /Atmos/sensors/a3Sensor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | a3Sensor::a3Sensor(const t3Vector3f& origin, const t3Vector3f& lookat, const t3Vector3f& up, 6 | float focalLength, float apretureWidth, float apretureHeight, float canvasDistance, 7 | float focalDistance, float lensRadius, 8 | a3Film* image) 9 | : origin(origin), up(up), 10 | focalLength(focalLength), apreture(apretureWidth, apretureHeight), canvasDistance(canvasDistance), 11 | focalDistance(focalDistance), lensRadius(lensRadius), 12 | image(image) 13 | { 14 | // 这里不直接给出fov而是间接计算 15 | // 详情可见 http://www.scratchapixel.com/lessons/3d-basic-rendering/3d-viewing-pinhole-camera/virtual-pinhole-camera-model 16 | fov.x = 2.0f * t3Math::atanRad(focalLength / (apretureWidth / 2.0f)); 17 | fov.y = 2.0f * t3Math::atanRad(focalLength / (apretureHeight / 2.0f)); 18 | 19 | canvasSize.x = canvasDistance * t3Math::tanRad(fov.x / 2.0f); 20 | canvasSize.y = canvasDistance * t3Math::tanRad(fov.y / 2.0f); 21 | 22 | setCameraToWorld(origin, lookat, up); 23 | } 24 | 25 | float a3Sensor::castRay(const a3CameraSample* sample, a3Ray* ray) const 26 | { 27 | a3Log::warning("Unimplemented a3Camera::generateRay() method called"); 28 | 29 | return 0.0f; 30 | } 31 | 32 | void a3Sensor::setCameraToWorld(const t3Vector3f& origin, const t3Vector3f& lookat, const t3Vector3f& up) 33 | { 34 | this->origin = origin; 35 | this->lookat = lookat; 36 | this->direction = (lookat - origin).getNormalized(); 37 | 38 | if((up.getNormalized()).getCrossed(this->direction).length() == 0) 39 | { 40 | a3Log::error("\"up\" vector (%f, %f, %f) and viewing direction (%f, %f, %f) " 41 | "passed to LookAt are pointing in the same direction. Using " 42 | "the identity transformation.\n", up.x, up.y, up.z, direction.x, direction.y, 43 | direction.z); 44 | return; 45 | } 46 | 47 | this->right = (up.getNormalized()).getCrossed(this->direction).getNormalized(); 48 | this->up = this->direction.getCrossed(this->right); 49 | 50 | // 平移矩阵直接可直接作用光线原点 减少矩阵计算量 51 | // world to camera 52 | //cameraToWorld._mat[0].set(this->right.x, this->right.y, this->right.z, 0); 53 | //cameraToWorld._mat[1].set(this->up.x, this->up.y, this->up.z, 0); 54 | //cameraToWorld._mat[2].set(this->direction.x, this->direction.y, this->direction.z, 0); 55 | //cameraToWorld._mat[3].set(this->origin.x, this->origin.y, this->origin.z, 1); 56 | cameraToWorld._mat[0].set(this->right.x, this->up.x, this->direction.x, this->origin.x); 57 | cameraToWorld._mat[1].set(this->right.y, this->up.y, this->direction.y, this->origin.y); 58 | cameraToWorld._mat[2].set(this->right.z, this->up.z, this->direction.z, this->origin.z); 59 | cameraToWorld._mat[3].set(0, 0, 0, 1); 60 | 61 | // camera to world 62 | //cameraToWorld = cameraToWorld.getInverse(); 63 | } 64 | 65 | void a3Sensor::print() 66 | { 67 | a3Log::debug("Camera position: [%f, %f, %f]\n", origin.x, origin.y, origin.z); 68 | a3Log::debug("Camera lookat: [%f, %f, %f]\n", lookat.x, lookat.y, lookat.z); 69 | t3Vector3f oritation = (lookat - origin).getNormalized(); 70 | a3Log::debug("Camera oritation: [%f, %f, %f]\n", oritation.x, oritation.y, oritation.z); 71 | a3Log::debug("Camera up: [%f, %f, %f]\n", up.x, up.y, up.z); 72 | a3Log::debug("fov: %f, %f\n", t3Math::Rad2Deg(fov.x), t3Math::Rad2Deg(fov.y)); 73 | a3Log::debug("focal distance: %f, lens radius: %f\n", focalDistance, lensRadius); 74 | } 75 | -------------------------------------------------------------------------------- /test/ray.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() 11 | { 12 | for(size_t i = 0; i < 20; i++) 13 | a3Log::debug("%f\n", a3Random::randomFloat()); 14 | 15 | for(size_t i = 0; i < 20; i++) 16 | a3Log::debug("%d\n", a3Random::randomInt()); 17 | 18 | a3Sphere sphere(t3Vector3f(0, 10, 0), 10); 19 | 20 | sphere.getNormal(t3Vector3f(20, 10, 0)).print(); 21 | 22 | a3Film image(900, 900, "Atoms.ppm"); 23 | 24 | 25 | // 产生随机数种子 26 | std::random_device randoms; 27 | // mersenne twister engine 28 | std::mt19937 mt(randoms()), mersenneTwister(randoms()); 29 | // uniform distribution 30 | std::uniform_int_distribution<> uniformi(1, 6); 31 | std::uniform_real_distribution uniformf(0.0, 1.0); 32 | // normal distribution 33 | std::normal_distribution<> d(5, 2); 34 | 35 | #define RND (2.0*uniform(mersenneTwister)-1.0) 36 | #define RND2 (uniform(mersenneTwister)) 37 | 38 | #define A3RANDOM uniformf(mersenneTwister) 39 | 40 | for(int i = 0; i < 10; i++) 41 | std::cout << mt() << std::endl; 42 | 43 | for(int i = 0; i < 10; i++) 44 | std::cout << uniformi(mt) << std::endl; 45 | 46 | for(long i = 0; i < 1000000000; i++) 47 | { 48 | if((int)(uniformf(mersenneTwister)) == 1) 49 | std::cout << "RIRIRIRIRIR" << std::endl; 50 | //std::cout << uniformf(mersenneTwister) << std::endl; 51 | } 52 | 53 | for(int i = 0; i < image.width; i++) 54 | { 55 | for(int j = 0; j < image.height; j++) 56 | { 57 | // deprecated 58 | //image.pixels[i][j].set(A3RANDOM, A3RANDOM, A3RANDOM); 59 | } 60 | } 61 | 62 | image.write(); 63 | 64 | a3Ray ray(t3Vector3f(10, 0, 0), t3Vector3f(-1, 0, 0), 0.0f, 10000.0f); 65 | a3Sphere sphere1(t3Vector3f(0, 0, 0), 1.0f); 66 | 67 | ray.print(); 68 | sphere1.print(); 69 | float t; 70 | sphere1.intersect(ray, &t); 71 | std::cout << "相交测试最近点为: " << t << std::endl; 72 | 73 | // log test 74 | int a = 10; 75 | a3Log::error("这一段是错误Log, 紧接着一个int变量: a = %d\n", a); 76 | a3Log::warning("这一段是警告Log, 紧接着一个int变量: a = %d\n", a); 77 | a3Log::success("这一段是成功Log, 紧接着一个int变量: a = %d\n", a); 78 | a3Log::info("这一段是信息Log, 紧接着一个int变量: a = %d\n", a); 79 | a3Log::debug("这一段是信息Log, 紧接着一个int变量: a = %d\n", a); 80 | a3LogFile::debug("What are you talking about%d\n", a); 81 | 82 | a3LogFile::log(A3_LOG_LEVEL_DEBUG, "WTF", "log", "This is a File Log. a = %d\n", a); 83 | 84 | //a3LogFile::log(A3_LOG_LEVEL_DEBUG, "WTF", "log", "AAAAAAAAAAAAA. a = %d\n", a); 85 | //a3LogFile::log(A3_LOG_LEVEL_DEBUG, "WTF", "log", "AAAAAAAAAAAAA. a = %d\n", a); 86 | 87 | a3LogFile::error("This is a File Log. a = %d\n", a); 88 | a3LogFile::warning("This is a File Log. a = %d\n", a); 89 | a3LogFile::success("This is a File Log. a = %d\n", a); 90 | a3LogFile::info("This is a File Log. a = %d\n", a); 91 | a3LogFile::debug("This is a File Log. a = %d\n", a); 92 | 93 | //t2Log("这一段是信息Log, 紧接着一个int变量: a = %d\n", a); 94 | 95 | a3LogHTML::begin(); 96 | a3LogHTML::error("This is a File Log. a = %d\n", a); 97 | a3LogHTML::warning("This is a File Log. a = %d\n", a); 98 | a3LogHTML::success("This is a File Log. a = %d\n", a); 99 | a3LogHTML::info("This is a File Log. a = %d\n", a); 100 | a3LogHTML::debug("This is a File Log. a = %d\n", a); 101 | a3LogHTML::end(); 102 | 103 | getchar(); 104 | 105 | return 0; 106 | } -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/LinearList/t3Stack.h: -------------------------------------------------------------------------------- 1 | #ifndef T3_STACK_H 2 | #define T3_STACK_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | class t3Stack 10 | { 11 | public: 12 | t3Stack(); 13 | 14 | ~t3Stack(); 15 | 16 | // 放入给定值的拷贝 17 | void push(T &value); 18 | 19 | bool isEmpty(); 20 | 21 | bool isFull(); 22 | 23 | // 获取栈顶元素值 24 | T get(); 25 | 26 | // 弹出栈顶元素并返回 27 | T pop(); 28 | 29 | void print(); 30 | 31 | private: 32 | // 尽量不要扩建,效率很低 33 | void enlarge(); 34 | 35 | // 栈头 36 | T *head; 37 | 38 | // 栈顶指针 39 | int top; 40 | 41 | // C/C++无法记住申请的指针指向的内存长度大小 42 | int length; 43 | }; 44 | 45 | template 46 | t3Stack::t3Stack():head(NULL), length(0) 47 | { 48 | enlarge(); 49 | } 50 | 51 | template 52 | t3Stack::~t3Stack() 53 | { 54 | delete head; 55 | head = NULL; 56 | } 57 | 58 | // 放入给定值的拷贝 59 | template 60 | void t3Stack::push(T &value) 61 | { 62 | if(isFull()) 63 | enlarge(); 64 | 65 | head[++top] = value; 66 | 67 | //t3Log("Number Of Elements: %d\n", top+1); 68 | } 69 | 70 | // 获取栈顶元素值 71 | template 72 | T t3Stack::get() 73 | { 74 | if(isEmpty()) 75 | { 76 | t3PrintError("栈为空,无法获取元素"); 77 | return T(); 78 | } 79 | else 80 | return head[top]; 81 | } 82 | 83 | // 弹出栈顶元素并返回 84 | template 85 | T t3Stack::pop() 86 | { 87 | if(isEmpty()) 88 | { 89 | t3PrintError("栈为空,无法弹出元素"); 90 | // --!未来应该更改为断言而不是T() 91 | return T(); 92 | } 93 | else 94 | { 95 | // 实质内容没有被覆盖 96 | return head[top--]; 97 | } 98 | } 99 | 100 | template 101 | void t3Stack::enlarge() 102 | { 103 | if(head) 104 | { 105 | t3Log("t3Statck: enlarge!"); 106 | 107 | int orignalLength = length; 108 | // 扩增两倍 109 | length = 2 * orignalLength; 110 | 111 | T *temp = new T[length](); 112 | 113 | // 数据迁移 114 | // for(int i=0; i 142 | bool t3Stack::isEmpty() 143 | { 144 | if(top < 0) 145 | return true; 146 | else 147 | return false; 148 | } 149 | 150 | template 151 | bool t3Stack::isFull() 152 | { 153 | if(top >= length-1) 154 | return true; 155 | else 156 | return false; 157 | } 158 | 159 | 160 | template 161 | void t3Stack::print() 162 | { 163 | t3Log("------------------------------------------\n"); 164 | for(int i=0; i<=top; i++) 165 | { 166 | std::cout << "t3Stack[" << i << "]: " << head[i] << std::endl; 167 | } 168 | t3Log("\nMax Length: %d", length); 169 | t3Log("------------------------------------------\n"); 170 | } 171 | 172 | #endif -------------------------------------------------------------------------------- /Atmos/bsdf/a3Dielectric.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | a3Dielectric::a3Dielectric() 8 | { 9 | // bk7 10 | eta = 1.5046f; 11 | 12 | specularReflectance = a3Spectrum::one(); 13 | specularTransmittance = a3Spectrum::one(); 14 | } 15 | 16 | a3Spectrum a3Dielectric::eval(const a3BSDFSamplingRecord & bRec) const 17 | { 18 | float cosThetaT; 19 | float cosThetaI = a3CosTheta(bRec.wi); 20 | float cosThetaO = a3CosTheta(bRec.wo); 21 | 22 | float f = a3FresnelDielectric(cosThetaI, cosThetaT, eta); 23 | 24 | // wo in the reflect(spcular) direction, in the same side of the shading normal 25 | if(cosThetaI * cosThetaO >= 0) 26 | { 27 | t3Vector3f reflect = a3GetReflect(bRec.wi); 28 | 29 | if(t3Math::Abs(reflect.dot(bRec.wo) - 1) > A3_EPSILON_DELTA) 30 | return a3Spectrum::zero(); 31 | 32 | return specularReflectance * f; 33 | } 34 | // wo in the refract(transmission) direction, in the other side of the shading normal 35 | else 36 | { 37 | t3Vector3f refract = a3GetRefract(bRec.wi, cosThetaT, eta); 38 | 39 | if(t3Math::Abs(refract.dot(bRec.wo) - 1) > A3_EPSILON_DELTA) 40 | return a3Spectrum::zero(); 41 | 42 | // ray cross the surface from material inside to outside(> 0) 43 | float factor = cosThetaT < 0 ? 1 / eta : eta; 44 | 45 | // scaled to account for the solid angle compression that occurs when crossing the interface 46 | return specularTransmittance * (1 - f) * factor * factor; 47 | } 48 | } 49 | 50 | a3Spectrum a3Dielectric::sample(a3BSDFSamplingRecord & bRec) const 51 | { 52 | float cosThetaT; 53 | float cosThetaI = a3CosTheta(bRec.wi); 54 | 55 | float f = a3FresnelDielectric(cosThetaI, cosThetaT, eta); 56 | 57 | // the probability of reflection and refraction depend on the fresnel value 58 | if(a3Random::randomFloat() <= f) 59 | { 60 | bRec.wo = a3GetReflect(bRec.wi); 61 | bRec.eta = 1.0f; 62 | bRec.pdf = f; 63 | 64 | return specularReflectance; 65 | } 66 | else 67 | { 68 | bRec.wo = a3GetRefract(bRec.wi, cosThetaT, eta); 69 | bRec.eta = cosThetaT < 0 ? eta : 1 / eta; 70 | bRec.pdf = 1 - f; 71 | 72 | // ray cross the surface from material inside to outside(> 0) 73 | float factor = cosThetaT < 0 ? 1 / eta : eta; 74 | 75 | return specularTransmittance * factor * factor; 76 | } 77 | } 78 | 79 | float a3Dielectric::pdf(const a3BSDFSamplingRecord & bRec) const 80 | { 81 | float cosThetaT; 82 | float cosThetaI = a3CosTheta(bRec.wi); 83 | float cosThetaO = a3CosTheta(bRec.wo); 84 | 85 | float f = a3FresnelDielectric(cosThetaI, cosThetaT, eta); 86 | 87 | // wo in the reflect(spcular) direction, in the same side of the shading normal 88 | if(cosThetaI * cosThetaO >= 0) 89 | { 90 | t3Vector3f reflect = a3GetReflect(bRec.wi); 91 | 92 | if(t3Math::Abs(reflect.dot(bRec.wo) - 1) > A3_EPSILON_DELTA) 93 | return 0.0f; 94 | 95 | return f; 96 | } 97 | // wo in the refract(transmission) direction, in the other side of the shading normal 98 | else 99 | { 100 | t3Vector3f refract = a3GetRefract(bRec.wi, cosThetaT, eta); 101 | 102 | if(t3Math::Abs(refract.dot(bRec.wo) - 1) > A3_EPSILON_DELTA) 103 | return 0.0f; 104 | 105 | // scaled to account for the solid angle compression that occurs when crossing the interface 106 | return 1 - f; 107 | } 108 | } 109 | 110 | bool a3Dielectric::isDeltaDistribution() const 111 | { 112 | return true; 113 | } 114 | -------------------------------------------------------------------------------- /Atmos/core/a3Scene.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | a3Scene::a3Scene() 12 | { 13 | 14 | } 15 | 16 | // free the lights and shape outside 17 | a3Scene::~a3Scene() 18 | { 19 | } 20 | 21 | bool a3Scene::addShape(a3Shape* shape) 22 | { 23 | if(!check()) return false; 24 | 25 | return primitiveSet->addShape(shape); 26 | } 27 | 28 | bool a3Scene::addLight(a3Light* light) 29 | { 30 | if(!light) 31 | { 32 | a3Log::error("a3Scene::addLight() not allowed nullptr.\n", light); 33 | return false; 34 | } 35 | 36 | lights.push_back(light); 37 | return true; 38 | } 39 | 40 | bool a3Scene::check() const 41 | { 42 | if(!primitiveSet) 43 | { 44 | a3Log::error("Before a3Scene::render() was called, primitiveSet: %d not allocated\n", primitiveSet); 45 | return false; 46 | } 47 | 48 | return true; 49 | } 50 | 51 | bool a3Scene::intersect(const a3Ray& ray, a3IntersectRecord* its) const 52 | { 53 | bool find = primitiveSet->intersect(ray, its); 54 | if(find) 55 | { 56 | its->localToWorld = its->shape->getShadeToWorld(*its); 57 | its->worldToLocal = its->localToWorld.getInverse(); 58 | return true; 59 | } 60 | else 61 | return false; 62 | } 63 | 64 | bool a3Scene::intersect(const a3Ray& ray) const 65 | { 66 | return primitiveSet->intersect(ray); 67 | } 68 | 69 | a3Spectrum a3Scene::sampleDirect(a3LightSamplingRecord & lRec) const 70 | { 71 | if(lights.size() == 0) 72 | return a3Spectrum(); 73 | 74 | int numLights = lights.size(); 75 | float lightSelectPdf = 1.0f / numLights; 76 | 77 | // uniform sampling lights 78 | int index = a3Random::randomInt(0, numLights - 1); 79 | index = index >= numLights ? numLights - 1 : index; 80 | 81 | a3Spectrum L = lights[index]->sampleDirect(lRec); 82 | 83 | if(lRec.pdf != 0) 84 | { 85 | // test visibility ray(lightPoint -> hitPoint) 86 | a3Ray ray(lRec.p, lRec.d, A3_EPSILON, lRec.distance * (1.0f - A3_EPSILON_SHADOW)); 87 | 88 | if(intersect(ray)) 89 | // sth. between sampled point and hitpoint 90 | return a3Spectrum::zero(); 91 | 92 | // lights pdf 93 | lRec.pdf *= lightSelectPdf; 94 | lRec.light = lights[index]; 95 | 96 | // sample one light equal to all of it 97 | return L * numLights; 98 | } 99 | else 100 | // can't be sampled on the light 101 | return a3Spectrum::zero(); 102 | } 103 | 104 | float a3Scene::pdfLightDirect(const a3LightSamplingRecord & lRec) const 105 | { 106 | a3Light* light = lRec.light; 107 | if(light) 108 | return light->pdf(lRec) / lights.size(); 109 | else 110 | return 0.0f; 111 | } 112 | 113 | a3Spectrum a3Scene::Le(const t3Vector3f& d, const a3IntersectRecord& its) const 114 | { 115 | if(its.isLight()) 116 | return its.Le(d); 117 | else 118 | return a3Spectrum::zero(); 119 | } 120 | 121 | a3Light * a3Scene::getEnvironmentLight() const 122 | { 123 | for(auto l : lights) 124 | if(l->isEnvironment()) 125 | return l; 126 | 127 | return NULL; 128 | } 129 | 130 | a3Spectrum a3Scene::evalEnvironment(const a3Ray& ray) const 131 | { 132 | a3Spectrum L; 133 | 134 | // add radiance from environment light 135 | for(auto l : lights) 136 | if(l->isEnvironment()) 137 | L += l->evalEnvironment(ray); 138 | 139 | return L; 140 | } 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Atmos 2 | 3 | A Physically Based Renderer.(Not Finished Yet) 4 | 5 | Test_000027 6 | 7 | Video's([Youtube](https://www.youtube.com/watch?v=d6pLWDCjvSk) || [Youku](http://v.youku.com/v_show/id_XMTczMjI3NjY1Mg==.html#paction)) rendering was done by the [Atmos Renderer](https://github.com/BentleyBlanks/Atmos), water and other physics simulation were exported from [Blender](https://www.blender.org/). The [AtmosMovie](https://github.com/BentleyBlanks/AtmosMovie) was responsible for the auto-rendering. 120 frames in all, cost 25.3h. 8 | 9 | > In 2016, this demo and the Atmos Renderer, were as my graduation project from JiangNan University. 10 | 11 | Also developed an [Atmos Editor](https://github.com/BentleyBlanks/AtmosVisualizer/tree/master/AtmosVisualizer/AtmosEditor), supports multiple camera to set up the matrials, shapes, lights...And preview the final result in real-time camera. 12 | 13 | QQ图片20180203211712 14 | 15 | ## Build 16 | 17 | All thirdyparty libs are compiled by Visual Studio 2015. 18 | 19 | > If you're using other versions of VS, please compiled them manualy. 20 | 21 | ## Thirdyparty 22 | 23 | 1.[tinyobjloader](https://github.com/syoyo/tinyobjloader) Importing obj models. 24 | 25 | 2.[loadpng](http://lodev.org/lodepng/) encode / decode png image. 26 | 27 | 3.[t3DataStructures](https://github.com/BentleyBlanks/t3DataStructures) 28 | from Tatty3d, provide some fundamental modules. 29 | 30 | 4.[t3Math](https://github.com/BentleyBlanks/t3Math) from Tatty3d, for mathematical calculation. 31 | 32 | 5.[tinyexr](https://github.com/syoyo/tinyexr) encode / decode exr image. 33 | 34 | ## ScreenShots 35 | 36 | path dieletric texture 37 | 38 | hello 39 | 40 | spotlight path 41 | 42 | atmosPath 43 | 44 | ## Features 45 | 46 | 2. Visualizer Renderer for debug and visualization. 47 | 48 | 3. Triangle, Sphere, Disk, Plane shapes supported(with texture mapping). 49 | 50 | 4. Perspective(with DOF) Camera. 51 | 52 | 5. Environment, Point, Spot, Area Light supported. 53 | 54 | 6. BVH for faster intersection. 55 | 56 | 9. Easy to use log system, levels of urgency supported 57 | 58 | ```cpp 59 | a3Log::debug("Whos Your Daddy? %d\n", a); 60 | 61 | a3LogFile::debug("Whos Your Daddy? %d\n", a); 62 | 63 | a3LogHTML::begin(); 64 | a3LogHTML::debug("Whos Your Daddy? %d\n", a); 65 | a3LogHTML::end(); 66 | ``` 67 | > UTF-8 characters are not supported 68 | 69 | ## Author 70 | 71 | ``` cpp 72 | const char* 官某某 = "Bingo"; 73 | 74 | std::string 个人博客 = "http://bentleyblanks.github.io"; 75 | ``` 76 | 77 | -------------------------------------------------------------------------------- /test/exr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | //#define LOADING_FROM_FILE 8 | 9 | bool SaveEXR(const float* rgb, int width, int height, const char* outfilename) 10 | { 11 | float* channels[3]; 12 | 13 | EXRImage image; 14 | InitEXRImage(&image); 15 | 16 | image.num_channels = 3; 17 | 18 | // Must be BGR(A) order, since most of EXR viewers expect this channel order. 19 | const char* channel_names[] = {"B", "G", "R"}; // "B", "G", "R", "A" for RGBA image 20 | 21 | std::vector images[3]; 22 | images[0].resize(width * height); 23 | images[1].resize(width * height); 24 | images[2].resize(width * height); 25 | 26 | for(int i = 0; i < width * height; i++) 27 | { 28 | images[0][i] = rgb[3 * i + 0]; 29 | images[1][i] = rgb[3 * i + 1]; 30 | images[2][i] = rgb[3 * i + 2]; 31 | } 32 | 33 | float* image_ptr[3]; 34 | image_ptr[0] = &(images[2].at(0)); // B 35 | image_ptr[1] = &(images[1].at(0)); // G 36 | image_ptr[2] = &(images[0].at(0)); // R 37 | 38 | image.channel_names = channel_names; 39 | image.images = (unsigned char**) image_ptr; 40 | image.width = width; 41 | image.height = height; 42 | image.compression = TINYEXR_COMPRESSIONTYPE_ZIP; 43 | 44 | image.pixel_types = (int *) malloc(sizeof(int) * image.num_channels); 45 | image.requested_pixel_types = (int *) malloc(sizeof(int) * image.num_channels); 46 | for(int i = 0; i < image.num_channels; i++) 47 | { 48 | image.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image 49 | image.requested_pixel_types[i] = TINYEXR_PIXELTYPE_HALF; // pixel type of output image to be stored in .EXR 50 | } 51 | 52 | const char* err; 53 | int ret = SaveMultiChannelEXRToFile(&image, outfilename, &err); 54 | if(ret != 0) 55 | { 56 | fprintf(stderr, "Save EXR err: %s\n", err); 57 | return ret; 58 | } 59 | printf("Saved exr file. [ %s ] \n", outfilename); 60 | 61 | free(image.pixel_types); 62 | free(image.requested_pixel_types); 63 | 64 | return ret; 65 | 66 | } 67 | 68 | int main() 69 | { 70 | #ifndef LOADING_FROM_FILE 71 | const char* input = "../../../../resources/images/envmap.exr"; 72 | float* out; // width * height * RGBA 73 | int width; 74 | int height; 75 | const char* err; 76 | 77 | int ret = LoadEXR(&out, &width, &height, input, &err); 78 | 79 | if(ret == -1) 80 | { 81 | a3Log::print("%s\n", err); 82 | } 83 | 84 | for(int i = 0; i < height; i++) 85 | { 86 | for(int j = 0; j < width; j++) 87 | { 88 | a3Log::print("%f ", out[i * width + j + 0]); 89 | a3Log::print("%f ", out[i * width + j + 1]); 90 | a3Log::print("%f ", out[i * width + j + 2]); 91 | a3Log::print("%f\n", out[i * width + j + 3]); 92 | } 93 | } 94 | #else 95 | // loadingfrom file 96 | const char* input = "../../../../resources/imageas/envmap.exr"; 97 | const char* err; 98 | 99 | EXRImage exrImage; 100 | InitEXRImage(&exrImage); 101 | 102 | int ret = ParseMultiChannelEXRHeaderFromFile(&exrImage, input, &err); 103 | if(ret != 0) 104 | { 105 | fprintf(stderr, "Parse EXR err: %s\n", err); 106 | return; 107 | } 108 | 109 | //// Uncomment if you want reading HALF image as FLOAT. 110 | //for (int i = 0; i < exrImage.num_channels; i++) { 111 | // if (exrImage.pixel_types[i] = TINYEXR_PIXELTYPE_HALF) { 112 | // exrImage.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; 113 | // } 114 | //} 115 | 116 | ret = LoadMultiChannelEXRFromFile(&exrImage, input, &err); 117 | if(ret != 0) 118 | { 119 | fprintf(stderr, "Load EXR err: %s\n", err); 120 | return; 121 | } 122 | #endif 123 | 124 | // Saving exr file 125 | 126 | 127 | getchar(); 128 | return 0; 129 | } -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/LinearList/t3Queue.h: -------------------------------------------------------------------------------- 1 | #ifndef T3_QUEUE_H 2 | #define T3_QUEUE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | class t3Queue 10 | { 11 | public: 12 | t3Queue(); 13 | 14 | ~t3Queue(); 15 | 16 | // 放入给定值的拷贝 17 | void push(T &value); 18 | 19 | bool isEmpty(); 20 | 21 | bool isFull(); 22 | 23 | // 获取栈顶元素值 24 | T get(); 25 | 26 | // 弹出队列头部元素并返回 27 | T pop(); 28 | 29 | void print(); 30 | 31 | private: 32 | // 尽量不要扩建,效率很低 33 | void enlarge(); 34 | 35 | // 队列头 36 | T *head; 37 | 38 | // 首尾指针 front指向队列头部元素的前一个元素 rear指向队尾位置 39 | int front, rear; 40 | 41 | // C/C++无法记住申请的指针指向的内存长度大小 42 | int length; 43 | }; 44 | 45 | template 46 | t3Queue::t3Queue():head(NULL), front(0), rear(0) 47 | { 48 | enlarge(); 49 | } 50 | 51 | template 52 | t3Queue::~t3Queue() 53 | { 54 | delete head; 55 | head = NULL; 56 | } 57 | 58 | // 放入给定值的拷贝 59 | template 60 | void t3Queue::push(T &value) 61 | { 62 | if(isFull()) 63 | enlarge(); 64 | 65 | rear = (rear + 1) % length; 66 | head[rear] = value; 67 | } 68 | 69 | // 获取栈顶元素值 70 | template 71 | T t3Queue::get() 72 | { 73 | if(isEmpty()) 74 | { 75 | t3PrintError("队列为空,无法获取元素"); 76 | return NULL; 77 | } 78 | else 79 | return head[front]; 80 | } 81 | 82 | // 弹出队列头部元素并返回 83 | template 84 | T t3Queue::pop() 85 | { 86 | if(isEmpty()) 87 | { 88 | t3PrintError("队列为空,无法获取元素"); 89 | return NULL; 90 | } 91 | else 92 | { 93 | front = (front + 1) % length; 94 | return head[front]; 95 | } 96 | } 97 | 98 | template 99 | void t3Queue::enlarge() 100 | { 101 | if(head) 102 | { 103 | t3Log("t3Queue: enlarge!"); 104 | 105 | int orignalLength = length; 106 | // 扩增两倍 107 | length = 2 * orignalLength; 108 | 109 | T *temp = new T[length](); 110 | 111 | // 因为为循环队列的缘故 这里不能直接内存复制 不然中间会有隔断 112 | //memcpy(temp, head, sizeof(T) * length); 113 | for(int i = (front + 1) % orignalLength, j = 1; j<=orignalLength-1; i = (i + 1) % orignalLength, j++) 114 | { 115 | temp[j] = head[i]; 116 | } 117 | 118 | // 销毁原数据内容 119 | delete head; 120 | head = temp; 121 | 122 | front = 0; 123 | rear = orignalLength-1; 124 | } 125 | else 126 | { 127 | // 初始化 128 | head = new T[T3_QUEUE_DEFAULT_LENGTH](); 129 | 130 | length = T3_QUEUE_DEFAULT_LENGTH; 131 | // 栈顶 132 | front = rear = 0; 133 | } 134 | } 135 | 136 | template 137 | bool t3Queue::isEmpty() 138 | { 139 | if(front == rear) 140 | return true; 141 | else 142 | return false; 143 | } 144 | 145 | template 146 | bool t3Queue::isFull() 147 | { 148 | // 规定环形队列最多容纳length-1个元素 149 | if(((rear + 1) % length) == front) 150 | return true; 151 | else 152 | return false; 153 | } 154 | 155 | template 156 | void t3Queue::print() 157 | { 158 | t3Log("------------------------------------------\n"); 159 | // for(int i = (front + 1) % length; i<=rear; i = (i + 1) % length) 160 | // { 161 | // std::cout << "t3Queue[" << i << "]: " << head[i] << std::endl; 162 | // } 163 | for(int i = 0; i 4 | #include 5 | 6 | t3StringADT::t3StringADT() 7 | { 8 | lengthString = 0; 9 | lengthPattern = 0; 10 | string = NULL; 11 | pattern = NULL; 12 | } 13 | 14 | t3StringADT::t3StringADT(char* c) 15 | { 16 | create(c); 17 | 18 | lengthPattern = 0; 19 | pattern = NULL; 20 | } 21 | 22 | void t3StringADT::create(char *c) 23 | { 24 | if(!c) 25 | { 26 | t3PrintError("代匹配String字符串不能为空"); 27 | lengthString = 0; 28 | lengthPattern = 0; 29 | string = NULL; 30 | pattern = NULL; 31 | 32 | return; 33 | } 34 | 35 | // 已构造 需重定向内存 36 | if(string != NULL) 37 | { 38 | delete string; 39 | lengthString = 0; 40 | string = NULL; 41 | } 42 | 43 | lengthString = strlen(c); 44 | 45 | string = new char[lengthString](); 46 | strcpy(string, c); 47 | 48 | t3Log("t3StringADT: lengthString:%d, string:%s\n", lengthString, string); 49 | } 50 | 51 | void t3StringADT::setPattern(char* p) 52 | { 53 | if(!p) 54 | { 55 | t3PrintError("代匹配Pattern字符串不能为空"); 56 | return; 57 | } 58 | 59 | // 已构造 需重定向内存 60 | if(pattern != NULL) 61 | { 62 | delete pattern; 63 | lengthPattern = 0; 64 | pattern = NULL; 65 | } 66 | 67 | lengthPattern = strlen(p); 68 | 69 | pattern = new char[lengthPattern](); 70 | strcpy(pattern, p); 71 | 72 | t3Log("t3StringADT: lengthPattern:%d, pattern:%s\n", lengthPattern, pattern); 73 | 74 | // 失配数组分配内存 75 | if(next != NULL) 76 | { 77 | delete next; 78 | next = NULL; 79 | } 80 | 81 | next = new int[lengthPattern](); 82 | //t3Log("%d", sizeof(next)); 83 | // 84 | // memset(next, -1, sizeof(next)); 85 | // for(int i=0; i 0) 93 | { 94 | t3PrintError("Pattern字符串不能为空,请先setPattern()指定模式字符串"); 95 | return -1; 96 | } 97 | 98 | int i = 0, j = 0; 99 | // pattern/string末尾下标 100 | int lastPattern = lengthPattern-1, lastString = lengthString-1; 101 | // 当前循环代匹配字符下标 / 距离end长度为lengthPattern的起始下标 102 | int endMatch = lastPattern, startMatch = 0; 103 | 104 | for(; endMatch < lastString; endMatch++, startMatch++) 105 | { 106 | // 末位匹配 107 | if(string[endMatch] == pattern[lastPattern]) 108 | // core 109 | for(j = 0, i = startMatch; j 0) 121 | { 122 | t3PrintError("Pattern字符串不能为空,请先setPattern()指定模式字符串"); 123 | return -1; 124 | } 125 | 126 | // next数组初始化求值 127 | next[0] = -1; 128 | for(int j = 1, i = 0; j= 0) 135 | // 无法递推 相当于自身与自身KMP匹配 回溯到上一可能位置 136 | i = next[i]; 137 | 138 | if(pattern[j] == pattern[i+1]) 139 | // 从上一结果直接递推 140 | next[j] = i+1; 141 | else 142 | next[j] = -1; 143 | } 144 | 145 | // 实际匹配 146 | int i = 0, j = 0; 147 | while(i 2 | #include 3 | #include 4 | 5 | // --!Copyied From [PBRT grometry.h] 6 | a3AABB::a3AABB() : min(A3_INFINITY), max(-A3_INFINITY) 7 | { 8 | 9 | } 10 | 11 | a3AABB::a3AABB(const t3Vector3f& p):min(p), max(p) 12 | { 13 | 14 | } 15 | 16 | a3AABB::a3AABB(const t3Vector3f& p0, const t3Vector3f& p1):min(p0), max(p1) 17 | { 18 | 19 | } 20 | 21 | void a3AABB::set(const t3Vector3f& p0, const t3Vector3f& p1) 22 | { 23 | min = p0; 24 | max = p1; 25 | } 26 | 27 | bool a3AABB::overlaps(const a3AABB& b) const 28 | { 29 | bool x = (max.x >= b.min.x) && (min.x <= b.max.x); 30 | bool y = (max.y >= b.min.y) && (min.y <= b.max.y); 31 | bool z = (max.z >= b.min.z) && (min.z <= b.max.z); 32 | return (x && y && z); 33 | } 34 | 35 | bool a3AABB::inside(const t3Vector3f& point) const 36 | { 37 | return (point.x >= min.x && point.x <= max.x && 38 | point.y >= min.y && point.y <= max.y && 39 | point.z >= min.z && point.z <= max.z); 40 | } 41 | 42 | void a3AABB::expand(float delta) 43 | { 44 | min -= t3Vector3f(delta, delta, delta); 45 | max += t3Vector3f(delta, delta, delta); 46 | } 47 | 48 | float a3AABB::surfaceArea() const 49 | { 50 | t3Vector3f d = max - min; 51 | return 2.f * (d.x * d.y + d.x * d.z + d.y * d.z); 52 | } 53 | 54 | float a3AABB::volume() const 55 | { 56 | t3Vector3f d = max - min; 57 | return d.x * d.y * d.z; 58 | } 59 | 60 | int a3AABB::maxExtentIndex() const 61 | { 62 | t3Vector3f diagonal = max - min; 63 | if(diagonal.x > diagonal.y && diagonal.x > diagonal.z) 64 | return 0; 65 | else if(diagonal.y > diagonal.z) 66 | return 1; 67 | else 68 | return 2; 69 | } 70 | 71 | t3Vector3f a3AABB::centroid() const 72 | { 73 | return min * 0.5f + max * 0.5f; 74 | } 75 | 76 | t3Vector3f a3AABB::interpolate(float tx, float ty, float tz) 77 | { 78 | return t3Vector3f(t3Math::interpolate(min.x, max.x, tx), 79 | t3Math::interpolate(min.y, max.y, ty), 80 | t3Math::interpolate(min.z, max.z, tz)); 81 | } 82 | 83 | void a3AABB::boundingSphere(t3Vector3f* center, float* radius) const 84 | { 85 | *center = .5f * min + .5f * max; 86 | *radius = inside(*center) ? (*center - max).length() : 0.f; 87 | } 88 | 89 | bool a3AABB::intersect(const a3Ray& ray, float *hitt0, float *hitt1) const 90 | { 91 | float t0 = ray.minT, t1 = ray.maxT; 92 | for(int i = 0; i < 3; ++i) 93 | { 94 | // Update interval for _i_th bounding box slab 95 | float invRayDir = 1.f / ray.direction[i]; 96 | float tNear = (min[i] - ray.origin[i]) * invRayDir; 97 | float tFar = (max[i] - ray.origin[i]) * invRayDir; 98 | 99 | // Update parametric interval from slab intersection $t$s 100 | if(tNear > tFar) t3Math::swap(tNear, tFar); 101 | 102 | t0 = tNear > t0 ? tNear : t0; 103 | t1 = tFar < t1 ? tFar : t1; 104 | if(t0 > t1) return false; 105 | } 106 | if(hitt0) *hitt0 = t0; 107 | if(hitt1) *hitt1 = t1; 108 | return true; 109 | } 110 | 111 | a3AABB a3AABB::calUnion(const a3AABB& b, const t3Vector3f& p) 112 | { 113 | a3AABB ret = b; 114 | ret.min.x = t3Math::Min(b.min.x, p.x); 115 | ret.min.y = t3Math::Min(b.min.y, p.y); 116 | ret.min.z = t3Math::Min(b.min.z, p.z); 117 | ret.max.x = t3Math::Max(b.max.x, p.x); 118 | ret.max.y = t3Math::Max(b.max.y, p.y); 119 | ret.max.z = t3Math::Max(b.max.z, p.z); 120 | return ret; 121 | } 122 | 123 | a3AABB a3AABB::calUnion(const a3AABB& b, const a3AABB& b2) 124 | { 125 | a3AABB ret; 126 | ret.min.x = t3Math::Min(b.min.x, b2.min.x); 127 | ret.min.y = t3Math::Min(b.min.y, b2.min.y); 128 | ret.min.z = t3Math::Min(b.min.z, b2.min.z); 129 | ret.max.x = t3Math::Max(b.max.x, b2.max.x); 130 | ret.max.y = t3Math::Max(b.max.y, b2.max.y); 131 | ret.max.z = t3Math::Max(b.max.z, b2.max.z); 132 | return ret; 133 | } 134 | 135 | void a3AABB::print() 136 | { 137 | #ifdef _DEBUG 138 | min.print(); 139 | max.print(); 140 | #endif 141 | } 142 | 143 | void a3AABB::print(std::string name) 144 | { 145 | #ifdef _DEBUG 146 | min.print(name + ".min"); 147 | max.print(name + ".max"); 148 | #endif 149 | } 150 | -------------------------------------------------------------------------------- /Atmos/core/a3Record.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class a3Shape; 9 | class a3BSDF; 10 | class a3Light; 11 | 12 | // -------------------------BSDF------------------------- 13 | // Container for all information related to a surface intersection 14 | class a3IntersectRecord 15 | { 16 | public: 17 | a3IntersectRecord(): shape(NULL), t(FLT_MAX), u(0), v(0), vtu(0), vtv(0), vtw(0) {} 18 | 19 | // returns radiance emitted into direction d 20 | a3Spectrum Le(const t3Vector3f& d) const; 21 | 22 | // ray's t is valid or not 23 | bool isValid() const; 24 | 25 | // Is the intersected shape also a emitter? 26 | bool isLight() const; 27 | 28 | // get the light ptr from the shape(if exsited) 29 | a3Light* getLight() const; 30 | 31 | // get the normal vector on hit point 32 | t3Vector3f getNormal() const; 33 | 34 | // get the hit shape's bsdf 35 | const a3BSDF* getBSDF() const; 36 | 37 | // convert the local vector to world 38 | t3Vector3f toWorld(const t3Vector3f& localCoord); 39 | 40 | // convert the world vector to local 41 | t3Vector3f toLocal(const t3Vector3f& worldCoord); 42 | 43 | // world local convertion matrix 44 | t3Matrix4x4 localToWorld, worldToLocal; 45 | 46 | /// Distance traveled along the ray 47 | float t; 48 | 49 | /// Intersection point's uv coordinate 50 | float u, v; 51 | 52 | /// Intersection point's uvw texture coordinate 53 | float vtu, vtv, vtw; 54 | 55 | /// Pointer to the associated shape 56 | a3Shape *shape; 57 | 58 | /// Intersection point in 3D coordinates 59 | t3Vector3f p; 60 | }; 61 | 62 | // Generic sampling record for shapes 63 | class a3ShapeSamplingRecord 64 | { 65 | public: 66 | a3ShapeSamplingRecord() : pdf(0.0f){} 67 | 68 | /// Sampled position 69 | t3Vector3f p; 70 | 71 | /// Sampled surface normal 72 | t3Vector3f normal; 73 | 74 | /// Probability density at the sample 75 | float pdf; 76 | }; 77 | 78 | // All information that is required to sample or query a BSDF 79 | class a3BSDFSamplingRecord 80 | { 81 | public: 82 | // parameter not required in constructor would be updated when BSDF Sampling 83 | a3BSDFSamplingRecord(const a3IntersectRecord &its, const t3Vector3f& wi) 84 | :its(its), wi(wi) {} 85 | 86 | a3BSDFSamplingRecord(const a3IntersectRecord &its, const t3Vector3f& wi, const t3Vector3f& wo) 87 | :its(its), wi(wi), wo(wo) {} 88 | 89 | // Reference to the underlying surface interaction 90 | const a3IntersectRecord &its; 91 | 92 | // Normalized incident direction in local coordinates 93 | t3Vector3f wi; 94 | 95 | // Normalized outgoing direction in local coordinates 96 | t3Vector3f wo; 97 | 98 | // Relative index of refraction in the sampled direction 99 | float eta; 100 | 101 | /// Probability density at the sample 102 | float pdf; 103 | }; 104 | 105 | // -------------------------Light------------------------- 106 | // Record for solid-angle based area sampling techniques 107 | class a3LightSamplingRecord 108 | { 109 | public: 110 | // parameter not required in constructor would be updated when Light Sampling 111 | a3LightSamplingRecord(const t3Vector3f& hitPoint, const t3Vector3f& hitNormal) 112 | :hitPoint(hitPoint), hitNormal(hitNormal), distance(0.0f), pdf(0.0f), light(NULL){} 113 | 114 | void set(const t3Vector3f& hitPoint, const t3Vector3f& hitNormal); 115 | 116 | // Reference point for direct sampling 117 | t3Vector3f hitPoint; 118 | 119 | // normal vector associated with the reference point 120 | t3Vector3f hitNormal; 121 | 122 | /// the light be sampled 123 | a3Light* light; 124 | 125 | /// Sampled position 126 | t3Vector3f p; 127 | 128 | /// Distance from the reference point to the target direction 129 | float distance; 130 | 131 | /// Unit direction from the reference point to the target direction 132 | t3Vector3f d; 133 | 134 | /// Probability density at the sample 135 | float pdf; 136 | 137 | /// Sampled surface normal 138 | t3Vector3f normal; 139 | 140 | // 2D sample position associated with the record 141 | //t3Vector2f uv; 142 | }; -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/Common/t3Timer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | //#include 3 | 4 | // --!参考于http://nadeausoftware.com/articles/2012/04/c_c_tip_how_measure_elapsed_real_time_benchmarking 5 | #if defined(_WIN32) 6 | #include 7 | 8 | #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) 9 | #include /* POSIX flags */ 10 | #include /* clock_gettime(), time() */ 11 | #include /* gethrtime(), gettimeofday() */ 12 | 13 | #if defined(__MACH__) && defined(__APPLE__) 14 | #include 15 | #include 16 | #endif 17 | 18 | #else 19 | #error "Unable to define getRealTime( ) for an unknown OS." 20 | #endif 21 | 22 | /** 23 | * Returns the real time, in seconds, or -1.0 if an error occurred. 24 | * 25 | * Time is measured since an arbitrary and OS-dependent start time. 26 | * The returned real time is only useful for computing an elapsed time 27 | * between two calls to this function. 28 | */ 29 | double t3GetRealTime( ) 30 | { 31 | #if defined(_WIN32) 32 | FILETIME tm; 33 | ULONGLONG t; 34 | #if defined(NTDDI_WIN8) && NTDDI_VERSION >= NTDDI_WIN8 35 | /* Windows 8, Windows Server 2012 and later. ---------------- */ 36 | GetSystemTimeAsFileTime(&tm); 37 | //GetSystemTimePreciseAsFileTime( &tm ); 38 | #else 39 | /* Windows 2000 and later. ---------------------------------- */ 40 | GetSystemTimeAsFileTime( &tm ); 41 | #endif 42 | t = ((ULONGLONG)tm.dwHighDateTime << 32) | (ULONGLONG)tm.dwLowDateTime; 43 | return (double)t / 10000000.0; 44 | 45 | #elif (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__))) 46 | /* HP-UX, Solaris. ------------------------------------------ */ 47 | return (double)gethrtime( ) / 1000000000.0; 48 | 49 | #elif defined(__MACH__) && defined(__APPLE__) 50 | /* OSX. ----------------------------------------------------- */ 51 | static double timeConvert = 0.0; 52 | if ( timeConvert == 0.0 ) 53 | { 54 | mach_timebase_info_data_t timeBase; 55 | (void)mach_timebase_info( &timeBase ); 56 | timeConvert = (double)timeBase.numer / 57 | (double)timeBase.denom / 1000000000.0; 58 | } 59 | return (double)mach_absolute_time( ) * timeConvert; 60 | 61 | #elif defined(_POSIX_VERSION) 62 | /* POSIX. --------------------------------------------------- */ 63 | #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) 64 | { 65 | struct timespec ts; 66 | #if defined(CLOCK_MONOTONIC_PRECISE) 67 | /* BSD. --------------------------------------------- */ 68 | const clockid_t id = CLOCK_MONOTONIC_PRECISE; 69 | #elif defined(CLOCK_MONOTONIC_RAW) 70 | /* Linux. ------------------------------------------- */ 71 | const clockid_t id = CLOCK_MONOTONIC_RAW; 72 | #elif defined(CLOCK_HIGHRES) 73 | /* Solaris. ----------------------------------------- */ 74 | const clockid_t id = CLOCK_HIGHRES; 75 | #elif defined(CLOCK_MONOTONIC) 76 | /* AIX, BSD, Linux, POSIX, Solaris. ----------------- */ 77 | const clockid_t id = CLOCK_MONOTONIC; 78 | #elif defined(CLOCK_REALTIME) 79 | /* AIX, BSD, HP-UX, Linux, POSIX. ------------------- */ 80 | const clockid_t id = CLOCK_REALTIME; 81 | #else 82 | const clockid_t id = (clockid_t)-1; /* Unknown. */ 83 | #endif /* CLOCK_* */ 84 | if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 ) 85 | return (double)ts.tv_sec + 86 | (double)ts.tv_nsec / 1000000000.0; 87 | /* Fall thru. */ 88 | } 89 | #endif /* _POSIX_TIMERS */ 90 | 91 | /* AIX, BSD, Cygwin, HP-UX, Linux, OSX, POSIX, Solaris. ----- */ 92 | struct timeval tm; 93 | gettimeofday( &tm, NULL ); 94 | return (double)tm.tv_sec + (double)tm.tv_usec / 1000000.0; 95 | #else 96 | return -1.0; /* Failed. */ 97 | #endif 98 | } 99 | 100 | // 开始计时 101 | double t3Timer::start() 102 | { 103 | startTime = t3GetRealTime(); 104 | 105 | return startTime; 106 | } 107 | 108 | // 结束计时 109 | double t3Timer::end() 110 | { 111 | endTime = t3GetRealTime(); 112 | 113 | return endTime; 114 | } 115 | 116 | double t3Timer::difference() 117 | { 118 | return endTime - startTime; 119 | } 120 | 121 | -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/SparseMatrix/t3SparseMatrixADT.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // 创建一个最大能容纳maxRow x maxCol 非零元素个数count的稀疏矩阵 本质上是一维矩阵 5 | void t3SparseMatrixADT::create(int maxRow, int maxCol, int itemCount) 6 | { 7 | if(itemCount < 0) 8 | { 9 | t3PrintErrorArg("itemCount", itemCount, "非零元素个数不能小于0"); 10 | 11 | count = 0; 12 | 13 | return; 14 | } 15 | 16 | // 额外一行用于存放头结点 17 | m = new term[itemCount+1](); 18 | 19 | // 头结点保存矩阵信息 20 | m[0].row = maxRow; 21 | m[0].col = maxCol; 22 | m[0].value = itemCount; 23 | 24 | count = 1; 25 | } 26 | 27 | t3SparseMatrixADT* t3SparseMatrixADT::transpose() 28 | { 29 | if(m == NULL) 30 | { 31 | t3PrintError("矩阵未经过初始化 或 初始哈失败"); 32 | return NULL; 33 | } 34 | 35 | t3SparseMatrixADT *t = new t3SparseMatrixADT(); 36 | t->create(m[0].col, m[0].row, m[0].value); 37 | 38 | int num = m[0].value; 39 | if(num > 0) 40 | { 41 | // 遍历所有可能的列 42 | for(int i=0; iadd(m[j].col, m[j].row, m[j].value); 49 | } 50 | } 51 | } 52 | 53 | return t; 54 | } 55 | 56 | t3SparseMatrixADT* t3SparseMatrixADT::transposeFast() 57 | { 58 | if(m == NULL) 59 | { 60 | t3PrintError("矩阵未经过初始化 或 初始哈失败"); 61 | return NULL; 62 | } 63 | 64 | int num = m[0].value, numCol = m[0].col; 65 | 66 | // 每一列上元素个数 / 转置矩阵可被赋值的起始位置 67 | int *rowTerms = new int[numCol], *startingPos = new int[numCol]; 68 | 69 | t3SparseMatrixADT *t = NULL; 70 | 71 | if(num > 0) 72 | { 73 | t = new t3SparseMatrixADT(); 74 | t->create(numCol, m[0].row, m[0].value); 75 | 76 | // 初始化并计算每列上元素个数 77 | for(int i=0; im[j].col = m[i].row; 98 | t->m[j].row = m[i].col; 99 | t->m[j].value = m[i].value; 100 | 101 | // printf("j=%d\n", j); 102 | // printf("%d %d %d", m[i].row, m[i].col, m[i].value); 103 | // printf("\n"); 104 | // t->count++; 105 | 106 | // t->print(); 107 | } 108 | } 109 | 110 | return t; 111 | } 112 | 113 | void t3SparseMatrixADT::add(int row, int col, int value) 114 | { 115 | if(m == NULL || row > m[0].row || col > m[0].col || count >= m[0].row * m[0].col + 1) 116 | { 117 | t3PrintError("矩阵长度溢出 或 指定行列数有误 或 初始化失败"); 118 | return; 119 | } 120 | 121 | m[count].row = row; 122 | m[count].col = col; 123 | m[count].value = value; 124 | 125 | count++; 126 | } 127 | 128 | // 在矩阵中添加一项的拷贝 129 | void t3SparseMatrixADT::add(term& t) 130 | { 131 | if(m == NULL || t.row > m[0].row || t.col > m[0].col || count >= m[0].row * m[0].col + 1) 132 | { 133 | t3PrintError("矩阵长度溢出 或 指定行列数有误 或 初始化失败"); 134 | return; 135 | } 136 | 137 | m[count].row = t.row; 138 | m[count].col = t.col; 139 | m[count].value = t.value; 140 | 141 | count++; 142 | } 143 | 144 | void t3SparseMatrixADT::print() 145 | { 146 | t3Log("------------------------------------------\n"); 147 | t3Log(" 行 列 值\n"); 148 | 149 | for(int i=0; i 2 | #include 3 | #include 4 | #include 5 | //#include 6 | #include 7 | 8 | //template 9 | //t3BinaryTree::t3BinaryTree() 10 | //{ 11 | // 12 | //} 13 | // 14 | //template 15 | //bool t3BinaryTree::create(int preorder[], int inorder[], int length) 16 | //{ 17 | // if(!preorder || !inorder) 18 | // { 19 | // t3PrintError("前序/中序序列不能为空"); 20 | // return false; 21 | // } 22 | // 23 | // //int length = sizeof(preorder) / sizeof(preorder[0]); 24 | // for(int i=0; i 36 | //// offset为当前子树在先序序列中的起始序号 37 | //T* t3BinaryTree::buildInorderPreorder(int preorder[], int length, int offset, bool bRoot) 38 | //{ 39 | // if(length == 0) 40 | // return NULL; 41 | // int rootValue = preorder[0]; 42 | // // 当前子树根节点相对序号 43 | // int i = mapIndex[rootValue] - offset; 44 | // 45 | // t3TreeNode* root = new t3TreeNode(rootValue); 46 | // root->leftChild = buildInorderPreorder(preorder+1, i, offset, false); 47 | // root->rightChild = buildInorderPreorder(preorder+i+1, length - i - 1, offset + i + 1, false); 48 | // 49 | // // 是否为根 50 | // if(bRoot) 51 | // tree = root; 52 | // 53 | // return root; 54 | //} 55 | // 56 | //template 57 | //void t3BinaryTree::preorder() 58 | //{ 59 | // preorder(tree); 60 | //} 61 | // 62 | //template 63 | //void t3BinaryTree::inorder() 64 | //{ 65 | // inorder(tree); 66 | //} 67 | // 68 | //template 69 | //void t3BinaryTree::postorder() 70 | //{ 71 | // postorder(tree); 72 | //} 73 | // 74 | //template 75 | //void t3BinaryTree::levelorder() 76 | //{ 77 | // t3Stack stack; 78 | // 79 | // if(!tree) 80 | // return; 81 | // 82 | // stack.push(tree); 83 | // while(true) 84 | // { 85 | // if(stack.isEmpty()) 86 | // break; 87 | // 88 | // t3TreeNode *node = stack.pop(); 89 | // t3Log("% d ", node->data); 90 | // if(node->leftChild) 91 | // stack.push(node->leftChild); 92 | // if(node->rightChild) 93 | // stack.push(node->rightChild); 94 | // } 95 | //} 96 | // 97 | //template 98 | //t3BinaryTree* t3BinaryTree::copy() 99 | //{ 100 | // t3BinaryTree* temp = new t3BinaryTree(); 101 | // temp->tree = copy(tree); 102 | // return temp; 103 | //} 104 | // 105 | //// 指定树拷贝 106 | //template 107 | //T* t3BinaryTree::copy(T *root) 108 | //{ 109 | // if(!root) 110 | // return NULL; 111 | // 112 | // T *temp = new T(); 113 | // 114 | // temp->data = root->data; 115 | // temp->leftChild = copy(root->leftChild); 116 | // temp->rightChild = copy(root->rightChild); 117 | // 118 | // return temp; 119 | //} 120 | // 121 | //// 等价性 122 | //template 123 | //bool t3BinaryTree::equal(t3BinaryTree *root) 124 | //{ 125 | // return equal(tree, root->tree); 126 | //} 127 | // 128 | //template 129 | //bool t3BinaryTree::equal(T *first, T *second) 130 | //{ 131 | // // 两者皆空 / 非空那么数据域要相同 / 递归左右子树 132 | // return ((!first && !second) || (first && second && first->data == second->data) || 133 | // equal(first->leftChild, second->leftChild) || 134 | // equal(first->rightChild, second->rightChild)); 135 | //} 136 | // 137 | //template 138 | //T* t3BinaryTree::preorder(T* root) 139 | //{ 140 | // if(!root) 141 | // return NULL; 142 | // 143 | // t3Log(" %d ", root->data); 144 | // preorder(root->leftChild); 145 | // preorder(root->rightChild); 146 | // 147 | // return root; 148 | //} 149 | // 150 | //template 151 | //T* t3BinaryTree::inorder(T* root) 152 | //{ 153 | // if(!root) 154 | // return NULL; 155 | // 156 | // inorder(root->leftChild); 157 | // t3Log(" %d ", root->data); 158 | // inorder(root->rightChild); 159 | // 160 | // return root; 161 | //} 162 | // 163 | //template 164 | //T* t3BinaryTree::postorder(T* root) 165 | //{ 166 | // if(!root) 167 | // return NULL; 168 | // 169 | // postorder(root->leftChild); 170 | // postorder(root->rightChild); 171 | // t3Log(" %d ", root->data); 172 | // 173 | // return root; 174 | //} -------------------------------------------------------------------------------- /dependency/t3DataStructures/include/LinearList/t3Expression.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // 左括号始终栈外优先级最高始终进栈 在栈内时始终允许其他符号进栈 4 | // 栈内优先级 5 | static int isp[] = {0, 19, 12, 12, 13, 13, 13, 0}; 6 | // 栈外优先级 7 | static int icp[] = {20, 19, 12, 12, 13, 13, 13, 0}; 8 | 9 | t3Expression::t3Expression() 10 | { 11 | exp = ""; 12 | } 13 | 14 | // 给出中缀表达式 15 | void t3Expression::create(std::string s) 16 | { 17 | exp = s; 18 | } 19 | 20 | void t3Expression::toPostfix() 21 | { 22 | std::string temp; 23 | int n = 0; 24 | t3Precedence token = getToken(n); 25 | while(token != eos) 26 | { 27 | if(token == operand) 28 | temp += getChar(n); 29 | else if(token == rparen) 30 | { 31 | // 直到遇到左括号 32 | while (!postfixStack.isEmpty() && postfixStack.get() != lparen) 33 | temp += getSymbol(postfixStack.pop()); 34 | 35 | // 弹出左括号 36 | postfixStack.pop(); 37 | } 38 | else 39 | { 40 | // 若栈顶优先级高于栈外符号引入优先级 出栈 41 | while(!postfixStack.isEmpty() && isp[postfixStack.get()] >= icp[token]) 42 | temp += getSymbol(postfixStack.pop()); 43 | 44 | postfixStack.push(token); 45 | } 46 | 47 | token = getToken(++n); 48 | } 49 | 50 | // 弹出剩余标记符 51 | while(!postfixStack.isEmpty() && (token = postfixStack.pop()) != eos) 52 | temp += getSymbol(postfixStack.pop()); 53 | temp += " "; 54 | 55 | exp = temp; 56 | std::cout << "Infix to Postfix: " << exp << std::endl; 57 | } 58 | 59 | int t3Expression::evaluate() 60 | { 61 | if(exp == "") 62 | return NULL; 63 | 64 | int n = 0, op1 = 0, op2 = 0; 65 | t3Precedence token = getToken(n); 66 | while(token != eos) 67 | { 68 | // 操作数 69 | if(token == operand) 70 | { 71 | int temp = getChar(n) - '0'; 72 | valueStack.push(temp); 73 | } 74 | // 符号 75 | else 76 | { 77 | // 栈中必有两个以上操作数 78 | op2 = valueStack.pop(); 79 | op1 = valueStack.pop(); 80 | 81 | int result = 0; 82 | switch (token) { 83 | case plus: 84 | result = op1+op2; 85 | break; 86 | case minus: 87 | result = op1-op2; 88 | break; 89 | case times: 90 | result = op1*op2; 91 | break; 92 | case divide: 93 | result = op1/op2; 94 | break; 95 | case mod: 96 | result = op1%op2; 97 | break; 98 | } 99 | valueStack.push(result); 100 | } 101 | //t3Log("%d", n); 102 | token = getToken(++n); 103 | } 104 | 105 | return valueStack.pop(); 106 | } 107 | 108 | t3Precedence t3Expression::getToken(int n) 109 | { 110 | const char symbol = getChar(n); 111 | switch (symbol) { 112 | case '(': 113 | return lparen; 114 | case ')': 115 | return rparen; 116 | case '+': 117 | return plus; 118 | case '-': 119 | return minus; 120 | case '/': 121 | return divide; 122 | case '*': 123 | return times; 124 | case '%': 125 | return mod; 126 | case ' ': 127 | return eos; 128 | default: 129 | return operand; 130 | } 131 | } 132 | 133 | const char t3Expression::getChar(int n) 134 | { 135 | return *exp.substr(n, 1).c_str(); 136 | } 137 | 138 | const char t3Expression::getSymbol(t3Precedence p) 139 | { 140 | switch (p) { 141 | case plus: 142 | return '+'; 143 | case minus: 144 | return '-'; 145 | case times: 146 | return '*'; 147 | case divide: 148 | return '/'; 149 | case mod: 150 | return '%'; 151 | default: 152 | return NULL; 153 | } 154 | } 155 | 156 | void t3Expression::printToken(t3Precedence p) 157 | { 158 | switch (p) { 159 | case plus: 160 | t3Log("+"); 161 | break; 162 | case minus: 163 | t3Log("-"); 164 | break; 165 | case times: 166 | t3Log("*"); 167 | break; 168 | case divide: 169 | t3Log("/"); 170 | break; 171 | case mod: 172 | t3Log("%"); 173 | break; 174 | default: 175 | break; 176 | } 177 | } -------------------------------------------------------------------------------- /Atmos/sensors/a3PerspectiveSensor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | void checkImage(a3Film* image) 12 | { 13 | if(image) 14 | a3Log::debug("Generating rendered image, width:%d, height:%d\n", image->width, image->height); 15 | } 16 | 17 | a3PerspectiveSensor::a3PerspectiveSensor(const t3Vector3f& origin, const t3Vector3f& lookat, const t3Vector3f& up, 18 | float focalLength, float apretureWidth, float apretureHeight, float canvasDistance, 19 | float focalDistance, float lensRadius, 20 | a3Film* image) 21 | : a3Sensor(origin, lookat, up, 22 | focalLength, apretureWidth, apretureHeight, canvasDistance, 23 | focalDistance, lensRadius, 24 | image) 25 | { 26 | //random = new a3Random(); 27 | 28 | checkImage(image); 29 | } 30 | 31 | a3PerspectiveSensor::a3PerspectiveSensor(const t3Vector3f& origin, const t3Vector3f& lookat, const t3Vector3f& up, 32 | float fovX, float fovY, 33 | float focalDistance, float lensRadius, 34 | a3Film* image) 35 | : a3Sensor(origin, lookat, up, 36 | 1.0f, a3FovToApretureSizeDeg(fovX), a3FovToApretureSizeDeg(fovY), 1.0f, 37 | focalDistance, lensRadius, image) 38 | { 39 | //random = new a3Random(); 40 | 41 | checkImage(image); 42 | } 43 | 44 | a3PerspectiveSensor::a3PerspectiveSensor(const t3Vector3f& origin, const t3Vector3f& lookat, const t3Vector3f& up, 45 | float fov, 46 | float focalDistance, float lensRadius, 47 | a3Film* image) 48 | : a3Sensor(origin, lookat, up, 49 | 1.0f, a3FovToApretureSizeDeg(fov), a3FovToApretureSizeDeg(fov) * image->width / image->height, 1.0f, 50 | focalDistance, lensRadius, image) 51 | { 52 | //random = new a3Random(); 53 | 54 | checkImage(image); 55 | } 56 | 57 | float a3PerspectiveSensor::castRay(const a3CameraSample* sample, a3Ray* ray) const 58 | { 59 | // 不做空判断 60 | t3Vector2f rasterPosition(sample->imageX, sample->imageY); 61 | 62 | t3Vector3f cameraPosition; 63 | 64 | //// 成像空间到摄像机空间(画布空间)的转换 65 | //cameraPosition.x = 2 * rasterPosition.x * canvasSize.x / image->width - canvasSize.x; 66 | 67 | //cameraPosition.y = -2 * rasterPosition.y * canvasSize.y / image->height + canvasSize.y; 68 | 69 | //cameraPosition.z = canvasDistance; 70 | 71 | // raster to screen 72 | t3Vector2f screenPosition(rasterPosition.x - image->width / 2.0f, -rasterPosition.y + image->height / 2.0f); 73 | 74 | // screen to camera 75 | cameraPosition.x = 2 * canvasSize.x * screenPosition.x / image->width; 76 | 77 | cameraPosition.y = 2 * canvasSize.y * screenPosition.y / image->height; 78 | 79 | cameraPosition.z = canvasDistance; 80 | 81 | cameraPosition.normalize(); 82 | 83 | 84 | // 凸透镜相机模型存在景深 85 | if(lensRadius > 0.0f) 86 | { 87 | // 从摄像机位置到画布上出射光线 88 | ray->set(t3Vector3f::zero(), cameraPosition); 89 | 90 | // 在Square平面[0, 1]生成随机采样点 91 | float sampleU = a3Random::randomFloat(); 92 | float sampleV = a3Random::randomFloat(); 93 | 94 | t3Vector2f lens = a3UniformSampleDisk(sampleU, sampleV); 95 | 96 | lens.x *= lensRadius; 97 | lens.y *= lensRadius; 98 | 99 | // 需要多少个单位向量 100 | float t = focalDistance / ray->direction.z; 101 | t3Vector3f focusPoint = (*ray)(t); 102 | 103 | ray->origin = cameraToWorld * t3Vector3f(lens.x, lens.y, 0.0f); 104 | 105 | // camera to world 106 | focusPoint = cameraToWorld * focusPoint; 107 | ray->direction = (focusPoint - ray->origin).getNormalized(); 108 | } 109 | else 110 | { 111 | // camera to world 112 | ray->origin = cameraToWorld * t3Vector3f::zero(); 113 | 114 | cameraPosition = cameraToWorld * cameraPosition; 115 | ray->direction = (cameraPosition - ray->origin).getNormalized(); 116 | } 117 | 118 | return 1.0f; 119 | } 120 | -------------------------------------------------------------------------------- /Atmos/integrator/a3DirectLighting.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // core 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // --!Learned from [Mitsuba](http://www.mitsuba-renderer.org/) 13 | a3DirectLighting::a3DirectLighting(int numBxdfSamples, int numLightSamples) 14 | : numBxdfSamples(numBxdfSamples), numLightSamples(numLightSamples) 15 | { 16 | int sum = numBxdfSamples + numLightSamples; 17 | 18 | weightBSDF = 1.0f / numBxdfSamples; 19 | weightLight = 1.0f / numLightSamples; 20 | fracBSDF = numBxdfSamples / (float) sum; 21 | fracLight = numLightSamples / (float) sum; 22 | } 23 | 24 | a3DirectLighting::~a3DirectLighting() 25 | { 26 | } 27 | 28 | a3Spectrum a3DirectLighting::Li(const a3Ray & ray, const a3Scene & scene) const 29 | { 30 | a3Spectrum L; 31 | a3IntersectRecord its; 32 | 33 | // perform the first ray intersection 34 | if(!scene.intersect(ray, &its)) 35 | { 36 | // add environment radiance if ray hit nothing 37 | L += scene.evalEnvironment(ray); 38 | return L; 39 | } 40 | 41 | if(its.isLight()) 42 | // possibly include emitted radiance 43 | L += scene.Le(-ray.direction, its); 44 | 45 | // Estimate Direct Lighting 46 | a3LightSamplingRecord lRec(its.p, its.getNormal()); 47 | 48 | const a3BSDF* bsdf = its.getBSDF(); 49 | if(!bsdf) return L; 50 | 51 | // ===========================================Light Sampling =========================================== 52 | // Only use direct illumination sampling when the surface's BSDF is not delta distribution 53 | if(!bsdf->isDeltaDistribution()) 54 | { 55 | for(int i = 0; i < numLightSamples; i++) 56 | { 57 | // get (L / lightPdf) in direct illumination 58 | a3Spectrum value = scene.sampleDirect(lRec); 59 | 60 | if(value != a3Spectrum::zero()) 61 | { 62 | // wi, wo always point away scattering event 63 | a3BSDFSamplingRecord bRec(its, its.toLocal(-ray.direction), its.toLocal(-lRec.d)); 64 | 65 | a3Spectrum bsdfValue = bsdf->eval(bRec); 66 | 67 | // Evaluate BSDF(wi, wo) * cos(theta_o) 68 | if(bsdfValue != a3Spectrum::zero()) 69 | { 70 | // Calculate probility of sampling that direction using BSDF sampling 71 | float bsdfPdf = bsdf->pdf(bRec); 72 | 73 | // Multiple importance sampling 74 | float weight = a3MiWeight(lRec.pdf * fracLight, bsdfPdf * fracBSDF) * weightLight; 75 | 76 | L += value * bsdfValue * weight; 77 | } 78 | } 79 | } 80 | } 81 | 82 | 83 | // ===========================================BSDF Sampling=========================================== 84 | for(int i = 0; i < numBxdfSamples; i++) 85 | { 86 | a3LightSamplingRecord lRec(its.p, its.getNormal()); 87 | 88 | // Sample BSDF * cos(theta) and request the local density, wo 89 | a3BSDFSamplingRecord bRec(its, its.toLocal(-ray.direction)); 90 | a3Spectrum bsdfValue = bsdf->sample(bRec); 91 | if(bsdfValue == a3Spectrum::zero()) 92 | continue; 93 | 94 | // convert shading coordinate to world 95 | t3Vector3f wo = its.toWorld(bRec.wo); 96 | 97 | // wo normal on the same side 98 | t3Vector3f n = its.getNormal(); 99 | if(wo.dot(its.getNormal()) <= 0) 100 | continue; 101 | 102 | // trace a ray in wo 103 | a3Ray bsdfRay(its.p, wo); 104 | 105 | // would be set by a area light or a environment light 106 | a3Spectrum value; 107 | 108 | a3IntersectRecord bsdfIts; 109 | // intersection test to find light 110 | if(scene.intersect(bsdfRay, &bsdfIts)) 111 | { 112 | // area light 113 | if(!bsdfIts.isLight()) 114 | continue; 115 | 116 | //sum++; 117 | lRec.light = bsdfIts.getLight(); 118 | value = bsdfIts.Le(-bsdfRay.direction); 119 | } 120 | else 121 | { 122 | lRec.light = scene.getEnvironmentLight(); 123 | // environment light(may not existed) 124 | value = scene.evalEnvironment(ray); 125 | } 126 | 127 | if(value == a3Spectrum::zero()) 128 | continue; 129 | 130 | // Compute probility of generating that direction using light sampling 131 | float lightPdf = scene.pdfLightDirect(lRec); 132 | 133 | // Multiple importance sampling 134 | float weight = a3MiWeight(bRec.pdf * fracBSDF, lightPdf * fracLight) * weightBSDF; 135 | 136 | L += value * bsdfValue * weight; 137 | } 138 | 139 | return L; 140 | } 141 | --------------------------------------------------------------------------------