diff --git a/Builds/MSVC/Installer/FractoriumInstaller.wixproj b/Builds/MSVC/Installer/FractoriumInstaller.wixproj
index 0b83aad..0d7b452 100644
--- a/Builds/MSVC/Installer/FractoriumInstaller.wixproj
+++ b/Builds/MSVC/Installer/FractoriumInstaller.wixproj
@@ -6,7 +6,7 @@
3.7
{c8096c47-e358-438c-a520-146d46b0637d}
2.0
- Fractorium_1.0.0.14
+ Fractorium_1.0.0.15
Package
$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets
$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets
diff --git a/Builds/MSVC/Installer/Product.wxs b/Builds/MSVC/Installer/Product.wxs
index 8005ca9..a429897 100644
--- a/Builds/MSVC/Installer/Product.wxs
+++ b/Builds/MSVC/Installer/Product.wxs
@@ -1,6 +1,6 @@
-
+
@@ -13,7 +13,7 @@
-
+
+
@@ -84,6 +85,7 @@
+
@@ -316,4 +318,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Builds/MSVC/VS2017/Ember.rc b/Builds/MSVC/VS2017/Ember.rc
index e1d20d8..cd1a580 100644
Binary files a/Builds/MSVC/VS2017/Ember.rc and b/Builds/MSVC/VS2017/Ember.rc differ
diff --git a/Builds/MSVC/VS2017/Ember.vcxproj b/Builds/MSVC/VS2017/Ember.vcxproj
index e8162e1..7292477 100644
--- a/Builds/MSVC/VS2017/Ember.vcxproj
+++ b/Builds/MSVC/VS2017/Ember.vcxproj
@@ -115,6 +115,7 @@
+
@@ -151,6 +152,7 @@
+
diff --git a/Builds/MSVC/VS2017/Ember.vcxproj.filters b/Builds/MSVC/VS2017/Ember.vcxproj.filters
index e19c36a..b3b4441 100644
--- a/Builds/MSVC/VS2017/Ember.vcxproj.filters
+++ b/Builds/MSVC/VS2017/Ember.vcxproj.filters
@@ -128,6 +128,9 @@
Header Files\Variations
+
+ Header Files\Xml
+
@@ -160,6 +163,9 @@
Source Files
+
+ Header Files\Xml
+
diff --git a/Builds/MSVC/VS2017/EmberAnimate.rc b/Builds/MSVC/VS2017/EmberAnimate.rc
index 92d545c..b1c234f 100644
--- a/Builds/MSVC/VS2017/EmberAnimate.rc
+++ b/Builds/MSVC/VS2017/EmberAnimate.rc
@@ -49,8 +49,8 @@
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1, 0, 0, 14
- PRODUCTVERSION 1, 0, 0, 14
+ FILEVERSION 1, 0, 0, 15
+ PRODUCTVERSION 1, 0, 0, 15
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -67,12 +67,12 @@
BEGIN
VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Renders fractal flames as animations with motion blur"
- VALUE "FileVersion", "1, 0, 0, 14"
+ VALUE "FileVersion", "1, 0, 0, 15"
VALUE "InternalName", "EmberAnimate.exe"
- VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2018, GPL v3"
+ VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2019, GPL v3"
VALUE "OriginalFilename", "EmberAnimate.exe"
VALUE "ProductName", "Ember Animate"
- VALUE "ProductVersion", "1, 0, 0, 14"
+ VALUE "ProductVersion", "1, 0, 0, 15"
END
END
BLOCK "VarFileInfo"
diff --git a/Builds/MSVC/VS2017/EmberCL.rc b/Builds/MSVC/VS2017/EmberCL.rc
index 7d7c094..d8d1f2e 100644
Binary files a/Builds/MSVC/VS2017/EmberCL.rc and b/Builds/MSVC/VS2017/EmberCL.rc differ
diff --git a/Builds/MSVC/VS2017/EmberGenome.rc b/Builds/MSVC/VS2017/EmberGenome.rc
index aa13199..a07d554 100644
--- a/Builds/MSVC/VS2017/EmberGenome.rc
+++ b/Builds/MSVC/VS2017/EmberGenome.rc
@@ -49,8 +49,8 @@
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1, 0, 0, 14
- PRODUCTVERSION 1, 0, 0, 14
+ FILEVERSION 1, 0, 0, 15
+ PRODUCTVERSION 1, 0, 0, 15
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -67,12 +67,12 @@
BEGIN
VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Manipulates fractal flames parameter files"
- VALUE "FileVersion", "1, 0, 0, 14"
+ VALUE "FileVersion", "1, 0, 0, 15"
VALUE "InternalName", "EmberGenome.exe"
- VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2018, GPL v3"
+ VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2019, GPL v3"
VALUE "OriginalFilename", "EmberGenome.exe"
VALUE "ProductName", "Ember Genome"
- VALUE "ProductVersion", "1, 0, 0, 14"
+ VALUE "ProductVersion", "1, 0, 0, 15"
END
END
BLOCK "VarFileInfo"
diff --git a/Builds/MSVC/VS2017/EmberRender.rc b/Builds/MSVC/VS2017/EmberRender.rc
index 987f9bd..224f559 100644
--- a/Builds/MSVC/VS2017/EmberRender.rc
+++ b/Builds/MSVC/VS2017/EmberRender.rc
@@ -49,8 +49,8 @@
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1, 0, 0, 14
- PRODUCTVERSION 1, 0, 0, 14
+ FILEVERSION 1, 0, 0, 15
+ PRODUCTVERSION 1, 0, 0, 15
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -67,12 +67,12 @@
BEGIN
VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Renders fractal flames as single images"
- VALUE "FileVersion", "1, 0, 0, 14"
+ VALUE "FileVersion", "1, 0, 0, 15"
VALUE "InternalName", "EmberRender.exe"
- VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2018, GPL v3"
+ VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2019, GPL v3"
VALUE "OriginalFilename", "EmberRender.exe"
VALUE "ProductName", "Ember Render"
- VALUE "ProductVersion", "1, 0, 0, 14"
+ VALUE "ProductVersion", "1, 0, 0, 15"
END
END
BLOCK "VarFileInfo"
diff --git a/Builds/MSVC/VS2017/Fractorium.rc b/Builds/MSVC/VS2017/Fractorium.rc
index 0a03cc5..ad173a0 100644
Binary files a/Builds/MSVC/VS2017/Fractorium.rc and b/Builds/MSVC/VS2017/Fractorium.rc differ
diff --git a/Builds/MSVC/VS2017/Fractorium.vcxproj b/Builds/MSVC/VS2017/Fractorium.vcxproj
index e5b1616..e64bf01 100644
--- a/Builds/MSVC/VS2017/Fractorium.vcxproj
+++ b/Builds/MSVC/VS2017/Fractorium.vcxproj
@@ -87,30 +87,14 @@
xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Deps\*.dll" "$(OutDir)"
xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
-
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\boxtail_pack_02.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\boxtail_pack_03_triangle.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\boxtail_pack_04_mineshack.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\fardareismai_pack_01_variety_number_128.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\fardareismai_pack_02_b_sides.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\fardareismai_pack_03_old_and_new.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\fardareismai_pack_04_hoard.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\fractaldesire_pack_01.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\rce_ordinary_pack_01_colornation.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\tatasz_pack_01.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\tatasz_pack_02_colder.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\tatasz_pack_02_dark.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\tatasz_pack_02_warmer.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\tatasz_pack_03.gradient" "$(OutDir)"
-
+xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\*.gradient" "$(OutDir)"
+xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\*.ugr" "$(OutDir)"
xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\dark_windows.qss" "$(OutDir)"
-
xcopy /F /Y /R /D "$(QTDIR)\bin\Qt5Cored.dll" "$(OutDir)"
xcopy /F /Y /R /D "$(QTDIR)\bin\Qt5Guid.dll" "$(OutDir)"
xcopy /F /Y /R /D "$(QTDIR)\bin\Qt5Widgetsd.dll" "$(OutDir)"
-
xcopy /F /Y /R /D "$(QTDIR)\plugins\platforms\qwindowsd.dll" "$(OutDir)\platforms\"
-
+xcopy /F /Y /R /D "$(QTDIR)\plugins\imageformats\qjpegd.dll" "$(OutDir)\imageformats\"
@@ -145,29 +129,14 @@ xcopy /F /Y /R /D "$(QTDIR)\plugins\platforms\qwindowsd.dll" "$(OutDir)\platform
xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Deps\*.dll" "$(OutDir)"
xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
-
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\boxtail_pack_02.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\boxtail_pack_03_triangle.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\boxtail_pack_04_mineshack.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\fardareismai_pack_01_variety_number_128.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\fardareismai_pack_02_b_sides.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\fardareismai_pack_03_old_and_new.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\fardareismai_pack_04_hoard.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\fractaldesire_pack_01.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\rce_ordinary_pack_01_colornation.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\tatasz_pack_01.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\tatasz_pack_02_colder.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\tatasz_pack_02_dark.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\tatasz_pack_02_warmer.gradient" "$(OutDir)"
-xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\tatasz_pack_03.gradient" "$(OutDir)"
-
+xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\*.gradient" "$(OutDir)"
+xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\*.ugr" "$(OutDir)"
xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\dark_windows.qss" "$(OutDir)"
-
xcopy /F /Y /R /D "$(QTDIR)\bin\Qt5Core.dll" "$(OutDir)"
xcopy /F /Y /R /D "$(QTDIR)\bin\Qt5Gui.dll" "$(OutDir)"
xcopy /F /Y /R /D "$(QTDIR)\bin\Qt5Widgets.dll" "$(OutDir)"
-
-xcopy /F /Y /R /D "$(QTDIR)\plugins\platforms\qwindows.dll" "$(OutDir)\platforms\"
+xcopy /F /Y /R /D "$(QTDIR)\plugins\platforms\qwindows.dll" "$(OutDir)\platforms\"
+xcopy /F /Y /R /D "$(QTDIR)\plugins\imageformats\qjpeg.dll" "$(OutDir)\imageformats\"
diff --git a/Builds/QtCreator/Ember/Ember.pro b/Builds/QtCreator/Ember/Ember.pro
index 44da87e..98ac54e 100644
--- a/Builds/QtCreator/Ember/Ember.pro
+++ b/Builds/QtCreator/Ember/Ember.pro
@@ -43,6 +43,7 @@ SOURCES += \
$$PRJ_SRC_DIR/RendererBase.cpp \
$$PRJ_SRC_DIR/Renderer.cpp \
$$PRJ_SRC_DIR/VariationList.cpp \
+ $$PRJ_SRC_DIR/Spline.cpp \
$$PRJ_SRC_DIR/XmlToEmber.cpp
include(deployment.pri)
@@ -51,6 +52,7 @@ qtcAddDeployment()
HEADERS += \
$$PRJ_SRC_DIR/Affine2D.h \
$$PRJ_SRC_DIR/CarToRas.h \
+ $$PRJ_SRC_DIR/Spline.h \
$$PRJ_SRC_DIR/Curves.h \
$$PRJ_SRC_DIR/DensityFilter.h \
$$PRJ_SRC_DIR/EmberDefines.h \
diff --git a/Builds/QtCreator/Fractorium/Fractorium.pro b/Builds/QtCreator/Fractorium/Fractorium.pro
index ca11c7e..31d14b2 100644
--- a/Builds/QtCreator/Fractorium/Fractorium.pro
+++ b/Builds/QtCreator/Fractorium/Fractorium.pro
@@ -28,6 +28,10 @@ CONFIG(release, debug|release) {
qtplatforms.path = $$BIN_INSTALL_DIR\platforms
qtplatforms.files = $$(QTDIR)\plugins\platforms\qwindows.dll
INSTALLS += qtplatforms
+
+ qimageformats.path = $$BIN_INSTALL_DIR\imageformats
+ qimageformats.files = $$(QTDIR)\plugins\imageformats\qjpeg.dll
+ INSTALLS += qimageformats
}
CONFIG(debug, debug|release) {
@@ -38,6 +42,10 @@ CONFIG(debug, debug|release) {
qtplatforms.path = $$BIN_INSTALL_DIR\platforms
qtplatforms.files = $$(QTDIR)\plugins\platforms\qwindowsd.dll
INSTALLS += qtplatforms
+
+ qimageformats.path = $$BIN_INSTALL_DIR\imageformats
+ qimageformats.files = $$(QTDIR)\plugins\imageformats\qjpeg.dll
+ INSTALLS += qimageformats
}
}
diff --git a/Builds/QtCreator/defaults.pri b/Builds/QtCreator/defaults.pri
index a1e9978..4b86194 100644
--- a/Builds/QtCreator/defaults.pri
+++ b/Builds/QtCreator/defaults.pri
@@ -1,4 +1,4 @@
-VERSION = 1.0.0.14
+VERSION = 1.0.0.15
win32:CONFIG += skip_target_version_ext
CONFIG += c++14
diff --git a/Data/Bench/EmberBench.ps1 b/Data/Bench/EmberBench.ps1
index e612a38..0768cdf 100644
--- a/Data/Bench/EmberBench.ps1
+++ b/Data/Bench/EmberBench.ps1
@@ -71,6 +71,10 @@ function TestFileSupersamples([string]$filename, [string]$precision, [string]$su
function BenchAllForFile([string]$filename)
{
+ #if you want to test extreme speed on your GPU, add this option, --sbpctth=1.0, to increase the amount of each sub batch that is done on each opencl thread per kernel launch.
+ #set the value from somewhere between 0.025 (the default) and 1.0 (the max).
+ #this usuall results in a roughly 1% speed improvement.
+ #however, it can cause the render to fail, especially on the golubaja_rippingfrominside_complexcode and zy0rg_six_bigcomplexcode flames when using double precision.
$misc = "--opencl --device=" + $devices
TestFileSupersamples $filename "--sp" "_f32_cpu" $script:cpuquality ""
TestFileSupersamples $filename "" "_f64_cpu" $script:cpuquality ""
@@ -87,13 +91,13 @@ $fileOne = $benchprefix + "tatasz_springcrown_manysimplexforms.flame"
BenchAllForFile $fileOne
$fileOne = $benchprefix + "tyrantwave_flippeddisc_normal.flame"
-BenchAllForFile $fileOne
+#BenchAllForFile $fileOne
$fileOne = $benchprefix + "golubaja_rippingfrominside_complexcode.flame"
BenchAllForFile $fileOne
$fileOne = $benchprefix + "zy0rg_six_bigcomplexcode.flame"
-BenchAllForFile $fileOne
+#BenchAllForFile $fileOne
$Script:totalOutput | Out-File -FilePath benchout.txt
$table | Export-Csv -Path ".\benchout.csv" -Force -NoTypeInformation
diff --git a/Data/Bench/mfeemster_basicmemory.flame b/Data/Bench/mfeemster_basicmemory.flame
index 2a7ccdc..92d0e7d 100644
--- a/Data/Bench/mfeemster_basicmemory.flame
+++ b/Data/Bench/mfeemster_basicmemory.flame
@@ -1,6 +1,6 @@
-
-
+
+
F1DFDDFAEAEDFDEDEEFDEFEFFFF0F3FCEBF3FDEBEBFBE7E8
FEDADEF8D9E1F1D4D8DFC2C4D89CB8AB82A2934C6E814A5D
@@ -35,8 +35,10 @@
E2D4E3C6B7CA9F8EAE667DA96B6071483B573A3247312A49
28213320172A151314100702090001020001010000050100
-
-
+
+
+
+
diff --git a/Data/dark_linux.qss b/Data/dark_linux.qss
index 1638c0e..2d9b3b7 100644
--- a/Data/dark_linux.qss
+++ b/Data/dark_linux.qss
@@ -39,7 +39,7 @@ QDockWidget::float-button
QDockWidget::title
{
- margin: 1px;
+ margin: 0px;
padding: 2px;
background-color: gray;
}
@@ -418,7 +418,7 @@ QHeaderView::section::horizontal:enabled
{
color: black;
background-color: darkgray;
- border: 0px solid darkgray;
+ border: 1px solid darkgray;
border-right: 1px solid gray;
padding-top: 0px;
padding-bottom: 0px;
@@ -620,8 +620,12 @@ QSpinBox#ThreadCountSpin,
QSpinBox#RandomCountSpin,
QSpinBox#CpuSubBatchSpin,
QSpinBox#OpenCLSubBatchSpin,
+QSpinBox#CpuQualitySpin,
+QSpinBox#OpenCLQualitySpin,
+QDoubleSpinBox#OpenCLSubBatchPctSpin,
QSpinBox#FinalRenderCurrentSpin,
-QSpinBox#FinalRenderThreadCountSpin
+QSpinBox#FinalRenderThreadCountSpin,
+QDoubleSpinBox#FinalRenderOpenCLSubBatchPctSpin
{
padding: 2px;
border: 1px solid gray;
@@ -630,8 +634,12 @@ QSpinBox#FinalRenderThreadCountSpin
QSpinBox#ThreadCountSpin:disabled,
QSpinBox#CpuSubBatchSpin:disabled,
QSpinBox#OpenCLSubBatchSpin:disabled,
+QSpinBox#CpuQualitySpin:disabled,
+QSpinBox#OpenCLQualitySpin:disabled,
+QDoubleSpinBox#OpenCLSubBatchPctSpin:disabled,
QSpinBox#FinalRenderCurrentSpin:disabled,
-QSpinBox#FinalRenderThreadCountSpin:disabled
+QSpinBox#FinalRenderThreadCountSpin:disabled,
+QDoubleSpinBox#FinalRenderOpenCLSubBatchPctSpin:disabled
{
padding: 2px;
border: 1px solid rgb(35, 35, 35);
diff --git a/Data/dark_mac.qss b/Data/dark_mac.qss
index 85adb9b..9379e45 100644
--- a/Data/dark_mac.qss
+++ b/Data/dark_mac.qss
@@ -39,7 +39,7 @@ QDockWidget::float-button
QDockWidget::title
{
- margin: 1px;
+ margin: 0px;
padding: 2px;
background-color: gray;
}
@@ -419,7 +419,7 @@ QHeaderView::section::horizontal:enabled
{
color: black;
background-color: darkgray;
- border: 0px solid darkgray;
+ border: 1px solid darkgray;
border-right: 1px solid gray;
padding-top: 0px;
padding-bottom: 0px;
@@ -621,8 +621,12 @@ QSpinBox#ThreadCountSpin,
QSpinBox#RandomCountSpin,
QSpinBox#CpuSubBatchSpin,
QSpinBox#OpenCLSubBatchSpin,
+QSpinBox#CpuQualitySpin,
+QSpinBox#OpenCLQualitySpin,
+QDoubleSpinBox#OpenCLSubBatchPctSpin,
QSpinBox#FinalRenderCurrentSpin,
-QSpinBox#FinalRenderThreadCountSpin
+QSpinBox#FinalRenderThreadCountSpin,
+QDoubleSpinBox#FinalRenderOpenCLSubBatchPctSpin
{
padding: 2px;
border: 1px solid gray;
@@ -631,8 +635,12 @@ QSpinBox#FinalRenderThreadCountSpin
QSpinBox#ThreadCountSpin:disabled,
QSpinBox#CpuSubBatchSpin:disabled,
QSpinBox#OpenCLSubBatchSpin:disabled,
+QSpinBox#CpuQualitySpin:disabled,
+QSpinBox#OpenCLQualitySpin:disabled,
+QDoubleSpinBox#OpenCLSubBatchPctSpin:disabled,
QSpinBox#FinalRenderCurrentSpin:disabled,
-QSpinBox#FinalRenderThreadCountSpin:disabled
+QSpinBox#FinalRenderThreadCountSpin:disabled,
+QDoubleSpinBox#FinalRenderOpenCLSubBatchPctSpin:disabled
{
padding: 2px;
border: 1px solid rgb(35, 35, 35);
diff --git a/Data/dark_windows.qss b/Data/dark_windows.qss
index 1638c0e..2d9b3b7 100644
--- a/Data/dark_windows.qss
+++ b/Data/dark_windows.qss
@@ -39,7 +39,7 @@ QDockWidget::float-button
QDockWidget::title
{
- margin: 1px;
+ margin: 0px;
padding: 2px;
background-color: gray;
}
@@ -418,7 +418,7 @@ QHeaderView::section::horizontal:enabled
{
color: black;
background-color: darkgray;
- border: 0px solid darkgray;
+ border: 1px solid darkgray;
border-right: 1px solid gray;
padding-top: 0px;
padding-bottom: 0px;
@@ -620,8 +620,12 @@ QSpinBox#ThreadCountSpin,
QSpinBox#RandomCountSpin,
QSpinBox#CpuSubBatchSpin,
QSpinBox#OpenCLSubBatchSpin,
+QSpinBox#CpuQualitySpin,
+QSpinBox#OpenCLQualitySpin,
+QDoubleSpinBox#OpenCLSubBatchPctSpin,
QSpinBox#FinalRenderCurrentSpin,
-QSpinBox#FinalRenderThreadCountSpin
+QSpinBox#FinalRenderThreadCountSpin,
+QDoubleSpinBox#FinalRenderOpenCLSubBatchPctSpin
{
padding: 2px;
border: 1px solid gray;
@@ -630,8 +634,12 @@ QSpinBox#FinalRenderThreadCountSpin
QSpinBox#ThreadCountSpin:disabled,
QSpinBox#CpuSubBatchSpin:disabled,
QSpinBox#OpenCLSubBatchSpin:disabled,
+QSpinBox#CpuQualitySpin:disabled,
+QSpinBox#OpenCLQualitySpin:disabled,
+QDoubleSpinBox#OpenCLSubBatchPctSpin:disabled,
QSpinBox#FinalRenderCurrentSpin:disabled,
-QSpinBox#FinalRenderThreadCountSpin:disabled
+QSpinBox#FinalRenderThreadCountSpin:disabled,
+QDoubleSpinBox#FinalRenderOpenCLSubBatchPctSpin:disabled
{
padding: 2px;
border: 1px solid rgb(35, 35, 35);
diff --git a/Source/Ember/Curves.h b/Source/Ember/Curves.h
index 32cf561..36267a2 100644
--- a/Source/Ember/Curves.h
+++ b/Source/Ember/Curves.h
@@ -2,6 +2,9 @@
#include "Utils.h"
#include "Isaac.h"
+#include "Curves.h"
+
+#define CURVE_POINTS 5
///
/// Curves class.
@@ -10,8 +13,9 @@
namespace EmberNs
{
///
-/// The Bezier curves used to adjust the colors during final accumulation.
-/// This functionality was gotten directly from Apophysis.
+/// The b-spline curves used to adjust the colors during final accumulation.
+/// This functionality was gotten inferred from Chaotica.
+/// Note this is now incompatible with Apophysis, which uses Bezier curves instead.
///
template
class EMBER_API Curves
@@ -69,14 +73,23 @@ public:
template
Curves& operator = (const Curves& curves)
{
- for (size_t i = 0; i < 4; i++)
+ int i = 0;
+
+ for (auto& pp : curves.m_Points)
{
- m_Points[i][0].x = T(curves.m_Points[i][0].x); m_Points[i][0].y = T(curves.m_Points[i][0].y); m_Weights[i].x = T(curves.m_Weights[i].x);
- m_Points[i][1].x = T(curves.m_Points[i][1].x); m_Points[i][1].y = T(curves.m_Points[i][1].y); m_Weights[i].y = T(curves.m_Weights[i].y);
- m_Points[i][2].x = T(curves.m_Points[i][2].x); m_Points[i][2].y = T(curves.m_Points[i][2].y); m_Weights[i].z = T(curves.m_Weights[i].z);
- m_Points[i][3].x = T(curves.m_Points[i][3].x); m_Points[i][3].y = T(curves.m_Points[i][3].y); m_Weights[i].w = T(curves.m_Weights[i].w);
+ int j = 0;
+ m_Points[i].clear();
+
+ for (auto& p : pp)
+ {
+ m_Points[i].push_back(p);
+ j++;
+ }
+
+ i++;
}
+ i = 0;
return *this;
}
@@ -88,13 +101,23 @@ public:
template
Curves& operator += (const Curves& curves)
{
- for (size_t i = 0; i < 4; i++)
+ int i = 0;
+
+ for (auto& pp : m_Points)
{
- m_Points[i][0] += curves.m_Points[i][0];
- m_Points[i][1] += curves.m_Points[i][1];
- m_Points[i][2] += curves.m_Points[i][2];
- m_Points[i][3] += curves.m_Points[i][3];
- m_Weights[i] += curves.m_Weights[i];
+ int j = 0;
+
+ for (auto& p : pp)
+ {
+ if (j < curves.m_Points[i].size())
+ p += curves.m_Points[i][j];
+ else
+ break;
+
+ j++;
+ }
+
+ i++;
}
return *this;
@@ -108,13 +131,23 @@ public:
template
Curves& operator *= (const Curves& curves)
{
- for (size_t i = 0; i < 4; i++)
+ int i = 0;
+
+ for (auto& pp : m_Points)
{
- m_Points[i][0] *= curves.m_Points[i][0];
- m_Points[i][1] *= curves.m_Points[i][1];
- m_Points[i][2] *= curves.m_Points[i][2];
- m_Points[i][3] *= curves.m_Points[i][3];
- m_Weights[i] *= curves.m_Weights[i];
+ int j = 0;
+
+ for (auto& p : pp)
+ {
+ if (j < curves.m_Points[i].size())
+ p *= curves.m_Points[i][j];
+ else
+ break;
+
+ j++;
+ }
+
+ i++;
}
return *this;
@@ -128,14 +161,9 @@ public:
template
Curves& operator *= (const U& t)
{
- for (size_t i = 0; i < 4; i++)
- {
- m_Points[i][0] *= T(t);
- m_Points[i][1] *= T(t);
- m_Points[i][2] *= T(t);
- m_Points[i][3] *= T(t);
- m_Weights[i] *= T(t);
- }
+ for (auto& pp : m_Points)
+ for (auto& p : pp)
+ p *= T(t);
return *this;
}
@@ -147,11 +175,12 @@ public:
{
for (size_t i = 0; i < 4; i++)
{
- m_Points[i][0] = v2T(0);//0,0 -> 0,0 -> 1,1 -> 1,1.
- m_Points[i][1] = v2T(0);
- m_Points[i][2] = v2T(1);
- m_Points[i][3] = v2T(1);
- m_Weights[i] = v4T(1);
+ m_Points[i].resize(5);
+ m_Points[i][0] = v2T(0);
+ m_Points[i][1] = v2T(T(0.25));
+ m_Points[i][2] = v2T(T(0.50));
+ m_Points[i][3] = v2T(T(0.75));
+ m_Points[i][4] = v2T(1);
}
}
@@ -162,11 +191,12 @@ public:
{
if (i < 4)
{
- m_Points[i][0] = v2T(0);//0,0 -> 0,0 -> 1,1 -> 1,1.
- m_Points[i][1] = v2T(0);
- m_Points[i][2] = v2T(1);
- m_Points[i][3] = v2T(1);
- m_Weights[i] = v4T(1);
+ m_Points[i].resize(5);
+ m_Points[i][0] = v2T(0);
+ m_Points[i][1] = v2T(T(0.25));
+ m_Points[i][2] = v2T(T(0.50));
+ m_Points[i][3] = v2T(T(0.75));
+ m_Points[i][4] = v2T(1);
}
}
@@ -175,8 +205,8 @@ public:
///
void Clear()
{
- memset(&m_Points, 0, sizeof(m_Points));
- memset(&m_Weights, 0, sizeof(m_Weights));
+ for (auto& p : m_Points)
+ p.clear();
}
///
@@ -189,10 +219,18 @@ public:
for (size_t i = 0; i < 4; i++)
{
+ if (m_Points[i].size() != CURVE_POINTS)
+ {
+ set = true;
+ break;
+ }
+
if ((m_Points[i][0] != v2T(0)) ||
- (m_Points[i][1] != v2T(0)) ||
- (m_Points[i][2] != v2T(1)) ||
- (m_Points[i][3] != v2T(1)))
+ (m_Points[i][1] != v2T(T(0.25))) ||
+ (m_Points[i][2] != v2T(T(0.50))) ||
+ (m_Points[i][3] != v2T(T(0.75))) ||
+ (m_Points[i][4] != v2T(1))
+ )
{
set = true;
break;
@@ -202,52 +240,9 @@ public:
return set;
}
- ///
- /// Wrapper around calling BezierSolve() on each of the 4 weight and point vectors.
- ///
- /// The position to apply
- /// vec4 that contains the y component of the solution for each vector in each component
- v4T BezierFunc(const T& t)
- {
- v4T result;
- v2T solution(0, 0);
- BezierSolve(t, m_Points[0], &m_Weights[0], solution); result.x = solution.y;
- BezierSolve(t, m_Points[1], &m_Weights[1], solution); result.y = solution.y;
- BezierSolve(t, m_Points[2], &m_Weights[2], solution); result.z = solution.y;
- BezierSolve(t, m_Points[3], &m_Weights[3], solution); result.w = solution.y;
- return result;
- }
-
-private:
- ///
- /// Solve the given point and weight vectors for the given position and store
- /// the output in the solution vec2 passed in.
- ///
- /// The position to apply
- /// A pointer to an array of 4 vec2
- /// A pointer to an array of 4 weights
- /// The vec2 to store the solution in
- void BezierSolve(const T& t, v2T* src, v4T* w, v2T& solution)
- {
- T s = 1 - t;
- T s2 = s * s;
- T s3 = s * s * s;
- T t2 = t * t;
- T t3 = t * t * t;
- T nom_x = (w->x * s3 * src->x) + (w->y * s2 * 3 * t * src[1].x) + (w->z * s * 3 * t2 * src[2].x) + (w->w * t3 * src[3].x);
- T nom_y = (w->x * s3 * src->y) + (w->y * s2 * 3 * t * src[1].y) + (w->z * s * 3 * t2 * src[2].y) + (w->w * t3 * src[3].y);
- T denom = (w->x * s3) + (w->y * s2 * 3 * t) + (w->z * s * 3 * t2) + (w->w * t3);
-
- if (std::isnan(nom_x) || std::isnan(nom_y) || std::isnan(denom) || denom == 0)
- return;
-
- solution.x = nom_x / denom;
- solution.y = nom_y / denom;
- }
public:
- v2T m_Points[4][4];
- v4T m_Weights[4];
+ std::array, 4> m_Points;
};
//Must declare this outside of the class to provide for both orders of parameters.
@@ -264,14 +259,9 @@ Curves operator * (const Curves& curves, const U& t)
T tt = T(t);
Curves c(curves);
- for (size_t i = 0; i < 4; i++)
- {
- c.m_Points[i][0] *= tt;
- c.m_Points[i][1] *= tt;
- c.m_Points[i][2] *= tt;
- c.m_Points[i][3] *= tt;
- c.m_Weights[i] *= tt;
- }
+ for (auto& pp : c.m_Points)
+ for (auto& p : pp)
+ p *= tt;
return c;
}
diff --git a/Source/Ember/Ember.cpp b/Source/Ember/Ember.cpp
index 67ebed0..c4c3d0e 100644
--- a/Source/Ember/Ember.cpp
+++ b/Source/Ember/Ember.cpp
@@ -31,6 +31,7 @@ template EMBER_API class QTIsaac;
#include "Xform.h"
#include "EmberMotion.h"
#include "EmberToXml.h"
+#include "Spline.h"
#include "XmlToEmber.h"
#include "SpatialFilter.h"
#include "DensityFilter.h"
@@ -77,6 +78,8 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(Sinusoidal, T) \
EXPORTPREPOSTREGVAR(Spherical, T) \
EXPORTPREPOSTREGVAR(Swirl, T) \
+ EXPORTPREPOSTREGVAR(Swirl3, T) \
+ EXPORTPREPOSTREGVAR(Swirl3r, T) \
EXPORTPREPOSTREGVAR(Horseshoe, T) \
EXPORTPREPOSTREGVAR(Polar, T) \
EXPORTPREPOSTREGVAR(Handkerchief, T) \
@@ -109,6 +112,7 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(JuliaScope, T) \
EXPORTPREPOSTREGVAR(Blur, T) \
EXPORTPREPOSTREGVAR(GaussianBlur, T) \
+ EXPORTPREPOSTREGVAR(Gaussian, T) \
EXPORTPREPOSTREGVAR(RadialBlur, T) \
EXPORTPREPOSTREGVAR(Pie, T) \
EXPORTPREPOSTREGVAR(Ngon, T) \
@@ -128,6 +132,7 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(Disc2, T) \
EXPORTPREPOSTREGVAR(SuperShape, T) \
EXPORTPREPOSTREGVAR(Flower, T) \
+ EXPORTPREPOSTREGVAR(FlowerDb, T) \
EXPORTPREPOSTREGVAR(Conic, T) \
EXPORTPREPOSTREGVAR(Parabola, T) \
EXPORTPREPOSTREGVAR(Bent2, T) \
@@ -145,9 +150,11 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(Loonie, T) \
EXPORTPREPOSTREGVAR(Modulus, T) \
EXPORTPREPOSTREGVAR(Oscilloscope, T) \
+ EXPORTPREPOSTREGVAR(Oscilloscope2, T) \
EXPORTPREPOSTREGVAR(Polar2, T) \
EXPORTPREPOSTREGVAR(Popcorn2, T) \
EXPORTPREPOSTREGVAR(Scry, T) \
+ EXPORTPREPOSTREGVAR(Scry2, T) \
EXPORTPREPOSTREGVAR(Separation, T) \
EXPORTPREPOSTREGVAR(Split, T) \
EXPORTPREPOSTREGVAR(Splits, T) \
@@ -158,6 +165,7 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(Whorl, T) \
EXPORTPREPOSTREGVAR(Waves2, T) \
EXPORTPREPOSTREGVAR(Exp, T) \
+ EXPORTPREPOSTREGVAR(Exp2, T) \
EXPORTPREPOSTREGVAR(Log, T) \
EXPORTPREPOSTREGVAR(Sin, T) \
EXPORTPREPOSTREGVAR(Cos, T) \
@@ -168,6 +176,7 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(Sinh, T) \
EXPORTPREPOSTREGVAR(Cosh, T) \
EXPORTPREPOSTREGVAR(Tanh, T) \
+ EXPORTPREPOSTREGVAR(TanhSpiral, T) \
EXPORTPREPOSTREGVAR(Sech, T) \
EXPORTPREPOSTREGVAR(Csch, T) \
EXPORTPREPOSTREGVAR(Coth, T) \
@@ -176,6 +185,7 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(Hemisphere, T) \
EXPORTPREPOSTREGVAR(Epispiral, T) \
EXPORTPREPOSTREGVAR(Bwraps, T) \
+ EXPORTPREPOSTREGVAR(BwrapsRand, T) \
EXPORTPREPOSTREGVAR(Extrude, T) \
EXPORTPREPOSTREGVAR(BlurCircle, T) \
EXPORTPREPOSTREGVAR(BlurZoom, T) \
@@ -196,6 +206,7 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(Fibonacci, T) \
EXPORTPREPOSTREGVAR(Fibonacci2, T) \
EXPORTPREPOSTREGVAR(Glynnia, T) \
+ EXPORTPREPOSTREGVAR(Glynnia2, T) \
EXPORTPREPOSTREGVAR(GridOut, T) \
EXPORTPREPOSTREGVAR(Hole, T) \
EXPORTPREPOSTREGVAR(Hypertile, T) \
@@ -241,6 +252,8 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(GlynnSim1, T) \
EXPORTPREPOSTREGVAR(GlynnSim2, T) \
EXPORTPREPOSTREGVAR(GlynnSim3, T) \
+ EXPORTPREPOSTREGVAR(GlynnSim4, T) \
+ EXPORTPREPOSTREGVAR(GlynnSim5, T) \
EXPORTPREPOSTREGVAR(Starblur, T) \
EXPORTPREPOSTREGVAR(Sineblur, T) \
EXPORTPREPOSTREGVAR(Circleblur, T) \
@@ -255,6 +268,7 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(Ovoid3D, T) \
EXPORTPREPOSTREGVAR(Spirograph, T) \
EXPORTPREPOSTREGVAR(Petal, T) \
+ EXPORTPREPOSTREGVAR(Spher, T) \
EXPORTPREPOSTREGVAR(RoundSpher, T) \
EXPORTPREPOSTREGVAR(RoundSpher3D, T) \
EXPORTPREPOSTREGVAR(SpiralWing, T) \
@@ -267,6 +281,8 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(Lissajous, T) \
EXPORTPREPOSTREGVAR(Svf, T) \
EXPORTPREPOSTREGVAR(Target, T) \
+ EXPORTPREPOSTREGVAR(Target0, T) \
+ EXPORTPREPOSTREGVAR(Target2, T) \
EXPORTPREPOSTREGVAR(Taurus, T) \
EXPORTPREPOSTREGVAR(Collideoscope, T) \
EXPORTPREPOSTREGVAR(BMod, T) \
@@ -275,6 +291,7 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(BCollide, T) \
EXPORTPREPOSTREGVAR(Eclipse, T) \
EXPORTPREPOSTREGVAR(FlipCircle, T) \
+ EXPORTPREPOSTREGVAR(FlipX, T) \
EXPORTPREPOSTREGVAR(FlipY, T) \
EXPORTPREPOSTREGVAR(ECollide, T) \
EXPORTPREPOSTREGVAR(EJulia, T) \
@@ -284,6 +301,7 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(ERotate, T) \
EXPORTPREPOSTREGVAR(EScale, T) \
EXPORTPREPOSTREGVAR(ESwirl, T) \
+ EXPORTPREPOSTREGVAR(LazyJess, T) \
EXPORTPREPOSTREGVAR(LazyTravis, T) \
EXPORTPREPOSTREGVAR(Squish, T) \
EXPORTPREPOSTREGVAR(Circus, T) \
@@ -311,6 +329,7 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(SuperShape3D, T) \
EXPORTPREPOSTREGVAR(Sphyp3D, T) \
EXPORTPREPOSTREGVAR(Circlecrop, T) \
+ EXPORTPREPOSTREGVAR(Circlecrop2, T) \
EXPORTPREPOSTREGVAR(Julian3Dx, T) \
EXPORTPREPOSTREGVAR(Fourth, T) \
EXPORTPREPOSTREGVAR(Mobiq, T) \
@@ -336,13 +355,13 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(Curvature, T) \
EXPORTPREPOSTREGVAR(Qode, T) \
EXPORTPREPOSTREGVAR(BlurHeart, T) \
- EXPORTPREPOSTREGVAR(Truchet, T) \
EXPORTPREPOSTREGVAR(Gdoffs, T) \
EXPORTPREPOSTREGVAR(Octagon, T) \
EXPORTPREPOSTREGVAR(Trade, T) \
EXPORTPREPOSTREGVAR(Juliac, T) \
EXPORTPREPOSTREGVAR(Blade3D, T) \
EXPORTPREPOSTREGVAR(Blob3D, T) \
+ EXPORTPREPOSTREGVAR(Block, T) \
EXPORTPREPOSTREGVAR(Blocky, T) \
EXPORTPREPOSTREGVAR(Bubble2, T) \
EXPORTPREPOSTREGVAR(CircleLinear, T) \
@@ -351,6 +370,7 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(Cubic3D, T) \
EXPORTPREPOSTREGVAR(CubicLattice3D, T) \
EXPORTPREPOSTREGVAR(Foci3D, T) \
+ EXPORTPREPOSTREGVAR(FociP, T) \
EXPORTPREPOSTREGVAR(Ho, T) \
EXPORTPREPOSTREGVAR(Julia3Dq, T) \
EXPORTPREPOSTREGVAR(Line, T) \
@@ -380,6 +400,7 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(BubbleT3D, T) \
EXPORTPREPOSTREGVAR(Synth, T) \
EXPORTPREPOSTREGVAR(Crackle, T) \
+ EXPORTPREPOSTREGVAR(Crackle2, T) \
EXPORTPREPOSTREGVAR(Erf, T) \
EXPORTPREPOSTREGVAR(Xerf, T) \
EXPORTPREPOSTREGVAR(W, T) \
@@ -398,7 +419,12 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(CircleSplit, T) \
EXPORTPREPOSTREGVAR(Cylinder2, T) \
EXPORTPREPOSTREGVAR(TileLog, T) \
+ EXPORTPREPOSTREGVAR(TileHlp, T) \
+ EXPORTPREPOSTREGVAR(Truchet, T) \
EXPORTPREPOSTREGVAR(TruchetFill, T) \
+ EXPORTPREPOSTREGVAR(TruchetGlyph, T) \
+ EXPORTPREPOSTREGVAR(TruchetInv, T) \
+ EXPORTPREPOSTREGVAR(TruchetKnot, T) \
EXPORTPREPOSTREGVAR(Waves2Radial, T) \
EXPORTPREPOSTREGVAR(Panorama1, T) \
EXPORTPREPOSTREGVAR(Panorama2, T) \
@@ -408,7 +434,44 @@ uint Timing::m_ProcessorCount;
EXPORTPREPOSTREGVAR(Cpow3, T) \
EXPORTPREPOSTREGVAR(Concentric, T) \
EXPORTPREPOSTREGVAR(Hypercrop, T) \
+ EXPORTPREPOSTREGVAR(Hypershift, T) \
EXPORTPREPOSTREGVAR(Hypershift2, T) \
+ EXPORTPREPOSTREGVAR(Lens, T) \
+ EXPORTPREPOSTREGVAR(Projective, T) \
+ EXPORTPREPOSTREGVAR(DepthBlur, T) \
+ EXPORTPREPOSTREGVAR(DepthBlur2, T) \
+ EXPORTPREPOSTREGVAR(DepthGaussian, T) \
+ EXPORTPREPOSTREGVAR(DepthGaussian2, T) \
+ EXPORTPREPOSTREGVAR(DepthNgon, T) \
+ EXPORTPREPOSTREGVAR(DepthNgon2, T) \
+ EXPORTPREPOSTREGVAR(DepthSine, T) \
+ EXPORTPREPOSTREGVAR(DepthSine2, T) \
+ EXPORTPREPOSTREGVAR(CothSpiral, T) \
+ EXPORTPREPOSTREGVAR(Dust, T) \
+ EXPORTPREPOSTREGVAR(Asteria, T) \
+ EXPORTPREPOSTREGVAR(Pulse, T) \
+ EXPORTPREPOSTREGVAR(Excinis, T) \
+ EXPORTPREPOSTREGVAR(Vibration, T) \
+ EXPORTPREPOSTREGVAR(Vibration2, T) \
+ EXPORTPREPOSTREGVAR(Arcsech, T) \
+ EXPORTPREPOSTREGVAR(Arcsech2, T) \
+ EXPORTPREPOSTREGVAR(Arcsinh, T) \
+ EXPORTPREPOSTREGVAR(Arctanh, T) \
+ EXPORTPREPOSTREGVAR(HexTruchet, T) \
+ EXPORTPREPOSTREGVAR(HexRand, T) \
+ EXPORTPREPOSTREGVAR(Smartshape, T) \
+ EXPORTPREPOSTREGVAR(Squares, T) \
+ EXPORTPREPOSTREGVAR(Starblur2, T) \
+ EXPORTPREPOSTREGVAR(UnicornGaloshen, T) \
+ EXPORTPREPOSTREGVAR(Dragonfire, T) \
+ EXPORTPREPOSTREGVAR(Henon, T) \
+ EXPORTPREPOSTREGVAR(Lozi, T) \
+ EXPORTPREPOSTREGVAR(PointSymmetry, T) \
+ EXPORTPREPOSTREGVAR(DSpherical, T) \
+ EXPORTPREPOSTREGVAR(Modulusx, T) \
+ EXPORTPREPOSTREGVAR(Modulusy, T) \
+ EXPORTPREPOSTREGVAR(Rotate, T) \
+ EXPORTPREPOSTREGVAR(Shift, T) \
template EMBER_API class PostSmartcropVariation; /*Only implemented as post.*/ \
EXPORTPREPOSTREGVAR(DCBubble, T) \
EXPORTPREPOSTREGVAR(DCCarpet, T) \
@@ -460,6 +523,7 @@ EXPORT_TWO_TYPE_EMBER(float, float)
//Only ever use float palettes.
template EMBER_API class Palette;
template EMBER_API class PaletteList;
+template EMBER_API class Spline;
#ifdef DO_DOUBLE
EXPORT_SINGLE_TYPE_EMBER(double)
diff --git a/Source/Ember/Ember.h b/Source/Ember/Ember.h
index a28d831..a4c85e3 100644
--- a/Source/Ember/Ember.h
+++ b/Source/Ember/Ember.h
@@ -106,6 +106,7 @@ public:
m_OrigFinalRasW = ember.m_OrigFinalRasW;
m_OrigFinalRasH = ember.m_OrigFinalRasH;
m_OrigPixPerUnit = T(ember.m_OrigPixPerUnit);
+ m_RandPointRange = T(ember.m_RandPointRange);
m_SubBatchSize = ember.m_SubBatchSize;
m_FuseCount = ember.m_FuseCount;
m_Supersample = ember.m_Supersample;
@@ -129,6 +130,7 @@ public:
m_Vibrancy = T(ember.m_Vibrancy);
m_GammaThresh = T(ember.m_GammaThresh);
m_HighlightPower = T(ember.m_HighlightPower);
+ m_K2 = T(ember.m_K2);
m_Time = T(ember.m_Time);
m_Background = ember.m_Background;
m_Interp = ember.m_Interp;
@@ -530,6 +532,7 @@ public:
/// New width
/// New height
/// True to only scale if the new dimensions are smaller than the original, else always scale.
+ /// Scale type used to specify how the image should be zoomed using the scale variable with respect to the new size. Possible scaling modes are: width, height, none.
void SetSizeAndAdjustScale(size_t width, size_t height, bool onlyScaleIfNewIsSmaller, eScaleType scaleType)
{
if ((onlyScaleIfNewIsSmaller && (width < m_OrigFinalRasW || height < m_OrigFinalRasH)) || !onlyScaleIfNewIsSmaller)
@@ -538,6 +541,8 @@ public:
m_PixelsPerUnit = m_OrigPixPerUnit * (T(width) / T(m_OrigFinalRasW));
else if (scaleType == eScaleType::SCALE_HEIGHT)
m_PixelsPerUnit = m_OrigPixPerUnit * (T(height) / T(m_OrigFinalRasH));
+ else
+ m_PixelsPerUnit = m_OrigPixPerUnit;
}
m_ScaleType = scaleType;
@@ -744,6 +749,7 @@ public:
InterpI<&Ember::m_FinalRasW>(embers, coefs, size);
InterpI<&Ember::m_FinalRasH>(embers, coefs, size);
InterpI<&Ember::m_SubBatchSize>(embers, coefs, size);
+ InterpT<&Ember::m_RandPointRange>(embers, coefs, size);
InterpI<&Ember::m_FuseCount>(embers, coefs, size);
InterpI<&Ember::m_Supersample>(embers, coefs, size);
InterpI<&Ember::m_TemporalSamples>(embers, coefs, size);
@@ -765,6 +771,7 @@ public:
InterpT<&Ember::m_Vibrancy>(embers, coefs, size);
InterpT<&Ember::m_GammaThresh>(embers, coefs, size);
InterpT<&Ember::m_HighlightPower>(embers, coefs, size);
+ InterpT<&Ember::m_K2>(embers, coefs, size);
InterpX, &Ember::m_Background>(embers, coefs, size); m_Background.a = bgAlphaSave;//Don't interp alpha.
InterpT<&Ember::m_TemporalFilterExp>(embers, coefs, size);
InterpT<&Ember::m_TemporalFilterWidth>(embers, coefs, size);
@@ -1309,6 +1316,14 @@ public:
APP_FMP(m_HighlightPower);
break;
+ case eEmberMotionParam::FLAME_MOTION_K2:
+ APP_FMP(m_K2);
+ break;
+
+ case eEmberMotionParam::FLAME_MOTION_RAND_RANGE:
+ APP_FMP(m_RandPointRange);
+ break;
+
case eEmberMotionParam::FLAME_MOTION_BACKGROUND_R:
APP_FMP(m_Background.r);
break;
@@ -1359,6 +1374,7 @@ public:
{
//If defaults are on, set to reasonable values.
m_HighlightPower = 1;
+ m_K2 = 0;
m_Background.Reset();
m_FinalRasW = 100;
m_FinalRasH = 100;
@@ -1375,6 +1391,7 @@ public:
m_CamMat = m3T(0);
m_Quality = 1;
m_SubBatchSize = 10240;
+ m_RandPointRange = 1;
m_FuseCount = 15;
m_MaxRadDE = T(9.0);
m_MinRadDE = 0;
@@ -1393,6 +1410,7 @@ public:
{
//Defaults are off, so set to UN-reasonable values.
m_HighlightPower = -1;
+ m_K2 = -1;
m_Background = Color(-1, -1, -1, 1);
m_FinalRasW = 0;
m_FinalRasH = 0;
@@ -1409,6 +1427,7 @@ public:
m_CamMat = m3T(999999);
m_Quality = -1;
m_SubBatchSize = 0;
+ m_RandPointRange = 0;
m_FuseCount = 0;
m_MaxRadDE = -1;
m_MinRadDE = -1;
@@ -1459,6 +1478,7 @@ public:
<< "Quality: " << m_Quality << "\n"
<< "Pixels Per Unit: " << m_PixelsPerUnit << "\n"
<< "Original Pixels Per Unit: " << m_OrigPixPerUnit << "\n"
+ << "Initial Point Range: " << m_RandPointRange << "\n"
<< "Sub Batch Size: " << m_SubBatchSize << "\n"
<< "Fuse Count: " << m_FuseCount << "\n"
<< "Zoom: " << m_Zoom << "\n"
@@ -1476,6 +1496,7 @@ public:
<< "Vibrancy: " << m_Vibrancy << "\n"
<< "Gamma Threshold: " << m_GammaThresh << "\n"
<< "Highlight Power: " << m_HighlightPower << "\n"
+ << "K2: " << m_K2 << "\n"
<< "Time: " << m_Time << "\n"
<< "Background: " << m_Background.r << ", " << m_Background.g << ", " << m_Background.b << ", " << m_Background.a << "\n"
<< "Interp: " << m_Interp << "\n"
@@ -1531,6 +1552,10 @@ public:
size_t m_OrigFinalRasH = 1080;//the dimension may change in an editor and the originals are needed for the aspect ratio.
T m_OrigPixPerUnit = 240;
+ //The range in the x and y directions from the center of the world space from which the initial random point will be selected at the start of each sub batch.
+ //Or when recovering from a bad point.
+ T m_RandPointRange = 1;
+
//The iteration depth. This was a rendering parameter in flam3 but has been made a member here
//so that it can be adjusted more easily.
size_t m_SubBatchSize = DEFAULT_SBS;
@@ -1628,6 +1653,9 @@ public:
//Xml field: "highlight_power".
T m_HighlightPower = 1;
+ //An alternative way to set brightness, ignored when zero.
+ T m_K2 = 0;
+
//When animating a file full of many embers, this value is used to specify the time in the animation
//that this ember should be rendered. They must all be sequential and increase by a default value of 1.
//Xml field: "time".
diff --git a/Source/Ember/EmberDefines.h b/Source/Ember/EmberDefines.h
index b46b1c8..45a933e 100644
--- a/Source/Ember/EmberDefines.h
+++ b/Source/Ember/EmberDefines.h
@@ -37,7 +37,7 @@ static void sincos(float x, float* s, float* c)
namespace EmberNs
{
-#define EMBER_VERSION "1.0.0.14"
+#define EMBER_VERSION "1.0.0.15"
#define EPS6 T(1e-6)
#define EPS std::numeric_limits::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way.
#define ISAAC_SIZE 4
@@ -106,6 +106,7 @@ static inline size_t NowMs() { return duration_cast(Clock::now().t
#define v2T glm::tvec2
#define v3T glm::tvec3
#define v4T glm::tvec4
+ #define v2F glm::tvec2
#define v4F glm::tvec4
#define v4D glm::tvec4
#define v4bT glm::tvec4
@@ -118,6 +119,7 @@ static inline size_t NowMs() { return duration_cast(Clock::now().t
#define v2T glm::detail::tvec2
#define v3T glm::detail::tvec3
#define v4T glm::detail::tvec4
+ #define v2F glm::detail::tvec2
#define v4F glm::detail::tvec4
#define v4D glm::detail::tvec4
#define v4bT glm::detail::tvec4
@@ -154,6 +156,8 @@ enum class eEmberMotionParam : et//These must remain in this order forever.
FLAME_MOTION_GAMMA,
FLAME_MOTION_GAMMA_THRESH,
FLAME_MOTION_HIGHLIGHT_POWER,
+ FLAME_MOTION_K2,
+ FLAME_MOTION_RAND_RANGE,
FLAME_MOTION_BACKGROUND_R,
FLAME_MOTION_BACKGROUND_G,
FLAME_MOTION_BACKGROUND_B,
diff --git a/Source/Ember/EmberToXml.cpp b/Source/Ember/EmberToXml.cpp
index 91be425..cb8d640 100644
--- a/Source/Ember/EmberToXml.cpp
+++ b/Source/Ember/EmberToXml.cpp
@@ -143,10 +143,12 @@ string EmberToXml::ToString(Ember& ember, const string& extraAttributes, s
os << " temporal_samples=\"" << ember.m_TemporalSamples << "\"";
os << " sub_batch_size=\"" << ember.m_SubBatchSize << "\"";
os << " fuse=\"" << ember.m_FuseCount << "\"";
+ os << " rand_range=\"" << ember.m_RandPointRange << "\"";
os << " background=\"" << ember.m_Background.r << " " << ember.m_Background.g << " " << ember.m_Background.b << "\"";
os << " brightness=\"" << ember.m_Brightness << "\"";
os << " gamma=\"" << ember.m_Gamma << "\"";
os << " highlight_power=\"" << ember.m_HighlightPower << "\"";
+ os << " logscale_k2=\"" << ember.m_K2 << "\"";
os << " vibrancy=\"" << ember.m_Vibrancy << "\"";
os << " estimator_radius=\"" << ember.m_MaxRadDE << "\"";
os << " estimator_minimum=\"" << ember.m_MinRadDE << "\"";
@@ -200,10 +202,42 @@ string EmberToXml::ToString(Ember& ember, const string& extraAttributes, s
{
os << ember.m_Curves.m_Points[ci][cj].x << " ";
os << ember.m_Curves.m_Points[ci][cj].y << " ";
- os << ember.m_Curves.m_Weights[ci][cj] << " ";
+ os << "1 ";
}
}
+ os << "\" overall_curve=\"";
+
+ for (glm::length_t cj = 0; cj < ember.m_Curves.m_Points[0].size(); cj++)
+ {
+ os << ember.m_Curves.m_Points[0][cj].x << " ";
+ os << ember.m_Curves.m_Points[0][cj].y << " ";
+ }
+
+ os << "\" red_curve=\"";
+
+ for (glm::length_t cj = 0; cj < ember.m_Curves.m_Points[1].size(); cj++)
+ {
+ os << ember.m_Curves.m_Points[1][cj].x << " ";
+ os << ember.m_Curves.m_Points[1][cj].y << " ";
+ }
+
+ os << "\" green_curve=\"";
+
+ for (glm::length_t cj = 0; cj < ember.m_Curves.m_Points[2].size(); cj++)
+ {
+ os << ember.m_Curves.m_Points[2][cj].x << " ";
+ os << ember.m_Curves.m_Points[2][cj].y << " ";
+ }
+
+ os << "\" blue_curve=\"";
+
+ for (glm::length_t cj = 0; cj < ember.m_Curves.m_Points[3].size(); cj++)
+ {
+ os << ember.m_Curves.m_Points[3][cj].x << " ";
+ os << ember.m_Curves.m_Points[3][cj].y << " ";
+ }
+
os << "\">\n";
for (i = 0; i < ember.m_EmberMotionElements.size(); ++i)
@@ -813,6 +847,14 @@ string EmberToXml::ToString(const EmberMotion& motion)
os << " highlight_power=\"" << motion.m_MotionParams[i].second << "\"";
break;
+ case eEmberMotionParam::FLAME_MOTION_K2:
+ os << " logscale_k2=\"" << motion.m_MotionParams[i].second << "\"";
+ break;
+
+ case eEmberMotionParam::FLAME_MOTION_RAND_RANGE:
+ os << " rand_range=\"" << motion.m_MotionParams[i].second << "\"";
+ break;
+
case eEmberMotionParam::FLAME_MOTION_BACKGROUND_R:
r = motion.m_MotionParams[i].second;
break;
diff --git a/Source/Ember/Iterator.h b/Source/Ember/Iterator.h
index 4d1dda8..afd4264 100644
--- a/Source/Ember/Iterator.h
+++ b/Source/Ember/Iterator.h
@@ -15,9 +15,7 @@ namespace EmberNs
using Iterator::NextXformFromIndex; \
using Iterator::DoFinalXform; \
using Iterator::DoBadVals;
-
-template class Renderer;
-
+
template
struct IterParams
{
@@ -40,7 +38,7 @@ struct IterParams
/// Flam3 needlessly computed the final xform on each fuse iteration only to throw it away. It's omitted here as an optimization.
/// Rather than place many conditionals inside the iteration loop, they are broken into separate classes depending
/// on what's contained in the ember's xforms.
-/// The biggest difference is whether xaos is present or not it requires extra work when picking
+/// The biggest difference is whether xaos is present or not, since it requires extra work when picking
/// the next random xform to use. Further, each of those is broken into two loops, one for embers with a final xform
/// and one without.
/// Last, the fuse loop and real loop are separated and duplicated to omit the conditional check for fuse inside the real loop.
@@ -52,9 +50,12 @@ class EMBER_API Iterator
{
public:
///
- /// Empty constructor and virtual destructor so proper derived class destructors get called.
+ /// Constructor that takes a pointer to the renderer which is calling this and a virtual destructor so proper derived class destructors get called.
///
- Iterator() = default;
+ Iterator()
+ {
+ }
+
virtual ~Iterator() = default;
Iterator(const Iterator& iter) = delete;
@@ -196,11 +197,12 @@ protected:
/// the coordinates of the output point are just set to a random number between -1 and 1.
///
/// The xforms array
+ /// The range in the x and y directions from the center of the world spcae from which to select the new random point
/// The counter for the total number of bad values this sub batch
/// The point which initially had the bad values and which will store the newly computed values
/// The random context this iterator is using
/// True if a good value was computed within 5 tries, else false
- inline bool DoBadVals(Xform* xforms, size_t& badVals, Point* point, QTIsaac& rand)
+ inline bool DoBadVals(Xform* xforms, T range, size_t& badVals, Point* point, QTIsaac& rand)
{
size_t xformIndex, consec = 0;
Point firstBadPoint;
@@ -209,8 +211,8 @@ protected:
{
consec++;
badVals++;
- firstBadPoint.m_X = rand.Frand11();//Re-randomize points, but keep the computed color and viz.
- firstBadPoint.m_Y = rand.Frand11();
+ firstBadPoint.m_X = rand.template Frand(-range, range);//Re-randomize points, but keep the computed color and viz.
+ firstBadPoint.m_Y = rand.template Frand(-range, range);
firstBadPoint.m_Z = 0;
firstBadPoint.m_ColorX = point->m_ColorX;
firstBadPoint.m_Opacity = point->m_Opacity;
@@ -223,8 +225,8 @@ protected:
//After 5 tries, nothing worked, so just assign random values between -1 and 1.
if (consec == 5)
{
- point->m_X = rand.Frand11();
- point->m_Y = rand.Frand11();
+ point->m_X = rand.template Frand(-range, range);
+ point->m_Y = rand.template Frand(-range, range);
point->m_Z = 0;
}
@@ -310,7 +312,7 @@ public:
for (i = 0; i < params.m_Skip; i++)//Fuse.
{
if (xforms[NextXformFromIndex(rand.Rand())].Apply(&p1, &p1, rand))
- DoBadVals(xforms, badVals, &p1, rand);
+ DoBadVals(xforms, ember.m_RandPointRange, badVals, &p1, rand);
}
DoFinalXform(ember, p1, samples, rand);//Apply to last fuse point and store as the first element in samples.
@@ -319,7 +321,7 @@ public:
for (i = 1; i < params.m_Count; i++)//Real loop.
{
if (xforms[NextXformFromIndex(rand.Rand())].Apply(&p1, &p1, rand))
- DoBadVals(xforms, badVals, &p1, rand);
+ DoBadVals(xforms, ember.m_RandPointRange, badVals, &p1, rand);
DoFinalXform(ember, p1, samples + i, rand);
ember.Proj(samples[i], rand);
@@ -332,7 +334,7 @@ public:
for (i = 0; i < params.m_Skip; i++)//Fuse.
{
if (xforms[NextXformFromIndex(rand.Rand())].Apply(&p1, &p1, rand))
- DoBadVals(xforms, badVals, &p1, rand);
+ DoBadVals(xforms, ember.m_RandPointRange, badVals, &p1, rand);
}
samples[0] = p1;
@@ -341,7 +343,7 @@ public:
for (i = 1; i < params.m_Count; i++)//Real loop.
{
if (xforms[NextXformFromIndex(rand.Rand())].Apply(&p1, &samples[i], rand))
- DoBadVals(xforms, badVals, samples + i, rand);
+ DoBadVals(xforms, ember.m_RandPointRange, badVals, samples + i, rand);
p1 = samples[i];
ember.Proj(samples[i], rand);
@@ -357,7 +359,7 @@ public:
for (i = 0; i < params.m_Skip; i++)//Fuse.
{
if (xforms[NextXformFromIndex(rand.Rand())].Apply(&p1, &p1, rand))
- DoBadVals(xforms, badVals, &p1, rand);
+ DoBadVals(xforms, ember.m_RandPointRange, badVals, &p1, rand);
}
DoFinalXform(ember, p1, samples, rand);//Apply to last fuse point and store as the first element in samples.
@@ -365,7 +367,7 @@ public:
for (i = 1; i < params.m_Count; i++)//Real loop.
{
if (xforms[NextXformFromIndex(rand.Rand())].Apply(&p1, &p1, rand))//Feed the resulting value of applying the randomly selected xform back into the next iter, and not the result of applying the final xform.
- DoBadVals(xforms, badVals, &p1, rand);
+ DoBadVals(xforms, ember.m_RandPointRange, badVals, &p1, rand);
DoFinalXform(ember, p1, samples + i, rand);
}
@@ -377,7 +379,7 @@ public:
for (i = 0; i < params.m_Skip; i++)//Fuse.
{
if (xforms[NextXformFromIndex(rand.Rand())].Apply(&p1, &p1, rand))
- DoBadVals(xforms, badVals, &p1, rand);
+ DoBadVals(xforms, ember.m_RandPointRange, badVals, &p1, rand);
}
samples[0] = p1;
@@ -385,7 +387,7 @@ public:
for (i = 0; i < params.m_Count - 1; i++)//Real loop.
{
if (xforms[NextXformFromIndex(rand.Rand())].Apply(samples + i, samples + i + 1, rand))
- DoBadVals(xforms, badVals, samples + i + 1, rand);
+ DoBadVals(xforms, ember.m_RandPointRange, badVals, samples + i + 1, rand);
}
}
}
@@ -415,12 +417,13 @@ public:
///
/// The xforms array
/// Index of the last used xform before calling this function
+ /// The range in the x and y directions from the center of the world spcae from which to select the new random point
/// The saved index of the last xform used within this function
/// The counter for the total number of bad values this sub batch
/// The point which initially had the bad values and which will store the newly computed values
/// The random context this iterator is using
/// True if a good value was computed within 5 tries, else false
- inline bool DoBadVals(Xform* xforms, size_t& xformIndex, size_t lastXformUsed, size_t& badVals, Point* point, QTIsaac& rand)
+ inline bool DoBadVals(Xform* xforms, size_t& xformIndex, T range, size_t lastXformUsed, size_t& badVals, Point* point, QTIsaac& rand)
{
size_t consec = 0;
Point firstBadPoint;
@@ -429,8 +432,8 @@ public:
{
consec++;
badVals++;
- firstBadPoint.m_X = rand.Frand11();//Re-randomize points, but keep the computed color and viz.
- firstBadPoint.m_Y = rand.Frand11();
+ firstBadPoint.m_X = rand.template Frand(-range, range);//Re-randomize points, but keep the computed color and viz.
+ firstBadPoint.m_Y = rand.template Frand(-range, range);
firstBadPoint.m_Z = 0;
firstBadPoint.m_ColorX = point->m_ColorX;
firstBadPoint.m_Opacity = point->m_Opacity;
@@ -443,8 +446,8 @@ public:
//After 5 tries, nothing worked, so just assign random.
if (consec == 5)
{
- point->m_X = rand.Frand11();
- point->m_Y = rand.Frand11();
+ point->m_X = rand.template Frand(-range, range);
+ point->m_Y = rand.template Frand(-range, range);
point->m_Z = 0;
}
@@ -479,7 +482,7 @@ public:
xformIndex = NextXformFromIndex(rand.Rand(), lastXformUsed);
if (xforms[xformIndex].Apply(&p1, &p1, rand))
- DoBadVals(xforms, xformIndex, lastXformUsed, badVals, &p1, rand);
+ DoBadVals(xforms, xformIndex, ember.m_RandPointRange, lastXformUsed, badVals, &p1, rand);
lastXformUsed = xformIndex + 1;//Store the last used transform.
}
@@ -492,7 +495,7 @@ public:
xformIndex = NextXformFromIndex(rand.Rand(), lastXformUsed);
if (xforms[xformIndex].Apply(&p1, &p1, rand))//Feed the resulting value of applying the randomly selected xform back into the next iter, and not the result of applying the final xform.
- DoBadVals(xforms, xformIndex, lastXformUsed, badVals, &p1, rand);
+ DoBadVals(xforms, xformIndex, ember.m_RandPointRange, lastXformUsed, badVals, &p1, rand);
DoFinalXform(ember, p1, samples + i, rand);
ember.Proj(samples[i], rand);
@@ -508,7 +511,7 @@ public:
xformIndex = NextXformFromIndex(rand.Rand(), lastXformUsed);
if (xforms[xformIndex].Apply(&p1, &p1, rand))
- DoBadVals(xforms, xformIndex, lastXformUsed, badVals, &p1, rand);
+ DoBadVals(xforms, xformIndex, ember.m_RandPointRange, lastXformUsed, badVals, &p1, rand);
lastXformUsed = xformIndex + 1;//Store the last used transform.
}
@@ -521,7 +524,7 @@ public:
xformIndex = NextXformFromIndex(rand.Rand(), lastXformUsed);
if (xforms[xformIndex].Apply(&p1, &p1, rand))
- DoBadVals(xforms, xformIndex, lastXformUsed, badVals, &p1, rand);
+ DoBadVals(xforms, xformIndex, ember.m_RandPointRange, lastXformUsed, badVals, &p1, rand);
samples[i] = p1;
ember.Proj(samples[i], rand);
@@ -540,7 +543,7 @@ public:
xformIndex = NextXformFromIndex(rand.Rand(), lastXformUsed);
if (xforms[xformIndex].Apply(&p1, &p1, rand))
- DoBadVals(xforms, xformIndex, lastXformUsed, badVals, &p1, rand);
+ DoBadVals(xforms, xformIndex, ember.m_RandPointRange, lastXformUsed, badVals, &p1, rand);
lastXformUsed = xformIndex + 1;//Store the last used transform.
}
@@ -552,7 +555,7 @@ public:
xformIndex = NextXformFromIndex(rand.Rand(), lastXformUsed);
if (xforms[xformIndex].Apply(&p1, &p1, rand))//Feed the resulting value of applying the randomly selected xform back into the next iter, and not the result of applying the final xform.
- DoBadVals(xforms, xformIndex, lastXformUsed, badVals, &p1, rand);
+ DoBadVals(xforms, xformIndex, ember.m_RandPointRange, lastXformUsed, badVals, &p1, rand);
DoFinalXform(ember, p1, samples + i, rand);
lastXformUsed = xformIndex + 1;//Store the last used transform.
@@ -567,7 +570,7 @@ public:
xformIndex = NextXformFromIndex(rand.Rand(), lastXformUsed);
if (xforms[xformIndex].Apply(&p1, &p1, rand))
- DoBadVals(xforms, xformIndex, lastXformUsed, badVals, &p1, rand);
+ DoBadVals(xforms, xformIndex, ember.m_RandPointRange, lastXformUsed, badVals, &p1, rand);
lastXformUsed = xformIndex + 1;//Store the last used transform.
}
@@ -579,7 +582,7 @@ public:
xformIndex = NextXformFromIndex(rand.Rand(), lastXformUsed);
if (xforms[xformIndex].Apply(samples + i, samples + i + 1, rand))
- DoBadVals(xforms, xformIndex, lastXformUsed, badVals, samples + i + 1, rand);
+ DoBadVals(xforms, xformIndex, ember.m_RandPointRange, lastXformUsed, badVals, samples + i + 1, rand);
lastXformUsed = xformIndex + 1;//Store the last used transform.
}
diff --git a/Source/Ember/Palette.h b/Source/Ember/Palette.h
index 2b88792..5af747a 100644
--- a/Source/Ember/Palette.h
+++ b/Source/Ember/Palette.h
@@ -415,6 +415,20 @@ public:
return v;
}
+ ///
+ /// Determine if a palette is all black.
+ ///
+ /// True if all colors are black, else false if at least one component of one color is non zero.
+ bool IsEmpty()
+ {
+ for (glm::length_t i = 0; i < Size(); i++)
+ for (glm::length_t j = 0; j < 3; j++)
+ if (m_Entries[i][j] != 0)
+ return false;
+
+ return true;
+ }
+
///
/// Convert RGB to HSV.
///
diff --git a/Source/Ember/PaletteList.cpp b/Source/Ember/PaletteList.cpp
index 3a8d85c..a637ea2 100644
--- a/Source/Ember/PaletteList.cpp
+++ b/Source/Ember/PaletteList.cpp
@@ -258,30 +258,39 @@ bool PaletteList::Add(const string& filename, bool force)
///
/// Get the palette at a random index in a random file in the map.
+/// Attempt to avoid selecting a palette which is all black.
///
/// A pointer to a random palette in a random file if successful, else nullptr.
template
Palette* PaletteList::GetRandomPalette()
{
- auto p = s_Palettes.begin();
- size_t i = 0, paletteFileIndex = QTIsaac::LockedRand() % Size();
+ size_t attempts = 0;
- //Move p forward i elements.
- while (i < paletteFileIndex && p != s_Palettes.end())
+ while (attempts < Size() * 10)
{
- ++i;
- ++p;
+ auto p = s_Palettes.begin();
+ auto paletteFileIndex = QTIsaac::LockedRand() % Size();
+ size_t i = 0;
+
+ //Move p forward i elements.
+ while (i < paletteFileIndex && p != s_Palettes.end())
+ {
+ ++i;
+ ++p;
+ }
+
+ if (i < Size())
+ {
+ size_t paletteIndex = QTIsaac::LockedRand() % p->second.size();
+
+ if (paletteIndex < p->second.size() && !p->second[paletteIndex].IsEmpty())
+ return &p->second[paletteIndex];
+ }
+
+ attempts++;
}
- if (i < Size())
- {
- size_t paletteIndex = QTIsaac::LockedRand() % p->second.size();
-
- if (paletteIndex < p->second.size())
- return &p->second[paletteIndex];
- }
-
- return nullptr;
+ return Size() ? &s_Palettes[0][0] : nullptr;
}
///
diff --git a/Source/Ember/Renderer.cpp b/Source/Ember/Renderer.cpp
index a348f78..2467b3e 100644
--- a/Source/Ember/Renderer.cpp
+++ b/Source/Ember/Renderer.cpp
@@ -99,7 +99,7 @@ template
void Renderer::ComputeQuality()
{
m_Scale = std::pow(T(2.0), Zoom());
- m_ScaledQuality = Quality() * m_Scale * m_Scale;
+ m_ScaledQuality = Quality() * SQR(m_Scale);
}
///
@@ -591,18 +591,23 @@ FilterAndAccum:
//Compute k1 and k2.
auto fullRun = eRenderStatus::RENDER_OK;//Whether density filtering was run to completion without aborting prematurely or triggering an error.
T area = FinalRasW() * FinalRasH() / (m_PixelsPerUnitX * m_PixelsPerUnitY);//Need to use temps from field if ever implemented.
- m_K1 = bucketT((Brightness() * 268) / 256);
+ m_K1 = Brightness();
- //When doing an interactive render, force output early on in the render process, before all iterations are done.
- //This presents a problem with the normal calculation of K2 since it relies on the quality value; it will scale the colors
- //to be very dark. Correct it by pretending the number of iters done is the exact quality desired and then scale according to that.
- if (forceOutput)
+ if (!m_Ember.m_K2 || forceOutput)
{
- T quality = (T(m_Stats.m_Iters) / T(FinalDimensions())) * (m_Scale * m_Scale);
- m_K2 = bucketT((Supersample() * Supersample()) / (area * quality * m_TemporalFilter->SumFilt()));
+ //When doing an interactive render, force output early on in the render process, before all iterations are done.
+ //This presents a problem with the normal calculation of K2 since it relies on the quality value; it will scale the colors
+ //to be very dark. Correct it by pretending the number of iters done is the exact quality desired and then scale according to that.
+ if (forceOutput)
+ {
+ T quality = (T(m_Stats.m_Iters) / T(FinalDimensions())) * (m_Scale * m_Scale);
+ m_K2 = bucketT((Supersample() * Supersample()) / (area * quality * m_TemporalFilter->SumFilt()));
+ }
+ else
+ m_K2 = bucketT((Supersample() * Supersample()) / (area * m_ScaledQuality * m_TemporalFilter->SumFilt()));
}
else
- m_K2 = bucketT((Supersample() * Supersample()) / (area * m_ScaledQuality * m_TemporalFilter->SumFilt()));
+ m_K2 = bucketT(m_Ember.m_K2);
if (!ResetBuckets(false, true))//Only the histogram was reset above, now reset the density filtering buffer.
{
@@ -1282,10 +1287,10 @@ EmberStats Renderer::Iterate(size_t iterCount, size_t temporalSample
//For example, if 51,000 are requested, and the sbs is 10,000, it should run 5 sub batches of 10,000 iters, and one final sub batch of 1,000 iters.
params.m_Count = std::min(params.m_Count, totalItersPerThread - m_SubBatch[threadIndex]);
//Use first as random point, the rest are iterated points.
- //Note that this gets reset with a new random point for each subBatchSize iterations.
+ //Note that this gets reset with a new random point for each SubBatchSize iterations.
//This helps correct if iteration happens to be on a bad trajectory.
- m_Samples[threadIndex][0].m_X = m_Rand[threadIndex].template Frand11();
- m_Samples[threadIndex][0].m_Y = m_Rand[threadIndex].template Frand11();
+ m_Samples[threadIndex][0].m_X = m_Rand[threadIndex].template Frand(-m_ThreadEmbers[threadIndex].m_RandPointRange, m_ThreadEmbers[threadIndex].m_RandPointRange);
+ m_Samples[threadIndex][0].m_Y = m_Rand[threadIndex].template Frand(-m_ThreadEmbers[threadIndex].m_RandPointRange, m_ThreadEmbers[threadIndex].m_RandPointRange);
m_Samples[threadIndex][0].m_Z = 0;//m_Ember.m_CamZPos;//Apo set this to 0, then made the user use special variations to kick it. It seems easier to just set it to zpos.
m_Samples[threadIndex][0].m_ColorX = m_Rand[threadIndex].template Frand01();
@@ -1727,9 +1732,21 @@ void Renderer::ComputeCurves()
{
//Timing t;
auto st = m_Csa.size();
+ vector> vals;
+ vals.reserve(m_Ember.m_Curves.m_Points[0].size());
- for (size_t i = 0; i < st; i++)
- m_Csa[i] = m_Ember.m_Curves.BezierFunc(i * ONE_OVER_CURVES_LENGTH_M1);
+ for (glm::length_t i = 0; i < m_Ember.m_Curves.m_Points.size(); i++)//Overall, r, g, b.
+ {
+ for (auto& p : m_Ember.m_Curves.m_Points[i])
+ vals.push_back(p);
+
+ Spline spline(vals);//Will internally sort.
+
+ for (glm::length_t j = 0; j < st; j++)
+ m_Csa[j][i] = spline.Interpolate(j * ONE_OVER_CURVES_LENGTH_M1);
+
+ vals.clear();
+ }
//t.Toc("ComputeCurves");
}
diff --git a/Source/Ember/Renderer.h b/Source/Ember/Renderer.h
index b8e0b60..c654ac1 100644
--- a/Source/Ember/Renderer.h
+++ b/Source/Ember/Renderer.h
@@ -7,6 +7,7 @@
#include "Interpolate.h"
#include "CarToRas.h"
#include "EmberToXml.h"
+#include "Spline.h"
///
/// Renderer.
@@ -157,6 +158,7 @@ private:
void VectorizedLogScale(size_t row, size_t rowEnd);
protected:
+//public:
T m_Scale;
T m_PixelsPerUnitX;
T m_PixelsPerUnitY;
diff --git a/Source/Ember/RendererBase.h b/Source/Ember/RendererBase.h
index 4d616e1..06ae94f 100644
--- a/Source/Ember/RendererBase.h
+++ b/Source/Ember/RendererBase.h
@@ -198,7 +198,6 @@ public:
bool InFinalAccum();
void* m_ProgressParameter = nullptr;
-
protected:
bool m_EarlyClip = false;
bool m_YAxisUp = false;
diff --git a/Source/Ember/Spline.cpp b/Source/Ember/Spline.cpp
new file mode 100644
index 0000000..2806bf3
--- /dev/null
+++ b/Source/Ember/Spline.cpp
@@ -0,0 +1,127 @@
+// This is a combination of this:
+// https://stackoverflow.com/questions/25379422/b-spline-curves/25379851#25379851
+// and this, but modified to operate on a spline with any number of points intead of just >= 4:
+//
+// Spline.cc
+// CubicSplineLib/
+//
+// Source file for the "CubicSpline" class. This object facilitates natural
+// cubic spline interpolation. Once instantiated the
+// constructor builds the spline polynomials on the intervals of the (x, y)
+// data provided and retains them for later invocation. Parallelized using
+// OpenMP.
+//
+// Copyright (C) Geoffrey Lentner 2015. All rights reserved.
+// See LICENCE file. (GPL v2.0)
+//
+// contact: Geoffrey Lentner, B.S.
+// Graduate Student / Researcher
+// 102 Natural Science Building
+// Department of Physics & Astronomy
+// University of Louisville
+// Louisville, KY 40292 USA
+//
+// email: geoffrey.lentner@louisville.edu
+//
+// updated: 2015-1-19 13:10:30 EST
+//
+#include "EmberPch.h"
+#include "Spline.h"
+
+namespace EmberNs
+{
+///
+/// Constructor that takes a vector of x,y points, optionally sorts them
+/// and builds the spline values.
+///
+/// The vector of x,y points
+/// True to skip sorting, false to sort.
+template
+Spline::Spline(const std::vector& _vals, bool sorted)
+{
+ n = int(_vals.size() - 1);
+ vals = _vals;
+
+ // if not suppressed, ensure 'x' elements are in ascending order
+ if (!sorted)
+ std::sort(vals.begin(), vals.end(), [&](const v2T & lhs, const v2T & rhs) { return lhs.x < rhs.x; });
+ BuildSplines();
+}
+
+///
+/// Compute spline values for the passed in points.
+/// This only needs to be done once.
+///
+template
+void Spline::BuildSplines()
+{
+ a.resize(n + 1);
+ b.resize(n + 1);
+ c.resize(n + 1);
+ d.resize(n + 1);
+ std::vector w(n);
+ std::vector h(n);
+ std::vector ftt(n + 1);
+
+ for (int i = 0; i < n; i++)
+ {
+ w[i] = (vals[i + 1].x - vals[i].x);
+ h[i] = (vals[i + 1].y - vals[i].y) / w[i];
+ }
+
+ ftt[0] = 0;
+
+ for (int i = 0; i < n - 1; i++)
+ ftt[i + 1] = 3 * (h[i + 1] - h[i]) / (w[i + 1] + w[i]);
+
+ ftt[n] = 0;
+
+ for (int i = 0; i < n; i++)
+ {
+ a[i] = (ftt[i + 1] - ftt[i]) / (6 * w[i]);
+ b[i] = ftt[i] / 2;
+ c[i] = h[i] - w[i] * (ftt[i + 1] + 2 * ftt[i]) / 6;
+ d[i] = vals[i].y;
+ }
+}
+
+///
+/// Wrapper to generate y points on the spline for a vector of passed in points.
+///
+/// The vector of x points to generate spline points for
+/// The vector of computed spline y points.
+template
+std::vector Spline::Interpolate(const std::vector& newX)
+{
+ std::vector output; output.resize(newX.size());
+
+ for (int i = 0; i < newX.size(); i++)
+ output[i] = Interpolate(newX[i]);
+
+ return output;
+}
+
+///
+/// Compute a y point on the spline for a the passed in value of x.
+///
+/// The x points to compute the spline point for
+/// The computed spline y points.
+template
+T Spline::Interpolate(T newX)
+{
+ ClampRef(newX, vals[0].x, vals[n].x);
+ int j = 0;
+
+ while (j < n && newX > vals[j + 1].x)
+ j++;
+
+ auto xmxj = newX - vals[j].x;
+ auto output = a[j] * (xmxj * xmxj * xmxj) +
+ b[j] * (xmxj * xmxj) +
+ c[j] * xmxj +
+ d[j];
+ return output;
+}
+
+template EMBER_API class Spline;
+}
diff --git a/Source/Ember/Spline.h b/Source/Ember/Spline.h
new file mode 100644
index 0000000..b208451
--- /dev/null
+++ b/Source/Ember/Spline.h
@@ -0,0 +1,55 @@
+// This is a combination of this:
+// https://stackoverflow.com/questions/25379422/b-spline-curves/25379851#25379851
+// and this, but modified to operate on a spline with any number of points intead of just >= 4:
+//
+// Spline.h
+// CubicSplineLib/
+//
+// Header file for the "CubicSpline" class. This object facilitates natural
+// cubic spline interpolation. Once instantiated the
+// constructor builds the spline polynomials on the intervals of the (x, y)
+// data provided and retains them for later invocation. Parallelized using
+// OpenMP.
+//
+// Copyright (C) Geoffrey Lentner 2015. All rights reserved.
+// See LICENCE file. (GPL v2.0)
+//
+// contact: Geoffrey Lentner, B.S.
+// Graduate Student / Researcher
+// 102 Natural Science Building
+// Department of Physics & Astronomy
+// University of Louisville
+// Louisville, KY 40292 USA
+//
+// email: geoffrey.lentner@louisville.edu
+//
+// updated: 2015-1-19 13:10:30 EST
+//
+#pragma once
+#include "Utils.h"
+
+namespace EmberNs
+{
+///
+/// Class taking passed in x,y points, sorting them, and providing a function
+/// to compute and return an interpolated spline curve for any value between the
+/// first and last x.
+/// Template argument expected to be float.
+///
+template
+class EMBER_API Spline
+{
+public:
+ Spline(const std::vector& _vals, bool sorted = false);
+ std::vector Interpolate(const std::vector& newX);
+ T Interpolate(T newX);
+
+private:
+ void BuildSplines();
+ std::vector vals;
+ std::vector a, b, c, d;
+ std::vector c_prime, d_prime;
+ std::vector k;
+ int n;
+};
+}
diff --git a/Source/Ember/Utils.h b/Source/Ember/Utils.h
index 0896a0b..671ea06 100644
--- a/Source/Ember/Utils.h
+++ b/Source/Ember/Utils.h
@@ -829,6 +829,34 @@ static inline T NormalizeDeg180(T angle)
return a;
}
+///
+/// Put an angular measurement in degrees into the range of 0 - 360.
+///
+/// The angle to normalize
+/// The normalized angle in a range of 0 - 360
+template
+static inline T NormalizeDeg360(T angle)
+{
+ if (angle > 360 || angle < -360)
+ angle = fmod(angle, T(360));
+
+ if (angle < 0)
+ angle += 360;
+
+ return angle;
+}
+
+///
+/// Convert an angle where 0 is up to a trigonometry style angle where 0 is to the right.
+///
+/// The angle to convert
+/// The trig equivalent of the angle passed in
+template
+static inline T ToTrigAngle(T angle)
+{
+ return NormalizeDeg360(90 - angle);
+}
+
///
/// Determine whether the passed in string ends with the passed in suffix, case sensitive.
///
@@ -841,6 +869,18 @@ static bool EndsWith(const std::string& str, const std::string& suffix)
str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}
+///
+/// Determine whether the passed in string starts with the passed in prefix, case sensitive.
+///
+/// The string to test
+/// The string to test for
+/// True if str starts with suffix, else false.
+static bool StartsWith(const std::string& str, const std::string& prefix)
+{
+ return str.size() >= prefix.size() &&
+ str.compare(0, prefix.size(), prefix) == 0;
+}
+
///
/// Return a lower case copy of a string.
///
diff --git a/Source/Ember/VarFuncs.h b/Source/Ember/VarFuncs.h
index c2449f3..e134920 100644
--- a/Source/Ember/VarFuncs.h
+++ b/Source/Ember/VarFuncs.h
@@ -50,6 +50,16 @@ public:
return modf(v, &dummy);
}
+ ///
+ /// Return the fractional part of a real number.
+ ///
+ /// The real number whose fractional part will be returned
+ /// The fractional part of the value passed in
+ static inline T Fract(T x)
+ {
+ return x - T(Floor(x));
+ }
+
///
/// Unsure.
///
@@ -191,7 +201,7 @@ public:
///
/// The value to hash
/// The hashed value
- static T Hash(int a)
+ static inline T Hash(int a)
{
a = (a ^ 61) ^ (a >> 16);
a = a + (a << 3);
@@ -201,6 +211,128 @@ public:
return (T)a / std::numeric_limits::max();
}
+ ///
+ /// Hash function gotten from Chaotica, which takes an x,y pair and hashes it.
+ /// Written by Thomas Ludwig and Tatyana Zabanova.
+ ///
+ /// The x value to hash
+ /// The y value to hash
+ /// The seed to hash with
+ /// The hashed value
+ static inline T HashShadertoy(T x, T y, T seed)
+ {
+ return Fract(std::sin(x * T(12.9898) + y * T(78.233) + seed) * T(43758.5453));
+ }
+
+ ///
+ /// For the vibration2 variation.
+ ///
+ /// T
+ static inline T Modulate(T amp, T freq, T x)
+ {
+ return amp * std::cos(x * freq * M_2PI);
+ }
+
+ ///
+ /// Divide real by complex.
+ ///
+ /// The real number
+ /// The complex number
+ /// x / a
+ static v2T RealDivComplex(T x, v2T a)
+ {
+ T s = x / Zeps(a.x * a.x + a.y * a.y);
+ return v2T(a.x * s, -a.y * s);
+ }
+
+ ///
+ /// Divide complex by complex.
+ ///
+ /// The first complex number
+ /// The secondcomplex number
+ /// a / b
+ static v2T ComplexDivComplex(v2T a, v2T b)
+ {
+ T s = T(1.0) / Zeps(b.x * b.x + b.y * b.y);
+ return v2T(a.x * b.x + a.y * b.y, a.y * b.x - a.x * b.y) * s;
+ }
+
+ ///
+ /// Multiple complex by real.
+ ///
+ /// The complex number
+ /// The real number
+ /// a * x
+ static v2T ComplexMultReal(v2T a, T x)
+ {
+ return v2T(a.x * x, a.y * x);
+ }
+
+ ///
+ /// Multiply complex by complex.
+ ///
+ /// The first complex number
+ /// The second complex number
+ /// a * b
+ static v2T ComplexMultComplex(v2T a, v2T b)
+ {
+ return v2T(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
+ }
+
+ ///
+ /// Add complex to complex.
+ ///
+ /// The first complex number
+ /// The second complex number
+ /// a + b
+ static v2T ComplexPlusComplex(v2T a, v2T b)
+ {
+ return v2T(a.x + b.x, a.y + b.y);
+ }
+
+ ///
+ /// Add complex to real.
+ ///
+ /// The complex number
+ /// The real number
+ /// a + x
+ static v2T ComplexPlusReal(v2T a, T x)
+ {
+ return v2T(a.x + x, a.y);
+ }
+
+ ///
+ /// Subtract real from complex.
+ ///
+ /// The complex number
+ /// The real number
+ /// a - x
+ static v2T ComplexMinusReal(v2T a, T x)
+ {
+ return v2T(a.x - x, a.y);
+ }
+
+ ///
+ /// Compute the square root of a complex number.
+ ///
+ /// The complex number
+ /// sqrt(a)
+ static v2T ComplexSqrt(v2T a)
+ {
+ T mag = Hypot(a.x, a.y);
+ return ComplexMultReal(v2T(std::sqrt(mag + a.x), Sign(a.y) * std::sqrt(mag - a.x)), T(0.5) * std::sqrt(T(2.0)));
+ }
+
+ ///
+ /// Compute the natural logarithm of a complex number.
+ ///
+ /// The complex number
+ /// log(a)
+ static v2T ComplexLog(v2T a)
+ {
+ return v2T(T(0.5) * std::log(a.x * a.x + a.y * a.y), std::atan2(a.y, a.x));
+ }
+
///
/// Retrieve information about a piece of shared data by looking
/// up its name.
@@ -567,9 +699,25 @@ private:
m_P = InitInts();
m_Grad = InitGrad();
m_Offsets = InitOffsets();
+ m_P1 = InitP1();
+ m_Q1 = InitQ1();
+ m_P2 = InitP2();
+ m_Q2 = InitQ2();
+ m_PC = InitPC();
+ m_QC = InitQC();
+ m_PS = InitPS();
+ m_QS = InitQS();
m_GlobalMap["NOISE_INDEX"] = make_pair(m_PFloats.data(), m_PFloats.size());
m_GlobalMap["NOISE_POINTS"] = make_pair(static_cast(&(m_Grad[0].x)), SizeOf(m_Grad) / sizeof(T));
m_GlobalMap["OFFSETS"] = make_pair(static_cast(&(m_Offsets[0].x)), SizeOf(m_Offsets) / sizeof(T));
+ m_GlobalMap["P1"] = make_pair(m_P1.data(), m_P1.size());
+ m_GlobalMap["Q1"] = make_pair(m_Q1.data(), m_Q1.size());
+ m_GlobalMap["P2"] = make_pair(m_P2.data(), m_P2.size());
+ m_GlobalMap["Q2"] = make_pair(m_Q2.data(), m_Q2.size());
+ m_GlobalMap["PC"] = make_pair(m_PC.data(), m_PC.size());
+ m_GlobalMap["QC"] = make_pair(m_QC.data(), m_QC.size());
+ m_GlobalMap["PS"] = make_pair(m_PS.data(), m_PS.size());
+ m_GlobalMap["QS"] = make_pair(m_QS.data(), m_QS.size());
}
///
@@ -993,8 +1141,179 @@ private:
return g;
}
+ ///
+ /// Initializes the P1 vector used in J1().
+ /// Note J1() comes with std in C++, but needed to be manually implemented in OpenCL.
+ ///
+ /// A copy of the locally declared vector
+ std::vector InitP1()
+ {
+ std::vector v =
+ {
+ T(-1.4258509801366645672e+11),
+ T(6.6781041261492395835e+09 ),
+ T(-1.1548696764841276794e+08),
+ T(9.8062904098958257677e+05 ),
+ T(-4.4615792982775076130e+03),
+ T(1.0650724020080236441e+01 ),
+ T(-1.0767857011487300348e-02)
+ };
+ return v;
+ }
+
+ ///
+ /// Initializes the Q1 vector used in J1().
+ /// Note J1() comes with std in C++, but needed to be manually implemented in OpenCL.
+ ///
+ /// A copy of the locally declared vector
+ std::vector InitQ1()
+ {
+ std::vector v =
+ {
+ T(4.1868604460820175290e+12),
+ T(4.2091902282580133541e+10),
+ T(2.0228375140097033958e+08),
+ T(5.9117614494174794095e+05),
+ T(1.0742272239517380498e+03),
+ T(1.0),
+ T(0.0)
+ };
+ return v;
+ }
+
+ ///
+ /// Initializes the P2 vector used in J1().
+ /// Note J1() comes with std in C++, but needed to be manually implemented in OpenCL.
+ ///
+ /// A copy of the locally declared vector
+ std::vector InitP2()
+ {
+ std::vector v =
+ {
+ T(-1.7527881995806511112e+16),
+ T(1.6608531731299018674e+15 ),
+ T(-3.6658018905416665164e+13),
+ T(3.5580665670910619166e+11 ),
+ T(-1.8113931269860667829e+09),
+ T(5.0793266148011179143e+06 ),
+ T(-7.5023342220781607561e+03),
+ T(4.6179191852758252278e+00)
+ };
+ return v;
+ }
+
+ ///
+ /// Initializes the Q2 vector used in J1().
+ /// Note J1() comes with std in C++, but needed to be manually implemented in OpenCL.
+ ///
+ /// A copy of the locally declared vector
+ std::vector InitQ2()
+ {
+ std::vector v =
+ {
+ T(1.7253905888447681194e+18),
+ T(1.7128800897135812012e+16),
+ T(8.4899346165481429307e+13),
+ T(2.7622777286244082666e+11),
+ T(6.4872502899596389593e+08),
+ T(1.1267125065029138050e+06),
+ T(1.3886978985861357615e+03),
+ T(1.0)
+ };
+ return v;
+ }
+
+ ///
+ /// Initializes the PC vector used in J1().
+ /// Note J1() comes with std in C++, but needed to be manually implemented in OpenCL.
+ ///
+ /// A copy of the locally declared vector
+ std::vector InitPC()
+ {
+ std::vector v =
+ {
+ T(-4.4357578167941278571e+06),
+ T(-9.9422465050776411957e+06),
+ T(-6.6033732483649391093e+06),
+ T(-1.5235293511811373833e+06),
+ T(-1.0982405543459346727e+05),
+ T(-1.6116166443246101165e+03),
+ T(0.0)
+ };
+ return v;
+ }
+
+ ///
+ /// Initializes the QC vector used in J1().
+ /// Note J1() comes with std in C++, but needed to be manually implemented in OpenCL.
+ ///
+ /// A copy of the locally declared vector
+ std::vector InitQC()
+ {
+ std::vector v =
+ {
+ T(-4.4357578167941278568e+06),
+ T(-9.9341243899345856590e+06),
+ T(-6.5853394797230870728e+06),
+ T(-1.5118095066341608816e+06),
+ T(-1.0726385991103820119e+05),
+ T(-1.4550094401904961825e+03),
+ T(1.0)
+ };
+ return v;
+ }
+
+ ///
+ /// Initializes the PS vector used in J1().
+ /// Note J1() comes with std in C++, but needed to be manually implemented in OpenCL.
+ ///
+ /// A copy of the locally declared vector
+ std::vector InitPS()
+ {
+ std::vector v =
+ {
+ T(3.3220913409857223519e+04),
+ T(8.5145160675335701966e+04),
+ T(6.6178836581270835179e+04),
+ T(1.8494262873223866797e+04),
+ T(1.7063754290207680021e+03),
+ T(3.5265133846636032186e+01),
+ T(0.0)
+ };
+ return v;
+ }
+
+ ///
+ /// Initializes the QS vector used in J1().
+ /// Note J1() comes with std in C++, but needed to be manually implemented in OpenCL.
+ ///
+ /// A copy of the locally declared vector
+ std::vector InitQS()
+ {
+ std::vector v =
+ {
+ T(7.0871281941028743574e+05),
+ T(1.8194580422439972989e+06),
+ T(1.4194606696037208929e+06),
+ T(4.0029443582266975117e+05),
+ T(3.7890229745772202641e+04),
+ T(8.6383677696049909675e+02),
+ T(1.0)
+
+ };
+ return v;
+ }
+
std::vector m_P;
std::vector m_PFloats;
+ std::vector m_P1;
+ std::vector m_Q1;
+ std::vector m_P2;
+ std::vector m_Q2;
+ std::vector m_PC;
+ std::vector m_QC;
+ std::vector m_PS;
+ std::vector m_QS;
std::vector m_Offsets;
std::vector m_Grad;
std::unordered_map> m_GlobalMap;
diff --git a/Source/Ember/Variation.h b/Source/Ember/Variation.h
index e7d09e2..cdaf277 100644
--- a/Source/Ember/Variation.h
+++ b/Source/Ember/Variation.h
@@ -47,6 +47,11 @@ enum class eVariationAssignType : et
enum class eVariationId : et
{
VAR_ARCH,
+ VAR_ARCSECH,
+ VAR_ARCSECH2,
+ VAR_ARCSINH,
+ VAR_ARCTANH,
+ VAR_ASTERIA,
//VAR_ARCSINH,
//VAR_ARCTANH,
VAR_AUGER ,
@@ -62,6 +67,7 @@ enum class eVariationId : et
VAR_BLOB ,
VAR_BLOB2 ,
VAR_BLOB3D ,
+ VAR_BLOCK ,
VAR_BLOCKY ,
VAR_BLUR ,
VAR_BLUR_CIRCLE ,
@@ -81,11 +87,13 @@ enum class eVariationId : et
VAR_BUBBLET3D ,
VAR_BUTTERFLY ,
VAR_BWRAPS ,
+ VAR_BWRAPS_RAND ,
VAR_CARDIOID ,
VAR_CELL ,
VAR_CHECKS ,
VAR_CIRCLEBLUR ,
VAR_CIRCLECROP,
+ VAR_CIRCLECROP2,
VAR_CIRCLELINEAR,
VAR_CIRCLERAND,
VAR_CIRCLESPLIT,
@@ -104,12 +112,14 @@ enum class eVariationId : et
VAR_COSQ,
VAR_COT ,
VAR_COTH ,
+ VAR_COTH_SPIRAL,
VAR_COTHQ ,
VAR_COTQ ,
VAR_CPOW ,
VAR_CPOW2 ,
VAR_CPOW3 ,
VAR_CRACKLE ,
+ VAR_CRACKLE2 ,
VAR_CRESCENTS ,
VAR_CROB ,
VAR_CROP ,
@@ -130,10 +140,21 @@ enum class eVariationId : et
VAR_CYLINDER2,
VAR_DELTA_A ,
VAR_DEPTH,
+ VAR_DEPTH_BLUR,
+ VAR_DEPTH_BLUR2,
+ VAR_DEPTH_GAUSSIAN,
+ VAR_DEPTH_GAUSSIAN2,
+ VAR_DEPTH_NGON,
+ VAR_DEPTH_NGON2,
+ VAR_DEPTH_SINE,
+ VAR_DEPTH_SINE2,
VAR_DIAMOND ,
VAR_DISC ,
VAR_DISC2 ,
VAR_DISC3D ,
+ VAR_DRAGONFIRE,
+ VAR_DUST ,
+ VAR_D_SPHERICAL ,
VAR_ECLIPSE ,
VAR_ECOLLIDE ,
VAR_EDISC ,
@@ -151,7 +172,9 @@ enum class eVariationId : et
VAR_ESTIQ,
VAR_ESWIRL ,
VAR_EX ,
+ VAR_EXCINIS ,
VAR_EXP ,
+ VAR_EXP2 ,
VAR_EXPO ,
VAR_EXPONENTIAL ,
VAR_EXTRUDE ,
@@ -168,20 +191,27 @@ enum class eVariationId : et
VAR_FISHEYE ,
VAR_FLATTEN ,
VAR_FLIP_CIRCLE ,
+ VAR_FLIP_X ,
VAR_FLIP_Y ,
VAR_FLOWER ,
+ VAR_FLOWER_DB ,
VAR_FLUX ,
VAR_FOCI ,
VAR_FOCI3D ,
+ VAR_FOCI_P ,
VAR_FOURTH,
VAR_FUNNEL ,
VAR_GAMMA ,
+ VAR_GAUSSIAN,
VAR_GAUSSIAN_BLUR,
VAR_GDOFFS,
VAR_GLYNNIA ,
+ VAR_GLYNNIA2 ,
VAR_GLYNNSIM1 ,
VAR_GLYNNSIM2 ,
VAR_GLYNNSIM3 ,
+ VAR_GLYNNSIM4 ,
+ VAR_GLYNNSIM5 ,
VAR_GRIDOUT ,
VAR_HANDKERCHIEF,
VAR_HEART ,
@@ -189,15 +219,19 @@ enum class eVariationId : et
VAR_HELICOID,
VAR_HELIX,
VAR_HEMISPHERE ,
+ VAR_HENON ,
VAR_HEXAPLAY3D ,
VAR_HEXCROP ,
VAR_HEXES ,
VAR_HEXNIX3D ,
+ VAR_HEX_RAND,
+ VAR_HEX_TRUCHET,
VAR_HO ,
VAR_HOLE ,
VAR_HORSESHOE ,
VAR_HYPERBOLIC ,
VAR_HYPERCROP ,
+ VAR_HYPERSHIFT ,
VAR_HYPERSHIFT2 ,
VAR_HYPERTILE ,
VAR_HYPERTILE1 ,
@@ -222,8 +256,10 @@ enum class eVariationId : et
VAR_JULIAQ ,
VAR_JULIASCOPE ,
VAR_KALEIDOSCOPE,
- VAR_LAZY_TRAVIS ,
+ VAR_LAZYJESS ,
VAR_LAZYSUSAN ,
+ VAR_LAZY_TRAVIS ,
+ VAR_LENS ,
VAR_LINE ,
VAR_LINEAR ,
VAR_LINEAR_T ,
@@ -239,6 +275,7 @@ enum class eVariationId : et
VAR_LOONIE2 ,
VAR_LOONIE3 ,
VAR_LOONIE3D ,
+ VAR_LOZI ,
VAR_MASK ,
VAR_MCARPET ,
VAR_MIRROR_X,
@@ -249,6 +286,8 @@ enum class eVariationId : et
VAR_MOBIUS_STRIP,
VAR_MOBIUSN ,
VAR_MODULUS ,
+ VAR_MODULUSX ,
+ VAR_MODULUSY ,
VAR_MURL ,
VAR_MURL2 ,
VAR_NBLUR ,
@@ -259,6 +298,7 @@ enum class eVariationId : et
VAR_OCTAPOL ,
VAR_ORTHO ,
VAR_OSCILLOSCOPE,
+ VAR_OSCILLOSCOPE2,
VAR_OVOID ,
VAR_OVOID3D ,
VAR_PANORAMA1 ,
@@ -273,6 +313,7 @@ enum class eVariationId : et
VAR_PIXEL_FLOW ,
VAR_POINCARE ,
VAR_POINCARE3D ,
+ VAR_POINT_SYMMETRY,
VAR_POLAR ,
VAR_POLAR2 ,
VAR_POLYNOMIAL ,
@@ -282,10 +323,13 @@ enum class eVariationId : et
VAR_POW_BLOCK ,
VAR_POWER ,
VAR_PRESSURE_WAVE,
+ VAR_PROJECTIVE ,
VAR_PROSE3D ,
VAR_PSPHERE ,
+ VAR_PULSE ,
VAR_Q_ODE,
VAR_RADIAL_BLUR ,
+ //VAR_RADIAL_GAUSSIAN,
VAR_RAND_CUBES ,
VAR_RATIONAL3 ,
VAR_RAYS ,
@@ -298,12 +342,14 @@ enum class eVariationId : et
VAR_RINGS2 ,
VAR_RIPPLE ,
VAR_RIPPLED ,
+ VAR_ROTATE,
VAR_ROTATE_X,
VAR_ROTATE_Y,
VAR_ROTATE_Z,
VAR_ROUNDSPHER ,
VAR_ROUNDSPHER3D,
VAR_SCRY ,
+ VAR_SCRY2 ,
VAR_SCRY3D ,
VAR_SEC ,
VAR_SECANT2 ,
@@ -311,6 +357,7 @@ enum class eVariationId : et
VAR_SECHQ,
VAR_SECQ,
VAR_SEPARATION ,
+ VAR_SHIFT ,
VAR_SHRED_RAD ,
VAR_SHRED_LIN ,
VAR_SIGMOID ,
@@ -323,7 +370,9 @@ enum class eVariationId : et
VAR_SINUS_GRID ,
VAR_SINUSOIDAL ,
VAR_SINUSOIDAL3D,
+ VAR_SMARTSHAPE,
//VAR_SMARTCROP ,
+ VAR_SPHER ,
VAR_SPHEREBLUR ,
VAR_SPHERICAL ,
VAR_SPHERICAL3D ,
@@ -338,34 +387,48 @@ enum class eVariationId : et
VAR_SPLITS ,
VAR_SPLITS3D ,
VAR_SQUARE ,
+ VAR_SQUARES ,
VAR_SQUARE3D ,
VAR_SQUARIZE ,
VAR_SQUIRREL ,
VAR_SQUISH,
VAR_SSCHECKS ,
VAR_STARBLUR ,
+ VAR_STARBLUR2 ,
VAR_STRIPES ,
VAR_STWIN ,
VAR_SUPER_SHAPE ,
VAR_SUPER_SHAPE3D,
VAR_SVF ,
VAR_SWIRL ,
+ VAR_SWIRL3 ,
+ VAR_SWIRL3R ,
VAR_SYNTH ,
VAR_TAN ,
VAR_TANCOS,
VAR_TANGENT ,
VAR_TANH ,
VAR_TANHQ ,
+ VAR_TANH_SPIRAL ,
VAR_TANQ ,
VAR_TARGET ,
+ VAR_TARGET0 ,
+ VAR_TARGET2 ,
VAR_TAURUS ,
+ VAR_TILE_HLP,
VAR_TILE_LOG,
VAR_TRADE ,
VAR_TRUCHET,
VAR_TRUCHET_FILL,
+ VAR_TRUCHET_GLYPH,
+ VAR_TRUCHET_INV,
+ VAR_TRUCHET_KNOT,
VAR_TWINTRIAN ,
VAR_TWO_FACE ,
+ VAR_UNICORNGALOSHEN,
VAR_UNPOLAR ,
+ VAR_VIBRATION,
+ VAR_VIBRATION2,
VAR_VORON,
VAR_W ,
VAR_WAFFLE,
@@ -392,6 +455,11 @@ enum class eVariationId : et
VAR_ZTRANSLATE,
VAR_PRE_ARCH,
+ VAR_PRE_ARCSECH,
+ VAR_PRE_ARCSECH2,
+ VAR_PRE_ARCSINH,
+ VAR_PRE_ARCTANH,
+ VAR_PRE_ASTERIA,
//VAR_PRE_ARCSINH,
//VAR_PRE_ARCTANH,
VAR_PRE_AUGER,
@@ -407,6 +475,7 @@ enum class eVariationId : et
VAR_PRE_BLOB,
VAR_PRE_BLOB2,
VAR_PRE_BLOB3D,
+ VAR_PRE_BLOCK,
VAR_PRE_BLOCKY,
VAR_PRE_BLUR,
VAR_PRE_BLUR_CIRCLE,
@@ -426,11 +495,13 @@ enum class eVariationId : et
VAR_PRE_BUBBLET3D,
VAR_PRE_BUTTERFLY,
VAR_PRE_BWRAPS,
+ VAR_PRE_BWRAPS_RAND,
VAR_PRE_CARDIOID,
VAR_PRE_CELL,
VAR_PRE_CHECKS,
VAR_PRE_CIRCLEBLUR,
VAR_PRE_CIRCLECROP,
+ VAR_PRE_CIRCLECROP2,
VAR_PRE_CIRCLELINEAR,
VAR_PRE_CIRCLERAND,
VAR_PRE_CIRCLESPLIT,
@@ -449,12 +520,14 @@ enum class eVariationId : et
VAR_PRE_COSQ,
VAR_PRE_COT,
VAR_PRE_COTH,
+ VAR_PRE_COTH_SPIRAL,
VAR_PRE_COTHQ,
VAR_PRE_COTQ,
VAR_PRE_CPOW,
VAR_PRE_CPOW2,
VAR_PRE_CPOW3,
VAR_PRE_CRACKLE,
+ VAR_PRE_CRACKLE2,
VAR_PRE_CRESCENTS,
VAR_PRE_CROB,
VAR_PRE_CROP,
@@ -475,10 +548,21 @@ enum class eVariationId : et
VAR_PRE_CYLINDER2,
VAR_PRE_DELTA_A,
VAR_PRE_DEPTH,
+ VAR_PRE_DEPTH_BLUR,
+ VAR_PRE_DEPTH_BLUR2,
+ VAR_PRE_DEPTH_GAUSSIAN,
+ VAR_PRE_DEPTH_GAUSSIAN2,
+ VAR_PRE_DEPTH_NGON,
+ VAR_PRE_DEPTH_NGON2,
+ VAR_PRE_DEPTH_SINE,
+ VAR_PRE_DEPTH_SINE2,
VAR_PRE_DIAMOND,
VAR_PRE_DISC,
VAR_PRE_DISC2,
VAR_PRE_DISC3D,
+ VAR_PRE_DRAGONFIRE,
+ VAR_PRE_DUST,
+ VAR_PRE_D_SPHERICAL,
VAR_PRE_ECLIPSE,
VAR_PRE_ECOLLIDE,
VAR_PRE_EDISC,
@@ -496,7 +580,9 @@ enum class eVariationId : et
VAR_PRE_ESTIQ,
VAR_PRE_ESWIRL,
VAR_PRE_EX,
+ VAR_PRE_EXCINIS,
VAR_PRE_EXP,
+ VAR_PRE_EXP2,
VAR_PRE_EXPO,
VAR_PRE_EXPONENTIAL,
VAR_PRE_EXTRUDE,
@@ -513,20 +599,27 @@ enum class eVariationId : et
VAR_PRE_FISHEYE,
VAR_PRE_FLATTEN,
VAR_PRE_FLIP_CIRCLE,
+ VAR_PRE_FLIP_X,
VAR_PRE_FLIP_Y,
VAR_PRE_FLOWER,
+ VAR_PRE_FLOWER_DB,
VAR_PRE_FLUX,
VAR_PRE_FOCI,
VAR_PRE_FOCI3D,
+ VAR_PRE_FOCI_P,
VAR_PRE_FOURTH,
VAR_PRE_FUNNEL,
VAR_PRE_GAMMA,
+ VAR_PRE_GAUSSIAN,
VAR_PRE_GAUSSIAN_BLUR,
VAR_PRE_GDOFFS,
VAR_PRE_GLYNNIA,
+ VAR_PRE_GLYNNIA2,
VAR_PRE_GLYNNSIM1,
VAR_PRE_GLYNNSIM2,
VAR_PRE_GLYNNSIM3,
+ VAR_PRE_GLYNNSIM4,
+ VAR_PRE_GLYNNSIM5,
VAR_PRE_GRIDOUT,
VAR_PRE_HANDKERCHIEF,
VAR_PRE_HEART,
@@ -534,15 +627,19 @@ enum class eVariationId : et
VAR_PRE_HELICOID,
VAR_PRE_HELIX,
VAR_PRE_HEMISPHERE,
+ VAR_PRE_HENON,
VAR_PRE_HEXAPLAY3D,
VAR_PRE_HEXCROP,
VAR_PRE_HEXES,
VAR_PRE_HEXNIX3D,
+ VAR_PRE_HEX_RAND,
+ VAR_PRE_HEX_TRUCHET,
VAR_PRE_HO,
VAR_PRE_HOLE,
VAR_PRE_HORSESHOE,
VAR_PRE_HYPERBOLIC,
VAR_PRE_HYPERCROP,
+ VAR_PRE_HYPERSHIFT,
VAR_PRE_HYPERSHIFT2,
VAR_PRE_HYPERTILE,
VAR_PRE_HYPERTILE1,
@@ -567,8 +664,10 @@ enum class eVariationId : et
VAR_PRE_JULIAQ,
VAR_PRE_JULIASCOPE,
VAR_PRE_KALEIDOSCOPE,
- VAR_PRE_LAZY_TRAVIS,
+ VAR_PRE_LAZYJESS,
VAR_PRE_LAZYSUSAN,
+ VAR_PRE_LAZY_TRAVIS,
+ VAR_PRE_LENS,
VAR_PRE_LINE,
VAR_PRE_LINEAR,
VAR_PRE_LINEAR_T,
@@ -584,6 +683,7 @@ enum class eVariationId : et
VAR_PRE_LOONIE2,
VAR_PRE_LOONIE3,
VAR_PRE_LOONIE3D,
+ VAR_PRE_LOZI,
VAR_PRE_MASK,
VAR_PRE_MCARPET,
VAR_PRE_MIRROR_X,
@@ -594,6 +694,8 @@ enum class eVariationId : et
VAR_PRE_MOBIUS_STRIP,
VAR_PRE_MOBIUSN,
VAR_PRE_MODULUS,
+ VAR_PRE_MODULUSX,
+ VAR_PRE_MODULUSY,
VAR_PRE_MURL,
VAR_PRE_MURL2,
VAR_PRE_NBLUR,
@@ -604,6 +706,7 @@ enum class eVariationId : et
VAR_PRE_OCTAPOL,
VAR_PRE_ORTHO,
VAR_PRE_OSCILLOSCOPE,
+ VAR_PRE_OSCILLOSCOPE2,
VAR_PRE_OVOID,
VAR_PRE_OVOID3D,
VAR_PRE_PANORAMA1,
@@ -618,6 +721,7 @@ enum class eVariationId : et
VAR_PRE_PIXEL_FLOW,
VAR_PRE_POINCARE,
VAR_PRE_POINCARE3D,
+ VAR_PRE_POINT_SYMMETRY,
VAR_PRE_POLAR,
VAR_PRE_POLAR2,
VAR_PRE_POLYNOMIAL,
@@ -627,8 +731,10 @@ enum class eVariationId : et
VAR_PRE_POW_BLOCK,
VAR_PRE_POWER,
VAR_PRE_PRESSURE_WAVE,
+ VAR_PRE_PROJECTIVE,
VAR_PRE_PROSE3D,
VAR_PRE_PSPHERE,
+ VAR_PRE_PULSE,
VAR_PRE_Q_ODE,
VAR_PRE_RADIAL_BLUR,
VAR_PRE_RAND_CUBES,
@@ -643,12 +749,14 @@ enum class eVariationId : et
VAR_PRE_RINGS2,
VAR_PRE_RIPPLE,
VAR_PRE_RIPPLED,
+ VAR_PRE_ROTATE,
VAR_PRE_ROTATE_X,
VAR_PRE_ROTATE_Y,
VAR_PRE_ROTATE_Z,
VAR_PRE_ROUNDSPHER,
VAR_PRE_ROUNDSPHER3D,
VAR_PRE_SCRY,
+ VAR_PRE_SCRY2,
VAR_PRE_SCRY3D,
VAR_PRE_SEC,
VAR_PRE_SECANT2,
@@ -656,6 +764,7 @@ enum class eVariationId : et
VAR_PRE_SECHQ,
VAR_PRE_SECQ,
VAR_PRE_SEPARATION,
+ VAR_PRE_SHIFT,
VAR_PRE_SHRED_RAD,
VAR_PRE_SHRED_LIN,
VAR_PRE_SIGMOID,
@@ -668,7 +777,9 @@ enum class eVariationId : et
VAR_PRE_SINUS_GRID,
VAR_PRE_SINUSOIDAL,
VAR_PRE_SINUSOIDAL3D,
+ VAR_PRE_SMARTSHAPE,
//VAR_PRE_SMARTCROP,
+ VAR_PRE_SPHER,
VAR_PRE_SPHEREBLUR,
VAR_PRE_SPHERICAL,
VAR_PRE_SPHERICAL3D,
@@ -683,34 +794,48 @@ enum class eVariationId : et
VAR_PRE_SPLITS,
VAR_PRE_SPLITS3D,
VAR_PRE_SQUARE,
+ VAR_PRE_SQUARES,
VAR_PRE_SQUARE3D,
VAR_PRE_SQUARIZE,
VAR_PRE_SQUIRREL,
VAR_PRE_SQUISH,
VAR_PRE_SSCHECKS,
VAR_PRE_STARBLUR,
+ VAR_PRE_STARBLUR2,
VAR_PRE_STRIPES,
VAR_PRE_STWIN,
VAR_PRE_SUPER_SHAPE,
VAR_PRE_SUPER_SHAPE3D,
VAR_PRE_SVF,
VAR_PRE_SWIRL,
+ VAR_PRE_SWIRL3,
+ VAR_PRE_SWIRL3R,
VAR_PRE_SYNTH,
VAR_PRE_TAN,
VAR_PRE_TANCOS,
VAR_PRE_TANGENT,
VAR_PRE_TANH,
VAR_PRE_TANHQ,
+ VAR_PRE_TANH_SPIRAL,
VAR_PRE_TANQ,
VAR_PRE_TARGET,
+ VAR_PRE_TARGET0,
+ VAR_PRE_TARGET2,
VAR_PRE_TAURUS,
+ VAR_PRE_TILE_HLP,
VAR_PRE_TILE_LOG,
VAR_PRE_TRADE,
VAR_PRE_TRUCHET,
VAR_PRE_TRUCHET_FILL,
+ VAR_PRE_TRUCHET_GLYPH,
+ VAR_PRE_TRUCHET_INV,
+ VAR_PRE_TRUCHET_KNOT,
VAR_PRE_TWINTRIAN,
VAR_PRE_TWO_FACE,
+ VAR_PRE_UNICORNGALOSHEN,
VAR_PRE_UNPOLAR,
+ VAR_PRE_VIBRATION,
+ VAR_PRE_VIBRATION2,
VAR_PRE_VORON,
VAR_PRE_W,
VAR_PRE_WAFFLE,
@@ -737,6 +862,11 @@ enum class eVariationId : et
VAR_PRE_ZTRANSLATE,
VAR_POST_ARCH,
+ VAR_POST_ARCSECH,
+ VAR_POST_ARCSECH2,
+ VAR_POST_ARCSINH,
+ VAR_POST_ARCTANH,
+ VAR_POST_ASTERIA,
//VAR_POST_ARCSINH,
//VAR_POST_ARCTANH,
VAR_POST_AUGER,
@@ -752,6 +882,7 @@ enum class eVariationId : et
VAR_POST_BLOB,
VAR_POST_BLOB2,
VAR_POST_BLOB3D,
+ VAR_POST_BLOCK,
VAR_POST_BLOCKY,
VAR_POST_BLUR,
VAR_POST_BLUR_CIRCLE,
@@ -771,11 +902,13 @@ enum class eVariationId : et
VAR_POST_BUBBLET3D,
VAR_POST_BUTTERFLY,
VAR_POST_BWRAPS,
+ VAR_POST_BWRAPS_RAND,
VAR_POST_CARDIOID,
VAR_POST_CELL,
VAR_POST_CHECKS,
VAR_POST_CIRCLEBLUR,
VAR_POST_CIRCLECROP,
+ VAR_POST_CIRCLECROP2,
VAR_POST_CIRCLELINEAR,
VAR_POST_CIRCLERAND,
VAR_POST_CIRCLESPLIT,
@@ -794,12 +927,14 @@ enum class eVariationId : et
VAR_POST_COSQ,
VAR_POST_COT,
VAR_POST_COTH,
+ VAR_POST_COTH_SPIRAL,
VAR_POST_COTHQ,
VAR_POST_COTQ,
VAR_POST_CPOW,
VAR_POST_CPOW2,
VAR_POST_CPOW3,
VAR_POST_CRACKLE,
+ VAR_POST_CRACKLE2,
VAR_POST_CRESCENTS,
VAR_POST_CROB,
VAR_POST_CROP,
@@ -820,10 +955,21 @@ enum class eVariationId : et
VAR_POST_CYLINDER2,
VAR_POST_DELTA_A,
VAR_POST_DEPTH,
+ VAR_POST_DEPTH_BLUR,
+ VAR_POST_DEPTH_BLUR2,
+ VAR_POST_DEPTH_GAUSSIAN,
+ VAR_POST_DEPTH_GAUSSIAN2,
+ VAR_POST_DEPTH_NGON,
+ VAR_POST_DEPTH_NGON2,
+ VAR_POST_DEPTH_SINE,
+ VAR_POST_DEPTH_SINE2,
VAR_POST_DIAMOND,
VAR_POST_DISC,
VAR_POST_DISC2,
VAR_POST_DISC3D,
+ VAR_POST_DRAGONFIRE,
+ VAR_POST_DUST,
+ VAR_POST_D_SPHERICAL,
VAR_POST_ECLIPSE,
VAR_POST_ECOLLIDE,
VAR_POST_EDISC,
@@ -841,7 +987,9 @@ enum class eVariationId : et
VAR_POST_ESTIQ,
VAR_POST_ESWIRL,
VAR_POST_EX,
+ VAR_POST_EXCINIS,
VAR_POST_EXP,
+ VAR_POST_EXP2,
VAR_POST_EXPO,
VAR_POST_EXPONENTIAL,
VAR_POST_EXTRUDE,
@@ -858,20 +1006,27 @@ enum class eVariationId : et
VAR_POST_FISHEYE,
VAR_POST_FLATTEN,
VAR_POST_FLIP_CIRCLE,
+ VAR_POST_FLIP_X,
VAR_POST_FLIP_Y,
VAR_POST_FLOWER,
+ VAR_POST_FLOWER_DB,
VAR_POST_FLUX,
VAR_POST_FOCI,
VAR_POST_FOCI3D,
+ VAR_POST_FOCI_P,
VAR_POST_FOURTH,
VAR_POST_FUNNEL,
VAR_POST_GAMMA,
+ VAR_POST_GAUSSIAN,
VAR_POST_GAUSSIAN_BLUR,
VAR_POST_GDOFFS,
VAR_POST_GLYNNIA,
+ VAR_POST_GLYNNIA2,
VAR_POST_GLYNNSIM1,
VAR_POST_GLYNNSIM2,
VAR_POST_GLYNNSIM3,
+ VAR_POST_GLYNNSIM4,
+ VAR_POST_GLYNNSIM5,
VAR_POST_GRIDOUT,
VAR_POST_HANDKERCHIEF,
VAR_POST_HEART,
@@ -879,15 +1034,19 @@ enum class eVariationId : et
VAR_POST_HELICOID,
VAR_POST_HELIX,
VAR_POST_HEMISPHERE,
+ VAR_POST_HENON,
VAR_POST_HEXAPLAY3D,
VAR_POST_HEXCROP,
VAR_POST_HEXES,
VAR_POST_HEXNIX3D,
+ VAR_POST_HEX_RAND,
+ VAR_POST_HEX_TRUCHET,
VAR_POST_HO,
VAR_POST_HOLE,
VAR_POST_HORSESHOE,
VAR_POST_HYPERBOLIC,
VAR_POST_HYPERCROP,
+ VAR_POST_HYPERSHIFT,
VAR_POST_HYPERSHIFT2,
VAR_POST_HYPERTILE,
VAR_POST_HYPERTILE1,
@@ -912,8 +1071,10 @@ enum class eVariationId : et
VAR_POST_JULIAQ,
VAR_POST_JULIASCOPE,
VAR_POST_KALEIDOSCOPE,
- VAR_POST_LAZY_TRAVIS,
+ VAR_POST_LAZYJESS,
VAR_POST_LAZYSUSAN,
+ VAR_POST_LAZY_TRAVIS,
+ VAR_POST_LENS,
VAR_POST_LINE,
VAR_POST_LINEAR,
VAR_POST_LINEAR_T,
@@ -929,6 +1090,7 @@ enum class eVariationId : et
VAR_POST_LOONIE2,
VAR_POST_LOONIE3,
VAR_POST_LOONIE3D,
+ VAR_POST_LOZI,
VAR_POST_MASK,
VAR_POST_MCARPET,
VAR_POST_MIRROR_X,
@@ -939,6 +1101,8 @@ enum class eVariationId : et
VAR_POST_MOBIUS_STRIP,
VAR_POST_MOBIUSN,
VAR_POST_MODULUS,
+ VAR_POST_MODULUSX,
+ VAR_POST_MODULUSY,
VAR_POST_MURL,
VAR_POST_MURL2,
VAR_POST_NBLUR,
@@ -949,6 +1113,7 @@ enum class eVariationId : et
VAR_POST_OCTAPOL,
VAR_POST_ORTHO,
VAR_POST_OSCILLOSCOPE,
+ VAR_POST_OSCILLOSCOPE2,
VAR_POST_OVOID,
VAR_POST_OVOID3D,
VAR_POST_PANORAMA1,
@@ -963,6 +1128,7 @@ enum class eVariationId : et
VAR_POST_PIXEL_FLOW,
VAR_POST_POINCARE,
VAR_POST_POINCARE3D,
+ VAR_POST_POINT_SYMMETRY,
VAR_POST_POLAR,
VAR_POST_POLAR2,
VAR_POST_POLYNOMIAL,
@@ -972,8 +1138,10 @@ enum class eVariationId : et
VAR_POST_POW_BLOCK,
VAR_POST_POWER,
VAR_POST_PRESSURE_WAVE,
+ VAR_POST_PROJECTIVE,
VAR_POST_PROSE3D,
VAR_POST_PSPHERE,
+ VAR_POST_PULSE,
VAR_POST_Q_ODE,
VAR_POST_RADIAL_BLUR,
VAR_POST_RAND_CUBES,
@@ -988,12 +1156,14 @@ enum class eVariationId : et
VAR_POST_RINGS2,
VAR_POST_RIPPLE,
VAR_POST_RIPPLED,
+ VAR_POST_ROTATE,
VAR_POST_ROTATE_X,
VAR_POST_ROTATE_Y,
VAR_POST_ROTATE_Z,
VAR_POST_ROUNDSPHER,
VAR_POST_ROUNDSPHER3D,
VAR_POST_SCRY,
+ VAR_POST_SCRY2,
VAR_POST_SCRY3D,
VAR_POST_SEC,
VAR_POST_SECANT2,
@@ -1001,6 +1171,7 @@ enum class eVariationId : et
VAR_POST_SECHQ,
VAR_POST_SECQ,
VAR_POST_SEPARATION,
+ VAR_POST_SHIFT,
VAR_POST_SHRED_RAD,
VAR_POST_SHRED_LIN,
VAR_POST_SIGMOID,
@@ -1013,7 +1184,9 @@ enum class eVariationId : et
VAR_POST_SINUS_GRID,
VAR_POST_SINUSOIDAL,
VAR_POST_SINUSOIDAL3D,
+ VAR_POST_SMARTSHAPE,
VAR_POST_SMARTCROP,
+ VAR_POST_SPHER,
VAR_POST_SPHEREBLUR,
VAR_POST_SPHERICAL,
VAR_POST_SPHERICAL3D,
@@ -1028,34 +1201,48 @@ enum class eVariationId : et
VAR_POST_SPLITS,
VAR_POST_SPLITS3D,
VAR_POST_SQUARE,
+ VAR_POST_SQUARES,
VAR_POST_SQUARE3D,
VAR_POST_SQUARIZE,
VAR_POST_SQUIRREL,
VAR_POST_SQUISH,
VAR_POST_SSCHECKS,
VAR_POST_STARBLUR,
+ VAR_POST_STARBLUR2,
VAR_POST_STRIPES,
VAR_POST_STWIN,
VAR_POST_SUPER_SHAPE,
VAR_POST_SUPER_SHAPE3D,
VAR_POST_SVF,
VAR_POST_SWIRL,
+ VAR_POST_SWIRL3,
+ VAR_POST_SWIRL3R,
VAR_POST_SYNTH,
VAR_POST_TAN,
VAR_POST_TANCOS,
VAR_POST_TANGENT,
VAR_POST_TANH,
VAR_POST_TANHQ,
+ VAR_POST_TANH_SPIRAL,
VAR_POST_TANQ,
VAR_POST_TARGET,
+ VAR_POST_TARGET0,
+ VAR_POST_TARGET2,
VAR_POST_TAURUS,
+ VAR_POST_TILE_HLP,
VAR_POST_TILE_LOG,
VAR_POST_TRADE,
VAR_POST_TRUCHET,
VAR_POST_TRUCHET_FILL,
+ VAR_POST_TRUCHET_GLYPH,
+ VAR_POST_TRUCHET_INV,
+ VAR_POST_TRUCHET_KNOT,
VAR_POST_TWINTRIAN,
VAR_POST_TWO_FACE,
+ VAR_POST_UNICORNGALOSHEN,
VAR_POST_UNPOLAR,
+ VAR_POST_VIBRATION,
+ VAR_POST_VIBRATION2,
VAR_POST_VORON,
VAR_POST_W,
VAR_POST_WAFFLE,
diff --git a/Source/Ember/VariationList.cpp b/Source/Ember/VariationList.cpp
index fdae759..6327510 100644
--- a/Source/Ember/VariationList.cpp
+++ b/Source/Ember/VariationList.cpp
@@ -27,6 +27,8 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(Sinusoidal)
ADDPREPOSTREGVAR(Spherical)
ADDPREPOSTREGVAR(Swirl)
+ ADDPREPOSTREGVAR(Swirl3)
+ ADDPREPOSTREGVAR(Swirl3r)
ADDPREPOSTREGVAR(Horseshoe)
ADDPREPOSTREGVAR(Polar)
ADDPREPOSTREGVAR(Handkerchief)
@@ -59,6 +61,7 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(JuliaScope)
ADDPREPOSTREGVAR(Blur)
ADDPREPOSTREGVAR(GaussianBlur)
+ ADDPREPOSTREGVAR(Gaussian)
ADDPREPOSTREGVAR(RadialBlur)
ADDPREPOSTREGVAR(Pie)
ADDPREPOSTREGVAR(Ngon)
@@ -78,6 +81,7 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(Disc2)
ADDPREPOSTREGVAR(SuperShape)
ADDPREPOSTREGVAR(Flower)
+ ADDPREPOSTREGVAR(FlowerDb)
ADDPREPOSTREGVAR(Conic)
ADDPREPOSTREGVAR(Parabola)
ADDPREPOSTREGVAR(Bent2)
@@ -95,9 +99,11 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(Loonie)
ADDPREPOSTREGVAR(Modulus)
ADDPREPOSTREGVAR(Oscilloscope)
+ ADDPREPOSTREGVAR(Oscilloscope2)
ADDPREPOSTREGVAR(Polar2)
ADDPREPOSTREGVAR(Popcorn2)
ADDPREPOSTREGVAR(Scry)
+ ADDPREPOSTREGVAR(Scry2)
ADDPREPOSTREGVAR(Separation)
ADDPREPOSTREGVAR(Split)
ADDPREPOSTREGVAR(Splits)
@@ -108,6 +114,7 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(Whorl)
ADDPREPOSTREGVAR(Waves2)
ADDPREPOSTREGVAR(Exp)
+ ADDPREPOSTREGVAR(Exp2)
ADDPREPOSTREGVAR(Log)
ADDPREPOSTREGVAR(Sin)
ADDPREPOSTREGVAR(Cos)
@@ -118,6 +125,7 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(Sinh)
ADDPREPOSTREGVAR(Cosh)
ADDPREPOSTREGVAR(Tanh)
+ ADDPREPOSTREGVAR(TanhSpiral)
ADDPREPOSTREGVAR(Sech)
ADDPREPOSTREGVAR(Csch)
ADDPREPOSTREGVAR(Coth)
@@ -126,6 +134,7 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(Hemisphere)
ADDPREPOSTREGVAR(Epispiral)
ADDPREPOSTREGVAR(Bwraps)
+ ADDPREPOSTREGVAR(BwrapsRand)
ADDPREPOSTREGVAR(BlurCircle)
ADDPREPOSTREGVAR(BlurZoom)
ADDPREPOSTREGVAR(BlurPixelize)
@@ -146,6 +155,7 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(Fibonacci)
ADDPREPOSTREGVAR(Fibonacci2)
ADDPREPOSTREGVAR(Glynnia)
+ ADDPREPOSTREGVAR(Glynnia2)
ADDPREPOSTREGVAR(GridOut)
ADDPREPOSTREGVAR(Hole)
ADDPREPOSTREGVAR(Hypertile)
@@ -191,6 +201,8 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(GlynnSim1)
ADDPREPOSTREGVAR(GlynnSim2)
ADDPREPOSTREGVAR(GlynnSim3)
+ ADDPREPOSTREGVAR(GlynnSim4)
+ ADDPREPOSTREGVAR(GlynnSim5)
ADDPREPOSTREGVAR(Starblur)
ADDPREPOSTREGVAR(Sineblur)
ADDPREPOSTREGVAR(Circleblur)
@@ -205,6 +217,7 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(Ovoid3D)
ADDPREPOSTREGVAR(Spirograph)
ADDPREPOSTREGVAR(Petal)
+ ADDPREPOSTREGVAR(Spher)
ADDPREPOSTREGVAR(RoundSpher)
ADDPREPOSTREGVAR(RoundSpher3D)
ADDPREPOSTREGVAR(SpiralWing)
@@ -217,6 +230,8 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(Lissajous)
ADDPREPOSTREGVAR(Svf)
ADDPREPOSTREGVAR(Target)
+ ADDPREPOSTREGVAR(Target0)
+ ADDPREPOSTREGVAR(Target2)
ADDPREPOSTREGVAR(Taurus)
ADDPREPOSTREGVAR(Collideoscope)
ADDPREPOSTREGVAR(BMod)
@@ -225,6 +240,7 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(BCollide)
ADDPREPOSTREGVAR(Eclipse)
ADDPREPOSTREGVAR(FlipCircle)
+ ADDPREPOSTREGVAR(FlipX)
ADDPREPOSTREGVAR(FlipY)
ADDPREPOSTREGVAR(ECollide)
ADDPREPOSTREGVAR(EJulia)
@@ -234,6 +250,7 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(ERotate)
ADDPREPOSTREGVAR(EScale)
ADDPREPOSTREGVAR(ESwirl)
+ ADDPREPOSTREGVAR(LazyJess)
ADDPREPOSTREGVAR(LazyTravis)
ADDPREPOSTREGVAR(Squish)
ADDPREPOSTREGVAR(Circus)
@@ -262,6 +279,7 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(SuperShape3D)
ADDPREPOSTREGVAR(Sphyp3D)
ADDPREPOSTREGVAR(Circlecrop)
+ ADDPREPOSTREGVAR(Circlecrop2)
ADDPREPOSTREGVAR(Julian3Dx)
ADDPREPOSTREGVAR(Fourth)
ADDPREPOSTREGVAR(Mobiq)
@@ -288,12 +306,17 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(Qode)
ADDPREPOSTREGVAR(BlurHeart)
ADDPREPOSTREGVAR(Truchet)
+ ADDPREPOSTREGVAR(TruchetFill)
+ ADDPREPOSTREGVAR(TruchetGlyph)
+ ADDPREPOSTREGVAR(TruchetInv)
+ ADDPREPOSTREGVAR(TruchetKnot)
ADDPREPOSTREGVAR(Gdoffs)
ADDPREPOSTREGVAR(Octagon)
ADDPREPOSTREGVAR(Trade)
ADDPREPOSTREGVAR(Juliac)
ADDPREPOSTREGVAR(Blade3D)
ADDPREPOSTREGVAR(Blob3D)
+ ADDPREPOSTREGVAR(Block)
ADDPREPOSTREGVAR(Blocky)
ADDPREPOSTREGVAR(Bubble2)
ADDPREPOSTREGVAR(CircleLinear)
@@ -302,6 +325,7 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(Cubic3D)
ADDPREPOSTREGVAR(CubicLattice3D)
ADDPREPOSTREGVAR(Foci3D)
+ ADDPREPOSTREGVAR(FociP)
ADDPREPOSTREGVAR(Ho)
ADDPREPOSTREGVAR(Julia3Dq)
ADDPREPOSTREGVAR(Line)
@@ -331,6 +355,7 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(BubbleT3D)
ADDPREPOSTREGVAR(Synth)
ADDPREPOSTREGVAR(Crackle)
+ ADDPREPOSTREGVAR(Crackle2)
m_Variations.push_back(new PostSmartcropVariation());//Post only
ADDPREPOSTREGVAR(Xerf)
ADDPREPOSTREGVAR(Erf)
@@ -350,7 +375,7 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(CircleSplit)
ADDPREPOSTREGVAR(Cylinder2)
ADDPREPOSTREGVAR(TileLog)
- ADDPREPOSTREGVAR(TruchetFill)
+ ADDPREPOSTREGVAR(TileHlp)
ADDPREPOSTREGVAR(Waves2Radial)
ADDPREPOSTREGVAR(Panorama1)
ADDPREPOSTREGVAR(Panorama2)
@@ -360,7 +385,44 @@ VariationList::VariationList()
ADDPREPOSTREGVAR(Cpow3)
ADDPREPOSTREGVAR(Concentric)
ADDPREPOSTREGVAR(Hypercrop)
+ ADDPREPOSTREGVAR(Hypershift)
ADDPREPOSTREGVAR(Hypershift2)
+ ADDPREPOSTREGVAR(Lens)
+ ADDPREPOSTREGVAR(Projective)
+ ADDPREPOSTREGVAR(DepthBlur)
+ ADDPREPOSTREGVAR(DepthBlur2)
+ ADDPREPOSTREGVAR(DepthGaussian)
+ ADDPREPOSTREGVAR(DepthGaussian2)
+ ADDPREPOSTREGVAR(DepthNgon)
+ ADDPREPOSTREGVAR(DepthNgon2)
+ ADDPREPOSTREGVAR(DepthSine)
+ ADDPREPOSTREGVAR(DepthSine2)
+ ADDPREPOSTREGVAR(CothSpiral)
+ ADDPREPOSTREGVAR(Dust)
+ ADDPREPOSTREGVAR(Asteria)
+ ADDPREPOSTREGVAR(Pulse)
+ ADDPREPOSTREGVAR(Excinis)
+ ADDPREPOSTREGVAR(Vibration)
+ ADDPREPOSTREGVAR(Vibration2)
+ ADDPREPOSTREGVAR(Arcsech)
+ ADDPREPOSTREGVAR(Arcsech2)
+ ADDPREPOSTREGVAR(Arcsinh)
+ ADDPREPOSTREGVAR(Arctanh)
+ ADDPREPOSTREGVAR(HexTruchet)
+ ADDPREPOSTREGVAR(HexRand)
+ ADDPREPOSTREGVAR(Smartshape)
+ ADDPREPOSTREGVAR(Squares)
+ ADDPREPOSTREGVAR(Starblur2)
+ ADDPREPOSTREGVAR(UnicornGaloshen)
+ ADDPREPOSTREGVAR(Dragonfire)
+ ADDPREPOSTREGVAR(Henon)
+ ADDPREPOSTREGVAR(Lozi)
+ ADDPREPOSTREGVAR(PointSymmetry)
+ ADDPREPOSTREGVAR(DSpherical)
+ ADDPREPOSTREGVAR(Modulusx)
+ ADDPREPOSTREGVAR(Modulusy)
+ ADDPREPOSTREGVAR(Rotate)
+ ADDPREPOSTREGVAR(Shift)
//ADDPREPOSTREGVAR(LinearXZ)
//ADDPREPOSTREGVAR(LinearYZ)
//DC are special.
diff --git a/Source/Ember/Variations01.h b/Source/Ember/Variations01.h
index eb73a98..79c2e26 100644
--- a/Source/Ember/Variations01.h
+++ b/Source/Ember/Variations01.h
@@ -168,6 +168,157 @@ public:
}
};
+///
+/// swirl3.
+/// By Zy0rg.
+///
+template
+class Swirl3Variation : public ParametricVariation
+{
+public:
+ Swirl3Variation(T weight = 1.0) : ParametricVariation("swirl3", eVariationId::VAR_SWIRL3, weight, true, true, false, false, true)
+ {
+ Init();
+ }
+
+ PARVARCOPY(Swirl3Variation)
+
+ virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
+ {
+ T rad = helper.m_PrecalcSqrtSumSquares;
+ T ang = helper.m_PrecalcAtanyx + std::log(rad) * m_Shift;
+ helper.Out.x = m_Weight * rad * std::cos(ang);
+ helper.Out.y = m_Weight * rad * std::sin(ang);
+ helper.Out.z = DefaultZ(helper);
+ }
+
+ virtual string OpenCLString() const override
+ {
+ ostringstream ss, ss2;
+ intmax_t i = 0, varIndex = IndexInXform();
+ ss2 << "_" << XformIndexInEmber() << "]";
+ string index = ss2.str();
+ string weight = WeightDefineString();
+ string shift = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ ss << "\t{\n"
+ << "\t\treal_t rad = precalcSqrtSumSquares;\n"
+ << "\t\treal_t ang = fma(log(rad), " << shift << ", precalcAtanyx);\n"
+ << "\t\tvOut.x = " << weight << " * rad * cos(ang);\n"
+ << "\t\tvOut.y = " << weight << " * rad * sin(ang);\n"
+ << "\t\tvOut.z = " << DefaultZCl()
+ << "\t}\n";
+ return ss.str();
+ }
+
+protected:
+ void Init()
+ {
+ string prefix = Prefix();
+ m_Params.clear();
+ m_Params.push_back(ParamWithName(&m_Shift, prefix + "swirl3_shift", T(0.5)));
+ }
+
+private:
+ T m_Shift;
+};
+
+///
+/// swirl3r.
+/// By Zy0rg.
+///
+template
+class Swirl3rVariation : public ParametricVariation
+{
+public:
+ Swirl3rVariation(T weight = 1.0) : ParametricVariation("swirl3r", eVariationId::VAR_SWIRL3R, weight, true, true, false, false, true)
+ {
+ Init();
+ }
+
+ PARVARCOPY(Swirl3rVariation)
+
+ virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
+ {
+ T rad = helper.m_PrecalcSqrtSumSquares;
+ T ang = helper.m_PrecalcAtanyx;
+ T ang2;
+
+ if (rad < m_Minr)
+ ang2 = ang + m_Mina;
+ else if (rad > m_Maxr)
+ ang2 = ang + m_Maxa;
+ else
+ ang2 = ang + std::log(rad) * m_Shift;
+
+ helper.Out.x = m_Weight * rad * std::cos(ang2);
+ helper.Out.y = m_Weight * rad * std::sin(ang2);
+ helper.Out.z = DefaultZ(helper);
+ }
+
+ virtual string OpenCLString() const override
+ {
+ ostringstream ss, ss2;
+ intmax_t i = 0, varIndex = IndexInXform();
+ ss2 << "_" << XformIndexInEmber() << "]";
+ string index = ss2.str();
+ string weight = WeightDefineString();
+ string shift = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string mmin = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string mmax = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string minr = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string maxr = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string mina = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string maxa = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ ss << "\t{\n"
+ << "\t\treal_t rad = precalcSqrtSumSquares;\n"
+ << "\t\treal_t ang2, ang = precalcAtanyx;\n"
+ << "\n"
+ << "\t\tif (rad < " << minr << ")\n"
+ << "\t\t ang2 = ang + " << mina << ";\n"
+ << "\t\telse if (rad > " << maxr << ")\n"
+ << "\t\t ang2 = ang + " << maxa << ";\n"
+ << "\t\telse\n"
+ << "\t\t ang2 = ang + log(rad) * " << shift << ";\n"
+ << "\n"
+ << "\t\tvOut.x = " << weight << " * rad * cos(ang);\n"
+ << "\t\tvOut.y = " << weight << " * rad * sin(ang);\n"
+ << "\t\tvOut.z = " << DefaultZCl()
+ << "\t}\n";
+ return ss.str();
+ }
+
+ virtual void Precalc() override
+ {
+ m_Minr = std::min(m_Min, m_Max);
+ m_Maxr = std::max(m_Min, m_Max);
+ m_Mina = m_Minr > 0 ? std::log(m_Minr) * m_Shift : 0;
+ m_Maxa = m_Maxr > 0 ? std::log(m_Maxr) * m_Shift : 0;
+ }
+
+protected:
+ void Init()
+ {
+ string prefix = Prefix();
+ m_Params.clear();
+ m_Params.push_back(ParamWithName(&m_Shift, prefix + "swirl3r_shift", T(0.5)));
+ m_Params.push_back(ParamWithName(&m_Min, prefix + "swirl3r_min", T(0.5), eParamType::REAL, 0));
+ m_Params.push_back(ParamWithName(&m_Max, prefix + "swirl3r_max", 1, eParamType::REAL, 0));
+ m_Params.push_back(ParamWithName(true, &m_Minr, prefix + "swirl3r_minr"));//Precalc.
+ m_Params.push_back(ParamWithName(true, &m_Maxr, prefix + "swirl3r_maxr"));
+ m_Params.push_back(ParamWithName(true, &m_Mina, prefix + "swirl3r_mina"));
+ m_Params.push_back(ParamWithName(true, &m_Maxa, prefix + "swirl3r_maxa"));
+ }
+
+private:
+ T m_Shift;
+ T m_Min;
+ T m_Max;
+ T m_Minr;//Precalc.
+ T m_Maxr;
+ T m_Mina;
+ T m_Maxa;
+};
+
///
/// Horseshoe:
/// a = atan2(tx, ty);
@@ -1918,6 +2069,43 @@ public:
}
};
+///
+/// Gaussian.
+///
+template
+class GaussianVariation : public Variation
+{
+public:
+ GaussianVariation(T weight = 1.0) : Variation("gaussian", eVariationId::VAR_GAUSSIAN, weight) { }
+
+ VARCOPY(GaussianVariation)
+
+ virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
+ {
+ T angle = rand.Frand01() * M_2PI;
+ T r = m_Weight * (rand.Frand01() + rand.Frand01() + rand.Frand01() + rand.Frand01() - 2);
+ helper.Out.x = r * std::cos(angle) + helper.In.x;
+ helper.Out.y = r * std::sin(angle) + helper.In.y;
+ helper.Out.z = DefaultZ(helper);
+ }
+
+ virtual string OpenCLString() const override
+ {
+ ostringstream ss;
+ string weight = WeightDefineString();
+ intmax_t varIndex = IndexInXform();
+ ss << "\t{\n"
+ << "\t\treal_t angle = MwcNext01(mwc) * M_2PI;\n"
+ << "\t\treal_t r = " << weight << " * (MwcNext01(mwc) + MwcNext01(mwc) + MwcNext01(mwc) + MwcNext01(mwc) - (real_t)(2.0));\n"
+ << "\n"
+ << "\t\tvOut.x = fma(r, cos(angle), vIn.x);\n"
+ << "\t\tvOut.y = fma(r, sin(angle), vIn.y);\n"
+ << "\t\tvOut.z = " << DefaultZCl()
+ << "\t}\n";
+ return ss.str();
+ }
+};
+
///
/// Radial blur.
///
@@ -2512,7 +2700,7 @@ public:
string weight = WeightDefineString();
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
- << "\t\treal_t u = fma(" << weight << ", SQR(M_2_PI), 1 / Zeps(tan(precalcSqrtSumSquares)));\n";
+ << "\t\treal_t u = fma(" << weight << ", SQR(M2PI), 1 / Zeps(tan(precalcSqrtSumSquares)));\n";
if (m_VarType == eVariationType::VARTYPE_REG)
ss << "\t\toutPoint->m_X = outPoint->m_Y = 0;\n";
@@ -3066,6 +3254,77 @@ private:
T m_Holes;
};
+///
+/// flowerdb.
+/// By dark-beam.
+///
+template
+class FlowerDbVariation : public ParametricVariation
+{
+public:
+ FlowerDbVariation(T weight = 1.0) : ParametricVariation("flowerdb", eVariationId::VAR_FLOWER_DB, weight, true, true, false, false, true)
+ {
+ Init();
+ }
+
+ PARVARCOPY(FlowerDbVariation)
+
+ virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
+ {
+ T r = m_Weight * helper.m_PrecalcSqrtSumSquares;
+ T t = helper.m_PrecalcAtanyx;
+ T r2 = r * (std::abs((m_Spread + std::sin(m_Petals * t)) * cos(m_PetalsSplit * t)));
+ helper.Out.x = r2 * std::cos(t);
+ helper.Out.y = r2 * std::sin(t);
+ helper.Out.z = DefaultZ(helper);
+ }
+
+ virtual string OpenCLString() const override
+ {
+ ostringstream ss, ss2;
+ intmax_t i = 0, varIndex = IndexInXform();
+ ss2 << "_" << XformIndexInEmber() << "]";
+ string index = ss2.str();
+ string weight = WeightDefineString();
+ string petals = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string split = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string spread = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string petalssplit = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ ss << "\t{\n"
+ << "\t\treal_t r = " << weight << " * precalcSqrtSumSquares;\n"
+ << "\t\treal_t t = precalcAtanyx;\n"
+ << "\t\treal_t r2 = r * (fabs((" << spread << " + sin(" << petals << " * t)) * cos(" << petalssplit << " * t)));\n"
+ << "\n"
+ << "\t\tvOut.x = r * cos(t);\n"
+ << "\t\tvOut.y = r * sin(t);\n"
+ << "\t\tvOut.z = " << DefaultZCl()
+ << "\t}\n";
+ return ss.str();
+ }
+
+ virtual void Precalc() override
+ {
+ m_PetalsSplit = m_Petals * m_Split;
+ }
+
+protected:
+ void Init()
+ {
+ string prefix = Prefix();
+ m_Params.clear();
+ m_Params.push_back(ParamWithName(&m_Petals, prefix + "flowerdb_petals", 6));
+ m_Params.push_back(ParamWithName(&m_Split, prefix + "flowerdb_petal_split"));
+ m_Params.push_back(ParamWithName(&m_Spread, prefix + "flowerdb_petal_spread", 1));
+ m_Params.push_back(ParamWithName(true, &m_PetalsSplit, prefix + "flowerdb_petal_split_petals"));//Precalc.
+ }
+
+private:
+ T m_Petals;
+ T m_Split;
+ T m_Spread;
+ T m_PetalsSplit;//Precalc.
+};
+
///
/// Conic.
///
@@ -3985,20 +4244,52 @@ public:
//For this to be correct, it must always use double. So there is no point in switching precisions when using this variation.
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
- double x2 = 2 * helper.In.x;
- double u = helper.m_PrecalcSumSquares + x2;
- double v = helper.m_PrecalcSumSquares - x2;
- double xmaxm1 = 0.5 * (Sqrt1pm1(u) + Sqrt1pm1(v));
- double a = helper.In.x / (1 + xmaxm1);
- double ssx = xmaxm1 < 0 ? 0 : std::sqrt(xmaxm1);
- helper.Out.x = T(m_WeightDivPiDiv2 * std::asin(Clamp(a, -1.0, 1.0)));
+ if (typeid(T) == typeid(float))
+ {
+ T tmp = helper.m_PrecalcSumSquares + 1;
+ T x2 = 2 * helper.In.x;
+ T xmax = T(0.5) * (std::sqrt(tmp + x2) + std::sqrt(tmp - x2));
+ T a = helper.In.x / xmax;
+ T b = 1 - a * a;
+ T ssx = xmax - 1;
+ const T w = m_WeightDivPiDiv2;
- if (helper.In.y > 0)
- helper.Out.y = T(m_WeightDivPiDiv2 * std::log1p(xmaxm1 + ssx));
+ if (b < 0)
+ b = 0;
+ else
+ b = std::sqrt(b);
+
+ if (ssx < 0)
+ ssx = 0;
+ else
+ ssx = std::sqrt(ssx);
+
+ helper.Out.x = w * std::atan2(a, b);
+
+ if (helper.In.y > 0)
+ helper.Out.y = w * std::log(xmax + ssx);
+ else
+ helper.Out.y = -(w * std::log(xmax + ssx));
+
+ helper.Out.z = DefaultZ(helper);
+ }
else
- helper.Out.y = T(-(m_WeightDivPiDiv2 * std::log1p(xmaxm1 + ssx)));
+ {
+ double x2 = 2 * helper.In.x;
+ double u = helper.m_PrecalcSumSquares + x2;
+ double v = helper.m_PrecalcSumSquares - x2;
+ double xmaxm1 = 0.5 * (Sqrt1pm1(u) + Sqrt1pm1(v));
+ double a = helper.In.x / (1 + xmaxm1);
+ double ssx = xmaxm1 < 0 ? 0 : std::sqrt(xmaxm1);
+ helper.Out.x = T(m_WeightDivPiDiv2 * std::asin(Clamp(a, -1.0, 1.0)));
- helper.Out.z = DefaultZ(helper);
+ if (helper.In.y > 0)
+ helper.Out.y = T(m_WeightDivPiDiv2 * std::log1p(xmaxm1 + ssx));
+ else
+ helper.Out.y = T(-(m_WeightDivPiDiv2 * std::log1p(xmaxm1 + ssx)));
+
+ helper.Out.z = DefaultZ(helper);
+ }
}
virtual string OpenCLString() const override
@@ -4009,22 +4300,58 @@ public:
string index = ss2.str();
string weight = WeightDefineString();
string weightDivPiDiv2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
- ss << "\t{\n"
- << "\t\tdouble x2 = 2.0 * vIn.x;\n"
- << "\t\tdouble u = precalcSumSquares + x2;\n"
- << "\t\tdouble v = precalcSumSquares - x2;\n"
- << "\t\tdouble xmaxm1 = 0.5 * (Sqrt1pm1(u) + Sqrt1pm1(v));\n"
- << "\t\tdouble a = vIn.x / (1 + xmaxm1);\n"
- << "\t\tdouble ssx = xmaxm1 < 0 ? 0.0 : sqrt(xmaxm1);\n"
- << "\t\tvOut.x = (" << weightDivPiDiv2 << " * asin(clamp(a, (double)-1.0, (double)1.0)));\n"
- << "\n"
- << "\t\tif (vIn.y > 0)\n"
- << "\t\t\tvOut.y = " << weightDivPiDiv2 << " * log1p(xmaxm1 + ssx);\n"
- << "\t\telse\n"
- << "\t\t\tvOut.y = -(" << weightDivPiDiv2 << " * log1p(xmaxm1 + ssx));\n"
- << "\n"
- << "\t\tvOut.z = " << DefaultZCl()
- << "\t}\n";
+
+ if (typeid(T) == typeid(float))
+ {
+ ss << "\t{\n"
+ << "\t\treal_t tmp = precalcSumSquares + (real_t)(1.0);\n"
+ << "\t\treal_t x2 = (real_t)(2.0) * vIn.x;\n"
+ << "\t\treal_t xmax = (real_t)(0.5) * (sqrt(tmp + x2) + sqrt(tmp - x2));\n"
+ << "\t\treal_t a = vIn.x / xmax;\n"
+ << "\t\treal_t b = (real_t)(1.0) - a * a;\n"
+ << "\t\treal_t ssx = xmax - (real_t)(1.0);\n"
+ << "\t\tconst real_t w = " << weightDivPiDiv2 << ";\n"
+ << "\n"
+ << "\t\tif (b < 0)\n"
+ << "\t\t b = 0;\n"
+ << "\t\telse\n"
+ << "\t\t b = sqrt(b);\n"
+ << "\n"
+ << "\t\tif (ssx < 0)\n"
+ << "\t\t ssx = 0;\n"
+ << "\t\telse\n"
+ << "\t\t ssx = sqrt(ssx);\n"
+ << "\n"
+ << "\t\tvOut.x = w * atan2(a, b);\n"
+ << "\n"
+ << "\t\tif (vIn.y > 0)\n"
+ << "\t\t vOut.y = w * log(xmax + ssx);\n"
+ << "\t\telse\n"
+ << "\t\t vOut.y = -(w * log(xmax + ssx));\n"
+ << "\n"
+ << "\t\tvOut.z = " << DefaultZCl()
+ << "\t}\n";
+ }
+ else
+ {
+ ss << "\t{\n"
+ << "\t\tdouble x2 = 2.0 * vIn.x;\n"
+ << "\t\tdouble u = precalcSumSquares + x2;\n"
+ << "\t\tdouble v = precalcSumSquares - x2;\n"
+ << "\t\tdouble xmaxm1 = 0.5 * (Sqrt1pm1(u) + Sqrt1pm1(v));\n"
+ << "\t\tdouble a = vIn.x / (1 + xmaxm1);\n"
+ << "\t\tdouble ssx = xmaxm1 < 0 ? 0.0 : sqrt(xmaxm1);\n"
+ << "\t\tvOut.x = (" << weightDivPiDiv2 << " * asin(clamp(a, (double)-1.0, (double)1.0)));\n"
+ << "\n"
+ << "\t\tif (vIn.y > 0)\n"
+ << "\t\t\tvOut.y = " << weightDivPiDiv2 << " * log1p(xmaxm1 + ssx);\n"
+ << "\t\telse\n"
+ << "\t\t\tvOut.y = -(" << weightDivPiDiv2 << " * log1p(xmaxm1 + ssx));\n"
+ << "\n"
+ << "\t\tvOut.z = " << DefaultZCl()
+ << "\t}\n";
+ }
+
return ss.str();
}
@@ -4631,10 +4958,10 @@ protected:
{
string prefix = Prefix();
m_Params.clear();
- m_Params.push_back(ParamWithName(&m_Separation, prefix + "oscilloscope_separation", 1));//Params.
- m_Params.push_back(ParamWithName(&m_Frequency, prefix + "oscilloscope_frequency", T(M_PI)));
- m_Params.push_back(ParamWithName(&m_Amplitude, prefix + "oscilloscope_amplitude", 1));
- m_Params.push_back(ParamWithName(&m_Damping, prefix + "oscilloscope_damping"));
+ m_Params.push_back(ParamWithName(&m_Separation, prefix + "oscilloscope_separation", 1));//Params.
+ m_Params.push_back(ParamWithName(&m_Frequency, prefix + "oscilloscope_frequency", T(M_PI)));
+ m_Params.push_back(ParamWithName(&m_Amplitude, prefix + "oscilloscope_amplitude", 1));
+ m_Params.push_back(ParamWithName(&m_Damping, prefix + "oscilloscope_damping"));
m_Params.push_back(ParamWithName(true, &m_2PiFreq, prefix + "oscilloscope_2pifreq"));//Precalc.
}
@@ -4646,6 +4973,117 @@ private:
T m_2PiFreq;//Precalc.
};
+///
+/// Oscilloscope2.
+/// By dark-beam.
+///
+template
+class Oscilloscope2Variation : public ParametricVariation
+{
+public:
+ Oscilloscope2Variation(T weight = 1.0) : ParametricVariation("oscilloscope2", eVariationId::VAR_OSCILLOSCOPE2, weight)
+ {
+ Init();
+ }
+
+ PARVARCOPY(Oscilloscope2Variation)
+
+ virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
+ {
+ T t;
+ T pt = m_Perturbation * std::sin(m_Tpf2 * helper.In.y);
+
+ if (!m_Damping)
+ t = m_Amplitude * std::cos(m_Tpf * helper.In.x + pt) + m_Separation;
+ else
+ t = m_Amplitude * std::exp(-std::abs(helper.In.x) * m_Damping) * std::cos(m_Tpf * helper.In.x + pt) + m_Separation;
+
+ if (std::abs(helper.In.y) <= t)
+ {
+ helper.Out.x = -(m_Weight * helper.In.x);
+ helper.Out.y = -(m_Weight * helper.In.y);
+ }
+ else
+ {
+ helper.Out.x = m_Weight * helper.In.x;
+ helper.Out.y = m_Weight * helper.In.y;
+ }
+
+ helper.Out.z = DefaultZ(helper);
+ }
+
+ virtual string OpenCLString() const override
+ {
+ ostringstream ss, ss2;
+ intmax_t i = 0, varIndex = IndexInXform();
+ ss2 << "_" << XformIndexInEmber() << "]";
+ string index = ss2.str();
+ string weight = WeightDefineString();
+ string separation = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string frequencyx = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string frequencyy = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string amplitude = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string perturbation = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string damping = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string tpf = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string tpf2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ ss << "\t{\n"
+ << "\t\treal_t t;\n"
+ << "\t\treal_t pt = " << perturbation << " * sin(" << tpf2 << " * vIn.y);\n"
+ << "\n"
+ << "\t\tif (!" << damping << ")\n"
+ << "\t\t t = fma(" << amplitude << ", cos(fma(" << tpf << ", vIn.x, pt)), " << separation << ");\n"
+ << "\t\telse\n"
+ << "\t\t t = fma(" << amplitude << ", exp(-fabs(vIn.x) * " << damping << ") * cos(fma(" << tpf << ", vIn.x, pt)), " << separation << ");\n"
+ << "\n"
+ << "\t\tif (fabs(vIn.y) <= t)\n"
+ << "\t\t{\n"
+ << "\t\t vOut.x = -(" << weight << " * vIn.x);\n"
+ << "\t\t vOut.y = -(" << weight << " * vIn.y);\n"
+ << "\t\t}\n"
+ << "\t\telse\n"
+ << "\t\t{\n"
+ << "\t\t vOut.x = " << weight << " * vIn.x;\n"
+ << "\t\t vOut.y = " << weight << " * vIn.y;\n"
+ << "\t\t}\n"
+ << "\n"
+ << "\t\tvOut.z = " << DefaultZCl()
+ << "\t}\n";
+ return ss.str();
+ }
+
+ virtual void Precalc() override
+ {
+ m_Tpf = M_2PI * m_FrequencyX;
+ m_Tpf2 = M_2PI * m_FrequencyY;
+ }
+
+protected:
+ void Init()
+ {
+ string prefix = Prefix();
+ m_Params.clear();
+ m_Params.push_back(ParamWithName(&m_Separation, prefix + "oscilloscope2_separation", 1, eParamType::REAL, 0));//Params.
+ m_Params.push_back(ParamWithName(&m_FrequencyX, prefix + "oscilloscope2_frequencyx", T(M_PI)));
+ m_Params.push_back(ParamWithName(&m_FrequencyY, prefix + "oscilloscope2_frequencyy", T(M_PI)));
+ m_Params.push_back(ParamWithName(&m_Amplitude, prefix + "oscilloscope2_amplitude", 1));
+ m_Params.push_back(ParamWithName(&m_Perturbation, prefix + "oscilloscope2_perturbation", 1));
+ m_Params.push_back(ParamWithName(&m_Damping, prefix + "oscilloscope2_damping", 0, eParamType::INTEGER, 0, 1));
+ m_Params.push_back(ParamWithName(true, &m_Tpf, prefix + "oscilloscope2_tpf"));//Precalc.
+ m_Params.push_back(ParamWithName(true, &m_Tpf2, prefix + "oscilloscope2_tpf2"));
+ }
+
+private:
+ T m_Separation;//Params.
+ T m_FrequencyX;
+ T m_FrequencyY;
+ T m_Amplitude;
+ T m_Perturbation;
+ T m_Damping;
+ T m_Tpf;//Precalc.
+ T m_Tpf2;
+};
+
///
/// Polar2.
///
@@ -4833,6 +5271,97 @@ private:
T m_InvWeight;//Precalcs only, no params.
};
+///
+/// scry2.
+/// By dark-beam, modified by tatasz to increase the speed.
+///
+template
+class Scry2Variation : public ParametricVariation
+{
+public:
+ Scry2Variation(T weight = 1.0) : ParametricVariation("scry2", eVariationId::VAR_SCRY2, weight, true)
+ {
+ Init();
+ }
+
+ PARVARCOPY(Scry2Variation)
+
+ virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
+ {
+ T r2 = helper.m_PrecalcSumSquares;
+ T s = 1 / Zeps(std::sqrt(r2) * (r2 + 1));
+ T newX = helper.In.x * s;
+ T newY = helper.In.y * s;
+ T dang = (std::atan2(newY, newX) + T(M_PI)) / m_2PiOverPower;
+ T rad = std::sqrt(SQR(newX) + SQR(newY));
+ T zang1 = T(Floor(dang));
+ T xang1 = dang - zang1;
+ T xang2 = xang1 > 0.5 ? 1 - xang1 : xang1;
+ T zang = xang1 > 0.5 ? zang1 + 1 : zang1;
+ T sign = T(xang1 > 0.5 ? -1 : 1);
+ T xang = std::atan(xang2 * std::tan(m_2PiOverPower * T(0.5)) * 2) / m_2PiOverPower;
+ T coeff = 1 / std::cos(xang * m_2PiOverPower);
+ T ang = (zang + sign * xang) * m_2PiOverPower - T(M_PI);
+ helper.Out.x = m_Weight * coeff * rad * std::cos(ang);
+ helper.Out.y = m_Weight * coeff * rad * std::sin(ang);
+ helper.Out.z = DefaultZ(helper);
+ }
+
+ virtual string OpenCLString() const override
+ {
+ ostringstream ss, ss2;
+ int i = 0;
+ ss2 << "_" << XformIndexInEmber() << "]";
+ string index = ss2.str();
+ string weight = WeightDefineString();
+ string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string twopioverpower = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ ss << "\t{\n"
+ << "\t\treal_t r2 = precalcSumSquares;\n"
+ << "\t\treal_t s = 1 / Zeps(sqrt(r2) * (r2 + 1));\n"
+ << "\t\treal_t newX = vIn.x * s;\n"
+ << "\t\treal_t newY = vIn.y * s;\n"
+ << "\t\treal_t dang = (atan2(newY, newX) + MPI) / " << twopioverpower << ";\n"
+ << "\t\treal_t rad = sqrt(SQR(newX) + SQR(newY));\n"
+ << "\t\treal_t zang1 = floor(dang);\n"
+ << "\t\treal_t xang1 = dang - zang1;\n"
+ << "\t\treal_t xang2 = xang1 > 0.5 ? 1 - xang1 : xang1;\n"
+ << "\t\treal_t zang = xang1 > 0.5 ? zang1 + 1 : zang1;\n"
+ << "\t\treal_t sign = xang1 > 0.5 ? -1.0 : 1.0;\n"
+ << "\t\treal_t xang = atan(xang2 * tan(" << twopioverpower << " * 0.5) * 2) / " << twopioverpower << ";\n"
+ << "\t\treal_t coeff = 1 / cos(xang * " << twopioverpower << ");\n"
+ << "\t\treal_t ang = (zang + sign * xang) * " << twopioverpower << " - MPI;\n"
+ << "\t\tvOut.x = " << weight << " * coeff * rad * cos(ang);\n"
+ << "\t\tvOut.y = " << weight << " * coeff * rad * sin(ang);\n"
+ << "\t\tvOut.z = " << DefaultZCl()
+ << "\t}\n";
+ return ss.str();
+ }
+
+ virtual vector OpenCLGlobalFuncNames() const override
+ {
+ return vector { "Zeps" };
+ }
+
+ virtual void Precalc() override
+ {
+ m_2PiOverPower = M_2PI / Zeps(m_Power);
+ }
+
+protected:
+ void Init()
+ {
+ string prefix = Prefix();
+ m_Params.clear();
+ m_Params.push_back(ParamWithName(&m_Power, prefix + "scry2_power", 4));
+ m_Params.push_back(ParamWithName(true, &m_2PiOverPower, prefix + "scry2_2pi_over_power"));//Precalc.
+ }
+
+private:
+ T m_Power;
+ T m_2PiOverPower;//Precalc.
+};
+
///
/// Separation.
///
@@ -5597,7 +6126,6 @@ public:
{
ostringstream ss;
string weight = WeightDefineString();
- intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t expe = " << weight << " * exp(vIn.x);\n"
<< "\n"
@@ -5609,6 +6137,43 @@ public:
}
};
+///
+/// Exp2.
+/// By tatasz.
+///
+template
+class Exp2Variation : public Variation
+{
+public:
+ Exp2Variation(T weight = 1.0) : Variation("exp2", eVariationId::VAR_EXP2, weight) { }
+
+ VARCOPY(Exp2Variation)
+
+ virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
+ {
+ T ypi = helper.In.y * T(M_PI);
+ T expe = m_Weight * std::exp(helper.In.x * T(M_PI));
+ helper.Out.x = expe * std::cos(ypi);
+ helper.Out.y = expe * std::sin(ypi);
+ helper.Out.z = DefaultZ(helper);
+ }
+
+ virtual string OpenCLString() const override
+ {
+ ostringstream ss;
+ string weight = WeightDefineString();
+ ss << "\t{\n"
+ << "\t\treal_t ypi = vIn.y * MPI;\n"
+ << "\t\treal_t expe = " << weight << " * exp(vIn.x * MPI);\n"
+ << "\n"
+ << "\t\tvOut.x = expe * cos(ypi);\n"
+ << "\t\tvOut.y = expe * sin(ypi);\n"
+ << "\t\tvOut.z = " << DefaultZCl()
+ << "\t}\n";
+ return ss.str();
+ }
+};
+
///
/// Log.
///
@@ -6053,6 +6618,65 @@ public:
}
};
+///
+/// tanh_spiral.
+///
+template
+class TanhSpiralVariation : public ParametricVariation
+{
+public:
+ TanhSpiralVariation(T weight = 1.0) : ParametricVariation("tanh_spiral", eVariationId::VAR_TANH_SPIRAL, weight)
+ {
+ Init();
+ }
+
+ PARVARCOPY(TanhSpiralVariation)
+
+ virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
+ {
+ T t2 = (rand.Frand01() - T(0.5)) * M_2PI;
+ T aux = Zeps(std::cos(m_A * t2) + std::cosh(t2));
+ helper.Out.x = m_Weight * (std::sinh(t2) / aux);
+ helper.Out.y = m_Weight * (std::sin(m_A * t2) / aux);
+ helper.Out.z = DefaultZ(helper);
+ }
+
+ virtual string OpenCLString() const override
+ {
+ ostringstream ss, ss2;
+ intmax_t i = 0, varIndex = IndexInXform();
+ ss2 << "_" << XformIndexInEmber() << "]";
+ string index = ss2.str();
+ string weight = WeightDefineString();
+ string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ ss << "\t{\n"
+ << "\t\treal_t t2 = (MwcNext01(mwc) - 0.5) * M_2PI;\n"
+ << "\t\treal_t aux = Zeps(cos(" << a << " * t2) + cosh(t2));\n"
+ << "\n"
+ << "\t\tvOut.x = " << weight << " * (sinh(t2) / aux);\n"
+ << "\t\tvOut.y = " << weight << " * (sin(" << a << " * t2) / aux);\n"
+ << "\t\tvOut.z = " << DefaultZCl()
+ << "\t}\n";
+ return ss.str();
+ }
+
+ virtual vector OpenCLGlobalFuncNames() const override
+ {
+ return vector { "Zeps" };
+ }
+
+protected:
+ void Init()
+ {
+ string prefix = Prefix();
+ m_Params.clear();
+ m_Params.push_back(ParamWithName(&m_A, prefix + "tanh_spiral_a", 4));
+ }
+
+private:
+ T m_A;
+};
+
///
/// Sech
///
@@ -6364,6 +6988,8 @@ MAKEPREPOSTVAR(Linear, linear, LINEAR)
MAKEPREPOSTVAR(Sinusoidal, sinusoidal, SINUSOIDAL)
MAKEPREPOSTVAR(Spherical, spherical, SPHERICAL)
MAKEPREPOSTVAR(Swirl, swirl, SWIRL)
+MAKEPREPOSTPARVAR(Swirl3, swirl3, SWIRL3)
+MAKEPREPOSTPARVAR(Swirl3r, swirl3r, SWIRL3R)
MAKEPREPOSTVAR(Horseshoe, horseshoe, HORSESHOE)
MAKEPREPOSTVAR(Polar, polar, POLAR)
MAKEPREPOSTVAR(Handkerchief, handkerchief, HANDKERCHIEF)
@@ -6396,7 +7022,9 @@ MAKEPREPOSTPARVAR(JuliaNGeneric, julian, JULIAN)
MAKEPREPOSTPARVAR(JuliaScope, juliascope, JULIASCOPE)
MAKEPREPOSTVARASSIGN(Blur, blur, BLUR, eVariationAssignType::ASSIGNTYPE_SUM)
MAKEPREPOSTVARASSIGN(GaussianBlur, gaussian_blur, GAUSSIAN_BLUR, eVariationAssignType::ASSIGNTYPE_SUM)
+MAKEPREPOSTVAR(Gaussian, gaussian, GAUSSIAN)
MAKEPREPOSTPARVAR(RadialBlur, radial_blur, RADIAL_BLUR)
+//MAKEPREPOSTPARVAR(RadialGaussian, radial_gaussian, RADIAL_GAUSSIAN)
MAKEPREPOSTPARVARASSIGN(Pie, pie, PIE, eVariationAssignType::ASSIGNTYPE_SUM)
MAKEPREPOSTPARVAR(Ngon, ngon, NGON)
MAKEPREPOSTPARVAR(Curl, curl, CURL)
@@ -6415,6 +7043,7 @@ MAKEPREPOSTVAR(Cross, cross, CROSS)
MAKEPREPOSTPARVAR(Disc2, disc2, DISC2)
MAKEPREPOSTPARVAR(SuperShape, super_shape, SUPER_SHAPE)
MAKEPREPOSTPARVAR(Flower, flower, FLOWER)
+MAKEPREPOSTPARVAR(FlowerDb, flowerdb, FLOWER_DB)
MAKEPREPOSTPARVAR(Conic, conic, CONIC)
MAKEPREPOSTPARVAR(Parabola, parabola, PARABOLA)
MAKEPREPOSTPARVAR(Bent2, bent2, BENT2)
@@ -6432,9 +7061,11 @@ MAKEPREPOSTPARVAR(LazySusan, lazysusan, LAZYSUSAN)
MAKEPREPOSTPARVAR(Loonie, loonie, LOONIE)
MAKEPREPOSTPARVAR(Modulus, modulus, MODULUS)
MAKEPREPOSTPARVAR(Oscilloscope, oscilloscope, OSCILLOSCOPE)
+MAKEPREPOSTPARVAR(Oscilloscope2, oscilloscope2, OSCILLOSCOPE2)
MAKEPREPOSTPARVAR(Polar2, polar2, POLAR2)
MAKEPREPOSTPARVAR(Popcorn2, popcorn2, POPCORN2)
MAKEPREPOSTPARVAR(Scry, scry, SCRY)
+MAKEPREPOSTPARVAR(Scry2, scry2, SCRY2)
MAKEPREPOSTPARVAR(Separation, separation, SEPARATION)
MAKEPREPOSTPARVAR(Split, split, SPLIT)
MAKEPREPOSTPARVAR(Splits, splits, SPLITS)
@@ -6445,6 +7076,7 @@ MAKEPREPOSTPARVAR(WedgeSph, wedge_sph, WEDGE_SPH)
MAKEPREPOSTPARVAR(Whorl, whorl, WHORL)
MAKEPREPOSTPARVAR(Waves2, waves2, WAVES2)
MAKEPREPOSTVAR(Exp, exp, EXP)
+MAKEPREPOSTVAR(Exp2, exp2, EXP2)
MAKEPREPOSTPARVAR(Log, log, LOG)
MAKEPREPOSTVAR(Sin, sin, SIN)
MAKEPREPOSTVAR(Cos, cos, COS)
@@ -6455,6 +7087,7 @@ MAKEPREPOSTVAR(Cot, cot, COT)
MAKEPREPOSTVAR(Sinh, sinh, SINH)
MAKEPREPOSTVAR(Cosh, cosh, COSH)
MAKEPREPOSTVAR(Tanh, tanh, TANH)
+MAKEPREPOSTPARVAR(TanhSpiral, tanh_spiral, TANH_SPIRAL)
MAKEPREPOSTVAR(Sech, sech, SECH)
MAKEPREPOSTVAR(Csch, csch, CSCH)
MAKEPREPOSTVAR(Coth, coth, COTH)
diff --git a/Source/Ember/Variations02.h b/Source/Ember/Variations02.h
index feb311e..a5ea044 100644
--- a/Source/Ember/Variations02.h
+++ b/Source/Ember/Variations02.h
@@ -119,7 +119,7 @@ private:
///
/// Bwraps.
-/// Note, this is the same as bwraps2.
+/// Note, this is the same as bwraps7, which is the same as bwraps2 except for the precalc function.
///
template
class BwrapsVariation : public ParametricVariation
@@ -240,7 +240,7 @@ public:
virtual void Precalc() override
{
T radius = T(0.5) * (m_BwrapsCellsize / (1 + SQR(m_BwrapsSpace)));
- m_G2 = Zeps(SQR(m_BwrapsGain) / Zeps(radius));
+ m_G2 = SQR(m_BwrapsGain) + T(1.0e-6);
T maxBubble = m_G2 * radius;
if (maxBubble > 2)
@@ -283,6 +283,195 @@ private:
T m_Rfactor;
};
+///
+/// bwraps_rand.
+/// By tatasz.
+///
+template
+class BwrapsRandVariation : public ParametricVariation
+{
+public:
+ BwrapsRandVariation(T weight = 1.0) : ParametricVariation("bwraps_rand", eVariationId::VAR_BWRAPS_RAND, weight)
+ {
+ Init();
+ }
+
+ PARVARCOPY(BwrapsRandVariation)
+
+ virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
+ {
+ if (m_CellSize == 0)
+ {
+ helper.Out.x = helper.In.x * m_Weight;
+ helper.Out.y = helper.In.y * m_Weight;
+ }
+ else
+ {
+ T Cx = (Floor(helper.In.x * m_InvCellSize) + T(0.5)) * m_CellSize;
+ T Cy = (Floor(helper.In.y * m_InvCellSize) + T(0.5)) * m_CellSize;
+ T Lx = helper.In.x - Cx;
+ T Ly = helper.In.y - Cy;
+ T radius;
+
+ if (m_Symm == 0)
+ radius = m_HalfCellSizeOver1pSpaceSq * VarFuncs::HashShadertoy(Cx, Cy, m_Seed);
+ else
+ radius = m_HalfCellSizeOver1pSpaceSq * VarFuncs::HashShadertoy(SQR(Cx), SQR(Cy), m_Seed);
+
+ T mb = m_G2 * radius;
+ T max_bubble;
+
+ if (mb > 2)
+ max_bubble = 1;
+ else
+ max_bubble = mb / (mb * mb * T(0.25) + 1);
+
+ T r2 = SQR(radius);
+
+ if (SQR(Lx) + SQR(Ly) > r2)
+ {
+ helper.Out.x = helper.In.x * m_Weight;
+ helper.Out.y = helper.In.y * m_Weight;
+ }
+ else
+ {
+ T rfactor = radius / Zeps(max_bubble);
+ T Lx2 = Lx * m_G2;
+ T Ly2 = Ly * m_G2;
+ T r = rfactor / ((SQR(Lx2) + SQR(Ly2)) * T(0.25) + 1);
+ T Lx3 = Lx2 * r;
+ T Ly3 = Ly2 * r;
+ T r_2 = (SQR(Lx3) + SQR(Ly3)) / Zeps(r2);
+ T theta = m_InnerTwist * (1 - r_2) + m_OuterTwist * r_2;
+ T ct = std::cos(theta);
+ T st = std::sin(theta);
+ helper.Out.x = (Cx + ct * Lx3 + st * Ly3) * m_Weight;
+ helper.Out.y = (Cy - st * Lx3 + ct * Ly3) * m_Weight;
+ }
+ }
+
+ helper.Out.z = DefaultZ(helper);
+ }
+
+ virtual string OpenCLString() const override
+ {
+ ostringstream ss, ss2;
+ intmax_t i = 0, varIndex = IndexInXform();
+ ss2 << "_" << XformIndexInEmber() << "]";
+ string index = ss2.str();
+ string weight = WeightDefineString();
+ string cellsize = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string space = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string gain = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string innertwist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string outertwist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string symm = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string seed = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string invcellsize = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string g2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string spacesq = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string halfcellsizeover1pspacesq = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ ss << "\t{\n"
+ << "\t\tif (" << cellsize << " == 0)\n"
+ << "\t\t{\n"
+ << "\t\t vOut.x = vIn.x * " << weight << ";\n"
+ << "\t\t vOut.y = vIn.y * " << weight << ";\n"
+ << "\t\t}\n"
+ << "\t\telse\n"
+ << "\t\t{\n"
+ << "\t\t real_t Cx = (floor(vIn.x * " << invcellsize << ") + 0.5) * " << cellsize << ";\n"
+ << "\t\t real_t Cy = (floor(vIn.y * " << invcellsize << ") + 0.5) * " << cellsize << ";\n"
+ << "\t\t real_t Lx = vIn.x - Cx;\n"
+ << "\t\t real_t Ly = vIn.y - Cy;\n"
+ << "\t\t real_t radius;\n"
+ << "\n"
+ << "\t\t if (" << symm << " == 0)\n"
+ << "\t\t radius = " << halfcellsizeover1pspacesq << " * HashShadertoy(Cx, Cy, " << seed << ");\n"
+ << "\t\t else\n"
+ << "\t\t radius = " << halfcellsizeover1pspacesq << " * HashShadertoy(SQR(Cx), SQR(Cy), " << seed << ");\n"
+ << "\n"
+ << "\t\t real_t mb = " << g2 << " * radius;\n"
+ << "\t\t real_t max_bubble;\n"
+ << "\n"
+ << "\t\t if (mb > 2)\n"
+ << "\t\t max_bubble = 1;\n"
+ << "\t\t else\n"
+ << "\t\t max_bubble = mb / fma(SQR(mb), 0.25, 1.0);\n"
+ << "\n"
+ << "\t\t real_t r2 = SQR(radius);\n"
+ << "\n"
+ << "\t\t if (SQR(Lx) + SQR(Ly) > r2)\n"
+ << "\t\t {\n"
+ << "\t\t vOut.x = vIn.x * " << weight << ";\n"
+ << "\t\t vOut.y = vIn.y * " << weight << ";\n"
+ << "\t\t }\n"
+ << "\t\t else\n"
+ << "\t\t {\n"
+ << "\t\t real_t rfactor = radius / Zeps(max_bubble);\n"
+ << "\t\t real_t Lx2 = Lx * " << g2 << ";\n"
+ << "\t\t real_t Ly2 = Ly * " << g2 << ";\n"
+ << "\t\t real_t r = rfactor / fma(fma(Lx2, Lx2, SQR(Ly2)), 0.25, 1.0);\n"
+ << "\t\t real_t Lx3 = Lx2 * r;\n"
+ << "\t\t real_t Ly3 = Ly2 * r;\n"
+ << "\t\t real_t r_2 = fma(Lx3, Lx3, SQR(Ly3)) / Zeps(r2);\n"
+ << "\t\t real_t theta = " << innertwist << " * (1.0 - r_2) + " << outertwist << " * r_2;\n"
+ << "\t\t real_t ct = cos(theta);\n"
+ << "\t\t real_t st = sin(theta);\n"
+ << "\n"
+ << "\t\t vOut.x = (Cx + ct * Lx3 + st * Ly3) * " << weight << ";\n"
+ << "\t\t vOut.y = (Cy - st * Lx3 + ct * Ly3) * " << weight << ";\n"
+ << "\t\t }\n"
+ << "\t\t}\n"
+ << "\t\tvOut.z = " << DefaultZCl()
+ << "\t}\n";
+ return ss.str();
+ }
+
+ virtual void Precalc() override
+ {
+ m_G2 = SQR(m_Gain);
+ m_InvCellSize = 1 / Zeps(m_CellSize);
+ m_SpaceSq = SQR(m_Space);
+ m_HalfCellSizeOver1pSpaceSq = T(0.5) * (m_CellSize / (1 + m_SpaceSq));
+ }
+
+ virtual vector OpenCLGlobalFuncNames() const override
+ {
+ return vector { "Zeps", "Fract", "HashShadertoy" };
+ }
+
+protected:
+ void Init()
+ {
+ string prefix = Prefix();
+ m_Params.clear();
+ m_Params.push_back(ParamWithName(&m_CellSize, prefix + "bwraps_rand_cellsize", 1));
+ m_Params.push_back(ParamWithName(&m_Space, prefix + "bwraps_rand_space"));
+ m_Params.push_back(ParamWithName(&m_Gain, prefix + "bwraps_rand_gain", 2));
+ m_Params.push_back(ParamWithName(&m_InnerTwist, prefix + "bwraps_rand_inner_twist"));
+ m_Params.push_back(ParamWithName(&m_OuterTwist, prefix + "bwraps_rand_outer_twist"));
+ m_Params.push_back(ParamWithName(&m_Symm, prefix + "bwraps_rand_symm"));
+ m_Params.push_back(ParamWithName(&m_Seed, prefix + "bwraps_rand_seed", 1));
+ m_Params.push_back(ParamWithName(true, &m_InvCellSize, prefix + "bwraps_rand_inv_cellsize"));//Precalc.
+ m_Params.push_back(ParamWithName(true, &m_G2, prefix + "bwraps_rand_g2"));
+ m_Params.push_back(ParamWithName(true, &m_SpaceSq, prefix + "bwraps_rand_space_sq"));
+ m_Params.push_back(ParamWithName(true, &m_HalfCellSizeOver1pSpaceSq, prefix + "bwraps_rand_half_cellsize_over_1_plus_space_sq"));
+ }
+
+private:
+ T m_CellSize;
+ T m_Space;
+ T m_Gain;
+ T m_InnerTwist;
+ T m_OuterTwist;
+ T m_Symm;
+ T m_Seed;
+ T m_InvCellSize;//Precalc.
+ T m_G2;
+ T m_SpaceSq;
+ T m_HalfCellSizeOver1pSpaceSq;
+};
+
///
/// BlurCircle.
///
@@ -2452,7 +2641,7 @@ public:
<< "\t\t{\n"
<< "\t\t if (MwcNext01(mwc) > (real_t)(0.5))\n"
<< "\t\t {\n"
- << "\t\t d = sqrt(r + vIn.x);\n"
+ << "\t\t d = Zeps(sqrt(r + vIn.x));\n"
<< "\t\t vOut.x = -(" << v2 << " * d);\n"
<< "\t\t vOut.y = -(" << v2 << " / d * vIn.y);\n"
<< "\t\t }\n"
@@ -2492,6 +2681,132 @@ private:
T m_V2;//Precalcs only, no params.
};
+///
+/// Glynnia2.
+/// By guagapunyaimel.
+///
+template
+class Glynnia2Variation : public ParametricVariation
+{
+public:
+ Glynnia2Variation(T weight = 1.0) : ParametricVariation("glynnia2", eVariationId::VAR_GLYNNIA2, weight, true, true)
+ {
+ Init();
+ }
+
+ PARVARCOPY(Glynnia2Variation)
+
+ virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
+ {
+ T d, r = helper.m_PrecalcSqrtSumSquares;
+
+ if (r > 0 && helper.In.y > 0)
+ {
+ if (rand.Frand01() > T(0.5))
+ {
+ d = std::sqrt(r + helper.In.x);
+ helper.Out.x = m_V2 * d;
+ helper.Out.y = -(m_V2 / d * helper.In.y);
+ }
+ else
+ {
+ d = r + helper.In.x;
+ r = m_Weight / std::sqrt(r * (SQR(helper.In.y) + SQR(d)));
+ helper.Out.x = r * d;
+ helper.Out.y = r * helper.In.y;
+ }
+ }
+ else
+ {
+ if (rand.Frand01() > T(0.5))
+ {
+ d = Zeps(std::sqrt(r + helper.In.x));
+ helper.Out.x = -(m_V2 * d);
+ helper.Out.y = -(m_V2 / d * helper.In.y);
+ }
+ else
+ {
+ d = r + helper.In.x;
+ r = m_Weight / Zeps(std::sqrt(r * (SQR(helper.In.y) + SQR(d))));
+ helper.Out.x = -(r * d);
+ helper.Out.y = r * helper.In.y;
+ }
+ }
+
+ helper.Out.z = DefaultZ(helper);
+ }
+
+ virtual string OpenCLString() const override
+ {
+ ostringstream ss, ss2;
+ intmax_t i = 0, varIndex = IndexInXform();
+ ss2 << "_" << XformIndexInEmber() << "]";
+ string index = ss2.str();
+ string weight = WeightDefineString();
+ string v2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalcs only, no params.
+ ss << "\t{\n"
+ << "\t\treal_t d, r = precalcSqrtSumSquares;\n"
+ << "\n"
+ << "\t\tif (r > 0 && vIn.y > 0)\n"
+ << "\t\t{\n"
+ << "\t\t if (MwcNext01(mwc) > (real_t)(0.5))\n"
+ << "\t\t {\n"
+ << "\t\t d = sqrt(r + vIn.x);\n"
+ << "\t\t vOut.x = " << v2 << " * d;\n"
+ << "\t\t vOut.y = -(" << v2 << " / d * vIn.y);\n"
+ << "\t\t }\n"
+ << "\t\t else\n"
+ << "\t\t {\n"
+ << "\t\t d = r + vIn.x;\n"
+ << "\t\t r = " << weight << " / sqrt(r * fma(vIn.y, vIn.y, SQR(d)));\n"
+ << "\t\t vOut.x = r * d;\n"
+ << "\t\t vOut.y = r * vIn.y;\n"
+ << "\t\t }\n"
+ << "\t\t}\n"
+ << "\t\telse\n"
+ << "\t\t{\n"
+ << "\t\t if (MwcNext01(mwc) > (real_t)(0.5))\n"
+ << "\t\t {\n"
+ << "\t\t d = Zeps(sqrt(r + vIn.x));\n"
+ << "\t\t vOut.x = -(" << v2 << " * d);\n"
+ << "\t\t vOut.y = -(" << v2 << " / d * vIn.y);\n"
+ << "\t\t }\n"
+ << "\t\t else\n"
+ << "\t\t {\n"
+ << "\t\t d = r + vIn.x;\n"
+ << "\t\t r = " << weight << " / Zeps(sqrt(r * fma(vIn.y, vIn.y, SQR(d))));\n"
+ << "\t\t vOut.x = -(r * d);\n"
+ << "\t\t vOut.y = r * vIn.y;\n"
+ << "\t\t }\n"
+ << "\t\t}\n"
+ << "\n"
+ << "\t\tvOut.z = " << DefaultZCl()
+ << "\t}\n";
+ return ss.str();
+ }
+
+ virtual void Precalc() override
+ {
+ m_V2 = m_Weight * std::sqrt(T(2)) / 2;
+ }
+
+ virtual vector OpenCLGlobalFuncNames() const override
+ {
+ return vector { "Zeps" };
+ }
+
+protected:
+ void Init()
+ {
+ string prefix = Prefix();
+ m_Params.clear();
+ m_Params.push_back(ParamWithName(true, &m_V2, prefix + "glynnia2_v2"));//Precalcs only, no params.
+ }
+
+private:
+ T m_V2;//Precalcs only, no params.
+};
+
///
/// GridOut.
///
@@ -5657,6 +5972,7 @@ private:
MAKEPREPOSTVAR(Hemisphere, hemisphere, HEMISPHERE)
MAKEPREPOSTPARVAR(Epispiral, epispiral, EPISPIRAL)
MAKEPREPOSTPARVAR(Bwraps, bwraps, BWRAPS)
+MAKEPREPOSTPARVAR(BwrapsRand, bwraps_rand, BWRAPS_RAND)
MAKEPREPOSTVARASSIGN(BlurCircle, blur_circle, BLUR_CIRCLE, eVariationAssignType::ASSIGNTYPE_SUM)
MAKEPREPOSTPARVAR(BlurZoom, blur_zoom, BLUR_ZOOM)
MAKEPREPOSTPARVAR(BlurPixelize, blur_pixelize, BLUR_PIXELIZE)
@@ -5686,6 +6002,7 @@ MAKEPREPOSTVAR(FDisc, fdisc, FDISC)
MAKEPREPOSTPARVAR(Fibonacci, fibonacci, FIBONACCI)
MAKEPREPOSTPARVAR(Fibonacci2, fibonacci2, FIBONACCI2)
MAKEPREPOSTPARVAR(Glynnia, glynnia, GLYNNIA)
+MAKEPREPOSTPARVAR(Glynnia2, glynnia2, GLYNNIA2)
MAKEPREPOSTVAR(GridOut, gridout, GRIDOUT)
MAKEPREPOSTPARVAR(Hole, hole, HOLE)
MAKEPREPOSTPARVAR(Hypertile, hypertile, HYPERTILE)
diff --git a/Source/Ember/Variations03.h b/Source/Ember/Variations03.h
index 71a8393..239dede 100644
--- a/Source/Ember/Variations03.h
+++ b/Source/Ember/Variations03.h
@@ -721,7 +721,7 @@ protected:
{
string prefix = Prefix();
m_Params.clear();
- m_Params.push_back(ParamWithName(&m_Radius, prefix + "GlynnSim2_radius", 1));
+ m_Params.push_back(ParamWithName(&m_Radius, prefix + "GlynnSim2_radius", 1, eParamType::REAL, 0));
m_Params.push_back(ParamWithName(&m_Thickness, prefix + "GlynnSim2_thickness", T(0.1), eParamType::REAL, 0, 1));
m_Params.push_back(ParamWithName(&m_Contrast, prefix + "GlynnSim2_contrast", T(0.5), eParamType::REAL, 0, 1));
m_Params.push_back(ParamWithName(&m_Pow, prefix + "GlynnSim2_pow", T(1.5)));
@@ -919,6 +919,219 @@ private:
T m_Gamma;
};
+///
+/// GlynnSim4.
+///
+template
+class GlynnSim4Variation : public ParametricVariation
+{
+public:
+ GlynnSim4Variation(T weight = 1.0) : ParametricVariation("GlynnSim4", eVariationId::VAR_GLYNNSIM4, weight, true, true)
+ {
+ Init();
+ }
+
+ PARVARCOPY(GlynnSim4Variation)
+
+ virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
+ {
+ if (helper.m_PrecalcSqrtSumSquares < m_Radius)
+ {
+ helper.Out.x = m_Weight * m_X;
+ helper.Out.y = m_Weight * m_Y;
+ }
+ else
+ {
+ T alpha = std::abs(m_Radius / Zeps(helper.m_PrecalcSqrtSumSquares));
+
+ if (rand.Frand01() > m_Contrast * std::pow(alpha, m_Pow))
+ {
+ helper.Out.x = m_Weight * helper.In.x;
+ helper.Out.y = m_Weight * helper.In.y;
+ }
+ else
+ {
+ helper.Out.x = m_Weight * SQR(alpha) * helper.In.x;
+ helper.Out.y = m_Weight * SQR(alpha) * helper.In.y;
+ }
+ }
+
+ helper.Out.z = DefaultZ(helper);
+ }
+
+ virtual string OpenCLString() const override
+ {
+ ostringstream ss, ss2;
+ intmax_t i = 0, varIndex = IndexInXform();
+ ss2 << "_" << XformIndexInEmber() << "]";
+ string index = ss2.str();
+ string weight = WeightDefineString();
+ string radius = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string contrast = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string pow = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
+ ss << "\t{\n"
+ << "\t\tif (precalcSqrtSumSquares < " << radius << ")\n"
+ << "\t\t{\n"
+ << "\t\t vOut.x = " << weight << " * " << x << ";\n"
+ << "\t\t vOut.y = " << weight << " * " << y << ";\n"
+ << "\t\t}\n"
+ << "\t\telse\n"
+ << "\t\t{\n"
+ << "\t\t real_t alpha = fabs(" << radius << " / Zeps(precalcSqrtSumSquares));\n"
+ << "\n"
+ << "\t\t if (MwcNext01(mwc) > " << contrast << " * pow(alpha, " << pow << "))\n"
+ << "\t\t {\n"
+ << "\t\t vOut.x = " << weight << " * vIn.x;\n"
+ << "\t\t vOut.y = " << weight << " * vIn.y;\n"
+ << "\t\t }\n"
+ << "\t\t else\n"
+ << "\t\t {\n"
+ << "\t\t vOut.x = " << weight << " * SQR(alpha) * vIn.x;\n"
+ << "\t\t vOut.y = " << weight << " * SQR(alpha) * vIn.y;\n"
+ << "\t\t }\n"
+ << "\t\t}\n"
+ << "\n"
+ << "\t\tvOut.z = " << DefaultZCl()
+ << "\t}\n";
+ return ss.str();
+ }
+
+ virtual vector OpenCLGlobalFuncNames() const override
+ {
+ return vector { "Zeps" };
+ }
+
+protected:
+ void Init()
+ {
+ string prefix = Prefix();
+ m_Params.clear();
+ m_Params.push_back(ParamWithName(&m_Radius, prefix + "GlynnSim4_radius", 1));
+ m_Params.push_back(ParamWithName