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,491 @@
|
|
|
1
|
+
package org.sunflow.core.renderer;
|
|
2
|
+
|
|
3
|
+
import org.sunflow.PluginRegistry;
|
|
4
|
+
import org.sunflow.core.BucketOrder;
|
|
5
|
+
import org.sunflow.core.Display;
|
|
6
|
+
import org.sunflow.core.Filter;
|
|
7
|
+
import org.sunflow.core.ImageSampler;
|
|
8
|
+
import org.sunflow.core.Instance;
|
|
9
|
+
import org.sunflow.core.IntersectionState;
|
|
10
|
+
import org.sunflow.core.Options;
|
|
11
|
+
import org.sunflow.core.Scene;
|
|
12
|
+
import org.sunflow.core.Shader;
|
|
13
|
+
import org.sunflow.core.ShadingState;
|
|
14
|
+
import org.sunflow.core.bucket.BucketOrderFactory;
|
|
15
|
+
import org.sunflow.core.filter.BoxFilter;
|
|
16
|
+
import org.sunflow.image.Color;
|
|
17
|
+
import org.sunflow.image.formats.GenericBitmap;
|
|
18
|
+
import org.sunflow.math.MathUtils;
|
|
19
|
+
import org.sunflow.math.QMC;
|
|
20
|
+
import org.sunflow.system.Timer;
|
|
21
|
+
import org.sunflow.system.UI;
|
|
22
|
+
import org.sunflow.system.UI.Module;
|
|
23
|
+
|
|
24
|
+
public class BucketRenderer implements ImageSampler {
|
|
25
|
+
|
|
26
|
+
private Scene scene;
|
|
27
|
+
private Display display;
|
|
28
|
+
// resolution
|
|
29
|
+
private int imageWidth;
|
|
30
|
+
private int imageHeight;
|
|
31
|
+
// bucketing
|
|
32
|
+
private String bucketOrderName;
|
|
33
|
+
private BucketOrder bucketOrder;
|
|
34
|
+
private int bucketSize;
|
|
35
|
+
private int bucketCounter;
|
|
36
|
+
private int[] bucketCoords;
|
|
37
|
+
private boolean dumpBuckets;
|
|
38
|
+
// anti-aliasing
|
|
39
|
+
private int minAADepth;
|
|
40
|
+
private int maxAADepth;
|
|
41
|
+
private int superSampling;
|
|
42
|
+
private float contrastThreshold;
|
|
43
|
+
private boolean jitter;
|
|
44
|
+
private boolean displayAA;
|
|
45
|
+
// derived quantities
|
|
46
|
+
private double invSuperSampling;
|
|
47
|
+
private int subPixelSize;
|
|
48
|
+
private int minStepSize;
|
|
49
|
+
private int maxStepSize;
|
|
50
|
+
private int sigmaOrder;
|
|
51
|
+
private int sigmaLength;
|
|
52
|
+
private float thresh;
|
|
53
|
+
private boolean useJitter;
|
|
54
|
+
// filtering
|
|
55
|
+
private String filterName;
|
|
56
|
+
private Filter filter;
|
|
57
|
+
private int fs;
|
|
58
|
+
private float fhs;
|
|
59
|
+
|
|
60
|
+
public BucketRenderer() {
|
|
61
|
+
bucketSize = 32;
|
|
62
|
+
bucketOrderName = "hilbert";
|
|
63
|
+
displayAA = false;
|
|
64
|
+
contrastThreshold = 0.1f;
|
|
65
|
+
filterName = "box";
|
|
66
|
+
jitter = false; // off by default
|
|
67
|
+
dumpBuckets = false; // for debugging only - not user settable
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public boolean prepare(Options options, Scene scene, int w, int h) {
|
|
71
|
+
this.scene = scene;
|
|
72
|
+
imageWidth = w;
|
|
73
|
+
imageHeight = h;
|
|
74
|
+
|
|
75
|
+
// fetch options
|
|
76
|
+
bucketSize = options.getInt("bucket.size", bucketSize);
|
|
77
|
+
bucketOrderName = options.getString("bucket.order", bucketOrderName);
|
|
78
|
+
minAADepth = options.getInt("aa.min", minAADepth);
|
|
79
|
+
maxAADepth = options.getInt("aa.max", maxAADepth);
|
|
80
|
+
superSampling = options.getInt("aa.samples", superSampling);
|
|
81
|
+
displayAA = options.getBoolean("aa.display", displayAA);
|
|
82
|
+
jitter = options.getBoolean("aa.jitter", jitter);
|
|
83
|
+
contrastThreshold = options.getFloat("aa.contrast", contrastThreshold);
|
|
84
|
+
|
|
85
|
+
// limit bucket size and compute number of buckets in each direction
|
|
86
|
+
bucketSize = MathUtils.clamp(bucketSize, 16, 512);
|
|
87
|
+
int numBucketsX = (imageWidth + bucketSize - 1) / bucketSize;
|
|
88
|
+
int numBucketsY = (imageHeight + bucketSize - 1) / bucketSize;
|
|
89
|
+
bucketOrder = BucketOrderFactory.create(bucketOrderName);
|
|
90
|
+
bucketCoords = bucketOrder.getBucketSequence(numBucketsX, numBucketsY);
|
|
91
|
+
// validate AA options
|
|
92
|
+
minAADepth = MathUtils.clamp(minAADepth, -4, 5);
|
|
93
|
+
maxAADepth = MathUtils.clamp(maxAADepth, minAADepth, 5);
|
|
94
|
+
superSampling = MathUtils.clamp(superSampling, 1, 256);
|
|
95
|
+
invSuperSampling = 1.0 / superSampling;
|
|
96
|
+
// compute AA stepping sizes
|
|
97
|
+
subPixelSize = (maxAADepth > 0) ? (1 << maxAADepth) : 1;
|
|
98
|
+
minStepSize = maxAADepth >= 0 ? 1 : 1 << (-maxAADepth);
|
|
99
|
+
if (minAADepth == maxAADepth) {
|
|
100
|
+
maxStepSize = minStepSize;
|
|
101
|
+
} else {
|
|
102
|
+
maxStepSize = minAADepth > 0 ? 1 << minAADepth : subPixelSize << (-minAADepth);
|
|
103
|
+
}
|
|
104
|
+
useJitter = jitter && maxAADepth > 0;
|
|
105
|
+
// compute anti-aliasing contrast thresholds
|
|
106
|
+
contrastThreshold = MathUtils.clamp(contrastThreshold, 0, 1);
|
|
107
|
+
thresh = contrastThreshold * (float) Math.pow(2.0f, minAADepth);
|
|
108
|
+
// read filter settings from scene
|
|
109
|
+
filterName = options.getString("filter", filterName);
|
|
110
|
+
filter = PluginRegistry.FILTER_PLUGINS.createObject(filterName);
|
|
111
|
+
// adjust filter
|
|
112
|
+
if (filter == null) {
|
|
113
|
+
UI.printWarning(Module.BCKT, "Unrecognized filter type: \"%s\" - defaulting to box", filterName);
|
|
114
|
+
filter = new BoxFilter();
|
|
115
|
+
filterName = "box";
|
|
116
|
+
}
|
|
117
|
+
fhs = filter.getSize() * 0.5f;
|
|
118
|
+
fs = (int) Math.ceil(subPixelSize * (fhs - 0.5f));
|
|
119
|
+
|
|
120
|
+
// prepare QMC sampling
|
|
121
|
+
sigmaOrder = Math.min(QMC.MAX_SIGMA_ORDER, Math.max(0, maxAADepth) + 13); // FIXME: how big should the table be?
|
|
122
|
+
sigmaLength = 1 << sigmaOrder;
|
|
123
|
+
UI.printInfo(Module.BCKT, "Bucket renderer settings:");
|
|
124
|
+
UI.printInfo(Module.BCKT, " * Resolution: %dx%d", imageWidth, imageHeight);
|
|
125
|
+
UI.printInfo(Module.BCKT, " * Bucket size: %d", bucketSize);
|
|
126
|
+
UI.printInfo(Module.BCKT, " * Number of buckets: %dx%d", numBucketsX, numBucketsY);
|
|
127
|
+
if (minAADepth != maxAADepth) {
|
|
128
|
+
UI.printInfo(Module.BCKT, " * Anti-aliasing: %s -> %s (adaptive)", aaDepthToString(minAADepth), aaDepthToString(maxAADepth));
|
|
129
|
+
} else {
|
|
130
|
+
UI.printInfo(Module.BCKT, " * Anti-aliasing: %s (fixed)", aaDepthToString(minAADepth));
|
|
131
|
+
}
|
|
132
|
+
UI.printInfo(Module.BCKT, " * Rays per sample: %d", superSampling);
|
|
133
|
+
UI.printInfo(Module.BCKT, " * Subpixel jitter: %s", useJitter ? "on" : (jitter ? "auto-off" : "off"));
|
|
134
|
+
UI.printInfo(Module.BCKT, " * Contrast threshold: %.2f", contrastThreshold);
|
|
135
|
+
UI.printInfo(Module.BCKT, " * Filter type: %s", filterName);
|
|
136
|
+
UI.printInfo(Module.BCKT, " * Filter size: %.2f pixels", filter.getSize());
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private String aaDepthToString(int depth) {
|
|
141
|
+
int pixelAA = (depth) < 0 ? -(1 << (-depth)) : (1 << depth);
|
|
142
|
+
return String.format("%s%d sample%s", depth < 0 ? "1/" : "", pixelAA * pixelAA, depth == 0 ? "" : "s");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
public void render(Display display) {
|
|
146
|
+
this.display = display;
|
|
147
|
+
display.imageBegin(imageWidth, imageHeight, bucketSize);
|
|
148
|
+
// set members variables
|
|
149
|
+
bucketCounter = 0;
|
|
150
|
+
// start task
|
|
151
|
+
UI.taskStart("Rendering", 0, bucketCoords.length);
|
|
152
|
+
Timer timer = new Timer();
|
|
153
|
+
timer.start();
|
|
154
|
+
BucketThread[] renderThreads = new BucketThread[scene.getThreads()];
|
|
155
|
+
for (int i = 0; i < renderThreads.length; i++) {
|
|
156
|
+
renderThreads[i] = new BucketThread(i);
|
|
157
|
+
renderThreads[i].setPriority(scene.getThreadPriority());
|
|
158
|
+
renderThreads[i].start();
|
|
159
|
+
}
|
|
160
|
+
for (int i = 0; i < renderThreads.length; i++) {
|
|
161
|
+
try {
|
|
162
|
+
renderThreads[i].join();
|
|
163
|
+
} catch (InterruptedException e) {
|
|
164
|
+
UI.printError(Module.BCKT, "Bucket processing thread %d of %d was interrupted", i + 1, renderThreads.length);
|
|
165
|
+
} finally {
|
|
166
|
+
renderThreads[i].updateStats();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
UI.taskStop();
|
|
170
|
+
timer.end();
|
|
171
|
+
UI.printInfo(Module.BCKT, "Render time: %s", timer.toString());
|
|
172
|
+
display.imageEnd();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private class BucketThread extends Thread {
|
|
176
|
+
|
|
177
|
+
private final int threadID;
|
|
178
|
+
private final IntersectionState istate;
|
|
179
|
+
|
|
180
|
+
BucketThread(int threadID) {
|
|
181
|
+
this.threadID = threadID;
|
|
182
|
+
istate = new IntersectionState();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@Override
|
|
186
|
+
public void run() {
|
|
187
|
+
while (true) {
|
|
188
|
+
int bx, by;
|
|
189
|
+
synchronized (BucketRenderer.this) {
|
|
190
|
+
if (bucketCounter >= bucketCoords.length) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
UI.taskUpdate(bucketCounter);
|
|
194
|
+
bx = bucketCoords[bucketCounter + 0];
|
|
195
|
+
by = bucketCoords[bucketCounter + 1];
|
|
196
|
+
bucketCounter += 2;
|
|
197
|
+
}
|
|
198
|
+
renderBucket(display, bx, by, threadID, istate);
|
|
199
|
+
if (UI.taskCanceled()) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
void updateStats() {
|
|
206
|
+
scene.accumulateStats(istate);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
private void renderBucket(Display display, int bx, int by, int threadID, IntersectionState istate) {
|
|
211
|
+
// pixel sized extents
|
|
212
|
+
int x0 = bx * bucketSize;
|
|
213
|
+
int y0 = by * bucketSize;
|
|
214
|
+
int bw = Math.min(bucketSize, imageWidth - x0);
|
|
215
|
+
int bh = Math.min(bucketSize, imageHeight - y0);
|
|
216
|
+
|
|
217
|
+
// prepare bucket
|
|
218
|
+
display.imagePrepare(x0, y0, bw, bh, threadID);
|
|
219
|
+
|
|
220
|
+
Color[] bucketRGB = new Color[bw * bh];
|
|
221
|
+
float[] bucketAlpha = new float[bw * bh];
|
|
222
|
+
|
|
223
|
+
// subpixel extents
|
|
224
|
+
int sx0 = x0 * subPixelSize - fs;
|
|
225
|
+
int sy0 = y0 * subPixelSize - fs;
|
|
226
|
+
int sbw = bw * subPixelSize + fs * 2;
|
|
227
|
+
int sbh = bh * subPixelSize + fs * 2;
|
|
228
|
+
|
|
229
|
+
// round up to align with maximum step size
|
|
230
|
+
sbw = (sbw + (maxStepSize - 1)) & (~(maxStepSize - 1));
|
|
231
|
+
sbh = (sbh + (maxStepSize - 1)) & (~(maxStepSize - 1));
|
|
232
|
+
// extra padding as needed
|
|
233
|
+
if (maxStepSize > 1) {
|
|
234
|
+
sbw++;
|
|
235
|
+
sbh++;
|
|
236
|
+
}
|
|
237
|
+
// allocate bucket memory
|
|
238
|
+
ImageSample[] samples = new ImageSample[sbw * sbh];
|
|
239
|
+
// allocate samples and compute jitter offsets
|
|
240
|
+
float invSubPixelSize = 1.0f / subPixelSize;
|
|
241
|
+
for (int y = 0, index = 0; y < sbh; y++) {
|
|
242
|
+
for (int x = 0; x < sbw; x++, index++) {
|
|
243
|
+
int sx = sx0 + x;
|
|
244
|
+
int sy = sy0 + y;
|
|
245
|
+
int j = sx & (sigmaLength - 1);
|
|
246
|
+
int k = sy & (sigmaLength - 1);
|
|
247
|
+
int i = (j << sigmaOrder) + QMC.sigma(k, sigmaOrder);
|
|
248
|
+
float dx = useJitter ? (float) QMC.halton(0, k) : 0.5f;
|
|
249
|
+
float dy = useJitter ? (float) QMC.halton(0, j) : 0.5f;
|
|
250
|
+
float rx = (sx + dx) * invSubPixelSize;
|
|
251
|
+
float ry = (sy + dy) * invSubPixelSize;
|
|
252
|
+
ry = imageHeight - ry;
|
|
253
|
+
samples[index] = new ImageSample(rx, ry, i);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
for (int x = 0; x < sbw - 1; x += maxStepSize) {
|
|
257
|
+
for (int y = 0; y < sbh - 1; y += maxStepSize) {
|
|
258
|
+
refineSamples(samples, sbw, x, y, maxStepSize, thresh, istate);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (dumpBuckets) {
|
|
262
|
+
UI.printInfo(Module.BCKT, "Dumping bucket [%d, %d] to file ...", bx, by);
|
|
263
|
+
GenericBitmap bitmap = new GenericBitmap(sbw, sbh);
|
|
264
|
+
for (int y = sbh - 1, index = 0; y >= 0; y--) {
|
|
265
|
+
for (int x = 0; x < sbw; x++, index++) {
|
|
266
|
+
bitmap.writePixel(x, y, samples[index].c, samples[index].alpha);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
bitmap.save(String.format("bucket_%04d_%04d.png", bx, by));
|
|
270
|
+
}
|
|
271
|
+
if (displayAA) {
|
|
272
|
+
// color coded image of what is visible
|
|
273
|
+
float invArea = invSubPixelSize * invSubPixelSize;
|
|
274
|
+
for (int y = 0, index = 0; y < bh; y++) {
|
|
275
|
+
for (int x = 0; x < bw; x++, index++) {
|
|
276
|
+
int sampled = 0;
|
|
277
|
+
for (int i = 0; i < subPixelSize; i++) {
|
|
278
|
+
for (int j = 0; j < subPixelSize; j++) {
|
|
279
|
+
int sx = x * subPixelSize + fs + i;
|
|
280
|
+
int sy = y * subPixelSize + fs + j;
|
|
281
|
+
int s = sx + sy * sbw;
|
|
282
|
+
sampled += samples[s].sampled() ? 1 : 0;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
bucketRGB[index] = new Color(sampled * invArea);
|
|
286
|
+
bucketAlpha[index] = 1.0f;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
} else {
|
|
290
|
+
// filter samples into pixels
|
|
291
|
+
float cy = imageHeight - (y0 + 0.5f);
|
|
292
|
+
for (int y = 0, index = 0; y < bh; y++, cy--) {
|
|
293
|
+
float cx = x0 + 0.5f;
|
|
294
|
+
for (int x = 0; x < bw; x++, index++, cx++) {
|
|
295
|
+
Color c = Color.black();
|
|
296
|
+
float a = 0;
|
|
297
|
+
float weight = 0.0f;
|
|
298
|
+
for (int j = -fs, sy = y * subPixelSize; j <= fs; j++, sy++) {
|
|
299
|
+
for (int i = -fs, sx = x * subPixelSize, s = sx + sy * sbw; i <= fs; i++, sx++, s++) {
|
|
300
|
+
float dx = samples[s].rx - cx;
|
|
301
|
+
if (Math.abs(dx) > fhs) {
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
float dy = samples[s].ry - cy;
|
|
305
|
+
if (Math.abs(dy) > fhs) {
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
float f = filter.get(dx, dy);
|
|
309
|
+
c.madd(f, samples[s].c);
|
|
310
|
+
a += f * samples[s].alpha;
|
|
311
|
+
weight += f;
|
|
312
|
+
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
float invWeight = 1.0f / weight;
|
|
316
|
+
c.mul(invWeight);
|
|
317
|
+
a *= invWeight;
|
|
318
|
+
bucketRGB[index] = c;
|
|
319
|
+
bucketAlpha[index] = a;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
// update pixels
|
|
324
|
+
display.imageUpdate(x0, y0, bw, bh, bucketRGB, bucketAlpha);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
private void computeSubPixel(ImageSample sample, IntersectionState istate) {
|
|
328
|
+
float x = sample.rx;
|
|
329
|
+
float y = sample.ry;
|
|
330
|
+
double q0 = QMC.halton(1, sample.i);
|
|
331
|
+
double q1 = QMC.halton(2, sample.i);
|
|
332
|
+
double q2 = QMC.halton(3, sample.i);
|
|
333
|
+
if (superSampling > 1) {
|
|
334
|
+
// multiple sampling
|
|
335
|
+
sample.add(scene.getRadiance(istate, x, y, q1, q2, q0, sample.i, 4, null));
|
|
336
|
+
for (int i = 1; i < superSampling; i++) {
|
|
337
|
+
double time = QMC.mod1(q0 + i * invSuperSampling);
|
|
338
|
+
double lensU = QMC.mod1(q1 + QMC.halton(0, i));
|
|
339
|
+
double lensV = QMC.mod1(q2 + QMC.halton(1, i));
|
|
340
|
+
sample.add(scene.getRadiance(istate, x, y, lensU, lensV, time, sample.i + i, 4, null));
|
|
341
|
+
}
|
|
342
|
+
sample.scale((float) invSuperSampling);
|
|
343
|
+
} else {
|
|
344
|
+
// single sample
|
|
345
|
+
sample.set(scene.getRadiance(istate, x, y, q1, q2, q0, sample.i, 4, null));
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
private void refineSamples(ImageSample[] samples, int sbw, int x, int y, int stepSize, float thresh, IntersectionState istate) {
|
|
350
|
+
int dx = stepSize;
|
|
351
|
+
int dy = stepSize * sbw;
|
|
352
|
+
int i00 = x + y * sbw;
|
|
353
|
+
ImageSample s00 = samples[i00];
|
|
354
|
+
ImageSample s01 = samples[i00 + dy];
|
|
355
|
+
ImageSample s10 = samples[i00 + dx];
|
|
356
|
+
ImageSample s11 = samples[i00 + dx + dy];
|
|
357
|
+
if (!s00.sampled()) {
|
|
358
|
+
computeSubPixel(s00, istate);
|
|
359
|
+
}
|
|
360
|
+
if (!s01.sampled()) {
|
|
361
|
+
computeSubPixel(s01, istate);
|
|
362
|
+
}
|
|
363
|
+
if (!s10.sampled()) {
|
|
364
|
+
computeSubPixel(s10, istate);
|
|
365
|
+
}
|
|
366
|
+
if (!s11.sampled()) {
|
|
367
|
+
computeSubPixel(s11, istate);
|
|
368
|
+
}
|
|
369
|
+
if (stepSize > minStepSize) {
|
|
370
|
+
if (s00.isDifferent(s01, thresh) || s00.isDifferent(s10, thresh) || s00.isDifferent(s11, thresh) || s01.isDifferent(s11, thresh) || s10.isDifferent(s11, thresh) || s01.isDifferent(s10, thresh)) {
|
|
371
|
+
stepSize >>= 1;
|
|
372
|
+
thresh *= 2;
|
|
373
|
+
refineSamples(samples, sbw, x, y, stepSize, thresh, istate);
|
|
374
|
+
refineSamples(samples, sbw, x + stepSize, y, stepSize, thresh, istate);
|
|
375
|
+
refineSamples(samples, sbw, x, y + stepSize, stepSize, thresh, istate);
|
|
376
|
+
refineSamples(samples, sbw, x + stepSize, y + stepSize, stepSize, thresh, istate);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// interpolate remaining samples
|
|
382
|
+
float ds = 1.0f / stepSize;
|
|
383
|
+
for (int i = 0; i <= stepSize; i++) {
|
|
384
|
+
for (int j = 0; j <= stepSize; j++) {
|
|
385
|
+
if (!samples[x + i + (y + j) * sbw].processed()) {
|
|
386
|
+
ImageSample.bilerp(samples[x + i + (y + j) * sbw], s00, s01, s10, s11, i * ds, j * ds);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
private static final class ImageSample {
|
|
393
|
+
|
|
394
|
+
float rx, ry;
|
|
395
|
+
int i, n;
|
|
396
|
+
Color c;
|
|
397
|
+
float alpha;
|
|
398
|
+
Instance instance;
|
|
399
|
+
Shader shader;
|
|
400
|
+
float nx, ny, nz;
|
|
401
|
+
|
|
402
|
+
ImageSample(float rx, float ry, int i) {
|
|
403
|
+
this.rx = rx;
|
|
404
|
+
this.ry = ry;
|
|
405
|
+
this.i = i;
|
|
406
|
+
n = 0;
|
|
407
|
+
c = null;
|
|
408
|
+
alpha = 0;
|
|
409
|
+
instance = null;
|
|
410
|
+
shader = null;
|
|
411
|
+
nx = ny = nz = 1;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
final void set(ShadingState state) {
|
|
415
|
+
if (state == null) {
|
|
416
|
+
c = Color.BLACK;
|
|
417
|
+
} else {
|
|
418
|
+
c = state.getResult();
|
|
419
|
+
shader = state.getShader();
|
|
420
|
+
instance = state.getInstance();
|
|
421
|
+
if (state.getNormal() != null) {
|
|
422
|
+
nx = state.getNormal().x;
|
|
423
|
+
ny = state.getNormal().y;
|
|
424
|
+
nz = state.getNormal().z;
|
|
425
|
+
}
|
|
426
|
+
alpha = state.getInstance() == null ? 0 : 1;
|
|
427
|
+
}
|
|
428
|
+
n = 1;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
final void add(ShadingState state) {
|
|
432
|
+
if (n == 0) {
|
|
433
|
+
c = Color.black();
|
|
434
|
+
}
|
|
435
|
+
if (state != null) {
|
|
436
|
+
c.add(state.getResult());
|
|
437
|
+
alpha += state.getInstance() == null ? 0 : 1;
|
|
438
|
+
}
|
|
439
|
+
n++;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
final void scale(float s) {
|
|
443
|
+
c.mul(s);
|
|
444
|
+
alpha *= s;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
final boolean processed() {
|
|
448
|
+
return c != null;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
final boolean sampled() {
|
|
452
|
+
return n > 0;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
final boolean isDifferent(ImageSample sample, float thresh) {
|
|
456
|
+
if (instance != sample.instance) {
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
if (shader != sample.shader) {
|
|
460
|
+
return true;
|
|
461
|
+
}
|
|
462
|
+
if (Color.hasContrast(c, sample.c, thresh)) {
|
|
463
|
+
return true;
|
|
464
|
+
}
|
|
465
|
+
if (Math.abs(alpha - sample.alpha) / (alpha + sample.alpha) > thresh) {
|
|
466
|
+
return true;
|
|
467
|
+
}
|
|
468
|
+
// only compare normals if this pixel has not been averaged
|
|
469
|
+
float dot = (nx * sample.nx + ny * sample.ny + nz * sample.nz);
|
|
470
|
+
return dot < 0.9f;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
static final ImageSample bilerp(ImageSample result, ImageSample i00, ImageSample i01, ImageSample i10, ImageSample i11, float dx, float dy) {
|
|
474
|
+
float k00 = (1.0f - dx) * (1.0f - dy);
|
|
475
|
+
float k01 = (1.0f - dx) * dy;
|
|
476
|
+
float k10 = dx * (1.0f - dy);
|
|
477
|
+
float k11 = dx * dy;
|
|
478
|
+
Color c00 = i00.c;
|
|
479
|
+
Color c01 = i01.c;
|
|
480
|
+
Color c10 = i10.c;
|
|
481
|
+
Color c11 = i11.c;
|
|
482
|
+
Color c = Color.mul(k00, c00);
|
|
483
|
+
c.madd(k01, c01);
|
|
484
|
+
c.madd(k10, c10);
|
|
485
|
+
c.madd(k11, c11);
|
|
486
|
+
result.c = c;
|
|
487
|
+
result.alpha = k00 * i00.alpha + k01 * i01.alpha + k10 * i10.alpha + k11 * i11.alpha;
|
|
488
|
+
return result;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|