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,65 @@
1
+ package org.sunflow.core.gi;
2
+
3
+ import org.sunflow.core.GIEngine;
4
+ import org.sunflow.core.Options;
5
+ import org.sunflow.core.Ray;
6
+ import org.sunflow.core.Scene;
7
+ import org.sunflow.core.ShadingState;
8
+ import org.sunflow.image.Color;
9
+ import org.sunflow.math.OrthoNormalBasis;
10
+ import org.sunflow.math.Vector3;
11
+ import org.sunflow.system.UI;
12
+ import org.sunflow.system.UI.Module;
13
+
14
+ public class PathTracingGIEngine implements GIEngine {
15
+
16
+ private int samples;
17
+
18
+ @Override
19
+ public boolean init(Options options, Scene scene) {
20
+ samples = options.getInt("gi.path.samples", 16);
21
+ samples = Math.max(0, samples);
22
+ UI.printInfo(Module.LIGHT, "Path tracer settings:");
23
+ UI.printInfo(Module.LIGHT, " * Samples: %d", samples);
24
+ return true;
25
+ }
26
+
27
+ @Override
28
+ public Color getIrradiance(ShadingState state, Color diffuseReflectance) {
29
+ if (samples <= 0) {
30
+ return Color.BLACK;
31
+ }
32
+ // compute new sample
33
+ Color irr = Color.black();
34
+ OrthoNormalBasis onb = state.getBasis();
35
+ Vector3 w = new Vector3();
36
+ int n = state.getDiffuseDepth() == 0 ? samples : 1;
37
+ for (int i = 0; i < n; i++) {
38
+ float xi = (float) state.getRandom(i, 0, n);
39
+ float xj = (float) state.getRandom(i, 1, n);
40
+ float phi = (float) (xi * 2 * Math.PI);
41
+ float cosPhi = (float) Math.cos(phi);
42
+ float sinPhi = (float) Math.sin(phi);
43
+ float sinTheta = (float) Math.sqrt(xj);
44
+ float cosTheta = (float) Math.sqrt(1.0f - xj);
45
+ w.x = cosPhi * sinTheta;
46
+ w.y = sinPhi * sinTheta;
47
+ w.z = cosTheta;
48
+ onb.transform(w);
49
+ ShadingState temp = state.traceFinalGather(new Ray(state.getPoint(), w), i);
50
+ if (temp != null) {
51
+ temp.getInstance().prepareShadingState(temp);
52
+ if (temp.getShader() != null) {
53
+ irr.add(temp.getShader().getRadiance(temp));
54
+ }
55
+ }
56
+ }
57
+ irr.mul((float) Math.PI / n);
58
+ return irr;
59
+ }
60
+
61
+ @Override
62
+ public Color getGlobalRadiance(ShadingState state) {
63
+ return Color.BLACK;
64
+ }
65
+ }
@@ -0,0 +1,103 @@
1
+ package org.sunflow.core.light;
2
+
3
+ import org.sunflow.SunflowAPI;
4
+ import org.sunflow.core.Instance;
5
+ import org.sunflow.core.LightSample;
6
+ import org.sunflow.core.LightSource;
7
+ import org.sunflow.core.ParameterList;
8
+ import org.sunflow.core.Ray;
9
+ import org.sunflow.core.ShadingState;
10
+ import org.sunflow.image.Color;
11
+ import org.sunflow.math.OrthoNormalBasis;
12
+ import org.sunflow.math.Point3;
13
+ import org.sunflow.math.Vector3;
14
+
15
+ public class DirectionalSpotlight implements LightSource {
16
+
17
+ private Point3 src;
18
+ private Vector3 dir;
19
+ private OrthoNormalBasis basis;
20
+ private float r, r2;
21
+ private Color radiance;
22
+
23
+ public DirectionalSpotlight() {
24
+ src = new Point3(0, 0, 0);
25
+ dir = new Vector3(0, 0, -1);
26
+ dir.normalize();
27
+ basis = OrthoNormalBasis.makeFromW(dir);
28
+ r = 1;
29
+ r2 = r * r;
30
+ radiance = Color.WHITE;
31
+ }
32
+
33
+ @Override
34
+ public boolean update(ParameterList pl, SunflowAPI api) {
35
+ src = pl.getPoint("source", src);
36
+ dir = pl.getVector("dir", dir);
37
+ dir.normalize();
38
+ r = pl.getFloat("radius", r);
39
+ basis = OrthoNormalBasis.makeFromW(dir);
40
+ r2 = r * r;
41
+ radiance = pl.getColor("radiance", radiance);
42
+ return true;
43
+ }
44
+
45
+ @Override
46
+ public int getNumSamples() {
47
+ return 1;
48
+ }
49
+
50
+ public int getLowSamples() {
51
+ return 1;
52
+ }
53
+
54
+ @Override
55
+ public void getSamples(ShadingState state) {
56
+ if (Vector3.dot(dir, state.getGeoNormal()) < 0 && Vector3.dot(dir, state.getNormal()) < 0) {
57
+ // project point onto source plane
58
+ float x = state.getPoint().x - src.x;
59
+ float y = state.getPoint().y - src.y;
60
+ float z = state.getPoint().z - src.z;
61
+ float t = ((x * dir.x) + (y * dir.y) + (z * dir.z));
62
+ if (t >= 0.0) {
63
+ x -= (t * dir.x);
64
+ y -= (t * dir.y);
65
+ z -= (t * dir.z);
66
+ if (((x * x) + (y * y) + (z * z)) <= r2) {
67
+ Point3 p = new Point3();
68
+ p.x = src.x + x;
69
+ p.y = src.y + y;
70
+ p.z = src.z + z;
71
+ LightSample dest = new LightSample();
72
+ dest.setShadowRay(new Ray(state.getPoint(), p));
73
+ dest.setRadiance(radiance, radiance);
74
+ dest.traceShadow(state);
75
+ state.addSample(dest);
76
+ }
77
+ }
78
+ }
79
+ }
80
+
81
+ @Override
82
+ public void getPhoton(double randX1, double randY1, double randX2, double randY2, Point3 p, Vector3 dir, Color power) {
83
+ float phi = (float) (2 * Math.PI * randX1);
84
+ float s = (float) Math.sqrt(1.0f - randY1);
85
+ dir.x = r * (float) Math.cos(phi) * s;
86
+ dir.y = r * (float) Math.sin(phi) * s;
87
+ dir.z = 0;
88
+ basis.transform(dir);
89
+ Point3.add(src, dir, p);
90
+ dir.set(this.dir);
91
+ power.set(radiance).mul((float) Math.PI * r2);
92
+ }
93
+
94
+ @Override
95
+ public float getPower() {
96
+ return radiance.copy().mul((float) Math.PI * r2).getLuminance();
97
+ }
98
+
99
+ @Override
100
+ public Instance createInstance() {
101
+ return null;
102
+ }
103
+ }
@@ -0,0 +1,303 @@
1
+ package org.sunflow.core.light;
2
+
3
+ import org.sunflow.SunflowAPI;
4
+ import org.sunflow.core.Instance;
5
+ import org.sunflow.core.IntersectionState;
6
+ import org.sunflow.core.LightSample;
7
+ import org.sunflow.core.LightSource;
8
+ import org.sunflow.core.ParameterList;
9
+ import org.sunflow.core.PrimitiveList;
10
+ import org.sunflow.core.Ray;
11
+ import org.sunflow.core.Shader;
12
+ import org.sunflow.core.ShadingState;
13
+ import org.sunflow.core.Texture;
14
+ import org.sunflow.core.TextureCache;
15
+ import org.sunflow.image.Bitmap;
16
+ import org.sunflow.image.Color;
17
+ import org.sunflow.math.BoundingBox;
18
+ import org.sunflow.math.Matrix4;
19
+ import org.sunflow.math.OrthoNormalBasis;
20
+ import org.sunflow.math.Point3;
21
+ import org.sunflow.math.QMC;
22
+ import org.sunflow.math.Vector3;
23
+
24
+ public class ImageBasedLight implements PrimitiveList, LightSource, Shader {
25
+
26
+ private Texture texture;
27
+ private OrthoNormalBasis basis;
28
+ private int numSamples;
29
+ private int numLowSamples;
30
+ private float jacobian;
31
+ private float[] colHistogram;
32
+ private float[][] imageHistogram;
33
+ private Vector3[] samples;
34
+ private Vector3[] lowSamples;
35
+ private Color[] colors;
36
+ private Color[] lowColors;
37
+
38
+ public ImageBasedLight() {
39
+ texture = null;
40
+ updateBasis(new Vector3(0, 0, -1), new Vector3(0, 1, 0));
41
+ numSamples = 64;
42
+ numLowSamples = 8;
43
+ }
44
+
45
+ private void updateBasis(Vector3 center, Vector3 up) {
46
+ if (center != null && up != null) {
47
+ basis = OrthoNormalBasis.makeFromWV(center, up);
48
+ basis.swapWU();
49
+ basis.flipV();
50
+ }
51
+ }
52
+
53
+ @Override
54
+ public boolean update(ParameterList pl, SunflowAPI api) {
55
+ updateBasis(pl.getVector("center", null), pl.getVector("up", null));
56
+ numSamples = pl.getInt("samples", numSamples);
57
+ numLowSamples = pl.getInt("lowsamples", numLowSamples);
58
+ String filename = pl.getString("texture", null);
59
+ if (filename != null) {
60
+ texture = TextureCache.getTexture(api.resolveTextureFilename(filename), false);
61
+ }
62
+
63
+ // no texture provided
64
+ if (texture == null) {
65
+ return false;
66
+ }
67
+ Bitmap b = texture.getBitmap();
68
+ if (b == null) {
69
+ return false;
70
+ }
71
+
72
+ // rebuild histograms if this is a new texture
73
+ if (filename != null) {
74
+ imageHistogram = new float[b.getWidth()][b.getHeight()];
75
+ colHistogram = new float[b.getWidth()];
76
+ float du = 1.0f / b.getWidth();
77
+ float dv = 1.0f / b.getHeight();
78
+ for (int x = 0; x < b.getWidth(); x++) {
79
+ for (int y = 0; y < b.getHeight(); y++) {
80
+ float u = (x + 0.5f) * du;
81
+ float v = (y + 0.5f) * dv;
82
+ Color c = texture.getPixel(u, v);
83
+ imageHistogram[x][y] = c.getLuminance() * (float) Math.sin(Math.PI * v);
84
+ if (y > 0) {
85
+ imageHistogram[x][y] += imageHistogram[x][y - 1];
86
+ }
87
+ }
88
+ colHistogram[x] = imageHistogram[x][b.getHeight() - 1];
89
+ if (x > 0) {
90
+ colHistogram[x] += colHistogram[x - 1];
91
+ }
92
+ for (int y = 0; y < b.getHeight(); y++) {
93
+ imageHistogram[x][y] /= imageHistogram[x][b.getHeight() - 1];
94
+ }
95
+ }
96
+ for (int x = 0; x < b.getWidth(); x++) {
97
+ colHistogram[x] /= colHistogram[b.getWidth() - 1];
98
+ }
99
+ jacobian = (float) (2 * Math.PI * Math.PI) / (b.getWidth() * b.getHeight());
100
+ }
101
+ // take fixed samples
102
+ if (pl.getBoolean("fixed", samples != null)) {
103
+ // high density samples
104
+ samples = new Vector3[numSamples];
105
+ colors = new Color[numSamples];
106
+ generateFixedSamples(samples, colors);
107
+ // low density samples
108
+ lowSamples = new Vector3[numLowSamples];
109
+ lowColors = new Color[numLowSamples];
110
+ generateFixedSamples(lowSamples, lowColors);
111
+ } else {
112
+ // turn off
113
+ samples = lowSamples = null;
114
+ colors = lowColors = null;
115
+ }
116
+ return true;
117
+ }
118
+
119
+ private void generateFixedSamples(Vector3[] samples, Color[] colors) {
120
+ for (int i = 0; i < samples.length; i++) {
121
+ double randX = (double) i / (double) samples.length;
122
+ double randY = QMC.halton(0, i);
123
+ int x = 0;
124
+ while (randX >= colHistogram[x] && x < colHistogram.length - 1) {
125
+ x++;
126
+ }
127
+ float[] rowHistogram = imageHistogram[x];
128
+ int y = 0;
129
+ while (randY >= rowHistogram[y] && y < rowHistogram.length - 1) {
130
+ y++;
131
+ }
132
+ // sample from (x, y)
133
+ float u = (float) ((x == 0) ? (randX / colHistogram[0]) : ((randX - colHistogram[x - 1]) / (colHistogram[x] - colHistogram[x - 1])));
134
+ float v = (float) ((y == 0) ? (randY / rowHistogram[0]) : ((randY - rowHistogram[y - 1]) / (rowHistogram[y] - rowHistogram[y - 1])));
135
+
136
+ float px = ((x == 0) ? colHistogram[0] : (colHistogram[x] - colHistogram[x - 1]));
137
+ float py = ((y == 0) ? rowHistogram[0] : (rowHistogram[y] - rowHistogram[y - 1]));
138
+
139
+ float su = (x + u) / colHistogram.length;
140
+ float sv = (y + v) / rowHistogram.length;
141
+
142
+ float invP = (float) Math.sin(sv * Math.PI) * jacobian / (numSamples * px * py);
143
+ samples[i] = getDirection(su, sv);
144
+ basis.transform(samples[i]);
145
+ colors[i] = texture.getPixel(su, sv).mul(invP);
146
+ }
147
+ }
148
+
149
+ @Override
150
+ public void prepareShadingState(ShadingState state) {
151
+ if (state.includeLights()) {
152
+ state.setShader(this);
153
+ }
154
+ }
155
+
156
+ @Override
157
+ public void intersectPrimitive(Ray r, int primID, IntersectionState state) {
158
+ if (r.getMax() == Float.POSITIVE_INFINITY) {
159
+ state.setIntersection(0);
160
+ }
161
+ }
162
+
163
+ @Override
164
+ public int getNumPrimitives() {
165
+ return 1;
166
+ }
167
+
168
+ @Override
169
+ public float getPrimitiveBound(int primID, int i) {
170
+ return 0;
171
+ }
172
+
173
+ @Override
174
+ public BoundingBox getWorldBounds(Matrix4 o2w) {
175
+ return null;
176
+ }
177
+
178
+ @Override
179
+ public PrimitiveList getBakingPrimitives() {
180
+ return null;
181
+ }
182
+
183
+ @Override
184
+ public int getNumSamples() {
185
+ return numSamples;
186
+ }
187
+
188
+ @Override
189
+ public void getSamples(ShadingState state) {
190
+ if (samples == null) {
191
+ int n = state.getDiffuseDepth() > 0 ? 1 : numSamples;
192
+ for (int i = 0; i < n; i++) {
193
+ // random offset on unit square, we use the infinite version of
194
+ // getRandom because the light sampling is adaptive
195
+ double randX = state.getRandom(i, 0, n);
196
+ double randY = state.getRandom(i, 1, n);
197
+ int x = 0;
198
+ while (randX >= colHistogram[x] && x < colHistogram.length - 1) {
199
+ x++;
200
+ }
201
+ float[] rowHistogram = imageHistogram[x];
202
+ int y = 0;
203
+ while (randY >= rowHistogram[y] && y < rowHistogram.length - 1) {
204
+ y++;
205
+ }
206
+ // sample from (x, y)
207
+ float u = (float) ((x == 0) ? (randX / colHistogram[0]) : ((randX - colHistogram[x - 1]) / (colHistogram[x] - colHistogram[x - 1])));
208
+ float v = (float) ((y == 0) ? (randY / rowHistogram[0]) : ((randY - rowHistogram[y - 1]) / (rowHistogram[y] - rowHistogram[y - 1])));
209
+
210
+ float px = ((x == 0) ? colHistogram[0] : (colHistogram[x] - colHistogram[x - 1]));
211
+ float py = ((y == 0) ? rowHistogram[0] : (rowHistogram[y] - rowHistogram[y - 1]));
212
+
213
+ float su = (x + u) / colHistogram.length;
214
+ float sv = (y + v) / rowHistogram.length;
215
+ float invP = (float) Math.sin(sv * Math.PI) * jacobian / (n * px * py);
216
+ Vector3 dir = getDirection(su, sv);
217
+ basis.transform(dir);
218
+ if (Vector3.dot(dir, state.getGeoNormal()) > 0) {
219
+ LightSample dest = new LightSample();
220
+ dest.setShadowRay(new Ray(state.getPoint(), dir));
221
+ dest.getShadowRay().setMax(Float.MAX_VALUE);
222
+ Color radiance = texture.getPixel(su, sv);
223
+ dest.setRadiance(radiance, radiance);
224
+ dest.getDiffuseRadiance().mul(invP);
225
+ dest.getSpecularRadiance().mul(invP);
226
+ dest.traceShadow(state);
227
+ state.addSample(dest);
228
+ }
229
+ }
230
+ } else {
231
+ if (state.getDiffuseDepth() > 0) {
232
+ for (int i = 0; i < numLowSamples; i++) {
233
+ if (Vector3.dot(lowSamples[i], state.getGeoNormal()) > 0 && Vector3.dot(lowSamples[i], state.getNormal()) > 0) {
234
+ LightSample dest = new LightSample();
235
+ dest.setShadowRay(new Ray(state.getPoint(), lowSamples[i]));
236
+ dest.getShadowRay().setMax(Float.MAX_VALUE);
237
+ dest.setRadiance(lowColors[i], lowColors[i]);
238
+ dest.traceShadow(state);
239
+ state.addSample(dest);
240
+ }
241
+ }
242
+ } else {
243
+ for (int i = 0; i < numSamples; i++) {
244
+ if (Vector3.dot(samples[i], state.getGeoNormal()) > 0 && Vector3.dot(samples[i], state.getNormal()) > 0) {
245
+ LightSample dest = new LightSample();
246
+ dest.setShadowRay(new Ray(state.getPoint(), samples[i]));
247
+ dest.getShadowRay().setMax(Float.MAX_VALUE);
248
+ dest.setRadiance(colors[i], colors[i]);
249
+ dest.traceShadow(state);
250
+ state.addSample(dest);
251
+ }
252
+ }
253
+ }
254
+ }
255
+ }
256
+
257
+ @Override
258
+ public void getPhoton(double randX1, double randY1, double randX2, double randY2, Point3 p, Vector3 dir, Color power) {
259
+ }
260
+
261
+ @Override
262
+ public Color getRadiance(ShadingState state) {
263
+ // lookup texture based on ray direction
264
+ return state.includeLights() ? getColor(basis.untransform(state.getRay().getDirection(), new Vector3())) : Color.BLACK;
265
+ }
266
+
267
+ private Color getColor(Vector3 dir) {
268
+ float u, v;
269
+ // assume lon/lat format
270
+ double phi = 0, theta = 0;
271
+ phi = Math.acos(dir.y);
272
+ theta = Math.atan2(dir.z, dir.x);
273
+ u = (float) (0.5 - 0.5 * theta / Math.PI);
274
+ v = (float) (phi / Math.PI);
275
+ return texture.getPixel(u, v);
276
+ }
277
+
278
+ private Vector3 getDirection(float u, float v) {
279
+ Vector3 dest = new Vector3();
280
+ double phi = 0, theta = 0;
281
+ theta = u * 2 * Math.PI;
282
+ phi = v * Math.PI;
283
+ double sin_phi = Math.sin(phi);
284
+ dest.x = (float) (-sin_phi * Math.cos(theta));
285
+ dest.y = (float) Math.cos(phi);
286
+ dest.z = (float) (sin_phi * Math.sin(theta));
287
+ return dest;
288
+ }
289
+
290
+ @Override
291
+ public void scatterPhoton(ShadingState state, Color power) {
292
+ }
293
+
294
+ @Override
295
+ public float getPower() {
296
+ return 0;
297
+ }
298
+
299
+ @Override
300
+ public Instance createInstance() {
301
+ return Instance.createTemporary(this, null, this);
302
+ }
303
+ }