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,237 @@
|
|
|
1
|
+
package org.sunflow.core.renderer;
|
|
2
|
+
|
|
3
|
+
import org.sunflow.core.BucketOrder;
|
|
4
|
+
import org.sunflow.core.Display;
|
|
5
|
+
import org.sunflow.core.ImageSampler;
|
|
6
|
+
import org.sunflow.core.IntersectionState;
|
|
7
|
+
import org.sunflow.core.Options;
|
|
8
|
+
import org.sunflow.core.Scene;
|
|
9
|
+
import org.sunflow.core.ShadingCache;
|
|
10
|
+
import org.sunflow.core.ShadingState;
|
|
11
|
+
import org.sunflow.core.bucket.BucketOrderFactory;
|
|
12
|
+
import org.sunflow.image.Color;
|
|
13
|
+
import org.sunflow.math.MathUtils;
|
|
14
|
+
import org.sunflow.math.QMC;
|
|
15
|
+
import org.sunflow.system.Timer;
|
|
16
|
+
import org.sunflow.system.UI;
|
|
17
|
+
import org.sunflow.system.UI.Module;
|
|
18
|
+
|
|
19
|
+
public class MultipassRenderer implements ImageSampler {
|
|
20
|
+
|
|
21
|
+
private Scene scene;
|
|
22
|
+
private Display display;
|
|
23
|
+
// resolution
|
|
24
|
+
private int imageWidth;
|
|
25
|
+
private int imageHeight;
|
|
26
|
+
// bucketing
|
|
27
|
+
private String bucketOrderName;
|
|
28
|
+
private BucketOrder bucketOrder;
|
|
29
|
+
private int bucketSize;
|
|
30
|
+
private int bucketCounter;
|
|
31
|
+
private int[] bucketCoords;
|
|
32
|
+
// anti-aliasing
|
|
33
|
+
private int numSamples;
|
|
34
|
+
private float invNumSamples;
|
|
35
|
+
private boolean shadingCache;
|
|
36
|
+
|
|
37
|
+
public MultipassRenderer() {
|
|
38
|
+
bucketSize = 32;
|
|
39
|
+
bucketOrderName = "hilbert";
|
|
40
|
+
numSamples = 16;
|
|
41
|
+
shadingCache = false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@Override
|
|
45
|
+
public boolean prepare(Options options, Scene scene, int w, int h) {
|
|
46
|
+
this.scene = scene;
|
|
47
|
+
imageWidth = w;
|
|
48
|
+
imageHeight = h;
|
|
49
|
+
|
|
50
|
+
// fetch options
|
|
51
|
+
bucketSize = options.getInt("bucket.size", bucketSize);
|
|
52
|
+
bucketOrderName = options.getString("bucket.order", bucketOrderName);
|
|
53
|
+
numSamples = options.getInt("aa.samples", numSamples);
|
|
54
|
+
shadingCache = options.getBoolean("aa.cache", shadingCache);
|
|
55
|
+
|
|
56
|
+
// limit bucket size and compute number of buckets in each direction
|
|
57
|
+
bucketSize = MathUtils.clamp(bucketSize, 16, 512);
|
|
58
|
+
int numBucketsX = (imageWidth + bucketSize - 1) / bucketSize;
|
|
59
|
+
int numBucketsY = (imageHeight + bucketSize - 1) / bucketSize;
|
|
60
|
+
bucketOrder = BucketOrderFactory.create(bucketOrderName);
|
|
61
|
+
bucketCoords = bucketOrder.getBucketSequence(numBucketsX, numBucketsY);
|
|
62
|
+
// validate AA options
|
|
63
|
+
numSamples = Math.max(1, numSamples);
|
|
64
|
+
invNumSamples = 1.0f / numSamples;
|
|
65
|
+
// prepare QMC sampling
|
|
66
|
+
UI.printInfo(Module.BCKT, "Multipass renderer settings:");
|
|
67
|
+
UI.printInfo(Module.BCKT, " * Resolution: %dx%d", imageWidth, imageHeight);
|
|
68
|
+
UI.printInfo(Module.BCKT, " * Bucket size: %d", bucketSize);
|
|
69
|
+
UI.printInfo(Module.BCKT, " * Number of buckets: %dx%d", numBucketsX, numBucketsY);
|
|
70
|
+
UI.printInfo(Module.BCKT, " * Samples / pixel: %d", numSamples);
|
|
71
|
+
UI.printInfo(Module.BCKT, " * Shading cache: %s", shadingCache ? "enabled" : "disabled");
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@Override
|
|
76
|
+
public void render(Display display) {
|
|
77
|
+
this.display = display;
|
|
78
|
+
display.imageBegin(imageWidth, imageHeight, bucketSize);
|
|
79
|
+
// set members variables
|
|
80
|
+
bucketCounter = 0;
|
|
81
|
+
// start task
|
|
82
|
+
Timer timer = new Timer();
|
|
83
|
+
timer.start();
|
|
84
|
+
UI.taskStart("Rendering", 0, bucketCoords.length);
|
|
85
|
+
BucketThread[] renderThreads = new BucketThread[scene.getThreads()];
|
|
86
|
+
for (int i = 0; i < renderThreads.length; i++) {
|
|
87
|
+
renderThreads[i] = new BucketThread(i);
|
|
88
|
+
renderThreads[i].setPriority(scene.getThreadPriority());
|
|
89
|
+
renderThreads[i].start();
|
|
90
|
+
}
|
|
91
|
+
for (int i = 0; i < renderThreads.length; i++) {
|
|
92
|
+
try {
|
|
93
|
+
renderThreads[i].join();
|
|
94
|
+
} catch (InterruptedException e) {
|
|
95
|
+
UI.printError(Module.BCKT, "Bucket processing thread %d of %d was interrupted", i + 1, renderThreads.length);
|
|
96
|
+
} finally {
|
|
97
|
+
renderThreads[i].updateStats();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
UI.taskStop();
|
|
101
|
+
timer.end();
|
|
102
|
+
UI.printInfo(Module.BCKT, "Render time: %s", timer.toString());
|
|
103
|
+
display.imageEnd();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private class BucketThread extends Thread {
|
|
107
|
+
|
|
108
|
+
private final int threadID;
|
|
109
|
+
private final IntersectionState istate;
|
|
110
|
+
private final ShadingCache cache;
|
|
111
|
+
|
|
112
|
+
BucketThread(int threadID) {
|
|
113
|
+
this.threadID = threadID;
|
|
114
|
+
istate = new IntersectionState();
|
|
115
|
+
cache = shadingCache ? new ShadingCache() : null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@Override
|
|
119
|
+
public void run() {
|
|
120
|
+
while (true) {
|
|
121
|
+
int bx, by;
|
|
122
|
+
synchronized (MultipassRenderer.this) {
|
|
123
|
+
if (bucketCounter >= bucketCoords.length) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
UI.taskUpdate(bucketCounter);
|
|
127
|
+
bx = bucketCoords[bucketCounter + 0];
|
|
128
|
+
by = bucketCoords[bucketCounter + 1];
|
|
129
|
+
bucketCounter += 2;
|
|
130
|
+
}
|
|
131
|
+
renderBucket(display, bx, by, threadID, istate, cache);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
void updateStats() {
|
|
136
|
+
scene.accumulateStats(istate);
|
|
137
|
+
if (shadingCache) {
|
|
138
|
+
scene.accumulateStats(cache);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private void renderBucket(Display display, int bx, int by, int threadID, IntersectionState istate, ShadingCache cache) {
|
|
144
|
+
// pixel sized extents
|
|
145
|
+
int x0 = bx * bucketSize;
|
|
146
|
+
int y0 = by * bucketSize;
|
|
147
|
+
int bw = Math.min(bucketSize, imageWidth - x0);
|
|
148
|
+
int bh = Math.min(bucketSize, imageHeight - y0);
|
|
149
|
+
|
|
150
|
+
// prepare bucket
|
|
151
|
+
display.imagePrepare(x0, y0, bw, bh, threadID);
|
|
152
|
+
|
|
153
|
+
Color[] bucketRGB = new Color[bw * bh];
|
|
154
|
+
float[] bucketAlpha = new float[bw * bh];
|
|
155
|
+
|
|
156
|
+
for (int y = 0, i = 0, cy = imageHeight - 1 - y0; y < bh; y++, cy--) {
|
|
157
|
+
for (int x = 0, cx = x0; x < bw; x++, i++, cx++) {
|
|
158
|
+
// sample pixel
|
|
159
|
+
Color c = Color.black();
|
|
160
|
+
float a = 0;
|
|
161
|
+
int instance = ((cx & ((1 << QMC.MAX_SIGMA_ORDER) - 1)) << QMC.MAX_SIGMA_ORDER) + QMC.sigma(cy & ((1 << QMC.MAX_SIGMA_ORDER) - 1), QMC.MAX_SIGMA_ORDER);
|
|
162
|
+
double jitterX = QMC.halton(0, instance);
|
|
163
|
+
double jitterY = QMC.halton(1, instance);
|
|
164
|
+
double jitterT = QMC.halton(2, instance);
|
|
165
|
+
double jitterU = QMC.halton(3, instance);
|
|
166
|
+
double jitterV = QMC.halton(4, instance);
|
|
167
|
+
for (int s = 0; s < numSamples; s++) {
|
|
168
|
+
float rx = cx + 0.5f + (float) warpCubic(QMC.mod1(jitterX + s * invNumSamples));
|
|
169
|
+
float ry = cy + 0.5f + (float) warpCubic(QMC.mod1(jitterY + QMC.halton(0, s)));
|
|
170
|
+
double time = QMC.mod1(jitterT + QMC.halton(1, s));
|
|
171
|
+
double lensU = QMC.mod1(jitterU + QMC.halton(2, s));
|
|
172
|
+
double lensV = QMC.mod1(jitterV + QMC.halton(3, s));
|
|
173
|
+
ShadingState state = scene.getRadiance(istate, rx, ry, lensU, lensV, time, instance + s, 5, cache);
|
|
174
|
+
if (state != null) {
|
|
175
|
+
c.add(state.getResult());
|
|
176
|
+
a++;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
bucketRGB[i] = c.mul(invNumSamples);
|
|
180
|
+
bucketAlpha[i] = a * invNumSamples;
|
|
181
|
+
if (cache != null) {
|
|
182
|
+
cache.reset();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// update pixels
|
|
187
|
+
display.imageUpdate(x0, y0, bw, bh, bucketRGB, bucketAlpha);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Tent filter warping function.
|
|
192
|
+
*
|
|
193
|
+
* @param x sample in the [0,1) range
|
|
194
|
+
* @return warped sample in the [-1,+1) range
|
|
195
|
+
*/
|
|
196
|
+
@SuppressWarnings("unused")
|
|
197
|
+
private static float warpTent(float x) {
|
|
198
|
+
if (x < 0.5f) {
|
|
199
|
+
return -1 + (float) Math.sqrt(2 * x);
|
|
200
|
+
} else {
|
|
201
|
+
return +1 - (float) Math.sqrt(2 - 2 * x);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Cubic BSpline warping functions. Formulas from: "Generation of Stratified
|
|
207
|
+
* Samples for B-Spline Pixel Filtering"
|
|
208
|
+
* http://www.cs.utah.edu/~mstark/papers/
|
|
209
|
+
*
|
|
210
|
+
* @param x samples in the [0,1) range
|
|
211
|
+
* @return warped sample in the [-2,+2) range
|
|
212
|
+
*/
|
|
213
|
+
private static double warpCubic(double x) {
|
|
214
|
+
if (x < (1.0 / 24)) {
|
|
215
|
+
return qpow(24 * x) - 2;
|
|
216
|
+
}
|
|
217
|
+
if (x < 0.5f) {
|
|
218
|
+
return distb1((24.0 / 11.0) * (x - (1.0 / 24.0))) - 1;
|
|
219
|
+
}
|
|
220
|
+
if (x < (23.0f / 24)) {
|
|
221
|
+
return 1 - distb1((24.0 / 11.0) * ((23.0 / 24.0) - x));
|
|
222
|
+
}
|
|
223
|
+
return 2 - qpow(24 * (1 - x));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private static double qpow(double x) {
|
|
227
|
+
return Math.sqrt(Math.sqrt(x));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
private static double distb1(double x) {
|
|
231
|
+
double u = x;
|
|
232
|
+
for (int i = 0; i < 5; i++) {
|
|
233
|
+
u = (11 * x + u * u * (6 + u * (8 - 9 * u))) / (4 + 12 * u * (1 + u * (1 - u)));
|
|
234
|
+
}
|
|
235
|
+
return u;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
package org.sunflow.core.renderer;
|
|
2
|
+
|
|
3
|
+
import java.util.concurrent.PriorityBlockingQueue;
|
|
4
|
+
|
|
5
|
+
import org.sunflow.core.Display;
|
|
6
|
+
import org.sunflow.core.ImageSampler;
|
|
7
|
+
import org.sunflow.core.IntersectionState;
|
|
8
|
+
import org.sunflow.core.Options;
|
|
9
|
+
import org.sunflow.core.Scene;
|
|
10
|
+
import org.sunflow.core.ShadingState;
|
|
11
|
+
import org.sunflow.image.Color;
|
|
12
|
+
import org.sunflow.math.QMC;
|
|
13
|
+
import org.sunflow.system.Timer;
|
|
14
|
+
import org.sunflow.system.UI;
|
|
15
|
+
import org.sunflow.system.UI.Module;
|
|
16
|
+
|
|
17
|
+
public class ProgressiveRenderer implements ImageSampler {
|
|
18
|
+
|
|
19
|
+
private Scene scene;
|
|
20
|
+
private int imageWidth, imageHeight;
|
|
21
|
+
private PriorityBlockingQueue<SmallBucket> smallBucketQueue;
|
|
22
|
+
private Display display;
|
|
23
|
+
private int counter, counterMax;
|
|
24
|
+
|
|
25
|
+
public ProgressiveRenderer() {
|
|
26
|
+
imageWidth = 640;
|
|
27
|
+
imageHeight = 480;
|
|
28
|
+
smallBucketQueue = null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@Override
|
|
32
|
+
public boolean prepare(Options options, Scene scene, int w, int h) {
|
|
33
|
+
this.scene = scene;
|
|
34
|
+
imageWidth = w;
|
|
35
|
+
imageHeight = h;
|
|
36
|
+
// prepare table used by deterministic anti-aliasing
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@Override
|
|
41
|
+
public void render(Display display) {
|
|
42
|
+
this.display = display;
|
|
43
|
+
display.imageBegin(imageWidth, imageHeight, 0);
|
|
44
|
+
// create first bucket
|
|
45
|
+
SmallBucket b = new SmallBucket();
|
|
46
|
+
b.x = b.y = 0;
|
|
47
|
+
int s = Math.max(imageWidth, imageHeight);
|
|
48
|
+
b.size = 1;
|
|
49
|
+
while (b.size < s) {
|
|
50
|
+
b.size <<= 1;
|
|
51
|
+
}
|
|
52
|
+
smallBucketQueue = new PriorityBlockingQueue<>();
|
|
53
|
+
smallBucketQueue.add(b);
|
|
54
|
+
UI.taskStart("Progressive Render", 0, imageWidth * imageHeight);
|
|
55
|
+
Timer t = new Timer();
|
|
56
|
+
t.start();
|
|
57
|
+
counter = 0;
|
|
58
|
+
counterMax = imageWidth * imageHeight;
|
|
59
|
+
|
|
60
|
+
SmallBucketThread[] renderThreads = new SmallBucketThread[scene.getThreads()];
|
|
61
|
+
for (int i = 0; i < renderThreads.length; i++) {
|
|
62
|
+
renderThreads[i] = new SmallBucketThread();
|
|
63
|
+
renderThreads[i].start();
|
|
64
|
+
}
|
|
65
|
+
for (int i = 0; i < renderThreads.length; i++) {
|
|
66
|
+
try {
|
|
67
|
+
renderThreads[i].join();
|
|
68
|
+
} catch (InterruptedException e) {
|
|
69
|
+
UI.printError(Module.IPR, "Thread %d of %d was interrupted", i + 1, renderThreads.length);
|
|
70
|
+
} finally {
|
|
71
|
+
renderThreads[i].updateStats();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
UI.taskStop();
|
|
75
|
+
t.end();
|
|
76
|
+
UI.printInfo(Module.IPR, "Rendering time: %s", t.toString());
|
|
77
|
+
display.imageEnd();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private class SmallBucketThread extends Thread {
|
|
81
|
+
|
|
82
|
+
private final IntersectionState istate = new IntersectionState();
|
|
83
|
+
|
|
84
|
+
@Override
|
|
85
|
+
public void run() {
|
|
86
|
+
while (true) {
|
|
87
|
+
int n = progressiveRenderNext(istate);
|
|
88
|
+
synchronized (ProgressiveRenderer.this) {
|
|
89
|
+
if (counter >= counterMax) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
counter += n;
|
|
93
|
+
UI.taskUpdate(counter);
|
|
94
|
+
}
|
|
95
|
+
if (UI.taskCanceled()) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
void updateStats() {
|
|
102
|
+
scene.accumulateStats(istate);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private int progressiveRenderNext(IntersectionState istate) {
|
|
107
|
+
final int TASK_SIZE = 16;
|
|
108
|
+
SmallBucket first = smallBucketQueue.poll();
|
|
109
|
+
if (first == null) {
|
|
110
|
+
return 0;
|
|
111
|
+
}
|
|
112
|
+
int ds = first.size / TASK_SIZE;
|
|
113
|
+
boolean useMask = !smallBucketQueue.isEmpty();
|
|
114
|
+
int mask = 2 * first.size / TASK_SIZE - 1;
|
|
115
|
+
int pixels = 0;
|
|
116
|
+
for (int i = 0, y = first.y; i < TASK_SIZE && y < imageHeight; i++, y += ds) {
|
|
117
|
+
for (int j = 0, x = first.x; j < TASK_SIZE && x < imageWidth; j++, x += ds) {
|
|
118
|
+
// check to see if this is a pixel from a higher level tile
|
|
119
|
+
if (useMask && (x & mask) == 0 && (y & mask) == 0) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
int instance = ((x & ((1 << QMC.MAX_SIGMA_ORDER) - 1)) << QMC.MAX_SIGMA_ORDER) + QMC.sigma(y & ((1 << QMC.MAX_SIGMA_ORDER) - 1), QMC.MAX_SIGMA_ORDER);
|
|
123
|
+
double time = QMC.halton(1, instance);
|
|
124
|
+
double lensU = QMC.halton(2, instance);
|
|
125
|
+
double lensV = QMC.halton(3, instance);
|
|
126
|
+
ShadingState state = scene.getRadiance(istate, x, imageHeight - 1 - y, lensU, lensV, time, instance, 4, null);
|
|
127
|
+
Color c = state != null ? state.getResult() : Color.BLACK;
|
|
128
|
+
pixels++;
|
|
129
|
+
// fill region
|
|
130
|
+
display.imageFill(x, y, Math.min(ds, imageWidth - x), Math.min(ds, imageHeight - y), c, state == null ? 0 : 1);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (first.size >= 2 * TASK_SIZE) {
|
|
134
|
+
// generate child buckets
|
|
135
|
+
int size = first.size >>> 1;
|
|
136
|
+
for (int i = 0; i < 2; i++) {
|
|
137
|
+
if (first.y + i * size < imageHeight) {
|
|
138
|
+
for (int j = 0; j < 2; j++) {
|
|
139
|
+
if (first.x + j * size < imageWidth) {
|
|
140
|
+
SmallBucket b = new SmallBucket();
|
|
141
|
+
b.x = first.x + j * size;
|
|
142
|
+
b.y = first.y + i * size;
|
|
143
|
+
b.size = size;
|
|
144
|
+
b.constrast = 1.0f / size;
|
|
145
|
+
smallBucketQueue.put(b);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return pixels;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// progressive rendering
|
|
155
|
+
private static class SmallBucket implements Comparable<SmallBucket> {
|
|
156
|
+
|
|
157
|
+
int x, y, size;
|
|
158
|
+
float constrast;
|
|
159
|
+
|
|
160
|
+
@Override
|
|
161
|
+
public int compareTo(SmallBucket o) {
|
|
162
|
+
if (constrast < o.constrast) {
|
|
163
|
+
return -1;
|
|
164
|
+
}
|
|
165
|
+
if (constrast == o.constrast) {
|
|
166
|
+
return 0;
|
|
167
|
+
}
|
|
168
|
+
return 1;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
package org.sunflow.core.renderer;
|
|
2
|
+
|
|
3
|
+
import org.sunflow.core.Display;
|
|
4
|
+
import org.sunflow.core.ImageSampler;
|
|
5
|
+
import org.sunflow.core.IntersectionState;
|
|
6
|
+
import org.sunflow.core.Options;
|
|
7
|
+
import org.sunflow.core.Scene;
|
|
8
|
+
import org.sunflow.core.ShadingState;
|
|
9
|
+
import org.sunflow.image.Color;
|
|
10
|
+
import org.sunflow.system.Timer;
|
|
11
|
+
import org.sunflow.system.UI;
|
|
12
|
+
import org.sunflow.system.UI.Module;
|
|
13
|
+
|
|
14
|
+
public class SimpleRenderer implements ImageSampler {
|
|
15
|
+
|
|
16
|
+
private Scene scene;
|
|
17
|
+
private Display display;
|
|
18
|
+
private int imageWidth, imageHeight;
|
|
19
|
+
private int numBucketsX, numBucketsY;
|
|
20
|
+
private int bucketCounter, numBuckets;
|
|
21
|
+
|
|
22
|
+
@Override
|
|
23
|
+
public boolean prepare(Options options, Scene scene, int w, int h) {
|
|
24
|
+
this.scene = scene;
|
|
25
|
+
imageWidth = w;
|
|
26
|
+
imageHeight = h;
|
|
27
|
+
numBucketsX = (imageWidth + 31) >>> 5;
|
|
28
|
+
numBucketsY = (imageHeight + 31) >>> 5;
|
|
29
|
+
numBuckets = numBucketsX * numBucketsY;
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@Override
|
|
34
|
+
public void render(Display display) {
|
|
35
|
+
this.display = display;
|
|
36
|
+
display.imageBegin(imageWidth, imageHeight, 32);
|
|
37
|
+
// set members variables
|
|
38
|
+
bucketCounter = 0;
|
|
39
|
+
// start task
|
|
40
|
+
Timer timer = new Timer();
|
|
41
|
+
timer.start();
|
|
42
|
+
BucketThread[] renderThreads = new BucketThread[scene.getThreads()];
|
|
43
|
+
for (int i = 0; i < renderThreads.length; i++) {
|
|
44
|
+
renderThreads[i] = new BucketThread();
|
|
45
|
+
renderThreads[i].start();
|
|
46
|
+
}
|
|
47
|
+
for (int i = 0; i < renderThreads.length; i++) {
|
|
48
|
+
try {
|
|
49
|
+
renderThreads[i].join();
|
|
50
|
+
} catch (InterruptedException e) {
|
|
51
|
+
UI.printError(Module.BCKT, "Bucket processing thread %d of %d was interrupted", i + 1, renderThreads.length);
|
|
52
|
+
} finally {
|
|
53
|
+
renderThreads[i].updateStats();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
timer.end();
|
|
57
|
+
UI.printInfo(Module.BCKT, "Render time: %s", timer.toString());
|
|
58
|
+
display.imageEnd();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private class BucketThread extends Thread {
|
|
62
|
+
|
|
63
|
+
private final IntersectionState istate = new IntersectionState();
|
|
64
|
+
|
|
65
|
+
@Override
|
|
66
|
+
public void run() {
|
|
67
|
+
while (true) {
|
|
68
|
+
int bx, by;
|
|
69
|
+
synchronized (SimpleRenderer.this) {
|
|
70
|
+
if (bucketCounter >= numBuckets) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
by = bucketCounter / numBucketsX;
|
|
74
|
+
bx = bucketCounter % numBucketsX;
|
|
75
|
+
bucketCounter++;
|
|
76
|
+
}
|
|
77
|
+
renderBucket(bx, by, istate);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
void updateStats() {
|
|
82
|
+
scene.accumulateStats(istate);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public void renderBucket(int bx, int by, IntersectionState istate) {
|
|
87
|
+
// pixel sized extents
|
|
88
|
+
int x0 = bx * 32;
|
|
89
|
+
int y0 = by * 32;
|
|
90
|
+
int bw = Math.min(32, imageWidth - x0);
|
|
91
|
+
int bh = Math.min(32, imageHeight - y0);
|
|
92
|
+
|
|
93
|
+
Color[] bucketRGB = new Color[bw * bh];
|
|
94
|
+
float[] bucketAlpha = new float[bw * bh];
|
|
95
|
+
|
|
96
|
+
for (int y = 0, i = 0; y < bh; y++) {
|
|
97
|
+
for (int x = 0; x < bw; x++, i++) {
|
|
98
|
+
ShadingState state = scene.getRadiance(istate, x0 + x, imageHeight - 1 - (y0 + y), 0.0, 0.0, 0.0, 0, 0, null);
|
|
99
|
+
bucketRGB[i] = (state != null) ? state.getResult() : Color.BLACK;
|
|
100
|
+
bucketAlpha[i] = (state != null) ? 1 : 0;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// update pixels
|
|
104
|
+
display.imageUpdate(x0, y0, bw, bh, bucketRGB, bucketAlpha);
|
|
105
|
+
}
|
|
106
|
+
}
|