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.
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
+ }