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.
- checksums.yaml +7 -0
- data/.gitignore +53 -0
- data/.mvn/extensions.xml +8 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +6 -0
- data/LICENSE +674 -0
- data/README.md +2 -0
- data/Rakefile +43 -0
- data/docs/.gitignore +6 -0
- data/docs/_config.yml +20 -0
- data/docs/_includes/footer.html +38 -0
- data/docs/_includes/head.html +15 -0
- data/docs/_includes/header.html +27 -0
- data/docs/_includes/icon-github.html +1 -0
- data/docs/_includes/icon-github.svg +1 -0
- data/docs/_includes/icon-twitter.html +1 -0
- data/docs/_includes/icon-twitter.svg +1 -0
- data/docs/_layouts/default.html +20 -0
- data/docs/_layouts/page.html +14 -0
- data/docs/_layouts/post.html +15 -0
- data/docs/_posts/2017-01-08-animated_ray_tracing.md +72 -0
- data/docs/_posts/2017-01-08-welcome.md +78 -0
- data/docs/_sass/_base.scss +206 -0
- data/docs/_sass/_layout.scss +242 -0
- data/docs/_sass/_syntax-highlighting.scss +71 -0
- data/docs/about.md +12 -0
- data/docs/assets/Animation.ogv +0 -0
- data/docs/assets/Animation.png +0 -0
- data/docs/assets/basic.png +0 -0
- data/docs/assets/basic_traced.png +0 -0
- data/docs/css/main.scss +38 -0
- data/docs/favicon.ico +0 -0
- data/docs/feed.xml +30 -0
- data/docs/index.html +38 -0
- data/joonsrenderer.gemspec +23 -0
- data/lib/joonsrenderer.rb +12 -0
- data/lib/joonsrenderer/version.rb +3 -0
- data/pom.rb +75 -0
- data/pom.xml +163 -0
- data/src/main/java/SunflowGUI.java +1354 -0
- data/src/main/java/joons/JRFiller.java +79 -0
- data/src/main/java/joons/JRImagePanel.java +141 -0
- data/src/main/java/joons/JRRecorder.java +183 -0
- data/src/main/java/joons/JRStatics.java +199 -0
- data/src/main/java/joons/JoonsRenderer.java +837 -0
- data/src/main/java/org/sunflow/AsciiFileSunflowAPI.java +98 -0
- data/src/main/java/org/sunflow/Benchmark.java +313 -0
- data/src/main/java/org/sunflow/BinaryFileSunflowAPI.java +228 -0
- data/src/main/java/org/sunflow/FileSunflowAPI.java +354 -0
- data/src/main/java/org/sunflow/PluginRegistry.java +322 -0
- data/src/main/java/org/sunflow/RealtimeBenchmark.java +125 -0
- data/src/main/java/org/sunflow/RenderObjectMap.java +344 -0
- data/src/main/java/org/sunflow/SunflowAPI.java +762 -0
- data/src/main/java/org/sunflow/SunflowAPIInterface.java +277 -0
- data/src/main/java/org/sunflow/core/AccelerationStructure.java +20 -0
- data/src/main/java/org/sunflow/core/AccelerationStructureFactory.java +36 -0
- data/src/main/java/org/sunflow/core/BucketOrder.java +21 -0
- data/src/main/java/org/sunflow/core/Camera.java +125 -0
- data/src/main/java/org/sunflow/core/CameraLens.java +29 -0
- data/src/main/java/org/sunflow/core/CausticPhotonMapInterface.java +15 -0
- data/src/main/java/org/sunflow/core/Display.java +78 -0
- data/src/main/java/org/sunflow/core/Filter.java +27 -0
- data/src/main/java/org/sunflow/core/GIEngine.java +42 -0
- data/src/main/java/org/sunflow/core/Geometry.java +157 -0
- data/src/main/java/org/sunflow/core/GlobalPhotonMapInterface.java +21 -0
- data/src/main/java/org/sunflow/core/ImageSampler.java +26 -0
- data/src/main/java/org/sunflow/core/Instance.java +224 -0
- data/src/main/java/org/sunflow/core/InstanceList.java +83 -0
- data/src/main/java/org/sunflow/core/IntersectionState.java +120 -0
- data/src/main/java/org/sunflow/core/LightSample.java +104 -0
- data/src/main/java/org/sunflow/core/LightServer.java +382 -0
- data/src/main/java/org/sunflow/core/LightSource.java +67 -0
- data/src/main/java/org/sunflow/core/Modifier.java +16 -0
- data/src/main/java/org/sunflow/core/Options.java +20 -0
- data/src/main/java/org/sunflow/core/ParameterList.java +758 -0
- data/src/main/java/org/sunflow/core/PhotonStore.java +62 -0
- data/src/main/java/org/sunflow/core/PrimitiveList.java +70 -0
- data/src/main/java/org/sunflow/core/Ray.java +219 -0
- data/src/main/java/org/sunflow/core/RenderObject.java +25 -0
- data/src/main/java/org/sunflow/core/Scene.java +377 -0
- data/src/main/java/org/sunflow/core/SceneParser.java +58 -0
- data/src/main/java/org/sunflow/core/Shader.java +30 -0
- data/src/main/java/org/sunflow/core/ShadingCache.java +84 -0
- data/src/main/java/org/sunflow/core/ShadingState.java +939 -0
- data/src/main/java/org/sunflow/core/Statistics.java +85 -0
- data/src/main/java/org/sunflow/core/Tesselatable.java +36 -0
- data/src/main/java/org/sunflow/core/Texture.java +128 -0
- data/src/main/java/org/sunflow/core/TextureCache.java +48 -0
- data/src/main/java/org/sunflow/core/accel/BoundingIntervalHierarchy.java +652 -0
- data/src/main/java/org/sunflow/core/accel/KDTree.java +833 -0
- data/src/main/java/org/sunflow/core/accel/NullAccelerator.java +30 -0
- data/src/main/java/org/sunflow/core/accel/UniformGrid.java +329 -0
- data/src/main/java/org/sunflow/core/bucket/BucketOrderFactory.java +26 -0
- data/src/main/java/org/sunflow/core/bucket/ColumnBucketOrder.java +21 -0
- data/src/main/java/org/sunflow/core/bucket/DiagonalBucketOrder.java +28 -0
- data/src/main/java/org/sunflow/core/bucket/HilbertBucketOrder.java +65 -0
- data/src/main/java/org/sunflow/core/bucket/InvertedBucketOrder.java +28 -0
- data/src/main/java/org/sunflow/core/bucket/RandomBucketOrder.java +49 -0
- data/src/main/java/org/sunflow/core/bucket/RowBucketOrder.java +21 -0
- data/src/main/java/org/sunflow/core/bucket/SpiralBucketOrder.java +43 -0
- data/src/main/java/org/sunflow/core/camera/FisheyeLens.java +25 -0
- data/src/main/java/org/sunflow/core/camera/PinholeLens.java +43 -0
- data/src/main/java/org/sunflow/core/camera/SphericalLens.java +22 -0
- data/src/main/java/org/sunflow/core/camera/ThinLens.java +107 -0
- data/src/main/java/org/sunflow/core/display/FastDisplay.java +119 -0
- data/src/main/java/org/sunflow/core/display/FileDisplay.java +83 -0
- data/src/main/java/org/sunflow/core/display/FrameDisplay.java +97 -0
- data/src/main/java/org/sunflow/core/display/ImgPipeDisplay.java +109 -0
- data/src/main/java/org/sunflow/core/filter/BlackmanHarrisFilter.java +28 -0
- data/src/main/java/org/sunflow/core/filter/BoxFilter.java +16 -0
- data/src/main/java/org/sunflow/core/filter/CatmullRomFilter.java +29 -0
- data/src/main/java/org/sunflow/core/filter/CubicBSpline.java +32 -0
- data/src/main/java/org/sunflow/core/filter/GaussianFilter.java +24 -0
- data/src/main/java/org/sunflow/core/filter/LanczosFilter.java +30 -0
- data/src/main/java/org/sunflow/core/filter/MitchellFilter.java +28 -0
- data/src/main/java/org/sunflow/core/filter/SincFilter.java +25 -0
- data/src/main/java/org/sunflow/core/filter/TriangleFilter.java +16 -0
- data/src/main/java/org/sunflow/core/gi/AmbientOcclusionGIEngine.java +57 -0
- data/src/main/java/org/sunflow/core/gi/FakeGIEngine.java +48 -0
- data/src/main/java/org/sunflow/core/gi/InstantGI.java +194 -0
- data/src/main/java/org/sunflow/core/gi/IrradianceCacheGIEngine.java +268 -0
- data/src/main/java/org/sunflow/core/gi/PathTracingGIEngine.java +65 -0
- data/src/main/java/org/sunflow/core/light/DirectionalSpotlight.java +103 -0
- data/src/main/java/org/sunflow/core/light/ImageBasedLight.java +303 -0
- data/src/main/java/org/sunflow/core/light/PointLight.java +72 -0
- data/src/main/java/org/sunflow/core/light/SphereLight.java +166 -0
- data/src/main/java/org/sunflow/core/light/SunSkyLight.java +362 -0
- data/src/main/java/org/sunflow/core/light/TriangleMeshLight.java +296 -0
- data/src/main/java/org/sunflow/core/modifiers/BumpMappingModifier.java +37 -0
- data/src/main/java/org/sunflow/core/modifiers/NormalMapModifier.java +34 -0
- data/src/main/java/org/sunflow/core/modifiers/PerlinModifier.java +80 -0
- data/src/main/java/org/sunflow/core/parser/Keyword.java +39 -0
- data/src/main/java/org/sunflow/core/parser/RA2Parser.java +107 -0
- data/src/main/java/org/sunflow/core/parser/RA3Parser.java +68 -0
- data/src/main/java/org/sunflow/core/parser/SCAbstractParser.java +299 -0
- data/src/main/java/org/sunflow/core/parser/SCAsciiParser.java +251 -0
- data/src/main/java/org/sunflow/core/parser/SCBinaryParser.java +156 -0
- data/src/main/java/org/sunflow/core/parser/SCParser.java +1403 -0
- data/src/main/java/org/sunflow/core/parser/ShaveRibParser.java +174 -0
- data/src/main/java/org/sunflow/core/parser/TriParser.java +79 -0
- data/src/main/java/org/sunflow/core/photonmap/CausticPhotonMap.java +429 -0
- data/src/main/java/org/sunflow/core/photonmap/GlobalPhotonMap.java +530 -0
- data/src/main/java/org/sunflow/core/photonmap/GridPhotonMap.java +308 -0
- data/src/main/java/org/sunflow/core/primitive/Background.java +55 -0
- data/src/main/java/org/sunflow/core/primitive/BanchoffSurface.java +100 -0
- data/src/main/java/org/sunflow/core/primitive/Box.java +210 -0
- data/src/main/java/org/sunflow/core/primitive/CornellBox.java +476 -0
- data/src/main/java/org/sunflow/core/primitive/CubeGrid.java +318 -0
- data/src/main/java/org/sunflow/core/primitive/Cylinder.java +104 -0
- data/src/main/java/org/sunflow/core/primitive/Hair.java +275 -0
- data/src/main/java/org/sunflow/core/primitive/JuliaFractal.java +266 -0
- data/src/main/java/org/sunflow/core/primitive/ParticleSurface.java +114 -0
- data/src/main/java/org/sunflow/core/primitive/Plane.java +163 -0
- data/src/main/java/org/sunflow/core/primitive/QuadMesh.java +413 -0
- data/src/main/java/org/sunflow/core/primitive/Sphere.java +101 -0
- data/src/main/java/org/sunflow/core/primitive/SphereFlake.java +234 -0
- data/src/main/java/org/sunflow/core/primitive/Torus.java +145 -0
- data/src/main/java/org/sunflow/core/primitive/TriangleMesh.java +849 -0
- data/src/main/java/org/sunflow/core/renderer/BucketRenderer.java +491 -0
- data/src/main/java/org/sunflow/core/renderer/MultipassRenderer.java +237 -0
- data/src/main/java/org/sunflow/core/renderer/ProgressiveRenderer.java +171 -0
- data/src/main/java/org/sunflow/core/renderer/SimpleRenderer.java +106 -0
- data/src/main/java/org/sunflow/core/shader/AmbientOcclusionShader.java +53 -0
- data/src/main/java/org/sunflow/core/shader/AnisotropicWardShader.java +216 -0
- data/src/main/java/org/sunflow/core/shader/ConstantShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/DiffuseShader.java +65 -0
- data/src/main/java/org/sunflow/core/shader/GlassShader.java +147 -0
- data/src/main/java/org/sunflow/core/shader/IDShader.java +27 -0
- data/src/main/java/org/sunflow/core/shader/MirrorShader.java +68 -0
- data/src/main/java/org/sunflow/core/shader/NormalShader.java +32 -0
- data/src/main/java/org/sunflow/core/shader/PhongShader.java +89 -0
- data/src/main/java/org/sunflow/core/shader/PrimIDShader.java +30 -0
- data/src/main/java/org/sunflow/core/shader/QuickGrayShader.java +63 -0
- data/src/main/java/org/sunflow/core/shader/ShinyDiffuseShader.java +98 -0
- data/src/main/java/org/sunflow/core/shader/SimpleShader.java +24 -0
- data/src/main/java/org/sunflow/core/shader/TexturedAmbientOcclusionShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedDiffuseShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedPhongShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedShinyDiffuseShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedWardShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/UVShader.java +27 -0
- data/src/main/java/org/sunflow/core/shader/UberShader.java +149 -0
- data/src/main/java/org/sunflow/core/shader/ViewCausticsShader.java +33 -0
- data/src/main/java/org/sunflow/core/shader/ViewGlobalPhotonsShader.java +25 -0
- data/src/main/java/org/sunflow/core/shader/ViewIrradianceShader.java +25 -0
- data/src/main/java/org/sunflow/core/shader/WireframeShader.java +83 -0
- data/src/main/java/org/sunflow/core/tesselatable/BezierMesh.java +254 -0
- data/src/main/java/org/sunflow/core/tesselatable/FileMesh.java +251 -0
- data/src/main/java/org/sunflow/core/tesselatable/Gumbo.java +1147 -0
- data/src/main/java/org/sunflow/core/tesselatable/Teapot.java +237 -0
- data/src/main/java/org/sunflow/image/Bitmap.java +15 -0
- data/src/main/java/org/sunflow/image/BitmapReader.java +39 -0
- data/src/main/java/org/sunflow/image/BitmapWriter.java +79 -0
- data/src/main/java/org/sunflow/image/BlackbodySpectrum.java +16 -0
- data/src/main/java/org/sunflow/image/ChromaticitySpectrum.java +55 -0
- data/src/main/java/org/sunflow/image/Color.java +374 -0
- data/src/main/java/org/sunflow/image/ColorEncoder.java +94 -0
- data/src/main/java/org/sunflow/image/ColorFactory.java +122 -0
- data/src/main/java/org/sunflow/image/ConstantSpectralCurve.java +21 -0
- data/src/main/java/org/sunflow/image/IrregularSpectralCurve.java +57 -0
- data/src/main/java/org/sunflow/image/RGBSpace.java +207 -0
- data/src/main/java/org/sunflow/image/RegularSpectralCurve.java +30 -0
- data/src/main/java/org/sunflow/image/SpectralCurve.java +118 -0
- data/src/main/java/org/sunflow/image/XYZColor.java +50 -0
- data/src/main/java/org/sunflow/image/formats/BitmapBlack.java +27 -0
- data/src/main/java/org/sunflow/image/formats/BitmapG8.java +36 -0
- data/src/main/java/org/sunflow/image/formats/BitmapGA8.java +30 -0
- data/src/main/java/org/sunflow/image/formats/BitmapRGB8.java +40 -0
- data/src/main/java/org/sunflow/image/formats/BitmapRGBA8.java +40 -0
- data/src/main/java/org/sunflow/image/formats/BitmapRGBE.java +60 -0
- data/src/main/java/org/sunflow/image/formats/BitmapXYZ.java +38 -0
- data/src/main/java/org/sunflow/image/formats/GenericBitmap.java +73 -0
- data/src/main/java/org/sunflow/image/readers/BMPBitmapReader.java +39 -0
- data/src/main/java/org/sunflow/image/readers/HDRBitmapReader.java +155 -0
- data/src/main/java/org/sunflow/image/readers/IGIBitmapReader.java +104 -0
- data/src/main/java/org/sunflow/image/readers/JPGBitmapReader.java +39 -0
- data/src/main/java/org/sunflow/image/readers/PNGBitmapReader.java +40 -0
- data/src/main/java/org/sunflow/image/readers/TGABitmapReader.java +141 -0
- data/src/main/java/org/sunflow/image/writers/EXRBitmapWriter.java +395 -0
- data/src/main/java/org/sunflow/image/writers/HDRBitmapWriter.java +54 -0
- data/src/main/java/org/sunflow/image/writers/IGIBitmapWriter.java +75 -0
- data/src/main/java/org/sunflow/image/writers/PNGBitmapWriter.java +39 -0
- data/src/main/java/org/sunflow/image/writers/TGABitmapWriter.java +63 -0
- data/src/main/java/org/sunflow/math/BoundingBox.java +340 -0
- data/src/main/java/org/sunflow/math/MathUtils.java +159 -0
- data/src/main/java/org/sunflow/math/Matrix4.java +573 -0
- data/src/main/java/org/sunflow/math/MovingMatrix4.java +119 -0
- data/src/main/java/org/sunflow/math/OrthoNormalBasis.java +110 -0
- data/src/main/java/org/sunflow/math/PerlinScalar.java +331 -0
- data/src/main/java/org/sunflow/math/PerlinVector.java +132 -0
- data/src/main/java/org/sunflow/math/Point2.java +36 -0
- data/src/main/java/org/sunflow/math/Point3.java +133 -0
- data/src/main/java/org/sunflow/math/QMC.java +209 -0
- data/src/main/java/org/sunflow/math/Solvers.java +142 -0
- data/src/main/java/org/sunflow/math/Vector3.java +197 -0
- data/src/main/java/org/sunflow/system/BenchmarkFramework.java +73 -0
- data/src/main/java/org/sunflow/system/BenchmarkTest.java +17 -0
- data/src/main/java/org/sunflow/system/ByteUtil.java +119 -0
- data/src/main/java/org/sunflow/system/FileUtils.java +27 -0
- data/src/main/java/org/sunflow/system/ImagePanel.java +282 -0
- data/src/main/java/org/sunflow/system/Memory.java +18 -0
- data/src/main/java/org/sunflow/system/Parser.java +162 -0
- data/src/main/java/org/sunflow/system/Plugins.java +142 -0
- data/src/main/java/org/sunflow/system/RenderGlobalsPanel.java +209 -0
- data/src/main/java/org/sunflow/system/SearchPath.java +67 -0
- data/src/main/java/org/sunflow/system/Timer.java +53 -0
- data/src/main/java/org/sunflow/system/UI.java +112 -0
- data/src/main/java/org/sunflow/system/UserInterface.java +46 -0
- data/src/main/java/org/sunflow/system/ui/ConsoleInterface.java +48 -0
- data/src/main/java/org/sunflow/system/ui/SilentInterface.java +28 -0
- data/src/main/java/org/sunflow/util/FastHashMap.java +220 -0
- data/src/main/java/org/sunflow/util/FloatArray.java +77 -0
- data/src/main/java/org/sunflow/util/IntArray.java +77 -0
- data/src/test/java/a_maintest.java +129 -0
- 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
|
+
}
|