joonsrenderer 1.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (255) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +53 -0
  3. data/.mvn/extensions.xml +8 -0
  4. data/CHANGELOG.md +2 -0
  5. data/Gemfile +6 -0
  6. data/LICENSE +674 -0
  7. data/README.md +2 -0
  8. data/Rakefile +43 -0
  9. data/docs/.gitignore +6 -0
  10. data/docs/_config.yml +20 -0
  11. data/docs/_includes/footer.html +38 -0
  12. data/docs/_includes/head.html +15 -0
  13. data/docs/_includes/header.html +27 -0
  14. data/docs/_includes/icon-github.html +1 -0
  15. data/docs/_includes/icon-github.svg +1 -0
  16. data/docs/_includes/icon-twitter.html +1 -0
  17. data/docs/_includes/icon-twitter.svg +1 -0
  18. data/docs/_layouts/default.html +20 -0
  19. data/docs/_layouts/page.html +14 -0
  20. data/docs/_layouts/post.html +15 -0
  21. data/docs/_posts/2017-01-08-animated_ray_tracing.md +72 -0
  22. data/docs/_posts/2017-01-08-welcome.md +78 -0
  23. data/docs/_sass/_base.scss +206 -0
  24. data/docs/_sass/_layout.scss +242 -0
  25. data/docs/_sass/_syntax-highlighting.scss +71 -0
  26. data/docs/about.md +12 -0
  27. data/docs/assets/Animation.ogv +0 -0
  28. data/docs/assets/Animation.png +0 -0
  29. data/docs/assets/basic.png +0 -0
  30. data/docs/assets/basic_traced.png +0 -0
  31. data/docs/css/main.scss +38 -0
  32. data/docs/favicon.ico +0 -0
  33. data/docs/feed.xml +30 -0
  34. data/docs/index.html +38 -0
  35. data/joonsrenderer.gemspec +23 -0
  36. data/lib/joonsrenderer.rb +12 -0
  37. data/lib/joonsrenderer/version.rb +3 -0
  38. data/pom.rb +75 -0
  39. data/pom.xml +163 -0
  40. data/src/main/java/SunflowGUI.java +1354 -0
  41. data/src/main/java/joons/JRFiller.java +79 -0
  42. data/src/main/java/joons/JRImagePanel.java +141 -0
  43. data/src/main/java/joons/JRRecorder.java +183 -0
  44. data/src/main/java/joons/JRStatics.java +199 -0
  45. data/src/main/java/joons/JoonsRenderer.java +837 -0
  46. data/src/main/java/org/sunflow/AsciiFileSunflowAPI.java +98 -0
  47. data/src/main/java/org/sunflow/Benchmark.java +313 -0
  48. data/src/main/java/org/sunflow/BinaryFileSunflowAPI.java +228 -0
  49. data/src/main/java/org/sunflow/FileSunflowAPI.java +354 -0
  50. data/src/main/java/org/sunflow/PluginRegistry.java +322 -0
  51. data/src/main/java/org/sunflow/RealtimeBenchmark.java +125 -0
  52. data/src/main/java/org/sunflow/RenderObjectMap.java +344 -0
  53. data/src/main/java/org/sunflow/SunflowAPI.java +762 -0
  54. data/src/main/java/org/sunflow/SunflowAPIInterface.java +277 -0
  55. data/src/main/java/org/sunflow/core/AccelerationStructure.java +20 -0
  56. data/src/main/java/org/sunflow/core/AccelerationStructureFactory.java +36 -0
  57. data/src/main/java/org/sunflow/core/BucketOrder.java +21 -0
  58. data/src/main/java/org/sunflow/core/Camera.java +125 -0
  59. data/src/main/java/org/sunflow/core/CameraLens.java +29 -0
  60. data/src/main/java/org/sunflow/core/CausticPhotonMapInterface.java +15 -0
  61. data/src/main/java/org/sunflow/core/Display.java +78 -0
  62. data/src/main/java/org/sunflow/core/Filter.java +27 -0
  63. data/src/main/java/org/sunflow/core/GIEngine.java +42 -0
  64. data/src/main/java/org/sunflow/core/Geometry.java +157 -0
  65. data/src/main/java/org/sunflow/core/GlobalPhotonMapInterface.java +21 -0
  66. data/src/main/java/org/sunflow/core/ImageSampler.java +26 -0
  67. data/src/main/java/org/sunflow/core/Instance.java +224 -0
  68. data/src/main/java/org/sunflow/core/InstanceList.java +83 -0
  69. data/src/main/java/org/sunflow/core/IntersectionState.java +120 -0
  70. data/src/main/java/org/sunflow/core/LightSample.java +104 -0
  71. data/src/main/java/org/sunflow/core/LightServer.java +382 -0
  72. data/src/main/java/org/sunflow/core/LightSource.java +67 -0
  73. data/src/main/java/org/sunflow/core/Modifier.java +16 -0
  74. data/src/main/java/org/sunflow/core/Options.java +20 -0
  75. data/src/main/java/org/sunflow/core/ParameterList.java +758 -0
  76. data/src/main/java/org/sunflow/core/PhotonStore.java +62 -0
  77. data/src/main/java/org/sunflow/core/PrimitiveList.java +70 -0
  78. data/src/main/java/org/sunflow/core/Ray.java +219 -0
  79. data/src/main/java/org/sunflow/core/RenderObject.java +25 -0
  80. data/src/main/java/org/sunflow/core/Scene.java +377 -0
  81. data/src/main/java/org/sunflow/core/SceneParser.java +58 -0
  82. data/src/main/java/org/sunflow/core/Shader.java +30 -0
  83. data/src/main/java/org/sunflow/core/ShadingCache.java +84 -0
  84. data/src/main/java/org/sunflow/core/ShadingState.java +939 -0
  85. data/src/main/java/org/sunflow/core/Statistics.java +85 -0
  86. data/src/main/java/org/sunflow/core/Tesselatable.java +36 -0
  87. data/src/main/java/org/sunflow/core/Texture.java +128 -0
  88. data/src/main/java/org/sunflow/core/TextureCache.java +48 -0
  89. data/src/main/java/org/sunflow/core/accel/BoundingIntervalHierarchy.java +652 -0
  90. data/src/main/java/org/sunflow/core/accel/KDTree.java +833 -0
  91. data/src/main/java/org/sunflow/core/accel/NullAccelerator.java +30 -0
  92. data/src/main/java/org/sunflow/core/accel/UniformGrid.java +329 -0
  93. data/src/main/java/org/sunflow/core/bucket/BucketOrderFactory.java +26 -0
  94. data/src/main/java/org/sunflow/core/bucket/ColumnBucketOrder.java +21 -0
  95. data/src/main/java/org/sunflow/core/bucket/DiagonalBucketOrder.java +28 -0
  96. data/src/main/java/org/sunflow/core/bucket/HilbertBucketOrder.java +65 -0
  97. data/src/main/java/org/sunflow/core/bucket/InvertedBucketOrder.java +28 -0
  98. data/src/main/java/org/sunflow/core/bucket/RandomBucketOrder.java +49 -0
  99. data/src/main/java/org/sunflow/core/bucket/RowBucketOrder.java +21 -0
  100. data/src/main/java/org/sunflow/core/bucket/SpiralBucketOrder.java +43 -0
  101. data/src/main/java/org/sunflow/core/camera/FisheyeLens.java +25 -0
  102. data/src/main/java/org/sunflow/core/camera/PinholeLens.java +43 -0
  103. data/src/main/java/org/sunflow/core/camera/SphericalLens.java +22 -0
  104. data/src/main/java/org/sunflow/core/camera/ThinLens.java +107 -0
  105. data/src/main/java/org/sunflow/core/display/FastDisplay.java +119 -0
  106. data/src/main/java/org/sunflow/core/display/FileDisplay.java +83 -0
  107. data/src/main/java/org/sunflow/core/display/FrameDisplay.java +97 -0
  108. data/src/main/java/org/sunflow/core/display/ImgPipeDisplay.java +109 -0
  109. data/src/main/java/org/sunflow/core/filter/BlackmanHarrisFilter.java +28 -0
  110. data/src/main/java/org/sunflow/core/filter/BoxFilter.java +16 -0
  111. data/src/main/java/org/sunflow/core/filter/CatmullRomFilter.java +29 -0
  112. data/src/main/java/org/sunflow/core/filter/CubicBSpline.java +32 -0
  113. data/src/main/java/org/sunflow/core/filter/GaussianFilter.java +24 -0
  114. data/src/main/java/org/sunflow/core/filter/LanczosFilter.java +30 -0
  115. data/src/main/java/org/sunflow/core/filter/MitchellFilter.java +28 -0
  116. data/src/main/java/org/sunflow/core/filter/SincFilter.java +25 -0
  117. data/src/main/java/org/sunflow/core/filter/TriangleFilter.java +16 -0
  118. data/src/main/java/org/sunflow/core/gi/AmbientOcclusionGIEngine.java +57 -0
  119. data/src/main/java/org/sunflow/core/gi/FakeGIEngine.java +48 -0
  120. data/src/main/java/org/sunflow/core/gi/InstantGI.java +194 -0
  121. data/src/main/java/org/sunflow/core/gi/IrradianceCacheGIEngine.java +268 -0
  122. data/src/main/java/org/sunflow/core/gi/PathTracingGIEngine.java +65 -0
  123. data/src/main/java/org/sunflow/core/light/DirectionalSpotlight.java +103 -0
  124. data/src/main/java/org/sunflow/core/light/ImageBasedLight.java +303 -0
  125. data/src/main/java/org/sunflow/core/light/PointLight.java +72 -0
  126. data/src/main/java/org/sunflow/core/light/SphereLight.java +166 -0
  127. data/src/main/java/org/sunflow/core/light/SunSkyLight.java +362 -0
  128. data/src/main/java/org/sunflow/core/light/TriangleMeshLight.java +296 -0
  129. data/src/main/java/org/sunflow/core/modifiers/BumpMappingModifier.java +37 -0
  130. data/src/main/java/org/sunflow/core/modifiers/NormalMapModifier.java +34 -0
  131. data/src/main/java/org/sunflow/core/modifiers/PerlinModifier.java +80 -0
  132. data/src/main/java/org/sunflow/core/parser/Keyword.java +39 -0
  133. data/src/main/java/org/sunflow/core/parser/RA2Parser.java +107 -0
  134. data/src/main/java/org/sunflow/core/parser/RA3Parser.java +68 -0
  135. data/src/main/java/org/sunflow/core/parser/SCAbstractParser.java +299 -0
  136. data/src/main/java/org/sunflow/core/parser/SCAsciiParser.java +251 -0
  137. data/src/main/java/org/sunflow/core/parser/SCBinaryParser.java +156 -0
  138. data/src/main/java/org/sunflow/core/parser/SCParser.java +1403 -0
  139. data/src/main/java/org/sunflow/core/parser/ShaveRibParser.java +174 -0
  140. data/src/main/java/org/sunflow/core/parser/TriParser.java +79 -0
  141. data/src/main/java/org/sunflow/core/photonmap/CausticPhotonMap.java +429 -0
  142. data/src/main/java/org/sunflow/core/photonmap/GlobalPhotonMap.java +530 -0
  143. data/src/main/java/org/sunflow/core/photonmap/GridPhotonMap.java +308 -0
  144. data/src/main/java/org/sunflow/core/primitive/Background.java +55 -0
  145. data/src/main/java/org/sunflow/core/primitive/BanchoffSurface.java +100 -0
  146. data/src/main/java/org/sunflow/core/primitive/Box.java +210 -0
  147. data/src/main/java/org/sunflow/core/primitive/CornellBox.java +476 -0
  148. data/src/main/java/org/sunflow/core/primitive/CubeGrid.java +318 -0
  149. data/src/main/java/org/sunflow/core/primitive/Cylinder.java +104 -0
  150. data/src/main/java/org/sunflow/core/primitive/Hair.java +275 -0
  151. data/src/main/java/org/sunflow/core/primitive/JuliaFractal.java +266 -0
  152. data/src/main/java/org/sunflow/core/primitive/ParticleSurface.java +114 -0
  153. data/src/main/java/org/sunflow/core/primitive/Plane.java +163 -0
  154. data/src/main/java/org/sunflow/core/primitive/QuadMesh.java +413 -0
  155. data/src/main/java/org/sunflow/core/primitive/Sphere.java +101 -0
  156. data/src/main/java/org/sunflow/core/primitive/SphereFlake.java +234 -0
  157. data/src/main/java/org/sunflow/core/primitive/Torus.java +145 -0
  158. data/src/main/java/org/sunflow/core/primitive/TriangleMesh.java +849 -0
  159. data/src/main/java/org/sunflow/core/renderer/BucketRenderer.java +491 -0
  160. data/src/main/java/org/sunflow/core/renderer/MultipassRenderer.java +237 -0
  161. data/src/main/java/org/sunflow/core/renderer/ProgressiveRenderer.java +171 -0
  162. data/src/main/java/org/sunflow/core/renderer/SimpleRenderer.java +106 -0
  163. data/src/main/java/org/sunflow/core/shader/AmbientOcclusionShader.java +53 -0
  164. data/src/main/java/org/sunflow/core/shader/AnisotropicWardShader.java +216 -0
  165. data/src/main/java/org/sunflow/core/shader/ConstantShader.java +31 -0
  166. data/src/main/java/org/sunflow/core/shader/DiffuseShader.java +65 -0
  167. data/src/main/java/org/sunflow/core/shader/GlassShader.java +147 -0
  168. data/src/main/java/org/sunflow/core/shader/IDShader.java +27 -0
  169. data/src/main/java/org/sunflow/core/shader/MirrorShader.java +68 -0
  170. data/src/main/java/org/sunflow/core/shader/NormalShader.java +32 -0
  171. data/src/main/java/org/sunflow/core/shader/PhongShader.java +89 -0
  172. data/src/main/java/org/sunflow/core/shader/PrimIDShader.java +30 -0
  173. data/src/main/java/org/sunflow/core/shader/QuickGrayShader.java +63 -0
  174. data/src/main/java/org/sunflow/core/shader/ShinyDiffuseShader.java +98 -0
  175. data/src/main/java/org/sunflow/core/shader/SimpleShader.java +24 -0
  176. data/src/main/java/org/sunflow/core/shader/TexturedAmbientOcclusionShader.java +31 -0
  177. data/src/main/java/org/sunflow/core/shader/TexturedDiffuseShader.java +31 -0
  178. data/src/main/java/org/sunflow/core/shader/TexturedPhongShader.java +31 -0
  179. data/src/main/java/org/sunflow/core/shader/TexturedShinyDiffuseShader.java +31 -0
  180. data/src/main/java/org/sunflow/core/shader/TexturedWardShader.java +31 -0
  181. data/src/main/java/org/sunflow/core/shader/UVShader.java +27 -0
  182. data/src/main/java/org/sunflow/core/shader/UberShader.java +149 -0
  183. data/src/main/java/org/sunflow/core/shader/ViewCausticsShader.java +33 -0
  184. data/src/main/java/org/sunflow/core/shader/ViewGlobalPhotonsShader.java +25 -0
  185. data/src/main/java/org/sunflow/core/shader/ViewIrradianceShader.java +25 -0
  186. data/src/main/java/org/sunflow/core/shader/WireframeShader.java +83 -0
  187. data/src/main/java/org/sunflow/core/tesselatable/BezierMesh.java +254 -0
  188. data/src/main/java/org/sunflow/core/tesselatable/FileMesh.java +251 -0
  189. data/src/main/java/org/sunflow/core/tesselatable/Gumbo.java +1147 -0
  190. data/src/main/java/org/sunflow/core/tesselatable/Teapot.java +237 -0
  191. data/src/main/java/org/sunflow/image/Bitmap.java +15 -0
  192. data/src/main/java/org/sunflow/image/BitmapReader.java +39 -0
  193. data/src/main/java/org/sunflow/image/BitmapWriter.java +79 -0
  194. data/src/main/java/org/sunflow/image/BlackbodySpectrum.java +16 -0
  195. data/src/main/java/org/sunflow/image/ChromaticitySpectrum.java +55 -0
  196. data/src/main/java/org/sunflow/image/Color.java +374 -0
  197. data/src/main/java/org/sunflow/image/ColorEncoder.java +94 -0
  198. data/src/main/java/org/sunflow/image/ColorFactory.java +122 -0
  199. data/src/main/java/org/sunflow/image/ConstantSpectralCurve.java +21 -0
  200. data/src/main/java/org/sunflow/image/IrregularSpectralCurve.java +57 -0
  201. data/src/main/java/org/sunflow/image/RGBSpace.java +207 -0
  202. data/src/main/java/org/sunflow/image/RegularSpectralCurve.java +30 -0
  203. data/src/main/java/org/sunflow/image/SpectralCurve.java +118 -0
  204. data/src/main/java/org/sunflow/image/XYZColor.java +50 -0
  205. data/src/main/java/org/sunflow/image/formats/BitmapBlack.java +27 -0
  206. data/src/main/java/org/sunflow/image/formats/BitmapG8.java +36 -0
  207. data/src/main/java/org/sunflow/image/formats/BitmapGA8.java +30 -0
  208. data/src/main/java/org/sunflow/image/formats/BitmapRGB8.java +40 -0
  209. data/src/main/java/org/sunflow/image/formats/BitmapRGBA8.java +40 -0
  210. data/src/main/java/org/sunflow/image/formats/BitmapRGBE.java +60 -0
  211. data/src/main/java/org/sunflow/image/formats/BitmapXYZ.java +38 -0
  212. data/src/main/java/org/sunflow/image/formats/GenericBitmap.java +73 -0
  213. data/src/main/java/org/sunflow/image/readers/BMPBitmapReader.java +39 -0
  214. data/src/main/java/org/sunflow/image/readers/HDRBitmapReader.java +155 -0
  215. data/src/main/java/org/sunflow/image/readers/IGIBitmapReader.java +104 -0
  216. data/src/main/java/org/sunflow/image/readers/JPGBitmapReader.java +39 -0
  217. data/src/main/java/org/sunflow/image/readers/PNGBitmapReader.java +40 -0
  218. data/src/main/java/org/sunflow/image/readers/TGABitmapReader.java +141 -0
  219. data/src/main/java/org/sunflow/image/writers/EXRBitmapWriter.java +395 -0
  220. data/src/main/java/org/sunflow/image/writers/HDRBitmapWriter.java +54 -0
  221. data/src/main/java/org/sunflow/image/writers/IGIBitmapWriter.java +75 -0
  222. data/src/main/java/org/sunflow/image/writers/PNGBitmapWriter.java +39 -0
  223. data/src/main/java/org/sunflow/image/writers/TGABitmapWriter.java +63 -0
  224. data/src/main/java/org/sunflow/math/BoundingBox.java +340 -0
  225. data/src/main/java/org/sunflow/math/MathUtils.java +159 -0
  226. data/src/main/java/org/sunflow/math/Matrix4.java +573 -0
  227. data/src/main/java/org/sunflow/math/MovingMatrix4.java +119 -0
  228. data/src/main/java/org/sunflow/math/OrthoNormalBasis.java +110 -0
  229. data/src/main/java/org/sunflow/math/PerlinScalar.java +331 -0
  230. data/src/main/java/org/sunflow/math/PerlinVector.java +132 -0
  231. data/src/main/java/org/sunflow/math/Point2.java +36 -0
  232. data/src/main/java/org/sunflow/math/Point3.java +133 -0
  233. data/src/main/java/org/sunflow/math/QMC.java +209 -0
  234. data/src/main/java/org/sunflow/math/Solvers.java +142 -0
  235. data/src/main/java/org/sunflow/math/Vector3.java +197 -0
  236. data/src/main/java/org/sunflow/system/BenchmarkFramework.java +73 -0
  237. data/src/main/java/org/sunflow/system/BenchmarkTest.java +17 -0
  238. data/src/main/java/org/sunflow/system/ByteUtil.java +119 -0
  239. data/src/main/java/org/sunflow/system/FileUtils.java +27 -0
  240. data/src/main/java/org/sunflow/system/ImagePanel.java +282 -0
  241. data/src/main/java/org/sunflow/system/Memory.java +18 -0
  242. data/src/main/java/org/sunflow/system/Parser.java +162 -0
  243. data/src/main/java/org/sunflow/system/Plugins.java +142 -0
  244. data/src/main/java/org/sunflow/system/RenderGlobalsPanel.java +209 -0
  245. data/src/main/java/org/sunflow/system/SearchPath.java +67 -0
  246. data/src/main/java/org/sunflow/system/Timer.java +53 -0
  247. data/src/main/java/org/sunflow/system/UI.java +112 -0
  248. data/src/main/java/org/sunflow/system/UserInterface.java +46 -0
  249. data/src/main/java/org/sunflow/system/ui/ConsoleInterface.java +48 -0
  250. data/src/main/java/org/sunflow/system/ui/SilentInterface.java +28 -0
  251. data/src/main/java/org/sunflow/util/FastHashMap.java +220 -0
  252. data/src/main/java/org/sunflow/util/FloatArray.java +77 -0
  253. data/src/main/java/org/sunflow/util/IntArray.java +77 -0
  254. data/src/test/java/a_maintest.java +129 -0
  255. 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
+ }