joonsrenderer 1.1-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +53 -0
- data/.mvn/extensions.xml +8 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +6 -0
- data/LICENSE +674 -0
- data/README.md +2 -0
- data/Rakefile +43 -0
- data/docs/.gitignore +6 -0
- data/docs/_config.yml +20 -0
- data/docs/_includes/footer.html +38 -0
- data/docs/_includes/head.html +15 -0
- data/docs/_includes/header.html +27 -0
- data/docs/_includes/icon-github.html +1 -0
- data/docs/_includes/icon-github.svg +1 -0
- data/docs/_includes/icon-twitter.html +1 -0
- data/docs/_includes/icon-twitter.svg +1 -0
- data/docs/_layouts/default.html +20 -0
- data/docs/_layouts/page.html +14 -0
- data/docs/_layouts/post.html +15 -0
- data/docs/_posts/2017-01-08-animated_ray_tracing.md +72 -0
- data/docs/_posts/2017-01-08-welcome.md +78 -0
- data/docs/_sass/_base.scss +206 -0
- data/docs/_sass/_layout.scss +242 -0
- data/docs/_sass/_syntax-highlighting.scss +71 -0
- data/docs/about.md +12 -0
- data/docs/assets/Animation.ogv +0 -0
- data/docs/assets/Animation.png +0 -0
- data/docs/assets/basic.png +0 -0
- data/docs/assets/basic_traced.png +0 -0
- data/docs/css/main.scss +38 -0
- data/docs/favicon.ico +0 -0
- data/docs/feed.xml +30 -0
- data/docs/index.html +38 -0
- data/joonsrenderer.gemspec +23 -0
- data/lib/joonsrenderer.rb +12 -0
- data/lib/joonsrenderer/version.rb +3 -0
- data/pom.rb +75 -0
- data/pom.xml +163 -0
- data/src/main/java/SunflowGUI.java +1354 -0
- data/src/main/java/joons/JRFiller.java +79 -0
- data/src/main/java/joons/JRImagePanel.java +141 -0
- data/src/main/java/joons/JRRecorder.java +183 -0
- data/src/main/java/joons/JRStatics.java +199 -0
- data/src/main/java/joons/JoonsRenderer.java +837 -0
- data/src/main/java/org/sunflow/AsciiFileSunflowAPI.java +98 -0
- data/src/main/java/org/sunflow/Benchmark.java +313 -0
- data/src/main/java/org/sunflow/BinaryFileSunflowAPI.java +228 -0
- data/src/main/java/org/sunflow/FileSunflowAPI.java +354 -0
- data/src/main/java/org/sunflow/PluginRegistry.java +322 -0
- data/src/main/java/org/sunflow/RealtimeBenchmark.java +125 -0
- data/src/main/java/org/sunflow/RenderObjectMap.java +344 -0
- data/src/main/java/org/sunflow/SunflowAPI.java +762 -0
- data/src/main/java/org/sunflow/SunflowAPIInterface.java +277 -0
- data/src/main/java/org/sunflow/core/AccelerationStructure.java +20 -0
- data/src/main/java/org/sunflow/core/AccelerationStructureFactory.java +36 -0
- data/src/main/java/org/sunflow/core/BucketOrder.java +21 -0
- data/src/main/java/org/sunflow/core/Camera.java +125 -0
- data/src/main/java/org/sunflow/core/CameraLens.java +29 -0
- data/src/main/java/org/sunflow/core/CausticPhotonMapInterface.java +15 -0
- data/src/main/java/org/sunflow/core/Display.java +78 -0
- data/src/main/java/org/sunflow/core/Filter.java +27 -0
- data/src/main/java/org/sunflow/core/GIEngine.java +42 -0
- data/src/main/java/org/sunflow/core/Geometry.java +157 -0
- data/src/main/java/org/sunflow/core/GlobalPhotonMapInterface.java +21 -0
- data/src/main/java/org/sunflow/core/ImageSampler.java +26 -0
- data/src/main/java/org/sunflow/core/Instance.java +224 -0
- data/src/main/java/org/sunflow/core/InstanceList.java +83 -0
- data/src/main/java/org/sunflow/core/IntersectionState.java +120 -0
- data/src/main/java/org/sunflow/core/LightSample.java +104 -0
- data/src/main/java/org/sunflow/core/LightServer.java +382 -0
- data/src/main/java/org/sunflow/core/LightSource.java +67 -0
- data/src/main/java/org/sunflow/core/Modifier.java +16 -0
- data/src/main/java/org/sunflow/core/Options.java +20 -0
- data/src/main/java/org/sunflow/core/ParameterList.java +758 -0
- data/src/main/java/org/sunflow/core/PhotonStore.java +62 -0
- data/src/main/java/org/sunflow/core/PrimitiveList.java +70 -0
- data/src/main/java/org/sunflow/core/Ray.java +219 -0
- data/src/main/java/org/sunflow/core/RenderObject.java +25 -0
- data/src/main/java/org/sunflow/core/Scene.java +377 -0
- data/src/main/java/org/sunflow/core/SceneParser.java +58 -0
- data/src/main/java/org/sunflow/core/Shader.java +30 -0
- data/src/main/java/org/sunflow/core/ShadingCache.java +84 -0
- data/src/main/java/org/sunflow/core/ShadingState.java +939 -0
- data/src/main/java/org/sunflow/core/Statistics.java +85 -0
- data/src/main/java/org/sunflow/core/Tesselatable.java +36 -0
- data/src/main/java/org/sunflow/core/Texture.java +128 -0
- data/src/main/java/org/sunflow/core/TextureCache.java +48 -0
- data/src/main/java/org/sunflow/core/accel/BoundingIntervalHierarchy.java +652 -0
- data/src/main/java/org/sunflow/core/accel/KDTree.java +833 -0
- data/src/main/java/org/sunflow/core/accel/NullAccelerator.java +30 -0
- data/src/main/java/org/sunflow/core/accel/UniformGrid.java +329 -0
- data/src/main/java/org/sunflow/core/bucket/BucketOrderFactory.java +26 -0
- data/src/main/java/org/sunflow/core/bucket/ColumnBucketOrder.java +21 -0
- data/src/main/java/org/sunflow/core/bucket/DiagonalBucketOrder.java +28 -0
- data/src/main/java/org/sunflow/core/bucket/HilbertBucketOrder.java +65 -0
- data/src/main/java/org/sunflow/core/bucket/InvertedBucketOrder.java +28 -0
- data/src/main/java/org/sunflow/core/bucket/RandomBucketOrder.java +49 -0
- data/src/main/java/org/sunflow/core/bucket/RowBucketOrder.java +21 -0
- data/src/main/java/org/sunflow/core/bucket/SpiralBucketOrder.java +43 -0
- data/src/main/java/org/sunflow/core/camera/FisheyeLens.java +25 -0
- data/src/main/java/org/sunflow/core/camera/PinholeLens.java +43 -0
- data/src/main/java/org/sunflow/core/camera/SphericalLens.java +22 -0
- data/src/main/java/org/sunflow/core/camera/ThinLens.java +107 -0
- data/src/main/java/org/sunflow/core/display/FastDisplay.java +119 -0
- data/src/main/java/org/sunflow/core/display/FileDisplay.java +83 -0
- data/src/main/java/org/sunflow/core/display/FrameDisplay.java +97 -0
- data/src/main/java/org/sunflow/core/display/ImgPipeDisplay.java +109 -0
- data/src/main/java/org/sunflow/core/filter/BlackmanHarrisFilter.java +28 -0
- data/src/main/java/org/sunflow/core/filter/BoxFilter.java +16 -0
- data/src/main/java/org/sunflow/core/filter/CatmullRomFilter.java +29 -0
- data/src/main/java/org/sunflow/core/filter/CubicBSpline.java +32 -0
- data/src/main/java/org/sunflow/core/filter/GaussianFilter.java +24 -0
- data/src/main/java/org/sunflow/core/filter/LanczosFilter.java +30 -0
- data/src/main/java/org/sunflow/core/filter/MitchellFilter.java +28 -0
- data/src/main/java/org/sunflow/core/filter/SincFilter.java +25 -0
- data/src/main/java/org/sunflow/core/filter/TriangleFilter.java +16 -0
- data/src/main/java/org/sunflow/core/gi/AmbientOcclusionGIEngine.java +57 -0
- data/src/main/java/org/sunflow/core/gi/FakeGIEngine.java +48 -0
- data/src/main/java/org/sunflow/core/gi/InstantGI.java +194 -0
- data/src/main/java/org/sunflow/core/gi/IrradianceCacheGIEngine.java +268 -0
- data/src/main/java/org/sunflow/core/gi/PathTracingGIEngine.java +65 -0
- data/src/main/java/org/sunflow/core/light/DirectionalSpotlight.java +103 -0
- data/src/main/java/org/sunflow/core/light/ImageBasedLight.java +303 -0
- data/src/main/java/org/sunflow/core/light/PointLight.java +72 -0
- data/src/main/java/org/sunflow/core/light/SphereLight.java +166 -0
- data/src/main/java/org/sunflow/core/light/SunSkyLight.java +362 -0
- data/src/main/java/org/sunflow/core/light/TriangleMeshLight.java +296 -0
- data/src/main/java/org/sunflow/core/modifiers/BumpMappingModifier.java +37 -0
- data/src/main/java/org/sunflow/core/modifiers/NormalMapModifier.java +34 -0
- data/src/main/java/org/sunflow/core/modifiers/PerlinModifier.java +80 -0
- data/src/main/java/org/sunflow/core/parser/Keyword.java +39 -0
- data/src/main/java/org/sunflow/core/parser/RA2Parser.java +107 -0
- data/src/main/java/org/sunflow/core/parser/RA3Parser.java +68 -0
- data/src/main/java/org/sunflow/core/parser/SCAbstractParser.java +299 -0
- data/src/main/java/org/sunflow/core/parser/SCAsciiParser.java +251 -0
- data/src/main/java/org/sunflow/core/parser/SCBinaryParser.java +156 -0
- data/src/main/java/org/sunflow/core/parser/SCParser.java +1403 -0
- data/src/main/java/org/sunflow/core/parser/ShaveRibParser.java +174 -0
- data/src/main/java/org/sunflow/core/parser/TriParser.java +79 -0
- data/src/main/java/org/sunflow/core/photonmap/CausticPhotonMap.java +429 -0
- data/src/main/java/org/sunflow/core/photonmap/GlobalPhotonMap.java +530 -0
- data/src/main/java/org/sunflow/core/photonmap/GridPhotonMap.java +308 -0
- data/src/main/java/org/sunflow/core/primitive/Background.java +55 -0
- data/src/main/java/org/sunflow/core/primitive/BanchoffSurface.java +100 -0
- data/src/main/java/org/sunflow/core/primitive/Box.java +210 -0
- data/src/main/java/org/sunflow/core/primitive/CornellBox.java +476 -0
- data/src/main/java/org/sunflow/core/primitive/CubeGrid.java +318 -0
- data/src/main/java/org/sunflow/core/primitive/Cylinder.java +104 -0
- data/src/main/java/org/sunflow/core/primitive/Hair.java +275 -0
- data/src/main/java/org/sunflow/core/primitive/JuliaFractal.java +266 -0
- data/src/main/java/org/sunflow/core/primitive/ParticleSurface.java +114 -0
- data/src/main/java/org/sunflow/core/primitive/Plane.java +163 -0
- data/src/main/java/org/sunflow/core/primitive/QuadMesh.java +413 -0
- data/src/main/java/org/sunflow/core/primitive/Sphere.java +101 -0
- data/src/main/java/org/sunflow/core/primitive/SphereFlake.java +234 -0
- data/src/main/java/org/sunflow/core/primitive/Torus.java +145 -0
- data/src/main/java/org/sunflow/core/primitive/TriangleMesh.java +849 -0
- data/src/main/java/org/sunflow/core/renderer/BucketRenderer.java +491 -0
- data/src/main/java/org/sunflow/core/renderer/MultipassRenderer.java +237 -0
- data/src/main/java/org/sunflow/core/renderer/ProgressiveRenderer.java +171 -0
- data/src/main/java/org/sunflow/core/renderer/SimpleRenderer.java +106 -0
- data/src/main/java/org/sunflow/core/shader/AmbientOcclusionShader.java +53 -0
- data/src/main/java/org/sunflow/core/shader/AnisotropicWardShader.java +216 -0
- data/src/main/java/org/sunflow/core/shader/ConstantShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/DiffuseShader.java +65 -0
- data/src/main/java/org/sunflow/core/shader/GlassShader.java +147 -0
- data/src/main/java/org/sunflow/core/shader/IDShader.java +27 -0
- data/src/main/java/org/sunflow/core/shader/MirrorShader.java +68 -0
- data/src/main/java/org/sunflow/core/shader/NormalShader.java +32 -0
- data/src/main/java/org/sunflow/core/shader/PhongShader.java +89 -0
- data/src/main/java/org/sunflow/core/shader/PrimIDShader.java +30 -0
- data/src/main/java/org/sunflow/core/shader/QuickGrayShader.java +63 -0
- data/src/main/java/org/sunflow/core/shader/ShinyDiffuseShader.java +98 -0
- data/src/main/java/org/sunflow/core/shader/SimpleShader.java +24 -0
- data/src/main/java/org/sunflow/core/shader/TexturedAmbientOcclusionShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedDiffuseShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedPhongShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedShinyDiffuseShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedWardShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/UVShader.java +27 -0
- data/src/main/java/org/sunflow/core/shader/UberShader.java +149 -0
- data/src/main/java/org/sunflow/core/shader/ViewCausticsShader.java +33 -0
- data/src/main/java/org/sunflow/core/shader/ViewGlobalPhotonsShader.java +25 -0
- data/src/main/java/org/sunflow/core/shader/ViewIrradianceShader.java +25 -0
- data/src/main/java/org/sunflow/core/shader/WireframeShader.java +83 -0
- data/src/main/java/org/sunflow/core/tesselatable/BezierMesh.java +254 -0
- data/src/main/java/org/sunflow/core/tesselatable/FileMesh.java +251 -0
- data/src/main/java/org/sunflow/core/tesselatable/Gumbo.java +1147 -0
- data/src/main/java/org/sunflow/core/tesselatable/Teapot.java +237 -0
- data/src/main/java/org/sunflow/image/Bitmap.java +15 -0
- data/src/main/java/org/sunflow/image/BitmapReader.java +39 -0
- data/src/main/java/org/sunflow/image/BitmapWriter.java +79 -0
- data/src/main/java/org/sunflow/image/BlackbodySpectrum.java +16 -0
- data/src/main/java/org/sunflow/image/ChromaticitySpectrum.java +55 -0
- data/src/main/java/org/sunflow/image/Color.java +374 -0
- data/src/main/java/org/sunflow/image/ColorEncoder.java +94 -0
- data/src/main/java/org/sunflow/image/ColorFactory.java +122 -0
- data/src/main/java/org/sunflow/image/ConstantSpectralCurve.java +21 -0
- data/src/main/java/org/sunflow/image/IrregularSpectralCurve.java +57 -0
- data/src/main/java/org/sunflow/image/RGBSpace.java +207 -0
- data/src/main/java/org/sunflow/image/RegularSpectralCurve.java +30 -0
- data/src/main/java/org/sunflow/image/SpectralCurve.java +118 -0
- data/src/main/java/org/sunflow/image/XYZColor.java +50 -0
- data/src/main/java/org/sunflow/image/formats/BitmapBlack.java +27 -0
- data/src/main/java/org/sunflow/image/formats/BitmapG8.java +36 -0
- data/src/main/java/org/sunflow/image/formats/BitmapGA8.java +30 -0
- data/src/main/java/org/sunflow/image/formats/BitmapRGB8.java +40 -0
- data/src/main/java/org/sunflow/image/formats/BitmapRGBA8.java +40 -0
- data/src/main/java/org/sunflow/image/formats/BitmapRGBE.java +60 -0
- data/src/main/java/org/sunflow/image/formats/BitmapXYZ.java +38 -0
- data/src/main/java/org/sunflow/image/formats/GenericBitmap.java +73 -0
- data/src/main/java/org/sunflow/image/readers/BMPBitmapReader.java +39 -0
- data/src/main/java/org/sunflow/image/readers/HDRBitmapReader.java +155 -0
- data/src/main/java/org/sunflow/image/readers/IGIBitmapReader.java +104 -0
- data/src/main/java/org/sunflow/image/readers/JPGBitmapReader.java +39 -0
- data/src/main/java/org/sunflow/image/readers/PNGBitmapReader.java +40 -0
- data/src/main/java/org/sunflow/image/readers/TGABitmapReader.java +141 -0
- data/src/main/java/org/sunflow/image/writers/EXRBitmapWriter.java +395 -0
- data/src/main/java/org/sunflow/image/writers/HDRBitmapWriter.java +54 -0
- data/src/main/java/org/sunflow/image/writers/IGIBitmapWriter.java +75 -0
- data/src/main/java/org/sunflow/image/writers/PNGBitmapWriter.java +39 -0
- data/src/main/java/org/sunflow/image/writers/TGABitmapWriter.java +63 -0
- data/src/main/java/org/sunflow/math/BoundingBox.java +340 -0
- data/src/main/java/org/sunflow/math/MathUtils.java +159 -0
- data/src/main/java/org/sunflow/math/Matrix4.java +573 -0
- data/src/main/java/org/sunflow/math/MovingMatrix4.java +119 -0
- data/src/main/java/org/sunflow/math/OrthoNormalBasis.java +110 -0
- data/src/main/java/org/sunflow/math/PerlinScalar.java +331 -0
- data/src/main/java/org/sunflow/math/PerlinVector.java +132 -0
- data/src/main/java/org/sunflow/math/Point2.java +36 -0
- data/src/main/java/org/sunflow/math/Point3.java +133 -0
- data/src/main/java/org/sunflow/math/QMC.java +209 -0
- data/src/main/java/org/sunflow/math/Solvers.java +142 -0
- data/src/main/java/org/sunflow/math/Vector3.java +197 -0
- data/src/main/java/org/sunflow/system/BenchmarkFramework.java +73 -0
- data/src/main/java/org/sunflow/system/BenchmarkTest.java +17 -0
- data/src/main/java/org/sunflow/system/ByteUtil.java +119 -0
- data/src/main/java/org/sunflow/system/FileUtils.java +27 -0
- data/src/main/java/org/sunflow/system/ImagePanel.java +282 -0
- data/src/main/java/org/sunflow/system/Memory.java +18 -0
- data/src/main/java/org/sunflow/system/Parser.java +162 -0
- data/src/main/java/org/sunflow/system/Plugins.java +142 -0
- data/src/main/java/org/sunflow/system/RenderGlobalsPanel.java +209 -0
- data/src/main/java/org/sunflow/system/SearchPath.java +67 -0
- data/src/main/java/org/sunflow/system/Timer.java +53 -0
- data/src/main/java/org/sunflow/system/UI.java +112 -0
- data/src/main/java/org/sunflow/system/UserInterface.java +46 -0
- data/src/main/java/org/sunflow/system/ui/ConsoleInterface.java +48 -0
- data/src/main/java/org/sunflow/system/ui/SilentInterface.java +28 -0
- data/src/main/java/org/sunflow/util/FastHashMap.java +220 -0
- data/src/main/java/org/sunflow/util/FloatArray.java +77 -0
- data/src/main/java/org/sunflow/util/IntArray.java +77 -0
- data/src/test/java/a_maintest.java +129 -0
- metadata +300 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
package org.sunflow.core;
|
|
2
|
+
|
|
3
|
+
import org.sunflow.SunflowAPI;
|
|
4
|
+
import org.sunflow.math.BoundingBox;
|
|
5
|
+
import org.sunflow.math.Matrix4;
|
|
6
|
+
|
|
7
|
+
final class InstanceList implements PrimitiveList {
|
|
8
|
+
|
|
9
|
+
private Instance[] instances;
|
|
10
|
+
private Instance[] lights;
|
|
11
|
+
|
|
12
|
+
InstanceList() {
|
|
13
|
+
instances = new Instance[0];
|
|
14
|
+
clearLightSources();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
InstanceList(Instance[] instances) {
|
|
18
|
+
this.instances = instances;
|
|
19
|
+
clearLightSources();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
void addLightSourceInstances(Instance[] lights) {
|
|
23
|
+
this.lights = lights;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void clearLightSources() {
|
|
27
|
+
lights = new Instance[0];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@Override
|
|
31
|
+
public final float getPrimitiveBound(int primID, int i) {
|
|
32
|
+
if (primID < instances.length) {
|
|
33
|
+
return instances[primID].getBounds().getBound(i);
|
|
34
|
+
} else {
|
|
35
|
+
return lights[primID - instances.length].getBounds().getBound(i);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@Override
|
|
40
|
+
public final BoundingBox getWorldBounds(Matrix4 o2w) {
|
|
41
|
+
BoundingBox bounds = new BoundingBox();
|
|
42
|
+
for (Instance i : instances) {
|
|
43
|
+
bounds.include(i.getBounds());
|
|
44
|
+
}
|
|
45
|
+
for (Instance i : lights) {
|
|
46
|
+
bounds.include(i.getBounds());
|
|
47
|
+
}
|
|
48
|
+
return bounds;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@Override
|
|
52
|
+
public final void intersectPrimitive(Ray r, int primID, IntersectionState state) {
|
|
53
|
+
if (primID < instances.length) {
|
|
54
|
+
instances[primID].intersect(r, state);
|
|
55
|
+
} else {
|
|
56
|
+
lights[primID - instances.length].intersect(r, state);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@Override
|
|
61
|
+
public final int getNumPrimitives() {
|
|
62
|
+
return instances.length + lights.length;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public final int getNumPrimitives(int primID) {
|
|
66
|
+
return primID < instances.length ? instances[primID].getNumPrimitives() : lights[primID - instances.length].getNumPrimitives();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@Override
|
|
70
|
+
public final void prepareShadingState(ShadingState state) {
|
|
71
|
+
state.getInstance().prepareShadingState(state);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@Override
|
|
75
|
+
public boolean update(ParameterList pl, SunflowAPI api) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@Override
|
|
80
|
+
public PrimitiveList getBakingPrimitives() {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
package org.sunflow.core;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This class is used to store ray/object intersections. It also provides
|
|
5
|
+
* additional data to assist {@link AccelerationStructure} objects with
|
|
6
|
+
* traversal.
|
|
7
|
+
*/
|
|
8
|
+
public final class IntersectionState {
|
|
9
|
+
|
|
10
|
+
private static final int MAX_STACK_SIZE = 64;
|
|
11
|
+
float time;
|
|
12
|
+
float u, v, w;
|
|
13
|
+
Instance instance;
|
|
14
|
+
int id;
|
|
15
|
+
private final StackNode[][] stacks = new StackNode[2][MAX_STACK_SIZE];
|
|
16
|
+
Instance current;
|
|
17
|
+
long numEyeRays;
|
|
18
|
+
long numShadowRays;
|
|
19
|
+
long numReflectionRays;
|
|
20
|
+
long numGlossyRays;
|
|
21
|
+
long numRefractionRays;
|
|
22
|
+
long numRays;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Traversal stack node, helps with tree-based {@link AccelerationStructure}
|
|
26
|
+
* traversal.
|
|
27
|
+
*/
|
|
28
|
+
public static final class StackNode {
|
|
29
|
+
|
|
30
|
+
public int node;
|
|
31
|
+
public float near;
|
|
32
|
+
public float far;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Initializes all traversal stacks.
|
|
37
|
+
*/
|
|
38
|
+
public IntersectionState() {
|
|
39
|
+
for (int i = 0; i < stacks.length; i++) {
|
|
40
|
+
for (int j = 0; j < stacks[i].length; j++) {
|
|
41
|
+
stacks[i][j] = new StackNode();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Returns the time at which the intersection should be calculated. This
|
|
48
|
+
* will be constant for a given ray-tree. This value is guarenteed to be
|
|
49
|
+
* between the camera's shutter open and shutter close time.
|
|
50
|
+
*
|
|
51
|
+
* @return time value
|
|
52
|
+
*/
|
|
53
|
+
public float getTime() {
|
|
54
|
+
return time;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get stack object for tree based {@link AccelerationStructure}s.
|
|
59
|
+
*
|
|
60
|
+
* @return array of stack nodes
|
|
61
|
+
*/
|
|
62
|
+
public final StackNode[] getStack() {
|
|
63
|
+
return current == null ? stacks[0] : stacks[1];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Checks to see if a hit has been recorded.
|
|
68
|
+
*
|
|
69
|
+
* @return <code>true</code> if a hit has been recorded, <code>false</code>
|
|
70
|
+
* otherwise
|
|
71
|
+
*/
|
|
72
|
+
public final boolean hit() {
|
|
73
|
+
return instance != null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Record an intersection with the specified primitive id. The parent object
|
|
78
|
+
* is assumed to be the current instance. The u and v parameters are used to
|
|
79
|
+
* pinpoint the location on the surface if needed.
|
|
80
|
+
*
|
|
81
|
+
* @param id primitive id of the intersected object
|
|
82
|
+
*/
|
|
83
|
+
public final void setIntersection(int id) {
|
|
84
|
+
instance = current;
|
|
85
|
+
this.id = id;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Record an intersection with the specified primitive id. The parent object
|
|
90
|
+
* is assumed to be the current instance. The u and v parameters are used to
|
|
91
|
+
* pinpoint the location on the surface if needed.
|
|
92
|
+
*
|
|
93
|
+
* @param id primitive id of the intersected object
|
|
94
|
+
* @param u u surface paramater of the intersection point
|
|
95
|
+
* @param v v surface parameter of the intersection point
|
|
96
|
+
*/
|
|
97
|
+
public final void setIntersection(int id, float u, float v) {
|
|
98
|
+
instance = current;
|
|
99
|
+
this.id = id;
|
|
100
|
+
this.u = u;
|
|
101
|
+
this.v = v;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Record an intersection with the specified primitive id. The parent object
|
|
106
|
+
* is assumed to be the current instance. The u and v parameters are used to
|
|
107
|
+
* pinpoint the location on the surface if needed.
|
|
108
|
+
*
|
|
109
|
+
* @param id primitive id of the intersected object
|
|
110
|
+
* @param u u surface paramater of the intersection point
|
|
111
|
+
* @param v v surface parameter of the intersection point
|
|
112
|
+
*/
|
|
113
|
+
public final void setIntersection(int id, float u, float v, float w) {
|
|
114
|
+
instance = current;
|
|
115
|
+
this.id = id;
|
|
116
|
+
this.u = u;
|
|
117
|
+
this.v = v;
|
|
118
|
+
this.w = w;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
package org.sunflow.core;
|
|
2
|
+
|
|
3
|
+
import org.sunflow.image.Color;
|
|
4
|
+
import org.sunflow.math.Vector3;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a sample taken from a light source that faces a point being
|
|
8
|
+
* shaded.
|
|
9
|
+
*/
|
|
10
|
+
public class LightSample {
|
|
11
|
+
|
|
12
|
+
private Ray shadowRay; // ray to be used to evaluate if the point is in
|
|
13
|
+
// shadow
|
|
14
|
+
private Color ldiff;
|
|
15
|
+
private Color lspec;
|
|
16
|
+
LightSample next; // pointer to next item in a linked list of samples
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Creates a new light sample object (invalid by default).
|
|
20
|
+
*/
|
|
21
|
+
public LightSample() {
|
|
22
|
+
ldiff = lspec = null;
|
|
23
|
+
shadowRay = null;
|
|
24
|
+
next = null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
boolean isValid() {
|
|
28
|
+
return ldiff != null && lspec != null && shadowRay != null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Set the current shadow ray. The ray's direction is used as the sample's
|
|
33
|
+
* orientation.
|
|
34
|
+
*
|
|
35
|
+
* @param shadowRay shadow ray from the point being shaded towards the light
|
|
36
|
+
*/
|
|
37
|
+
public void setShadowRay(Ray shadowRay) {
|
|
38
|
+
this.shadowRay = shadowRay;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Trace the shadow ray, attenuating the sample's color by the opacity of
|
|
43
|
+
* intersected objects.
|
|
44
|
+
*
|
|
45
|
+
* @param state shading state representing the point to be shaded
|
|
46
|
+
*/
|
|
47
|
+
public final void traceShadow(ShadingState state) {
|
|
48
|
+
Color opacity = state.traceShadow(shadowRay);
|
|
49
|
+
Color.blend(ldiff, Color.BLACK, opacity, ldiff);
|
|
50
|
+
Color.blend(lspec, Color.BLACK, opacity, lspec);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get the sample's shadow ray.
|
|
55
|
+
*
|
|
56
|
+
* @return shadow ray
|
|
57
|
+
*/
|
|
58
|
+
public Ray getShadowRay() {
|
|
59
|
+
return shadowRay;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get diffuse radiance.
|
|
64
|
+
*
|
|
65
|
+
* @return diffuse radiance
|
|
66
|
+
*/
|
|
67
|
+
public Color getDiffuseRadiance() {
|
|
68
|
+
return ldiff;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get specular radiance.
|
|
73
|
+
*
|
|
74
|
+
* @return specular radiance
|
|
75
|
+
*/
|
|
76
|
+
public Color getSpecularRadiance() {
|
|
77
|
+
return lspec;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Set the diffuse and specular radiance emitted by the current light
|
|
82
|
+
* source. These should usually be the same, but are distinguished to allow
|
|
83
|
+
* for non-physical light setups or light source types which compute diffuse
|
|
84
|
+
* and specular responses seperately.
|
|
85
|
+
*
|
|
86
|
+
* @param d diffuse radiance
|
|
87
|
+
* @param s specular radiance
|
|
88
|
+
*/
|
|
89
|
+
public void setRadiance(Color d, Color s) {
|
|
90
|
+
ldiff = d.copy();
|
|
91
|
+
lspec = s.copy();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Compute a dot product between the current shadow ray direction and the
|
|
96
|
+
* specified vector.
|
|
97
|
+
*
|
|
98
|
+
* @param v direction vector
|
|
99
|
+
* @return dot product of the vector with the shadow ray direction
|
|
100
|
+
*/
|
|
101
|
+
public float dot(Vector3 v) {
|
|
102
|
+
return shadowRay.dot(v);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
package org.sunflow.core;
|
|
2
|
+
|
|
3
|
+
import org.sunflow.PluginRegistry;
|
|
4
|
+
import org.sunflow.image.Color;
|
|
5
|
+
import org.sunflow.math.Point3;
|
|
6
|
+
import org.sunflow.math.QMC;
|
|
7
|
+
import org.sunflow.math.Vector3;
|
|
8
|
+
import org.sunflow.system.Timer;
|
|
9
|
+
import org.sunflow.system.UI;
|
|
10
|
+
import org.sunflow.system.UI.Module;
|
|
11
|
+
|
|
12
|
+
class LightServer {
|
|
13
|
+
// parent
|
|
14
|
+
|
|
15
|
+
private Scene scene;
|
|
16
|
+
// lighting
|
|
17
|
+
LightSource[] lights;
|
|
18
|
+
// shading override
|
|
19
|
+
private Shader shaderOverride;
|
|
20
|
+
private boolean shaderOverridePhotons;
|
|
21
|
+
// direct illumination
|
|
22
|
+
private int maxDiffuseDepth;
|
|
23
|
+
private int maxReflectionDepth;
|
|
24
|
+
private int maxRefractionDepth;
|
|
25
|
+
// indirect illumination
|
|
26
|
+
private CausticPhotonMapInterface causticPhotonMap;
|
|
27
|
+
private GIEngine giEngine;
|
|
28
|
+
private int photonCounter;
|
|
29
|
+
|
|
30
|
+
LightServer(Scene scene) {
|
|
31
|
+
this.scene = scene;
|
|
32
|
+
lights = new LightSource[0];
|
|
33
|
+
causticPhotonMap = null;
|
|
34
|
+
|
|
35
|
+
shaderOverride = null;
|
|
36
|
+
shaderOverridePhotons = false;
|
|
37
|
+
|
|
38
|
+
maxDiffuseDepth = 1;
|
|
39
|
+
maxReflectionDepth = 4;
|
|
40
|
+
maxRefractionDepth = 4;
|
|
41
|
+
|
|
42
|
+
causticPhotonMap = null;
|
|
43
|
+
giEngine = null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
void setLights(LightSource[] lights) {
|
|
47
|
+
this.lights = lights;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
Scene getScene() {
|
|
51
|
+
return scene;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
void setShaderOverride(Shader shader, boolean photonOverride) {
|
|
55
|
+
shaderOverride = shader;
|
|
56
|
+
shaderOverridePhotons = photonOverride;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
boolean build(Options options) {
|
|
60
|
+
// read options
|
|
61
|
+
maxDiffuseDepth = options.getInt("depths.diffuse", maxDiffuseDepth);
|
|
62
|
+
maxReflectionDepth = options.getInt("depths.reflection", maxReflectionDepth);
|
|
63
|
+
maxRefractionDepth = options.getInt("depths.refraction", maxRefractionDepth);
|
|
64
|
+
String giEngineType = options.getString("gi.engine", null);
|
|
65
|
+
giEngine = PluginRegistry.GI_ENGINE_PLUGINS.createObject(giEngineType);
|
|
66
|
+
String caustics = options.getString("caustics", null);
|
|
67
|
+
causticPhotonMap = PluginRegistry.CAUSTIC_PHOTON_MAP_PLUGINS.createObject(caustics);
|
|
68
|
+
|
|
69
|
+
// validate options
|
|
70
|
+
maxDiffuseDepth = Math.max(0, maxDiffuseDepth);
|
|
71
|
+
maxReflectionDepth = Math.max(0, maxReflectionDepth);
|
|
72
|
+
maxRefractionDepth = Math.max(0, maxRefractionDepth);
|
|
73
|
+
|
|
74
|
+
Timer t = new Timer();
|
|
75
|
+
t.start();
|
|
76
|
+
// count total number of light samples
|
|
77
|
+
int numLightSamples = 0;
|
|
78
|
+
for (int i = 0; i < lights.length; i++) {
|
|
79
|
+
numLightSamples += lights[i].getNumSamples();
|
|
80
|
+
}
|
|
81
|
+
// initialize gi engine
|
|
82
|
+
if (giEngine != null) {
|
|
83
|
+
if (!giEngine.init(options, scene)) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (!calculatePhotons(causticPhotonMap, "caustic", 0, options)) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
t.end();
|
|
92
|
+
UI.printInfo(Module.LIGHT, "Light Server stats:");
|
|
93
|
+
UI.printInfo(Module.LIGHT, " * Light sources found: %d", lights.length);
|
|
94
|
+
UI.printInfo(Module.LIGHT, " * Light samples: %d", numLightSamples);
|
|
95
|
+
UI.printInfo(Module.LIGHT, " * Max raytrace depth:");
|
|
96
|
+
UI.printInfo(Module.LIGHT, " - Diffuse %d", maxDiffuseDepth);
|
|
97
|
+
UI.printInfo(Module.LIGHT, " - Reflection %d", maxReflectionDepth);
|
|
98
|
+
UI.printInfo(Module.LIGHT, " - Refraction %d", maxRefractionDepth);
|
|
99
|
+
UI.printInfo(Module.LIGHT, " * GI engine %s", giEngineType == null ? "none" : giEngineType);
|
|
100
|
+
UI.printInfo(Module.LIGHT, " * Caustics: %s", caustics == null ? "none" : caustics);
|
|
101
|
+
UI.printInfo(Module.LIGHT, " * Shader override: %b", shaderOverride);
|
|
102
|
+
UI.printInfo(Module.LIGHT, " * Photon override: %b", shaderOverridePhotons);
|
|
103
|
+
UI.printInfo(Module.LIGHT, " * Build time: %s", t.toString());
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
void showStats() {
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
boolean calculatePhotons(final PhotonStore map, String type, final int seed, Options options) {
|
|
111
|
+
if (map == null) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
if (lights.length == 0) {
|
|
115
|
+
UI.printError(Module.LIGHT, "Unable to trace %s photons, no lights in scene", type);
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
final float[] histogram = new float[lights.length];
|
|
119
|
+
histogram[0] = lights[0].getPower();
|
|
120
|
+
for (int i = 1; i < lights.length; i++) {
|
|
121
|
+
histogram[i] = histogram[i - 1] + lights[i].getPower();
|
|
122
|
+
}
|
|
123
|
+
UI.printInfo(Module.LIGHT, "Tracing %s photons ...", type);
|
|
124
|
+
map.prepare(options, scene.getBounds());
|
|
125
|
+
int numEmittedPhotons = map.numEmit();
|
|
126
|
+
if (numEmittedPhotons <= 0 || histogram[histogram.length - 1] <= 0) {
|
|
127
|
+
UI.printError(Module.LIGHT, "Photon mapping enabled, but no %s photons to emit", type);
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
UI.taskStart("Tracing " + type + " photons", 0, numEmittedPhotons);
|
|
131
|
+
Thread[] photonThreads = new Thread[scene.getThreads()];
|
|
132
|
+
final float scale = 1.0f / numEmittedPhotons;
|
|
133
|
+
int delta = numEmittedPhotons / photonThreads.length;
|
|
134
|
+
photonCounter = 0;
|
|
135
|
+
Timer photonTimer = new Timer();
|
|
136
|
+
photonTimer.start();
|
|
137
|
+
for (int i = 0; i < photonThreads.length; i++) {
|
|
138
|
+
final int threadID = i;
|
|
139
|
+
final int start = threadID * delta;
|
|
140
|
+
final int end = (threadID == (photonThreads.length - 1)) ? numEmittedPhotons : (threadID + 1) * delta;
|
|
141
|
+
photonThreads[i] = new Thread(new Runnable() {
|
|
142
|
+
public void run() {
|
|
143
|
+
IntersectionState istate = new IntersectionState();
|
|
144
|
+
for (int i = start; i < end; i++) {
|
|
145
|
+
synchronized (LightServer.this) {
|
|
146
|
+
UI.taskUpdate(photonCounter);
|
|
147
|
+
photonCounter++;
|
|
148
|
+
if (UI.taskCanceled()) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
int qmcI = i + seed;
|
|
154
|
+
|
|
155
|
+
double rand = QMC.halton(0, qmcI) * histogram[histogram.length - 1];
|
|
156
|
+
int j = 0;
|
|
157
|
+
while (rand >= histogram[j] && j < histogram.length) {
|
|
158
|
+
j++;
|
|
159
|
+
}
|
|
160
|
+
// make sure we didn't pick a zero-probability light
|
|
161
|
+
if (j == histogram.length) {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
double randX1 = (j == 0) ? rand / histogram[0] : (rand - histogram[j]) / (histogram[j] - histogram[j - 1]);
|
|
166
|
+
double randY1 = QMC.halton(1, qmcI);
|
|
167
|
+
double randX2 = QMC.halton(2, qmcI);
|
|
168
|
+
double randY2 = QMC.halton(3, qmcI);
|
|
169
|
+
Point3 pt = new Point3();
|
|
170
|
+
Vector3 dir = new Vector3();
|
|
171
|
+
Color power = new Color();
|
|
172
|
+
lights[j].getPhoton(randX1, randY1, randX2, randY2, pt, dir, power);
|
|
173
|
+
power.mul(scale);
|
|
174
|
+
Ray r = new Ray(pt, dir);
|
|
175
|
+
scene.trace(r, istate);
|
|
176
|
+
if (istate.hit()) {
|
|
177
|
+
shadePhoton(ShadingState.createPhotonState(r, istate, qmcI, map, LightServer.this), power);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
photonThreads[i].setPriority(scene.getThreadPriority());
|
|
183
|
+
photonThreads[i].start();
|
|
184
|
+
}
|
|
185
|
+
for (int i = 0; i < photonThreads.length; i++) {
|
|
186
|
+
try {
|
|
187
|
+
photonThreads[i].join();
|
|
188
|
+
} catch (InterruptedException e) {
|
|
189
|
+
UI.printError(Module.LIGHT, "Photon thread %d of %d was interrupted", i + 1, photonThreads.length);
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (UI.taskCanceled()) {
|
|
194
|
+
UI.taskStop(); // shut down task cleanly
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
photonTimer.end();
|
|
198
|
+
UI.taskStop();
|
|
199
|
+
UI.printInfo(Module.LIGHT, "Tracing time for %s photons: %s", type, photonTimer.toString());
|
|
200
|
+
map.init();
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
void shadePhoton(ShadingState state, Color power) {
|
|
205
|
+
state.getInstance().prepareShadingState(state);
|
|
206
|
+
Shader shader = getPhotonShader(state);
|
|
207
|
+
// scatter photon
|
|
208
|
+
if (shader != null) {
|
|
209
|
+
shader.scatterPhoton(state, power);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
void traceDiffusePhoton(ShadingState previous, Ray r, Color power) {
|
|
214
|
+
if (previous.getDiffuseDepth() >= maxDiffuseDepth) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
IntersectionState istate = previous.getIntersectionState();
|
|
218
|
+
scene.trace(r, istate);
|
|
219
|
+
if (previous.getIntersectionState().hit()) {
|
|
220
|
+
// create a new shading context
|
|
221
|
+
ShadingState state = ShadingState.createDiffuseBounceState(previous, r, 0);
|
|
222
|
+
shadePhoton(state, power);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
void traceReflectionPhoton(ShadingState previous, Ray r, Color power) {
|
|
227
|
+
if (previous.getReflectionDepth() >= maxReflectionDepth) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
IntersectionState istate = previous.getIntersectionState();
|
|
231
|
+
scene.trace(r, istate);
|
|
232
|
+
if (previous.getIntersectionState().hit()) {
|
|
233
|
+
// create a new shading context
|
|
234
|
+
ShadingState state = ShadingState.createReflectionBounceState(previous, r, 0);
|
|
235
|
+
shadePhoton(state, power);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
void traceRefractionPhoton(ShadingState previous, Ray r, Color power) {
|
|
240
|
+
if (previous.getRefractionDepth() >= maxRefractionDepth) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
IntersectionState istate = previous.getIntersectionState();
|
|
244
|
+
scene.trace(r, istate);
|
|
245
|
+
if (previous.getIntersectionState().hit()) {
|
|
246
|
+
// create a new shading context
|
|
247
|
+
ShadingState state = ShadingState.createRefractionBounceState(previous, r, 0);
|
|
248
|
+
shadePhoton(state, power);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
private Shader getShader(ShadingState state) {
|
|
253
|
+
return shaderOverride != null ? shaderOverride : state.getShader();
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
private Shader getPhotonShader(ShadingState state) {
|
|
257
|
+
return (shaderOverride != null && shaderOverridePhotons) ? shaderOverride : state.getShader();
|
|
258
|
+
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
ShadingState getRadiance(float rx, float ry, float time, int i, int d, Ray r, IntersectionState istate, ShadingCache cache) {
|
|
262
|
+
// set this value once - will stay constant for the entire ray-tree
|
|
263
|
+
istate.time = time;
|
|
264
|
+
scene.trace(r, istate);
|
|
265
|
+
if (istate.hit()) {
|
|
266
|
+
ShadingState state = ShadingState.createState(istate, rx, ry, time, r, i, d, this);
|
|
267
|
+
state.getInstance().prepareShadingState(state);
|
|
268
|
+
Shader shader = getShader(state);
|
|
269
|
+
if (shader == null) {
|
|
270
|
+
state.setResult(Color.BLACK);
|
|
271
|
+
return state;
|
|
272
|
+
}
|
|
273
|
+
if (cache != null) {
|
|
274
|
+
Color c = cache.lookup(state, shader);
|
|
275
|
+
if (c != null) {
|
|
276
|
+
state.setResult(c);
|
|
277
|
+
return state;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
state.setResult(shader.getRadiance(state));
|
|
281
|
+
if (cache != null) {
|
|
282
|
+
cache.add(state, shader, state.getResult());
|
|
283
|
+
}
|
|
284
|
+
checkNanInf(state.getResult());
|
|
285
|
+
return state;
|
|
286
|
+
} else {
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private static final void checkNanInf(Color c) {
|
|
292
|
+
if (c.isNan()) {
|
|
293
|
+
UI.printWarning(Module.LIGHT, "NaN shading sample!");
|
|
294
|
+
} else if (c.isInf()) {
|
|
295
|
+
UI.printWarning(Module.LIGHT, "Inf shading sample!");
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
void shadeBakeResult(ShadingState state) {
|
|
300
|
+
Shader shader = getShader(state);
|
|
301
|
+
if (shader != null) {
|
|
302
|
+
state.setResult(shader.getRadiance(state));
|
|
303
|
+
} else {
|
|
304
|
+
state.setResult(Color.BLACK);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
Color shadeHit(ShadingState state) {
|
|
309
|
+
state.getInstance().prepareShadingState(state);
|
|
310
|
+
Shader shader = getShader(state);
|
|
311
|
+
return (shader != null) ? shader.getRadiance(state) : Color.BLACK;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
Color traceGlossy(ShadingState previous, Ray r, int i) {
|
|
315
|
+
// limit path depth and disable caustic paths
|
|
316
|
+
if (previous.getReflectionDepth() >= maxReflectionDepth || previous.getDiffuseDepth() > 0) {
|
|
317
|
+
return Color.BLACK;
|
|
318
|
+
}
|
|
319
|
+
IntersectionState istate = previous.getIntersectionState();
|
|
320
|
+
istate.numGlossyRays++;
|
|
321
|
+
scene.trace(r, istate);
|
|
322
|
+
return istate.hit() ? shadeHit(ShadingState.createGlossyBounceState(previous, r, i)) : Color.BLACK;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
Color traceReflection(ShadingState previous, Ray r, int i) {
|
|
326
|
+
// limit path depth and disable caustic paths
|
|
327
|
+
if (previous.getReflectionDepth() >= maxReflectionDepth || previous.getDiffuseDepth() > 0) {
|
|
328
|
+
return Color.BLACK;
|
|
329
|
+
}
|
|
330
|
+
IntersectionState istate = previous.getIntersectionState();
|
|
331
|
+
istate.numReflectionRays++;
|
|
332
|
+
scene.trace(r, istate);
|
|
333
|
+
return istate.hit() ? shadeHit(ShadingState.createReflectionBounceState(previous, r, i)) : Color.BLACK;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
Color traceRefraction(ShadingState previous, Ray r, int i) {
|
|
337
|
+
// limit path depth and disable caustic paths
|
|
338
|
+
if (previous.getRefractionDepth() >= maxRefractionDepth || previous.getDiffuseDepth() > 0) {
|
|
339
|
+
return Color.BLACK;
|
|
340
|
+
}
|
|
341
|
+
IntersectionState istate = previous.getIntersectionState();
|
|
342
|
+
istate.numRefractionRays++;
|
|
343
|
+
scene.trace(r, istate);
|
|
344
|
+
return istate.hit() ? shadeHit(ShadingState.createRefractionBounceState(previous, r, i)) : Color.BLACK;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
ShadingState traceFinalGather(ShadingState previous, Ray r, int i) {
|
|
348
|
+
if (previous.getDiffuseDepth() >= maxDiffuseDepth) {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
IntersectionState istate = previous.getIntersectionState();
|
|
352
|
+
scene.trace(r, istate);
|
|
353
|
+
return istate.hit() ? ShadingState.createFinalGatherState(previous, r, i) : null;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
Color getGlobalRadiance(ShadingState state) {
|
|
357
|
+
if (giEngine == null) {
|
|
358
|
+
return Color.BLACK;
|
|
359
|
+
}
|
|
360
|
+
return giEngine.getGlobalRadiance(state);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
Color getIrradiance(ShadingState state, Color diffuseReflectance) {
|
|
364
|
+
// no gi engine, or we have already exceeded number of available bounces
|
|
365
|
+
if (giEngine == null || state.getDiffuseDepth() >= maxDiffuseDepth) {
|
|
366
|
+
return Color.BLACK;
|
|
367
|
+
}
|
|
368
|
+
return giEngine.getIrradiance(state, diffuseReflectance);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
void initLightSamples(ShadingState state) {
|
|
372
|
+
for (LightSource l : lights) {
|
|
373
|
+
l.getSamples(state);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
void initCausticSamples(ShadingState state) {
|
|
378
|
+
if (causticPhotonMap != null) {
|
|
379
|
+
causticPhotonMap.getSamples(state);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|