joonsrenderer 1.1-java

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