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