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,72 @@
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.Point3;
12
+ import org.sunflow.math.Vector3;
13
+
14
+ public class PointLight implements LightSource {
15
+
16
+ private Point3 lightPoint;
17
+ private Color power;
18
+
19
+ public PointLight() {
20
+ lightPoint = new Point3(0, 0, 0);
21
+ power = Color.WHITE;
22
+ }
23
+
24
+ @Override
25
+ public boolean update(ParameterList pl, SunflowAPI api) {
26
+ lightPoint = pl.getPoint("center", lightPoint);
27
+ power = pl.getColor("power", power);
28
+ return true;
29
+ }
30
+
31
+ @Override
32
+ public int getNumSamples() {
33
+ return 1;
34
+ }
35
+
36
+ @Override
37
+ public void getSamples(ShadingState state) {
38
+ Vector3 d = Point3.sub(lightPoint, state.getPoint(), new Vector3());
39
+ if (Vector3.dot(d, state.getNormal()) > 0 && Vector3.dot(d, state.getGeoNormal()) > 0) {
40
+ LightSample dest = new LightSample();
41
+ // prepare shadow ray
42
+ dest.setShadowRay(new Ray(state.getPoint(), lightPoint));
43
+ float scale = 1.0f / (float) (4 * Math.PI * lightPoint.distanceToSquared(state.getPoint()));
44
+ dest.setRadiance(power, power);
45
+ dest.getDiffuseRadiance().mul(scale);
46
+ dest.getSpecularRadiance().mul(scale);
47
+ dest.traceShadow(state);
48
+ state.addSample(dest);
49
+ }
50
+ }
51
+
52
+ @Override
53
+ public void getPhoton(double randX1, double randY1, double randX2, double randY2, Point3 p, Vector3 dir, Color power) {
54
+ p.set(lightPoint);
55
+ float phi = (float) (2 * Math.PI * randX1);
56
+ float s = (float) Math.sqrt(randY1 * (1.0f - randY1));
57
+ dir.x = (float) Math.cos(phi) * s;
58
+ dir.y = (float) Math.sin(phi) * s;
59
+ dir.z = (float) (1 - 2 * randY1);
60
+ power.set(this.power);
61
+ }
62
+
63
+ @Override
64
+ public float getPower() {
65
+ return power.getLuminance();
66
+ }
67
+
68
+ @Override
69
+ public Instance createInstance() {
70
+ return null;
71
+ }
72
+ }
@@ -0,0 +1,166 @@
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.Shader;
10
+ import org.sunflow.core.ShadingState;
11
+ import org.sunflow.core.primitive.Sphere;
12
+ import org.sunflow.image.Color;
13
+ import org.sunflow.math.Matrix4;
14
+ import org.sunflow.math.OrthoNormalBasis;
15
+ import org.sunflow.math.Point3;
16
+ import org.sunflow.math.Solvers;
17
+ import org.sunflow.math.Vector3;
18
+
19
+ public class SphereLight implements LightSource, Shader {
20
+
21
+ private Color radiance;
22
+ private int numSamples;
23
+ private Point3 center;
24
+ private float radius;
25
+ private float r2;
26
+
27
+ public SphereLight() {
28
+ radiance = Color.WHITE;
29
+ numSamples = 4;
30
+ center = new Point3();
31
+ radius = r2 = 1;
32
+ }
33
+
34
+ @Override
35
+ public boolean update(ParameterList pl, SunflowAPI api) {
36
+ radiance = pl.getColor("radiance", radiance);
37
+ numSamples = pl.getInt("samples", numSamples);
38
+ radius = pl.getFloat("radius", radius);
39
+ r2 = radius * radius;
40
+ center = pl.getPoint("center", center);
41
+ return true;
42
+ }
43
+
44
+ @Override
45
+ public int getNumSamples() {
46
+ return numSamples;
47
+ }
48
+
49
+ public int getLowSamples() {
50
+ return 1;
51
+ }
52
+
53
+ public boolean isVisible(ShadingState state) {
54
+ return state.getPoint().distanceToSquared(center) > r2;
55
+ }
56
+
57
+ public void getSamples(ShadingState state) {
58
+ if (getNumSamples() <= 0) {
59
+ return;
60
+ }
61
+ Vector3 wc = Point3.sub(center, state.getPoint(), new Vector3());
62
+ float l2 = wc.lengthSquared();
63
+ if (l2 <= r2) {
64
+ return; // inside the sphere?
65
+ } // top of the sphere as viewed from the current shading point
66
+ float topX = wc.x + state.getNormal().x * radius;
67
+ float topY = wc.y + state.getNormal().y * radius;
68
+ float topZ = wc.z + state.getNormal().z * radius;
69
+ if (state.getNormal().dot(topX, topY, topZ) <= 0) {
70
+ return; // top of the sphere is below the horizon
71
+ }
72
+ float cosThetaMax = (float) Math.sqrt(Math.max(0, 1 - r2 / Vector3.dot(wc, wc)));
73
+ OrthoNormalBasis basis = OrthoNormalBasis.makeFromW(wc);
74
+ int samples = state.getDiffuseDepth() > 0 ? 1 : getNumSamples();
75
+ float scale = (float) (2 * Math.PI * (1 - cosThetaMax));
76
+ Color c = Color.mul(scale / samples, radiance);
77
+ for (int i = 0; i < samples; i++) {
78
+ // random offset on unit square
79
+ double randX = state.getRandom(i, 0, samples);
80
+ double randY = state.getRandom(i, 1, samples);
81
+
82
+ // cone sampling
83
+ double cosTheta = (1 - randX) * cosThetaMax + randX;
84
+ double sinTheta = Math.sqrt(1 - cosTheta * cosTheta);
85
+ double phi = randY * 2 * Math.PI;
86
+ Vector3 dir = new Vector3((float) (Math.cos(phi) * sinTheta), (float) (Math.sin(phi) * sinTheta), (float) cosTheta);
87
+ basis.transform(dir);
88
+
89
+ // check that the direction of the sample is the same as the
90
+ // normal
91
+ float cosNx = Vector3.dot(dir, state.getNormal());
92
+ if (cosNx <= 0) {
93
+ continue;
94
+ }
95
+
96
+ float ocx = state.getPoint().x - center.x;
97
+ float ocy = state.getPoint().y - center.y;
98
+ float ocz = state.getPoint().z - center.z;
99
+ float qa = Vector3.dot(dir, dir);
100
+ float qb = 2 * ((dir.x * ocx) + (dir.y * ocy) + (dir.z * ocz));
101
+ float qc = ((ocx * ocx) + (ocy * ocy) + (ocz * ocz)) - r2;
102
+ double[] t = Solvers.solveQuadric(qa, qb, qc);
103
+ if (t == null) {
104
+ continue;
105
+ }
106
+ LightSample dest = new LightSample();
107
+ // compute shadow ray to the sampled point
108
+ dest.setShadowRay(new Ray(state.getPoint(), dir));
109
+ // FIXME: arbitrary bias, should handle as in other places
110
+ dest.getShadowRay().setMax((float) t[0] - 1e-3f);
111
+ // prepare sample
112
+ dest.setRadiance(c, c);
113
+ dest.traceShadow(state);
114
+ state.addSample(dest);
115
+ }
116
+ }
117
+
118
+ @Override
119
+ public void getPhoton(double randX1, double randY1, double randX2, double randY2, Point3 p, Vector3 dir, Color power) {
120
+ float z = (float) (1 - 2 * randX2);
121
+ float r = (float) Math.sqrt(Math.max(0, 1 - z * z));
122
+ float phi = (float) (2 * Math.PI * randY2);
123
+ float x = r * (float) Math.cos(phi);
124
+ float y = r * (float) Math.sin(phi);
125
+ p.x = center.x + x * radius;
126
+ p.y = center.y + y * radius;
127
+ p.z = center.z + z * radius;
128
+ OrthoNormalBasis basis = OrthoNormalBasis.makeFromW(new Vector3(x, y, z));
129
+ phi = (float) (2 * Math.PI * randX1);
130
+ float cosPhi = (float) Math.cos(phi);
131
+ float sinPhi = (float) Math.sin(phi);
132
+ float sinTheta = (float) Math.sqrt(randY1);
133
+ float cosTheta = (float) Math.sqrt(1 - randY1);
134
+ dir.x = cosPhi * sinTheta;
135
+ dir.y = sinPhi * sinTheta;
136
+ dir.z = cosTheta;
137
+ basis.transform(dir);
138
+ power.set(radiance);
139
+ power.mul((float) (Math.PI * Math.PI * 4 * r2));
140
+ }
141
+
142
+ @Override
143
+ public float getPower() {
144
+ return radiance.copy().mul((float) (Math.PI * Math.PI * 4 * r2)).getLuminance();
145
+ }
146
+
147
+ @Override
148
+ public Color getRadiance(ShadingState state) {
149
+ if (!state.includeLights()) {
150
+ return Color.BLACK;
151
+ }
152
+ state.faceforward();
153
+ // emit constant radiance
154
+ return state.isBehind() ? Color.BLACK : radiance;
155
+ }
156
+
157
+ @Override
158
+ public void scatterPhoton(ShadingState state, Color power) {
159
+ // do not scatter photons
160
+ }
161
+
162
+ @Override
163
+ public Instance createInstance() {
164
+ return Instance.createTemporary(new Sphere(), Matrix4.translation(center.x, center.y, center.z).multiply(Matrix4.scale(radius)), this);
165
+ }
166
+ }
@@ -0,0 +1,362 @@
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.image.ChromaticitySpectrum;
14
+ import org.sunflow.image.Color;
15
+ import org.sunflow.image.ConstantSpectralCurve;
16
+ import org.sunflow.image.IrregularSpectralCurve;
17
+ import org.sunflow.image.RGBSpace;
18
+ import org.sunflow.image.RegularSpectralCurve;
19
+ import org.sunflow.image.SpectralCurve;
20
+ import org.sunflow.image.XYZColor;
21
+ import org.sunflow.math.BoundingBox;
22
+ import org.sunflow.math.MathUtils;
23
+ import org.sunflow.math.Matrix4;
24
+ import org.sunflow.math.OrthoNormalBasis;
25
+ import org.sunflow.math.Point3;
26
+ import org.sunflow.math.Vector3;
27
+
28
+ public class SunSkyLight implements LightSource, PrimitiveList, Shader {
29
+ // sunflow parameters
30
+
31
+ private int numSkySamples;
32
+ private OrthoNormalBasis basis;
33
+ private boolean groundExtendSky;
34
+ private Color groundColor;
35
+ // parameters to the model
36
+ private Vector3 sunDirWorld;
37
+ private float turbidity;
38
+ // derived quantities
39
+ private Vector3 sunDir;
40
+ private SpectralCurve sunSpectralRadiance;
41
+ private Color sunColor;
42
+ private float sunTheta;
43
+ private double zenithY, zenithx, zenithy;
44
+ private final double[] perezY = new double[5];
45
+ private final double[] perezx = new double[5];
46
+ private final double[] perezy = new double[5];
47
+ private float jacobian;
48
+ private float[] colHistogram;
49
+ private float[][] imageHistogram;
50
+ // constant data
51
+ private static final float[] SOL_AMPLITUDES = {165.5f, 162.3f, 211.2f,
52
+ 258.8f, 258.2f, 242.3f, 267.6f, 296.6f, 305.4f, 300.6f, 306.6f,
53
+ 288.3f, 287.1f, 278.2f, 271.0f, 272.3f, 263.6f, 255.0f, 250.6f,
54
+ 253.1f, 253.5f, 251.3f, 246.3f, 241.7f, 236.8f, 232.1f, 228.2f,
55
+ 223.4f, 219.7f, 215.3f, 211.0f, 207.3f, 202.4f, 198.7f, 194.3f,
56
+ 190.7f, 186.3f, 182.6f};
57
+ private static final RegularSpectralCurve SOL_CURVE = new RegularSpectralCurve(SOL_AMPLITUDES, 380, 750);
58
+ private static final float[] K_OWAVELENGTHS = {300, 305, 310, 315, 320,
59
+ 325, 330, 335, 340, 345, 350, 355, 445, 450, 455, 460, 465, 470,
60
+ 475, 480, 485, 490, 495, 500, 505, 510, 515, 520, 525, 530, 535,
61
+ 540, 545, 550, 555, 560, 565, 570, 575, 580, 585, 590, 595, 600,
62
+ 605, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720,
63
+ 730, 740, 750, 760, 770, 780, 790,};
64
+ private static final float[] K_OAMPLITUDES = {10.0f, 4.8f, 2.7f, 1.35f,
65
+ .8f, .380f, .160f, .075f, .04f, .019f, .007f, .0f, .003f, .003f,
66
+ .004f, .006f, .008f, .009f, .012f, .014f, .017f, .021f, .025f,
67
+ .03f, .035f, .04f, .045f, .048f, .057f, .063f, .07f, .075f, .08f,
68
+ .085f, .095f, .103f, .110f, .12f, .122f, .12f, .118f, .115f, .12f,
69
+ .125f, .130f, .12f, .105f, .09f, .079f, .067f, .057f, .048f, .036f,
70
+ .028f, .023f, .018f, .014f, .011f, .010f, .009f, .007f, .004f, .0f,
71
+ .0f};
72
+ private static final float[] K_GWAVELENGTHS = {759, 760, 770, 771};
73
+ private static final float[] K_GAMPLITUDES = {0, 3.0f, 0.210f, 0};
74
+ private static final float[] K_WA_WAVELENGTHS = {689, 690, 700, 710, 720,
75
+ 730, 740, 750, 760, 770, 780, 790, 800};
76
+ private static final float[] K_WA_AMPLITUDES = {0f, 0.160e-1f, 0.240e-1f,
77
+ 0.125e-1f, 0.100e+1f, 0.870f, 0.610e-1f, 0.100e-2f, 0.100e-4f,
78
+ 0.100e-4f, 0.600e-3f, 0.175e-1f, 0.360e-1f};
79
+ private static final IrregularSpectralCurve K_OCURVE = new IrregularSpectralCurve(K_OWAVELENGTHS, K_OAMPLITUDES);
80
+ private static final IrregularSpectralCurve K_GCURVE = new IrregularSpectralCurve(K_GWAVELENGTHS, K_GAMPLITUDES);
81
+ private static final IrregularSpectralCurve K_WA_CURVE = new IrregularSpectralCurve(K_WA_WAVELENGTHS, K_WA_AMPLITUDES);
82
+
83
+ public SunSkyLight() {
84
+ numSkySamples = 64;
85
+ sunDirWorld = new Vector3(1, 1, 1);
86
+ turbidity = 6;
87
+ basis = OrthoNormalBasis.makeFromWV(new Vector3(0, 0, 1), new Vector3(0, 1, 0));
88
+ groundExtendSky = false;
89
+ groundColor = Color.BLACK;
90
+ initSunSky();
91
+ }
92
+
93
+ private SpectralCurve computeAttenuatedSunlight(float theta, float turbidity) {
94
+ float[] data = new float[91]; // holds the sunsky curve data
95
+ final double alpha = 1.3;
96
+ final double lozone = 0.35;
97
+ final double w = 2.0;
98
+ double beta = 0.04608365822050 * turbidity - 0.04586025928522;
99
+ // Relative optical mass
100
+ double m = 1.0 / (Math.cos(theta) + 0.000940 * Math.pow(1.6386 - theta, -1.253));
101
+ for (int i = 0, lambda = 350; lambda <= 800; i++, lambda += 5) {
102
+ // Rayleigh scattering
103
+ double tauR = Math.exp(-m * 0.008735 * Math.pow(lambda / 1000.0, -4.08));
104
+ // Aerosol (water + dust) attenuation
105
+ double tauA = Math.exp(-m * beta * Math.pow(lambda / 1000.0, -alpha));
106
+ // Attenuation due to ozone absorption
107
+ double tauO = Math.exp(-m * K_OCURVE.sample(lambda) * lozone);
108
+ // Attenuation due to mixed gases absorption
109
+ double tauG = Math.exp(-1.41 * K_GCURVE.sample(lambda) * m / Math.pow(1.0 + 118.93 * K_GCURVE.sample(lambda) * m, 0.45));
110
+ // Attenuation due to water vapor absorption
111
+ double tauWA = Math.exp(-0.2385 * K_WA_CURVE.sample(lambda) * w * m / Math.pow(1.0 + 20.07 * K_WA_CURVE.sample(lambda) * w * m, 0.45));
112
+ // 100.0 comes from SOL_AMPLITUDES begin in wrong units.
113
+ double amp = /* 100.0 * */ SOL_CURVE.sample(lambda) * tauR * tauA * tauO * tauG * tauWA;
114
+ data[i] = (float) amp;
115
+ }
116
+ return new RegularSpectralCurve(data, 350, 800);
117
+ }
118
+
119
+ private double perezFunction(final double[] lam, double theta, double gamma, double lvz) {
120
+ double den = ((1.0 + lam[0] * Math.exp(lam[1])) * (1.0 + lam[2] * Math.exp(lam[3] * sunTheta) + lam[4] * Math.cos(sunTheta) * Math.cos(sunTheta)));
121
+ double num = ((1.0 + lam[0] * Math.exp(lam[1] / Math.cos(theta))) * (1.0 + lam[2] * Math.exp(lam[3] * gamma) + lam[4] * Math.cos(gamma) * Math.cos(gamma)));
122
+ return lvz * num / den;
123
+ }
124
+
125
+ private void initSunSky() {
126
+ // perform all the required initialization of constants
127
+ sunDirWorld.normalize();
128
+ sunDir = basis.untransform(sunDirWorld, new Vector3());
129
+ sunDir.normalize();
130
+ sunTheta = (float) Math.acos(MathUtils.clamp(sunDir.z, -1, 1));
131
+ if (sunDir.z > 0) {
132
+ sunSpectralRadiance = computeAttenuatedSunlight(sunTheta, turbidity);
133
+ // produce color suitable for rendering
134
+ sunColor = RGBSpace.SRGB.convertXYZtoRGB(sunSpectralRadiance.toXYZ().mul(1e-4f)).constrainRGB();
135
+ } else {
136
+ sunSpectralRadiance = new ConstantSpectralCurve(0);
137
+ }
138
+ // sunSolidAngle = (float) (0.25 * Math.PI * 1.39 * 1.39 / (150 * 150));
139
+ float theta2 = sunTheta * sunTheta;
140
+ float theta3 = sunTheta * theta2;
141
+ float T = turbidity;
142
+ float T2 = turbidity * turbidity;
143
+ double chi = (4.0 / 9.0 - T / 120.0) * (Math.PI - 2.0 * sunTheta);
144
+ zenithY = (4.0453 * T - 4.9710) * Math.tan(chi) - 0.2155 * T + 2.4192;
145
+ zenithY *= 1000; /* conversion from kcd/m^2 to cd/m^2 */
146
+ zenithx = (0.00165 * theta3 - 0.00374 * theta2 + 0.00208 * sunTheta + 0) * T2 + (-0.02902 * theta3 + 0.06377 * theta2 - 0.03202 * sunTheta + 0.00394) * T + (0.11693 * theta3 - 0.21196 * theta2 + 0.06052 * sunTheta + 0.25885);
147
+ zenithy = (0.00275 * theta3 - 0.00610 * theta2 + 0.00316 * sunTheta + 0) * T2 + (-0.04212 * theta3 + 0.08970 * theta2 - 0.04153 * sunTheta + 0.00515) * T + (0.15346 * theta3 - 0.26756 * theta2 + 0.06669 * sunTheta + 0.26688);
148
+
149
+ perezY[0] = 0.17872 * T - 1.46303;
150
+ perezY[1] = -0.35540 * T + 0.42749;
151
+ perezY[2] = -0.02266 * T + 5.32505;
152
+ perezY[3] = 0.12064 * T - 2.57705;
153
+ perezY[4] = -0.06696 * T + 0.37027;
154
+
155
+ perezx[0] = -0.01925 * T - 0.25922;
156
+ perezx[1] = -0.06651 * T + 0.00081;
157
+ perezx[2] = -0.00041 * T + 0.21247;
158
+ perezx[3] = -0.06409 * T - 0.89887;
159
+ perezx[4] = -0.00325 * T + 0.04517;
160
+
161
+ perezy[0] = -0.01669 * T - 0.26078;
162
+ perezy[1] = -0.09495 * T + 0.00921;
163
+ perezy[2] = -0.00792 * T + 0.21023;
164
+ perezy[3] = -0.04405 * T - 1.65369;
165
+ perezy[4] = -0.01092 * T + 0.05291;
166
+
167
+ final int w = 32, h = 32;
168
+ imageHistogram = new float[w][h];
169
+ colHistogram = new float[w];
170
+ float du = 1.0f / w;
171
+ float dv = 1.0f / h;
172
+ for (int x = 0; x < w; x++) {
173
+ for (int y = 0; y < h; y++) {
174
+ float u = (x + 0.5f) * du;
175
+ float v = (y + 0.5f) * dv;
176
+ Color c = getSkyRGB(getDirection(u, v));
177
+ imageHistogram[x][y] = c.getLuminance() * (float) Math.sin(Math.PI * v);
178
+ if (y > 0) {
179
+ imageHistogram[x][y] += imageHistogram[x][y - 1];
180
+ }
181
+ }
182
+ colHistogram[x] = imageHistogram[x][h - 1];
183
+ if (x > 0) {
184
+ colHistogram[x] += colHistogram[x - 1];
185
+ }
186
+ for (int y = 0; y < h; y++) {
187
+ imageHistogram[x][y] /= imageHistogram[x][h - 1];
188
+ }
189
+ }
190
+ for (int x = 0; x < w; x++) {
191
+ colHistogram[x] /= colHistogram[w - 1];
192
+ }
193
+ jacobian = (float) (2 * Math.PI * Math.PI) / (w * h);
194
+ }
195
+
196
+ @Override
197
+ public boolean update(ParameterList pl, SunflowAPI api) {
198
+ Vector3 up = pl.getVector("up", null);
199
+ Vector3 east = pl.getVector("east", null);
200
+ if (up != null && east != null) {
201
+ basis = OrthoNormalBasis.makeFromWV(up, east);
202
+ } else if (up != null) {
203
+ basis = OrthoNormalBasis.makeFromW(up);
204
+ }
205
+ numSkySamples = pl.getInt("samples", numSkySamples);
206
+ sunDirWorld = pl.getVector("sundir", sunDirWorld);
207
+ turbidity = pl.getFloat("turbidity", turbidity);
208
+ groundExtendSky = pl.getBoolean("ground.extendsky", groundExtendSky);
209
+ groundColor = pl.getColor("ground.color", groundColor);
210
+ // recompute model
211
+ initSunSky();
212
+ return true;
213
+ }
214
+
215
+ private Color getSkyRGB(Vector3 dir) {
216
+ if (dir.z < 0 && !groundExtendSky) {
217
+ return groundColor;
218
+ }
219
+ if (dir.z < 0.001f) {
220
+ dir.z = 0.001f;
221
+ }
222
+ dir.normalize();
223
+ double theta = Math.acos(MathUtils.clamp(dir.z, -1, 1));
224
+ double gamma = Math.acos(MathUtils.clamp(Vector3.dot(dir, sunDir), -1, 1));
225
+ double x = perezFunction(perezx, theta, gamma, zenithx);
226
+ double y = perezFunction(perezy, theta, gamma, zenithy);
227
+ double Y = perezFunction(perezY, theta, gamma, zenithY) * 1e-4;
228
+ XYZColor c = ChromaticitySpectrum.get((float) x, (float) y);
229
+ // XYZColor c = new ChromaticitySpectrum((float) x, (float) y).toXYZ();
230
+ float X = (float) (c.getX() * Y / c.getY());
231
+ float Z = (float) (c.getZ() * Y / c.getY());
232
+ return RGBSpace.SRGB.convertXYZtoRGB(X, (float) Y, Z);
233
+ }
234
+
235
+ @Override
236
+ public int getNumSamples() {
237
+ return 1 + numSkySamples;
238
+ }
239
+
240
+ @Override
241
+ public void getPhoton(double randX1, double randY1, double randX2, double randY2, Point3 p, Vector3 dir, Color power) {
242
+ // FIXME: not implemented
243
+ }
244
+
245
+ @Override
246
+ public float getPower() {
247
+ return 0;
248
+ }
249
+
250
+ @Override
251
+ public void getSamples(ShadingState state) {
252
+ if (Vector3.dot(sunDirWorld, state.getGeoNormal()) > 0 && Vector3.dot(sunDirWorld, state.getNormal()) > 0) {
253
+ LightSample dest = new LightSample();
254
+ dest.setShadowRay(new Ray(state.getPoint(), sunDirWorld));
255
+ dest.getShadowRay().setMax(Float.MAX_VALUE);
256
+ dest.setRadiance(sunColor, sunColor);
257
+ dest.traceShadow(state);
258
+ state.addSample(dest);
259
+ }
260
+ int n = state.getDiffuseDepth() > 0 ? 1 : numSkySamples;
261
+ for (int i = 0; i < n; i++) {
262
+ // random offset on unit square, we use the infinite version of
263
+ // getRandom because the light sampling is adaptive
264
+ double randX = state.getRandom(i, 0, n);
265
+ double randY = state.getRandom(i, 1, n);
266
+
267
+ int x = 0;
268
+ while (randX >= colHistogram[x] && x < colHistogram.length - 1) {
269
+ x++;
270
+ }
271
+ float[] rowHistogram = imageHistogram[x];
272
+ int y = 0;
273
+ while (randY >= rowHistogram[y] && y < rowHistogram.length - 1) {
274
+ y++;
275
+ }
276
+ // sample from (x, y)
277
+ float u = (float) ((x == 0) ? (randX / colHistogram[0]) : ((randX - colHistogram[x - 1]) / (colHistogram[x] - colHistogram[x - 1])));
278
+ float v = (float) ((y == 0) ? (randY / rowHistogram[0]) : ((randY - rowHistogram[y - 1]) / (rowHistogram[y] - rowHistogram[y - 1])));
279
+
280
+ float px = ((x == 0) ? colHistogram[0] : (colHistogram[x] - colHistogram[x - 1]));
281
+ float py = ((y == 0) ? rowHistogram[0] : (rowHistogram[y] - rowHistogram[y - 1]));
282
+
283
+ float su = (x + u) / colHistogram.length;
284
+ float sv = (y + v) / rowHistogram.length;
285
+ float invP = (float) Math.sin(sv * Math.PI) * jacobian / (n * px * py);
286
+ Vector3 localDir = getDirection(su, sv);
287
+ Vector3 dir = basis.transform(localDir, new Vector3());
288
+ if (Vector3.dot(dir, state.getGeoNormal()) > 0 && Vector3.dot(dir, state.getNormal()) > 0) {
289
+ LightSample dest = new LightSample();
290
+ dest.setShadowRay(new Ray(state.getPoint(), dir));
291
+ dest.getShadowRay().setMax(Float.MAX_VALUE);
292
+ Color radiance = getSkyRGB(localDir);
293
+ dest.setRadiance(radiance, radiance);
294
+ dest.getDiffuseRadiance().mul(invP);
295
+ dest.getSpecularRadiance().mul(invP);
296
+ dest.traceShadow(state);
297
+ state.addSample(dest);
298
+ }
299
+ }
300
+ }
301
+
302
+ @Override
303
+ public PrimitiveList getBakingPrimitives() {
304
+ return null;
305
+ }
306
+
307
+ @Override
308
+ public int getNumPrimitives() {
309
+ return 1;
310
+ }
311
+
312
+ @Override
313
+ public float getPrimitiveBound(int primID, int i) {
314
+ return 0;
315
+ }
316
+
317
+ @Override
318
+ public BoundingBox getWorldBounds(Matrix4 o2w) {
319
+ return null;
320
+ }
321
+
322
+ @Override
323
+ public void intersectPrimitive(Ray r, int primID, IntersectionState state) {
324
+ if (r.getMax() == Float.POSITIVE_INFINITY) {
325
+ state.setIntersection(0);
326
+ }
327
+ }
328
+
329
+ @Override
330
+ public void prepareShadingState(ShadingState state) {
331
+ if (state.includeLights()) {
332
+ state.setShader(this);
333
+ }
334
+ }
335
+
336
+ @Override
337
+ public Color getRadiance(ShadingState state) {
338
+ return getSkyRGB(basis.untransform(state.getRay().getDirection())).constrainRGB();
339
+ }
340
+
341
+ @Override
342
+ public void scatterPhoton(ShadingState state, Color power) {
343
+ // let photon escape
344
+ }
345
+
346
+ private Vector3 getDirection(float u, float v) {
347
+ Vector3 dest = new Vector3();
348
+ double phi = 0, theta = 0;
349
+ theta = u * 2 * Math.PI;
350
+ phi = v * Math.PI;
351
+ double sin_phi = Math.sin(phi);
352
+ dest.x = (float) (-sin_phi * Math.cos(theta));
353
+ dest.y = (float) Math.cos(phi);
354
+ dest.z = (float) (sin_phi * Math.sin(theta));
355
+ return dest;
356
+ }
357
+
358
+ @Override
359
+ public Instance createInstance() {
360
+ return Instance.createTemporary(this, null, this);
361
+ }
362
+ }