mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-01-21 05:00:06 -05:00
Features:
--Add support for Exr files which use 32-bit floats for each RGBA channel. Seems to come out too washed out. --Allow for clearing an individual color curve. --Allow for saving multiple image types in EmberRender and EmberAnimate. All writes are threaded. --Remove --bpc command line argument. Add format png16 as a replacement. --Remove --enable_jpg_comments and --enable_png_comments command line arguments, and replace them with --enable_comments which applies to jpg, png and exr. --Add menu items to variations and affine spinners which allow for easy entry of specific numeric values like pi. --Make final render dialog be wider rather than so tall. Bug fixes: --Fix some OpenCL compile errors on Mac. --Remove ability to save bitmap files on all platforms but Windows. Code changes: --New dependency on OpenEXR. --Allow Curves class to interact with objects of a different template type. --Make m_Curves member of Ember always use float as template type. --Set the length of the curves array to always be 2^17 which should offer enough precision with new 32-bit float pixel types. --Set pixel types to always be 32-bit float. This results in a major reduction of code in the final accumulation part of Renderer.h/cpp. --Remove corresponding code from RendererCL and FinalAccumOpenCLKernelCreator. --Remove Transparency, NumChannels and BytesPerPixel setters from Renderer.h/cpp. --Add new global functions to format final image buffers and place all alpha calculation and scaling code in them. --Blending is no longer needed in OpenGLWidget because of the new pixel type. --Make new class, AffineDoubleSpinBox. --Attempt to make file save dialog code work the same on all OSes. --Remove some unused functions.
This commit is contained in:
parent
d5760e451a
commit
de613404de
160
.gitignore
vendored
160
.gitignore
vendored
@ -89,3 +89,163 @@ Builds/include/GL
|
||||
/Builds/MSVC/VS2013/flam3-palettes.xml
|
||||
/Builds/MSVC/VS2015/flam3-palettes.xml
|
||||
*.dmg
|
||||
/Deps/include/OpenEXR/OpenEXRConfig.h
|
||||
/Deps/include/OpenEXR/ImfXdr.h
|
||||
/Deps/include/OpenEXR/ImfWav.h
|
||||
/Deps/include/OpenEXR/ImfVersion.h
|
||||
/Deps/include/OpenEXR/ImfVecAttribute.h
|
||||
/Deps/include/OpenEXR/ImfTimeCodeAttribute.h
|
||||
/Deps/include/OpenEXR/ImfTimeCode.h
|
||||
/Deps/include/OpenEXR/ImfTiledRgbaFile.h
|
||||
/Deps/include/OpenEXR/ImfTiledOutputPart.h
|
||||
/Deps/include/OpenEXR/ImfTiledOutputFile.h
|
||||
/Deps/include/OpenEXR/ImfTiledInputPart.h
|
||||
/Deps/include/OpenEXR/ImfTiledInputFile.h
|
||||
/Deps/include/OpenEXR/ImfTileDescriptionAttribute.h
|
||||
/Deps/include/OpenEXR/ImfTileDescription.h
|
||||
/Deps/include/OpenEXR/ImfThreading.h
|
||||
/Deps/include/OpenEXR/ImfTestFile.h
|
||||
/Deps/include/OpenEXR/ImfStringVectorAttribute.h
|
||||
/Deps/include/OpenEXR/ImfStringAttribute.h
|
||||
/Deps/include/OpenEXR/ImfStandardAttributes.h
|
||||
/Deps/include/OpenEXR/ImfSampleCountChannel.h
|
||||
/Deps/include/OpenEXR/ImfRgbaYca.h
|
||||
/Deps/include/OpenEXR/ImfRgbaFile.h
|
||||
/Deps/include/OpenEXR/ImfRgba.h
|
||||
/Deps/include/OpenEXR/ImfRationalAttribute.h
|
||||
/Deps/include/OpenEXR/ImfRational.h
|
||||
/Deps/include/OpenEXR/ImfPreviewImageAttribute.h
|
||||
/Deps/include/OpenEXR/ImfPreviewImage.h
|
||||
/Deps/include/OpenEXR/ImfPixelType.h
|
||||
/Deps/include/OpenEXR/ImfPartType.h
|
||||
/Deps/include/OpenEXR/ImfPartHelper.h
|
||||
/Deps/include/OpenEXR/ImfOutputPart.h
|
||||
/Deps/include/OpenEXR/ImfOutputFile.h
|
||||
/Deps/include/OpenEXR/ImfOpaqueAttribute.h
|
||||
/Deps/include/OpenEXR/ImfNamespace.h
|
||||
/Deps/include/OpenEXR/ImfName.h
|
||||
/Deps/include/OpenEXR/ImfMultiView.h
|
||||
/Deps/include/OpenEXR/ImfMultiPartOutputFile.h
|
||||
/Deps/include/OpenEXR/ImfMultiPartInputFile.h
|
||||
/Deps/include/OpenEXR/ImfMisc.h
|
||||
/Deps/include/OpenEXR/ImfMatrixAttribute.h
|
||||
/Deps/include/OpenEXR/ImfLut.h
|
||||
/Deps/include/OpenEXR/ImfLineOrderAttribute.h
|
||||
/Deps/include/OpenEXR/ImfLineOrder.h
|
||||
/Deps/include/OpenEXR/ImfKeyCodeAttribute.h
|
||||
/Deps/include/OpenEXR/ImfKeyCode.h
|
||||
/Deps/include/OpenEXR/ImfIO.h
|
||||
/Deps/include/OpenEXR/ImfIntAttribute.h
|
||||
/Deps/include/OpenEXR/ImfInt64.h
|
||||
/Deps/include/OpenEXR/ImfInputPart.h
|
||||
/Deps/include/OpenEXR/ImfInputFile.h
|
||||
/Deps/include/OpenEXR/ImfImageLevel.h
|
||||
/Deps/include/OpenEXR/ImfImageIO.h
|
||||
/Deps/include/OpenEXR/ImfImageDataWindow.h
|
||||
/Deps/include/OpenEXR/ImfImageChannelRenaming.h
|
||||
/Deps/include/OpenEXR/ImfImageChannel.h
|
||||
/Deps/include/OpenEXR/ImfImage.h
|
||||
/Deps/include/OpenEXR/ImfHuf.h
|
||||
/Deps/include/OpenEXR/ImfHeader.h
|
||||
/Deps/include/OpenEXR/ImfGenericOutputFile.h
|
||||
/Deps/include/OpenEXR/ImfGenericInputFile.h
|
||||
/Deps/include/OpenEXR/ImfFramesPerSecond.h
|
||||
/Deps/include/OpenEXR/ImfFrameBuffer.h
|
||||
/Deps/include/OpenEXR/ImfForward.h
|
||||
/Deps/include/OpenEXR/ImfFloatVectorAttribute.h
|
||||
/Deps/include/OpenEXR/ImfFloatAttribute.h
|
||||
/Deps/include/OpenEXR/ImfFlatImageLevel.h
|
||||
/Deps/include/OpenEXR/ImfFlatImageIO.h
|
||||
/Deps/include/OpenEXR/ImfFlatImageChannel.h
|
||||
/Deps/include/OpenEXR/ImfFlatImage.h
|
||||
/Deps/include/OpenEXR/ImfExport.h
|
||||
/Deps/include/OpenEXR/ImfEnvmapAttribute.h
|
||||
/Deps/include/OpenEXR/ImfEnvmap.h
|
||||
/Deps/include/OpenEXR/ImfDoubleAttribute.h
|
||||
/Deps/include/OpenEXR/ImfDeepTiledOutputPart.h
|
||||
/Deps/include/OpenEXR/ImfDeepTiledOutputFile.h
|
||||
/Deps/include/OpenEXR/ImfDeepTiledInputPart.h
|
||||
/Deps/include/OpenEXR/ImfDeepTiledInputFile.h
|
||||
/Deps/include/OpenEXR/ImfDeepScanLineOutputPart.h
|
||||
/Deps/include/OpenEXR/ImfDeepScanLineOutputFile.h
|
||||
/Deps/include/OpenEXR/ImfDeepScanLineInputPart.h
|
||||
/Deps/include/OpenEXR/ImfDeepScanLineInputFile.h
|
||||
/Deps/include/OpenEXR/ImfDeepImageStateAttribute.h
|
||||
/Deps/include/OpenEXR/ImfDeepImageState.h
|
||||
/Deps/include/OpenEXR/ImfDeepImageLevel.h
|
||||
/Deps/include/OpenEXR/ImfDeepImageIO.h
|
||||
/Deps/include/OpenEXR/ImfDeepImageChannel.h
|
||||
/Deps/include/OpenEXR/ImfDeepImage.h
|
||||
/Deps/include/OpenEXR/ImfDeepFrameBuffer.h
|
||||
/Deps/include/OpenEXR/ImfDeepCompositing.h
|
||||
/Deps/include/OpenEXR/ImfCRgbaFile.h
|
||||
/Deps/include/OpenEXR/ImfConvert.h
|
||||
/Deps/include/OpenEXR/ImfCompressionAttribute.h
|
||||
/Deps/include/OpenEXR/ImfCompression.h
|
||||
/Deps/include/OpenEXR/ImfCompositeDeepScanLine.h
|
||||
/Deps/include/OpenEXR/ImfChromaticitiesAttribute.h
|
||||
/Deps/include/OpenEXR/ImfChromaticities.h
|
||||
/Deps/include/OpenEXR/ImfChannelListAttribute.h
|
||||
/Deps/include/OpenEXR/ImfChannelList.h
|
||||
/Deps/include/OpenEXR/ImfBoxAttribute.h
|
||||
/Deps/include/OpenEXR/ImfB44Compressor.h
|
||||
/Deps/include/OpenEXR/ImfAttribute.h
|
||||
/Deps/include/OpenEXR/ImfArray.h
|
||||
/Deps/include/OpenEXR/ImfAcesFile.h
|
||||
/Deps/include/OpenEXR/ImathVecAlgo.h
|
||||
/Deps/include/OpenEXR/ImathVec.h
|
||||
/Deps/include/OpenEXR/ImathSphere.h
|
||||
/Deps/include/OpenEXR/ImathShear.h
|
||||
/Deps/include/OpenEXR/ImathRoots.h
|
||||
/Deps/include/OpenEXR/ImathRandom.h
|
||||
/Deps/include/OpenEXR/ImathQuat.h
|
||||
/Deps/include/OpenEXR/ImathPlatform.h
|
||||
/Deps/include/OpenEXR/ImathPlane.h
|
||||
/Deps/include/OpenEXR/ImathNamespace.h
|
||||
/Deps/include/OpenEXR/ImathMatrixAlgo.h
|
||||
/Deps/include/OpenEXR/ImathMatrix.h
|
||||
/Deps/include/OpenEXR/ImathMath.h
|
||||
/Deps/include/OpenEXR/ImathLineAlgo.h
|
||||
/Deps/include/OpenEXR/ImathLine.h
|
||||
/Deps/include/OpenEXR/ImathLimits.h
|
||||
/Deps/include/OpenEXR/ImathInterval.h
|
||||
/Deps/include/OpenEXR/ImathInt64.h
|
||||
/Deps/include/OpenEXR/ImathHalfLimits.h
|
||||
/Deps/include/OpenEXR/ImathGLU.h
|
||||
/Deps/include/OpenEXR/ImathGL.h
|
||||
/Deps/include/OpenEXR/ImathFun.h
|
||||
/Deps/include/OpenEXR/ImathFrustumTest.h
|
||||
/Deps/include/OpenEXR/ImathFrustum.h
|
||||
/Deps/include/OpenEXR/ImathFrame.h
|
||||
/Deps/include/OpenEXR/ImathForward.h
|
||||
/Deps/include/OpenEXR/ImathExport.h
|
||||
/Deps/include/OpenEXR/ImathExc.h
|
||||
/Deps/include/OpenEXR/ImathEuler.h
|
||||
/Deps/include/OpenEXR/ImathColorAlgo.h
|
||||
/Deps/include/OpenEXR/ImathColor.h
|
||||
/Deps/include/OpenEXR/ImathBoxAlgo.h
|
||||
/Deps/include/OpenEXR/ImathBox.h
|
||||
/Deps/include/OpenEXR/IlmThreadSemaphore.h
|
||||
/Deps/include/OpenEXR/IlmThreadPool.h
|
||||
/Deps/include/OpenEXR/IlmThreadNamespace.h
|
||||
/Deps/include/OpenEXR/IlmThreadMutex.h
|
||||
/Deps/include/OpenEXR/IlmThreadForward.h
|
||||
/Deps/include/OpenEXR/IlmThreadExport.h
|
||||
/Deps/include/OpenEXR/IlmThread.h
|
||||
/Deps/include/OpenEXR/IlmBaseConfig.h
|
||||
/Deps/include/OpenEXR/IexThrowErrnoExc.h
|
||||
/Deps/include/OpenEXR/IexNamespace.h
|
||||
/Deps/include/OpenEXR/IexMathIeeeExc.h
|
||||
/Deps/include/OpenEXR/IexMathFpu.h
|
||||
/Deps/include/OpenEXR/IexMathFloatExc.h
|
||||
/Deps/include/OpenEXR/IexMathExc.h
|
||||
/Deps/include/OpenEXR/IexMacros.h
|
||||
/Deps/include/OpenEXR/IexForward.h
|
||||
/Deps/include/OpenEXR/IexExport.h
|
||||
/Deps/include/OpenEXR/IexErrnoExc.h
|
||||
/Deps/include/OpenEXR/IexBaseExc.h
|
||||
/Deps/include/OpenEXR/Iex.h
|
||||
/Deps/include/OpenEXR/halfLimits.h
|
||||
/Deps/include/OpenEXR/halfFunction.h
|
||||
/Deps/include/OpenEXR/halfExport.h
|
||||
/Deps/include/OpenEXR/half.h
|
||||
|
@ -6,7 +6,7 @@
|
||||
<ProductVersion>3.7</ProductVersion>
|
||||
<ProjectGuid>{c8096c47-e358-438c-a520-146d46b0637d}</ProjectGuid>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<OutputName>Fractorium_1.0.0.4</OutputName>
|
||||
<OutputName>Fractorium_1.0.0.5</OutputName>
|
||||
<OutputType>Package</OutputType>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<?define ProductVersion="1.0.0.4" ?>
|
||||
<?define ProductVersion="1.0.0.5" ?>
|
||||
<?define ProductName="Fractorium $(var.ProductVersion) ($(var.GpuType))" ?>
|
||||
<?define UpgradeCode="{4714cd15-bfba-44f6-8059-9e1466ebfa6e}"?>
|
||||
<?define Manufacturer="Fractorium"?>
|
||||
@ -13,7 +13,7 @@
|
||||
<!--
|
||||
Change this for every release.
|
||||
-->
|
||||
<?define ProductCode="{344D73B1-F519-44CD-8F62-9FE6595816F9}"?>
|
||||
<?define ProductCode="{290BBFDC-BD1C-45F7-80AC-DE59BA4378F0}"?>
|
||||
|
||||
<Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="1033" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
|
||||
<Package
|
||||
|
Binary file not shown.
@ -49,8 +49,8 @@
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1, 0, 0, 4
|
||||
PRODUCTVERSION 1, 0, 0, 4
|
||||
FILEVERSION 1, 0, 0, 5
|
||||
PRODUCTVERSION 1, 0, 0, 5
|
||||
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.4"
|
||||
VALUE "FileVersion", "1.0.0.5"
|
||||
VALUE "InternalName", "EmberAnimate.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2017, GPL v3"
|
||||
VALUE "OriginalFilename", "EmberAnimate.exe"
|
||||
VALUE "ProductName", "Ember Animate"
|
||||
VALUE "ProductVersion", "1.0.0.4"
|
||||
VALUE "ProductVersion", "1.0.0.5"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -58,7 +58,7 @@
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ProgramDataBaseFileName>$(TargetDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(ProjectDir)..\..\..\Deps\include\OpenEXR;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>
|
||||
</DisableSpecificWarnings>
|
||||
<PrecompiledHeaderFile>EmberCommonPch.h</PrecompiledHeaderFile>
|
||||
@ -72,7 +72,7 @@
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;Half.lib;Iex.lib;IlmImf.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\Deps;$(AMDAPPSDKROOT)\lib\x86_64;$(CUDA_PATH)\lib\$(PlatformName)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
@ -90,7 +90,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ProgramDataBaseFileName>$(TargetDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(ProjectDir)..\..\..\Deps\include\OpenEXR;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>
|
||||
</DisableSpecificWarnings>
|
||||
<PrecompiledHeaderFile>EmberCommonPch.h</PrecompiledHeaderFile>
|
||||
@ -105,7 +105,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;Half.lib;Iex.lib;IlmImf.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\Deps;$(AMDAPPSDKROOT)\lib\x86_64;$(CUDA_PATH)\lib\$(PlatformName)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
|
Binary file not shown.
@ -49,8 +49,8 @@
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1, 0, 0, 4
|
||||
PRODUCTVERSION 1, 0, 0, 4
|
||||
FILEVERSION 1, 0, 0, 5
|
||||
PRODUCTVERSION 1, 0, 0, 5
|
||||
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.4"
|
||||
VALUE "FileVersion", "1.0.0.5"
|
||||
VALUE "InternalName", "EmberGenome.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2017, GPL v3"
|
||||
VALUE "OriginalFilename", "EmberGenome.exe"
|
||||
VALUE "ProductName", "Ember Genome"
|
||||
VALUE "ProductVersion", "1.0.0.4"
|
||||
VALUE "ProductVersion", "1.0.0.5"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -58,7 +58,7 @@
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ProgramDataBaseFileName>$(TargetDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(ProjectDir)..\..\..\Deps\include\OpenEXR;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>
|
||||
</DisableSpecificWarnings>
|
||||
<PrecompiledHeaderFile>EmberCommonPch.h</PrecompiledHeaderFile>
|
||||
@ -72,7 +72,7 @@
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;Half.lib;Iex.lib;IlmImf.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\Deps;$(AMDAPPSDKROOT)\lib\x86_64;$(CUDA_PATH)\lib\$(PlatformName)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
@ -90,7 +90,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ProgramDataBaseFileName>$(TargetDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(ProjectDir)..\..\..\Deps\include\OpenEXR;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>
|
||||
</DisableSpecificWarnings>
|
||||
<PrecompiledHeaderFile>EmberCommonPch.h</PrecompiledHeaderFile>
|
||||
@ -105,7 +105,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;Half.lib;Iex.lib;IlmImf.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\Deps;$(AMDAPPSDKROOT)\lib\x86_64;$(CUDA_PATH)\lib\$(PlatformName)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
|
@ -49,8 +49,8 @@
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1, 0, 0, 4
|
||||
PRODUCTVERSION 1, 0, 0, 4
|
||||
FILEVERSION 1, 0, 0, 5
|
||||
PRODUCTVERSION 1, 0, 0, 5
|
||||
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.4"
|
||||
VALUE "FileVersion", "1.0.0.5"
|
||||
VALUE "InternalName", "EmberRender.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2017, GPL v3"
|
||||
VALUE "OriginalFilename", "EmberRender.exe"
|
||||
VALUE "ProductName", "Ember Render"
|
||||
VALUE "ProductVersion", "1.0.0.4"
|
||||
VALUE "ProductVersion", "1.0.0.5"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -58,7 +58,7 @@
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ProgramDataBaseFileName>$(TargetDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(ProjectDir)..\..\..\Deps\include\OpenEXR;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>
|
||||
</DisableSpecificWarnings>
|
||||
<PrecompiledHeaderFile>EmberCommonPch.h</PrecompiledHeaderFile>
|
||||
@ -72,7 +72,7 @@
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;Half.lib;Iex.lib;IlmImf.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\Deps;$(AMDAPPSDKROOT)\lib\x86_64;$(CUDA_PATH)\lib\$(PlatformName)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
@ -90,7 +90,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ProgramDataBaseFileName>$(TargetDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(ProjectDir)..\..\..\Deps\include\OpenEXR;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>
|
||||
</DisableSpecificWarnings>
|
||||
<PrecompiledHeaderFile>EmberCommonPch.h</PrecompiledHeaderFile>
|
||||
@ -106,7 +106,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;Half.lib;Iex.lib;IlmImf.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\Deps;$(AMDAPPSDKROOT)\lib\x86_64;$(CUDA_PATH)\lib\$(PlatformName)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
|
@ -56,9 +56,9 @@
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;OPENEXR_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ProgramDataBaseFileName>$(TargetDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(ProjectDir)..\..\..\Deps\include\OpenEXR;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>
|
||||
</DisableSpecificWarnings>
|
||||
<PrecompiledHeaderFile>EmberCommonPch.h</PrecompiledHeaderFile>
|
||||
@ -72,7 +72,7 @@
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;opencl.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;Half.lib;IlmImf.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\Deps;$(AMDAPPSDKROOT)\lib\x86_64;$(CUDA_PATH)\lib\$(PlatformName)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
@ -88,9 +88,9 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;OPENEXR_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ProgramDataBaseFileName>$(TargetDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(ProjectDir)..\..\..\Deps\include\OpenEXR;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>
|
||||
</DisableSpecificWarnings>
|
||||
<PrecompiledHeaderFile>EmberCommonPch.h</PrecompiledHeaderFile>
|
||||
@ -105,7 +105,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;opencl.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;Half.lib;IlmImf.lib;opencl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\Deps;$(AMDAPPSDKROOT)\lib\x86_64;$(CUDA_PATH)\lib\$(PlatformName)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
|
Binary file not shown.
@ -57,7 +57,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>UNICODE;WIN32;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_MULTIMEDIA_LIB;QT_HELP_LIB;QT_OPENGL_LIB;QT_WIDGETS_LIB;QT_XML_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;.\PaletteEditor;$(QTDIR)\include;$(ProjectDir)..\..\..\Fractorium\GeneratedFiles;$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName;$(QTDIR)\..\qtmultimedia\include\QtMultimedia;$(QTDIR)\..\qtmultimedia\include;$(QTDIR)\..\qttools\include;$(QTDIR)\..\qttools\include\QtHelp;$(QTDIR)\include\QtConcurrent;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtOpenGL;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtXml;.\GeneratedFiles;$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\Fractorium;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include;.\GeneratedFiles\$(ConfigurationName);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.;.\PaletteEditor;$(QTDIR)\include;$(ProjectDir)..\..\..\Fractorium\GeneratedFiles;$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName;$(QTDIR)\..\qtmultimedia\include\QtMultimedia;$(QTDIR)\..\qtmultimedia\include;$(QTDIR)\..\qttools\include;$(QTDIR)\..\qttools\include\QtHelp;$(QTDIR)\include\QtConcurrent;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtOpenGL;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtXml;.\GeneratedFiles;$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\Fractorium;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(ProjectDir)..\..\..\Deps\include\OpenEXR;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include;.\GeneratedFiles\$(ConfigurationName);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
@ -81,7 +81,7 @@
|
||||
<OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\Deps;$(QTDIR)\lib;$(AMDAPPSDKROOT)\lib\x86_64;$(CUDA_PATH)\lib\$(PlatformName);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5OpenGLd.lib;opengl32.lib;glu32.lib;opencl.lib;Qt5Widgetsd.lib;Qt5Xmld.lib;Ws2_32.lib;libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5OpenGLd.lib;opengl32.lib;glu32.lib;opencl.lib;Qt5Widgetsd.lib;Qt5Xmld.lib;Ws2_32.lib;libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;Half.lib;Iex.lib;IlmImf.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Deps\*.dll" "$(OutDir)"
|
||||
@ -102,7 +102,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\tatasz_pack_02_dark.gradient" "$(
|
||||
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\dark.qss" "$(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)"
|
||||
@ -115,7 +115,7 @@ xcopy /F /Y /R /D "$(QTDIR)\plugins\platforms\qwindowsd.dll" "$(OutDir)\platform
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>UNICODE;WIN32;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_MULTIMEDIA_LIB;QT_HELP_LIB;QT_OPENGL_LIB;QT_WIDGETS_LIB;QT_XML_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;.\PaletteEditor;$(QTDIR)\include;$(ProjectDir)..\..\..\Fractorium\GeneratedFiles;$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName;$(QTDIR)\..\qtmultimedia\include\QtMultimedia;$(QTDIR)\..\qtmultimedia\include;$(QTDIR)\..\qttools\include;$(QTDIR)\..\qttools\include\QtHelp;$(QTDIR)\include\QtConcurrent;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtOpenGL;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtXml;.\GeneratedFiles;$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\Fractorium;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include;.\GeneratedFiles\$(ConfigurationName);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.;.\PaletteEditor;$(QTDIR)\include;$(ProjectDir)..\..\..\Fractorium\GeneratedFiles;$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName;$(QTDIR)\..\qtmultimedia\include\QtMultimedia;$(QTDIR)\..\qtmultimedia\include;$(QTDIR)\..\qttools\include;$(QTDIR)\..\qttools\include\QtHelp;$(QTDIR)\include\QtConcurrent;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtOpenGL;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtXml;.\GeneratedFiles;$(ProjectDir)..\..\..\Source\Ember;$(ProjectDir)..\..\..\Source\EmberCL;$(ProjectDir)..\..\..\Source\EmberCommon;$(ProjectDir)..\..\..\Source\Fractorium;$(ProjectDir)..\..\..\..\glm;$(ProjectDir)..\..\..\..\tbb\include;$(ProjectDir)..\..\..\..\libjpeg;$(ProjectDir)..\..\..\..\libpng;$(ProjectDir)..\..\..\..\libxml2\include;$(ProjectDir)..\..\..\Deps\include\OpenEXR;$(AMDAPPSDKROOT)\include;$(CUDA_PATH)\include;.\GeneratedFiles\$(ConfigurationName);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
|
||||
@ -138,7 +138,7 @@ xcopy /F /Y /R /D "$(QTDIR)\plugins\platforms\qwindowsd.dll" "$(OutDir)\platform
|
||||
<OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\Deps;$(QTDIR)\lib;$(AMDAPPSDKROOT)\lib\x86_64;$(CUDA_PATH)\lib\$(PlatformName);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>qtmain.lib;Qt5Core.lib;Qt5Gui.lib;Qt5OpenGL.lib;opengl32.lib;glu32.lib;opencl.lib;Qt5Widgets.lib;Ws2_32.lib;libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>qtmain.lib;Qt5Core.lib;Qt5Gui.lib;Qt5OpenGL.lib;opengl32.lib;glu32.lib;opencl.lib;Qt5Widgets.lib;Ws2_32.lib;libjpeg.lib;libpng.lib;libxml2.lib;tbb.lib;zlib.lib;Half.lib;Iex.lib;IlmImf.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<Version>0.1</Version>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
@ -160,7 +160,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\tatasz_pack_02_dark.gradient" "$(
|
||||
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\dark.qss" "$(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)"
|
||||
|
@ -1,6 +1,7 @@
|
||||
VERSION = 1.0.0.4
|
||||
VERSION = 1.0.0.5
|
||||
win32:CONFIG += skip_target_version_ext
|
||||
CONFIG += c++14
|
||||
|
||||
#message(PWD: $$absolute_path($$PWD))
|
||||
|
||||
#1) Declare the root of all files in this project, everything else will be
|
||||
@ -26,7 +27,7 @@ SRC_DIR = $$EMBER_ROOT/Source
|
||||
SRC_COMMON_DIR = $$absolute_path($$EMBER_ROOT/Source/EmberCommon)
|
||||
ASSETS_DIR = $$absolute_path($$EMBER_ROOT/Data)
|
||||
QTCREATOR_DIR = $$absolute_path($$EMBER_ROOT/Builds/QtCreator)
|
||||
win32:RCPATH=$$absolute_path($$QTCREATOR_DIR/../MSVC/VS2013)
|
||||
win32:RCPATH=$$absolute_path($$QTCREATOR_DIR/../MSVC/VS2015)
|
||||
|
||||
#4) Add up all include paths.
|
||||
INCLUDEPATH += $$LOCAL_INCLUDE_DIR
|
||||
@ -41,6 +42,7 @@ win32 {
|
||||
INCLUDEPATH += $$EXTERNAL_DIR/libxml2/include
|
||||
INCLUDEPATH += $$EXTERNAL_DIR/tbb/include
|
||||
INCLUDEPATH += $$EXTERNAL_DIR/zlib
|
||||
INCLUDEPATH += $$absolute_path($$EXTERNAL_LIB)/include/OpenEXR
|
||||
}
|
||||
|
||||
!win32 {
|
||||
@ -51,6 +53,7 @@ win32 {
|
||||
INCLUDEPATH += /usr/local/include/GL
|
||||
INCLUDEPATH += /usr/include/glm
|
||||
INCLUDEPATH += /usr/include/tbb
|
||||
INCLUDEPATH += /usr/include/OpenEXR
|
||||
|
||||
unix:!macx {
|
||||
INCLUDEPATH += /usr/include/libxml2
|
||||
@ -82,6 +85,9 @@ else {
|
||||
LIBS += $$absolute_path($$EXTERNAL_LIB)/libxml2.lib
|
||||
LIBS += $$absolute_path($$EXTERNAL_LIB)/tbb.lib
|
||||
LIBS += $$absolute_path($$EXTERNAL_LIB)/zlib.lib
|
||||
LIBS += $$absolute_path($$EXTERNAL_LIB)/Half.lib
|
||||
LIBS += $$absolute_path($$EXTERNAL_LIB)/Iex.lib
|
||||
LIBS += $$absolute_path($$EXTERNAL_LIB)/IlmImf.lib
|
||||
}
|
||||
|
||||
!win32 {
|
||||
@ -89,6 +95,9 @@ else {
|
||||
LIBS += -lpng
|
||||
LIBS += -ltbb
|
||||
LIBS += -lpthread
|
||||
LIBS += -lHalf
|
||||
LIBS += -lIex
|
||||
LIBS += -lIlmImf
|
||||
|
||||
unix:!macx {
|
||||
LIBS += -lxml2
|
||||
@ -242,6 +251,26 @@ win32 {
|
||||
tbb.path = $$BIN_INSTALL_DIR
|
||||
tbb.files = $$absolute_path($$EMBER_ROOT/Deps/tbb.dll)
|
||||
INSTALLS += tbb
|
||||
|
||||
half.path = $$BIN_INSTALL_DIR
|
||||
half.files = $$absolute_path($$EMBER_ROOT/Deps/Half.dll)
|
||||
INSTALLS += half
|
||||
|
||||
iex.path = $$BIN_INSTALL_DIR
|
||||
iex.files = $$absolute_path($$EMBER_ROOT/Deps/Iex-2_2.dll)
|
||||
INSTALLS += iex
|
||||
|
||||
imath.path = $$BIN_INSTALL_DIR
|
||||
imath.files = $$absolute_path($$EMBER_ROOT/Deps/Imath-2_2.dll)
|
||||
INSTALLS += imath
|
||||
|
||||
ilmthread.path = $$BIN_INSTALL_DIR
|
||||
ilmthread.files = $$absolute_path($$EMBER_ROOT/Deps/IlmThread-2_2.dll)
|
||||
INSTALLS += ilmthread
|
||||
|
||||
ilmimf.path = $$BIN_INSTALL_DIR
|
||||
ilmimf.files = $$absolute_path($$EMBER_ROOT/Deps/IlmImf-2_2.dll)
|
||||
INSTALLS += ilmimf
|
||||
}
|
||||
|
||||
#11) Print values of relevant variables for debugging.
|
||||
|
@ -85,7 +85,8 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="curves">The Curves object to add</param>
|
||||
/// <returns>Reference to updated self</returns>
|
||||
Curves<T>& operator += (const Curves<T>& curves)
|
||||
template <typename U>
|
||||
Curves<T>& operator += (const Curves<U>& curves)
|
||||
{
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
@ -93,8 +94,7 @@ public:
|
||||
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];
|
||||
m_Weights[i] += curves.m_Weights[i];
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -105,7 +105,8 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="curves">The Curves object to multiply this one by</param>
|
||||
/// <returns>Reference to updated self</returns>
|
||||
Curves<T>& operator *= (const Curves<T>& curves)
|
||||
template <typename U>
|
||||
Curves<T>& operator *= (const Curves<U>& curves)
|
||||
{
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
@ -113,8 +114,7 @@ public:
|
||||
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];
|
||||
m_Weights[i] *= curves.m_Weights[i];
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -125,16 +125,16 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="t">The scalar to multiply this object by</param>
|
||||
/// <returns>Reference to updated self</returns>
|
||||
Curves<T>& operator *= (const T& t)
|
||||
template <typename U>
|
||||
Curves<T>& operator *= (const U& t)
|
||||
{
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
m_Points[i][0] *= t;
|
||||
m_Points[i][1] *= t;
|
||||
m_Points[i][2] *= t;
|
||||
m_Points[i][3] *= t;
|
||||
|
||||
m_Weights[i] *= t;
|
||||
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);
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -151,7 +151,21 @@ public:
|
||||
m_Points[i][1] = v2T(0);
|
||||
m_Points[i][2] = v2T(1);
|
||||
m_Points[i][3] = v2T(1);
|
||||
m_Weights[i] = v4T(1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the a specific curve and its weight value to their default state.
|
||||
/// </summary>
|
||||
void Init(size_t i)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -176,9 +190,9 @@ public:
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
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(0)) ||
|
||||
(m_Points[i][2] != v2T(1)) ||
|
||||
(m_Points[i][3] != v2T(1)))
|
||||
{
|
||||
set = true;
|
||||
break;
|
||||
@ -197,12 +211,10 @@ public:
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -217,20 +229,14 @@ private:
|
||||
/// <param name="solution">The vec2 to store the solution in</param>
|
||||
void BezierSolve(const T& t, v2T* src, v4T* w, v2T& solution)
|
||||
{
|
||||
T s, s2, s3, t2, t3, nom_x, nom_y, denom;
|
||||
|
||||
s = 1 - t;
|
||||
s2 = s * s;
|
||||
s3 = s * s * s;
|
||||
t2 = t * t;
|
||||
t3 = 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);
|
||||
|
||||
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);
|
||||
|
||||
denom = (w->x * s3) + (w->y * s2 * 3 * t) + (w->z * s * 3 * t2) + (w->w * t3);
|
||||
|
||||
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;
|
||||
@ -247,24 +253,24 @@ public:
|
||||
//Must declare this outside of the class to provide for both orders of parameters.
|
||||
|
||||
/// <summary>
|
||||
/// Multiplication operator to multiply a Curves<T> object by a scalar of type T.
|
||||
/// Multiplication operator to multiply a Curves<T> object by a scalar of type U.
|
||||
/// </summary>
|
||||
/// <param name="curves">The curves object to multiply</param>
|
||||
/// <param name="t">The scalar to multiply curves by by</param>
|
||||
/// <returns>Copy of new Curves<T></returns>
|
||||
template<typename T>
|
||||
Curves<T> operator * (const Curves<T>& curves, const T& t)
|
||||
template <typename T, typename U>
|
||||
Curves<T> operator * (const Curves<T>& curves, const U& t)
|
||||
{
|
||||
T tt = T(t);
|
||||
Curves<T> c(curves);
|
||||
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
c.m_Points[i][0] *= t;
|
||||
c.m_Points[i][1] *= t;
|
||||
c.m_Points[i][2] *= t;
|
||||
c.m_Points[i][3] *= t;
|
||||
|
||||
c.m_Weights[i] *= t;
|
||||
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;
|
||||
}
|
||||
|
||||
return c;
|
||||
@ -276,8 +282,8 @@ Curves<T> operator * (const Curves<T>& curves, const T& t)
|
||||
/// <param name="t">The scalar to multiply curves by by</param>
|
||||
/// <param name="curves">The curves object to multiply</param>
|
||||
/// <returns>Copy of new Curves<T></returns>
|
||||
template<typename T>
|
||||
Curves<T> operator * (const T& t, const Curves<T>& curves)
|
||||
template <typename T, typename U>
|
||||
Curves<T> operator * (const U& t, const Curves<T>& curves)
|
||||
{
|
||||
return curves * t;
|
||||
}
|
||||
|
@ -727,7 +727,7 @@ public:
|
||||
InterpT<&Ember<T>::m_MinRadDE>(embers, coefs, size);
|
||||
InterpT<&Ember<T>::m_CurveDE>(embers, coefs, size);
|
||||
InterpT<&Ember<T>::m_SpatialFilterRadius>(embers, coefs, size);
|
||||
InterpX<Curves<T>, &Ember<T>::m_Curves>(embers, coefs, size);
|
||||
InterpX<Curves<float>, &Ember<T>::m_Curves>(embers, coefs, size);
|
||||
//Normally done in assignment, must manually do here.
|
||||
SetProjFunc();
|
||||
//An extra step needed here due to the OOD that was not needed in the original.
|
||||
@ -1653,7 +1653,7 @@ public:
|
||||
Palette<float> m_Palette;//Final palette that is actually used is a copy of this inside of render, which will be of type bucketT (float).
|
||||
|
||||
//Curves used to adjust the color during final accumulation.
|
||||
Curves<T> m_Curves;
|
||||
Curves<float> m_Curves;
|
||||
|
||||
//Strings.
|
||||
|
||||
|
@ -37,7 +37,7 @@ static void sincos(float x, float* s, float* c)
|
||||
|
||||
namespace EmberNs
|
||||
{
|
||||
#define EMBER_VERSION "1.0.0.4"
|
||||
#define EMBER_VERSION "1.0.0.5"
|
||||
#define EPS6 T(1e-6)
|
||||
#define EPS std::numeric_limits<T>::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way.
|
||||
#define ISAAC_SIZE 4
|
||||
@ -68,6 +68,9 @@ namespace EmberNs
|
||||
#define TMAX std::numeric_limits<T>::max()
|
||||
#define FLOAT_MAX_TAN 8388607.0f
|
||||
#define FLOAT_MIN_TAN -FLOAT_MAX_TAN
|
||||
#define CURVES_LENGTH 131072
|
||||
#define CURVES_LENGTH_M1 131071.0f
|
||||
#define ONE_OVER_CURVES_LENGTH_M1 7.62945273935e-6f
|
||||
#define EMPTYFIELD -9999
|
||||
typedef std::chrono::high_resolution_clock Clock;
|
||||
typedef std::chrono::duration<double, std::ratio<1, 1000>> DoubleMs;
|
||||
@ -110,6 +113,7 @@ typedef std::lock_guard <std::recursive_mutex> rlg;
|
||||
#define m3T glm::tmat3x3<T, glm::defaultp>
|
||||
#define m4T glm::tmat4x4<T, glm::defaultp>
|
||||
#define m23T glm::tmat2x3<T, glm::defaultp>
|
||||
typedef vector<glm::tvec4<float, glm::defaultp>> vv4F;
|
||||
#else
|
||||
#define v2T glm::detail::tvec2<T, glm::defaultp>
|
||||
#define v3T glm::detail::tvec3<T, glm::defaultp>
|
||||
@ -121,6 +125,7 @@ typedef std::lock_guard <std::recursive_mutex> rlg;
|
||||
#define m3T glm::detail::tmat3x3<T, glm::defaultp>
|
||||
#define m4T glm::detail::tmat4x4<T, glm::defaultp>
|
||||
#define m23T glm::detail::tmat2x3<T, glm::defaultp>
|
||||
typedef vector<glm::detail::tvec4<float, glm::defaultp>> vv4F;
|
||||
#endif
|
||||
|
||||
enum class eInterp : et { EMBER_INTERP_LINEAR = 0, EMBER_INTERP_SMOOTH = 1 };
|
||||
|
@ -9,7 +9,9 @@ namespace EmberNs
|
||||
template <typename T, typename bucketT>
|
||||
Renderer<T, bucketT>::Renderer()
|
||||
{
|
||||
m_Csa.resize(size_t(std::pow(size_t(256), BytesPerChannel())));//Need to at least have something here so the derived RendererCL can do the initial buffer allocation.
|
||||
//Use a very large number regardless of the size of the output pixels. This should be sufficient granularity, even though
|
||||
//it's technically less than the number of distinct values representable by a 32-bit float.
|
||||
m_Csa.resize(size_t(CURVES_LENGTH));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -344,7 +346,7 @@ bool Renderer<T, bucketT>::CreateTemporalFilter(bool& newAlloc)
|
||||
/// <param name="finalOffset">Offset in finalImage to store the pixels to. Default: 0.</param>
|
||||
/// <returns>True if nothing went wrong, else false.</returns>
|
||||
template <typename T, typename bucketT>
|
||||
eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, size_t subBatchCountOverride, bool forceOutput, size_t finalOffset)
|
||||
eRenderStatus Renderer<T, bucketT>::Run(vector<v4F>& finalImage, double time, size_t subBatchCountOverride, bool forceOutput, size_t finalOffset)
|
||||
{
|
||||
m_InRender = true;
|
||||
EnterRender();
|
||||
@ -645,7 +647,7 @@ AccumOnly:
|
||||
CreateSpatialFilter(newFilterAlloc);
|
||||
m_DensityFilterOffset = m_GutterWidth - size_t(Clamp<T>((T(m_SpatialFilter->FinalFilterWidth()) - T(Supersample())) / 2, 0, T(m_GutterWidth)));
|
||||
m_CurvesSet = m_Ember.m_Curves.CurvesSet();
|
||||
ComputeCurves(true);//Color curves must be re-calculated as well.
|
||||
ComputeCurves();//Color curves must be re-calculated as well.
|
||||
|
||||
if (AccumulatorToFinalImage(finalImage, finalOffset) == eRenderStatus::RENDER_OK)
|
||||
{
|
||||
@ -822,6 +824,7 @@ bool Renderer<T, bucketT>::ResetBuckets(bool resetHist, bool resetAccum)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// THIS IS UNUSED.
|
||||
/// Log scales a single row with a specially structured loop that will be vectorized by the compiler.
|
||||
/// Note this adds an epsilon to the denomiator used to compute the logScale
|
||||
/// value because the conditional check for zero would have prevented the loop from
|
||||
@ -882,7 +885,7 @@ eRenderStatus Renderer<T, bucketT>::LogScaleDensityFilter(bool forceOutput)
|
||||
bucketT* __restrict hist = glm::value_ptr(m_HistBuckets[i]);//Vectorizer can't tell these point to different locations.
|
||||
bucketT* __restrict acc = glm::value_ptr(m_AccumulatorBuckets[i]);
|
||||
|
||||
for (size_t v = 0; v < 4; v++)
|
||||
for (size_t v = 0; v < 4; v++)//Vectorized by compiler.
|
||||
acc[v] = hist[v] * logScale;
|
||||
}
|
||||
}
|
||||
@ -1063,7 +1066,7 @@ eRenderStatus Renderer<T, bucketT>::GaussianDensityFilter()
|
||||
/// <param name="finalOffset">Offset in the buffer to store the pixels to</param>
|
||||
/// <returns>True if not prematurely aborted, else false.</returns>
|
||||
template <typename T, typename bucketT>
|
||||
eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(vector<byte>& pixels, size_t finalOffset)
|
||||
eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(vector<v4F>& pixels, size_t finalOffset)
|
||||
{
|
||||
if (PrepFinalAccumVector(pixels))
|
||||
return AccumulatorToFinalImage(pixels.data(), finalOffset);
|
||||
@ -1079,14 +1082,13 @@ eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(vector<byte>& pixels
|
||||
/// <param name="finalOffset">Offset in the buffer to store the pixels to. Default: 0.</param>
|
||||
/// <returns>True if not prematurely aborted, else false.</returns>
|
||||
template <typename T, typename bucketT>
|
||||
eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(byte* pixels, size_t finalOffset)
|
||||
eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(v4F* pixels, size_t finalOffset)
|
||||
{
|
||||
if (!pixels)
|
||||
return eRenderStatus::RENDER_ERROR;
|
||||
|
||||
EnterFinalAccum();
|
||||
//Timing t(4);
|
||||
bool doAlpha = NumChannels() > 3;
|
||||
size_t filterWidth = m_SpatialFilter->FinalFilterWidth();
|
||||
bucketT g, linRange, vibrancy;
|
||||
Color<bucketT> background;
|
||||
@ -1104,7 +1106,7 @@ eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(byte* pixels, size_t
|
||||
|
||||
while (rowStart < rowEnd && !m_Abort)//Use the pointer itself as the offset to save an extra addition per iter.
|
||||
{
|
||||
GammaCorrection(*rowStart, background, g, linRange, vibrancy, true, false, glm::value_ptr(*rowStart));//Write back in place.
|
||||
GammaCorrection(*rowStart, background, g, linRange, vibrancy, false, glm::value_ptr(*rowStart));//Write back in place.
|
||||
rowStart++;
|
||||
}
|
||||
});
|
||||
@ -1123,11 +1125,12 @@ eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(byte* pixels, size_t
|
||||
parallel_for(size_t(0), FinalRasH(), size_t(1), [&](size_t j)
|
||||
{
|
||||
Color<bucketT> newBucket;
|
||||
size_t pixelsRowStart = (m_YAxisUp ? ((FinalRasH() - j) - 1) : j) * FinalRowSize();//Pull out of inner loop for optimization.
|
||||
size_t pixelsRowStart = (m_YAxisUp ? ((FinalRasH() - j) - 1) : j) * FinalRasW();//Pull out of inner loop for optimization.
|
||||
size_t y = m_DensityFilterOffset + (j * Supersample());//Start at the beginning row of each super sample block.
|
||||
size_t clampedFilterH = std::min(filterWidth, m_SuperRasH - y);//Make sure the filter doesn't go past the bottom of the gutter.
|
||||
auto pv4T = pixels + pixelsRowStart;
|
||||
|
||||
for (size_t i = 0; i < FinalRasW(); i++, pixelsRowStart += PixelSize())
|
||||
for (size_t i = 0; i < FinalRasW(); i++, pv4T++)
|
||||
{
|
||||
size_t ii, jj;
|
||||
size_t x = m_DensityFilterOffset + (i * Supersample());//Start at the beginning column of each super sample block.
|
||||
@ -1149,68 +1152,8 @@ eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(byte* pixels, size_t
|
||||
}
|
||||
}
|
||||
|
||||
if (BytesPerChannel() == 2)
|
||||
{
|
||||
auto p16 = reinterpret_cast<glm::uint16*>(pixels + pixelsRowStart);
|
||||
|
||||
if (EarlyClip())
|
||||
{
|
||||
newBucket *= bucketT(65535);
|
||||
|
||||
if (m_CurvesSet)
|
||||
{
|
||||
CurveAdjust(newBucket.r, 1);
|
||||
CurveAdjust(newBucket.g, 2);
|
||||
CurveAdjust(newBucket.b, 3);
|
||||
}
|
||||
|
||||
p16[0] = glm::uint16(Clamp<bucketT>(newBucket.r, 0, 65535));
|
||||
p16[1] = glm::uint16(Clamp<bucketT>(newBucket.g, 0, 65535));
|
||||
p16[2] = glm::uint16(Clamp<bucketT>(newBucket.b, 0, 65535));
|
||||
|
||||
if (doAlpha)
|
||||
{
|
||||
if (Transparency())
|
||||
p16[3] = byte(Clamp<bucketT>(newBucket.a, 0, 65535));
|
||||
else
|
||||
p16[3] = 65535;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GammaCorrection(*(reinterpret_cast<tvec4<bucketT, glm::defaultp>*>(&newBucket)), background, g, linRange, vibrancy, doAlpha, true, p16);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EarlyClip())
|
||||
{
|
||||
newBucket *= bucketT(255);
|
||||
|
||||
if (m_CurvesSet)
|
||||
{
|
||||
CurveAdjust(newBucket.r, 1);
|
||||
CurveAdjust(newBucket.g, 2);
|
||||
CurveAdjust(newBucket.b, 3);
|
||||
}
|
||||
|
||||
pixels[pixelsRowStart] = byte(Clamp<bucketT>(newBucket.r, 0, 255));
|
||||
pixels[pixelsRowStart + 1] = byte(Clamp<bucketT>(newBucket.g, 0, 255));
|
||||
pixels[pixelsRowStart + 2] = byte(Clamp<bucketT>(newBucket.b, 0, 255));
|
||||
|
||||
if (doAlpha)
|
||||
{
|
||||
if (Transparency())
|
||||
pixels[pixelsRowStart + 3] = byte(Clamp<bucketT>(newBucket.a, 0, 255));
|
||||
else
|
||||
pixels[pixelsRowStart + 3] = 255;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GammaCorrection(*(reinterpret_cast<tvec4<bucketT, glm::defaultp>*>(&newBucket)), background, g, linRange, vibrancy, doAlpha, true, pixels + pixelsRowStart);
|
||||
}
|
||||
}
|
||||
auto pf = reinterpret_cast<float*>(pv4T);
|
||||
GammaCorrection(*(reinterpret_cast<tvec4<bucketT, glm::defaultp>*>(&newBucket)), background, g, linRange, vibrancy, true, pf);
|
||||
}
|
||||
});
|
||||
|
||||
@ -1222,30 +1165,15 @@ eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(byte* pixels, size_t
|
||||
if (ph >= FinalRasH())
|
||||
ph = FinalRasH();
|
||||
|
||||
if (BytesPerChannel() == 1)
|
||||
for (j = 0; j < ph; j++)
|
||||
{
|
||||
for (j = 0; j < ph; j++)
|
||||
for (i = 0; i < FinalRasW(); i++)
|
||||
{
|
||||
for (i = 0; i < FinalRasW(); i++)
|
||||
{
|
||||
auto p = pixels + (NumChannels() * (i + j * FinalRasW()));
|
||||
p[0] = byte(m_TempEmber.m_Palette[i * 256 / FinalRasW()][0] * WHITE);//The palette is [0..1], output image is [0..255].
|
||||
p[1] = byte(m_TempEmber.m_Palette[i * 256 / FinalRasW()][1] * WHITE);
|
||||
p[2] = byte(m_TempEmber.m_Palette[i * 256 / FinalRasW()][2] * WHITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else//BPC == 2.
|
||||
{
|
||||
for (j = 0; j < ph; j++)
|
||||
{
|
||||
for (i = 0; i < FinalRasW(); i++)
|
||||
{
|
||||
auto p16 = reinterpret_cast<glm::uint16*>(pixels + (PixelSize() * (i + j * FinalRasW())));
|
||||
p16[0] = glm::uint16(m_TempEmber.m_Palette[i * 256 / FinalRasW()][0] * WHITE * bucketT(256)); //The palette is [0..1], output image is [0..65535].
|
||||
p16[1] = glm::uint16(m_TempEmber.m_Palette[i * 256 / FinalRasW()][1] * WHITE * bucketT(256));
|
||||
p16[2] = glm::uint16(m_TempEmber.m_Palette[i * 256 / FinalRasW()][2] * WHITE * bucketT(256));
|
||||
}
|
||||
auto p = pixels + (i + j * FinalRasW());
|
||||
p->r = m_TempEmber.m_Palette[i * 256 / FinalRasW()][0];
|
||||
p->g = m_TempEmber.m_Palette[i * 256 / FinalRasW()][1];
|
||||
p->b = m_TempEmber.m_Palette[i * 256 / FinalRasW()][2];
|
||||
p->a = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1322,7 +1250,6 @@ EmberStats Renderer<T, bucketT>::Iterate(size_t iterCount, size_t temporalSample
|
||||
//t.Tic();
|
||||
//Iterating, loop 3.
|
||||
m_BadVals[threadIndex] += m_Iterator->Iterate(m_ThreadEmbers[threadIndex], params, m_Samples[threadIndex].data(), m_Rand[threadIndex]);
|
||||
//m_BadVals[threadIndex] += m_Iterator->Iterate(m_Ember, params, m_Samples[threadIndex].data(), m_Rand[threadIndex]);
|
||||
//iterationTime += t.Toc();
|
||||
|
||||
if (m_LockAccum)
|
||||
@ -1677,112 +1604,97 @@ void Renderer<T, bucketT>::AddToAccum(const tvec4<bucketT, glm::defaultp>& bucke
|
||||
/// Because this code is used in both early and late clipping, a few extra arguments are passed
|
||||
/// to specify what actions to take. Coupled with an additional template argument, this allows
|
||||
/// using one function to perform all color clipping, gamma correction and final accumulation.
|
||||
/// Template argument accumT is expected to match bucketT for the case of early clipping, byte for late clip for
|
||||
/// images with one byte per channel and unsigned short for images with two bytes per channel.
|
||||
/// Template argument accumT is expected to always be float4.
|
||||
/// </summary>
|
||||
/// <param name="bucket">The pixel to correct</param>
|
||||
/// <param name="background">The background color</param>
|
||||
/// <param name="g">The gamma to use</param>
|
||||
/// <param name="linRange">The linear range to use</param>
|
||||
/// <param name="vibrancy">The vibrancy to use</param>
|
||||
/// <param name="doAlpha">True if either early clip, or late clip with 4 channel output, else false.</param>
|
||||
/// <param name="scale">True if late clip, else false.</param>
|
||||
/// <param name="correctedChannels">The storage space for the corrected values to be written to</param>
|
||||
template <typename T, typename bucketT>
|
||||
template <typename accumT>
|
||||
void Renderer<T, bucketT>::GammaCorrection(tvec4<bucketT, glm::defaultp>& bucket, Color<bucketT>& background, bucketT g, bucketT linRange, bucketT vibrancy, bool doAlpha, bool scale, accumT* correctedChannels)
|
||||
void Renderer<T, bucketT>::GammaCorrection(tvec4<bucketT, glm::defaultp>& bucket, Color<bucketT>& background, bucketT g, bucketT linRange, bucketT vibrancy, bool scale, accumT* correctedChannels)
|
||||
{
|
||||
bucketT alpha, ls, a, newRgb[3];//Would normally use a Color<bucketT>, but don't want to call a needless constructor every time this function is called, which is once per pixel.
|
||||
static bucketT scaleVal = numeric_limits<accumT>::max();
|
||||
auto bt1 = bucketT(1);
|
||||
|
||||
if (bucket.a <= 0)
|
||||
if (scale && EarlyClip())
|
||||
{
|
||||
alpha = 0;
|
||||
ls = 0;
|
||||
if (m_CurvesSet)
|
||||
{
|
||||
CurveAdjust(bucket.r, 1);
|
||||
CurveAdjust(bucket.g, 2);
|
||||
CurveAdjust(bucket.b, 3);
|
||||
}
|
||||
|
||||
correctedChannels[0] = accumT(Clamp<bucketT>(bucket.r, 0, bt1));
|
||||
correctedChannels[1] = accumT(Clamp<bucketT>(bucket.g, 0, bt1));
|
||||
correctedChannels[2] = accumT(Clamp<bucketT>(bucket.b, 0, bt1));
|
||||
correctedChannels[3] = accumT(Clamp<bucketT>(bucket.a, 0, bt1));
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = Palette<bucketT>::CalcAlpha(bucket.a, g, linRange);
|
||||
ls = vibrancy * alpha / bucket.a;
|
||||
ClampRef<bucketT>(alpha, 0, 1);
|
||||
}
|
||||
bucketT alpha, ls, a, newRgb[3];//Would normally use a Color<bucketT>, but don't want to call a needless constructor every time this function is called, which is once per pixel.
|
||||
|
||||
Palette<bucketT>::template CalcNewRgb<bucketT>(glm::value_ptr(bucket), ls, HighlightPower(), newRgb);
|
||||
|
||||
for (glm::length_t rgbi = 0; rgbi < 3; rgbi++)
|
||||
{
|
||||
a = newRgb[rgbi] + ((1 - vibrancy) * std::pow(std::abs(bucket[rgbi]), g));//Must use abs(), else it it could be a negative value and return NAN.
|
||||
|
||||
if (NumChannels() <= 3 || !Transparency())
|
||||
if (bucket.a <= 0)
|
||||
{
|
||||
alpha = 0;
|
||||
ls = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = Palette<bucketT>::CalcAlpha(bucket.a, g, linRange);
|
||||
ls = vibrancy * alpha / bucket.a;
|
||||
ClampRef<bucketT>(alpha, 0, 1);
|
||||
}
|
||||
|
||||
Palette<bucketT>::template CalcNewRgb<bucketT>(glm::value_ptr(bucket), ls, HighlightPower(), newRgb);
|
||||
|
||||
for (glm::length_t rgbi = 0; rgbi < 3; rgbi++)
|
||||
{
|
||||
a = newRgb[rgbi] + ((1 - vibrancy) * std::pow(std::abs(bucket[rgbi]), g));//Must use abs(), else it it could be a negative value and return NAN.
|
||||
a += (1 - alpha) * background[rgbi];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (alpha > 0)
|
||||
a /= alpha;
|
||||
else
|
||||
a = 0;
|
||||
}
|
||||
|
||||
if (!scale)
|
||||
{
|
||||
correctedChannels[rgbi] = accumT(Clamp<bucketT>(a, 0, 1.0));//Early clip, just assign directly.
|
||||
}
|
||||
else
|
||||
{
|
||||
a *= scaleVal;
|
||||
|
||||
if (m_CurvesSet)
|
||||
if (scale && m_CurvesSet)
|
||||
CurveAdjust(a, rgbi + 1);
|
||||
|
||||
correctedChannels[rgbi] = accumT(Clamp<bucketT>(a, 0, scaleVal));//Final accum, multiply by 255 for 8 bpc (0-255), or 65535 for 16 bpc (0-65535).
|
||||
correctedChannels[rgbi] = accumT(Clamp<bucketT>(a, 0, bt1));//Early clip, just assign directly.
|
||||
}
|
||||
}
|
||||
|
||||
if (doAlpha)
|
||||
{
|
||||
if (!scale)
|
||||
correctedChannels[3] = accumT(alpha);//Early clip, just assign alpha directly.
|
||||
else if (Transparency())
|
||||
correctedChannels[3] = accumT(alpha * scaleVal);//Final accum, 4 channels, using transparency. Scale alpha from 0-1 to 0-255 for 8 bpc or 0-65535 for 16 bpc.
|
||||
else
|
||||
correctedChannels[3] = accumT(scaleVal);//Final accum, 4 channels, but not using transparency. 255 for 8 bpc, 65535 for 16 bpc.
|
||||
correctedChannels[3] = accumT(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setup the curve values when they are being used.
|
||||
/// This will be either 255 values for bpc=8, or 65535 values for bpc=16.
|
||||
/// </summary>
|
||||
/// <param name="scale">Whether to scale from 0-1 to 0-255 or 0-65535</param>
|
||||
template <typename T, typename bucketT>
|
||||
void Renderer<T, bucketT>::ComputeCurves(bool scale)
|
||||
void Renderer<T, bucketT>::ComputeCurves()
|
||||
{
|
||||
if (m_CurvesSet)
|
||||
{
|
||||
m_Csa.resize(size_t(std::pow(size_t(256), BytesPerChannel())));
|
||||
Timing t;
|
||||
auto st = m_Csa.size();
|
||||
auto stm1 = st - 1;
|
||||
T tscale = scale ? T(stm1) : T(1);
|
||||
|
||||
for (size_t i = 0; i < st; i++)
|
||||
m_Csa[i] = m_Ember.m_Curves.BezierFunc(i / T(stm1)) * tscale;
|
||||
m_Csa[i] = m_Ember.m_Curves.BezierFunc(i * ONE_OVER_CURVES_LENGTH_M1);
|
||||
|
||||
t.Toc("ComputeCurves");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply the curve adjustment to a single channel.
|
||||
/// </summary>
|
||||
/// <param name="aScaled">The value of the channel to apply curve adjustment to, scaled to either 255 or 65535, depending on bpc.</param>
|
||||
/// <param name="aScaled">The value of the channel to apply curve adjustment to.</param>
|
||||
/// <param name="index">The index of the channel to apply curve adjustment to</param>
|
||||
template <typename T, typename bucketT>
|
||||
void Renderer<T, bucketT>::CurveAdjust(bucketT& aScaled, const glm::length_t& index)
|
||||
void Renderer<T, bucketT>::CurveAdjust(bucketT& a, const glm::length_t& index)
|
||||
{
|
||||
bucketT stm1 = bucketT(m_Csa.size() - 1);
|
||||
size_t tempIndex = size_t(Clamp<bucketT>(aScaled, 0, stm1));
|
||||
size_t tempIndex2 = size_t(Clamp<bucketT>(m_Csa[tempIndex].x, 0, stm1));
|
||||
aScaled = m_Csa[tempIndex2][index];
|
||||
size_t tempIndex = size_t(Clamp<bucketT>(a * CURVES_LENGTH_M1, 0, CURVES_LENGTH_M1));
|
||||
size_t tempIndex2 = size_t(Clamp<bucketT>(m_Csa[tempIndex].x * CURVES_LENGTH_M1, 0, CURVES_LENGTH_M1));
|
||||
a = m_Csa[tempIndex2][index];
|
||||
}
|
||||
|
||||
//This class had to be implemented in a cpp file because the compiler was breaking.
|
||||
|
@ -66,7 +66,7 @@ public:
|
||||
virtual bool CreateSpatialFilter(bool& newAlloc) override;
|
||||
virtual bool CreateTemporalFilter(bool& newAlloc) override;
|
||||
virtual size_t HistBucketSize() const override { return sizeof(tvec4<bucketT, glm::defaultp>); }
|
||||
virtual eRenderStatus Run(vector<byte>& finalImage, double time = 0, size_t subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) override;
|
||||
virtual eRenderStatus Run(vector<v4F>& finalImage, double time = 0, size_t subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) override;
|
||||
virtual EmberImageComments ImageComments(const EmberStats& stats, size_t printEditDepth = 0, bool hexPalette = true) override;
|
||||
|
||||
protected:
|
||||
@ -76,10 +76,10 @@ protected:
|
||||
virtual bool ResetBuckets(bool resetHist = true, bool resetAccum = true);
|
||||
virtual eRenderStatus LogScaleDensityFilter(bool forceOutput = false);
|
||||
virtual eRenderStatus GaussianDensityFilter();
|
||||
virtual eRenderStatus AccumulatorToFinalImage(vector<byte>& pixels, size_t finalOffset);
|
||||
virtual eRenderStatus AccumulatorToFinalImage(byte* pixels, size_t finalOffset);
|
||||
virtual eRenderStatus AccumulatorToFinalImage(vector<v4F>& pixels, size_t finalOffset);
|
||||
virtual eRenderStatus AccumulatorToFinalImage(v4F* pixels, size_t finalOffset);
|
||||
virtual EmberStats Iterate(size_t iterCount, size_t temporalSample);
|
||||
virtual void ComputeCurves(bool scale);
|
||||
virtual void ComputeCurves();
|
||||
|
||||
public:
|
||||
//Non-virtual render properties, getters and setters.
|
||||
@ -118,9 +118,7 @@ public:
|
||||
inline T CenterX() const;
|
||||
inline T CenterY() const;
|
||||
inline T Rotate() const;
|
||||
inline T Hue() const;
|
||||
inline bucketT Brightness() const;
|
||||
inline bucketT Contrast() const;
|
||||
inline bucketT Gamma() const;
|
||||
inline bucketT Vibrancy() const;
|
||||
inline bucketT GammaThresh() const;
|
||||
@ -154,8 +152,8 @@ protected:
|
||||
private:
|
||||
//Miscellaneous non-virtual functions used only in this class.
|
||||
void Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Point<T>* samples, size_t sampleCount, const Palette<bucketT>* palette);
|
||||
/*inline*/ void AddToAccum(const tvec4<bucketT, glm::defaultp>& bucket, intmax_t i, intmax_t ii, intmax_t j, intmax_t jj);
|
||||
template <typename accumT> void GammaCorrection(tvec4<bucketT, glm::defaultp>& bucket, Color<bucketT>& background, bucketT g, bucketT linRange, bucketT vibrancy, bool doAlpha, bool scale, accumT* correctedChannels);
|
||||
void AddToAccum(const tvec4<bucketT, glm::defaultp>& bucket, intmax_t i, intmax_t ii, intmax_t j, intmax_t jj);
|
||||
template <typename accumT> void GammaCorrection(tvec4<bucketT, glm::defaultp>& bucket, Color<bucketT>& background, bucketT g, bucketT linRange, bucketT vibrancy, bool scale, accumT* correctedChannels);
|
||||
void CurveAdjust(bucketT& a, const glm::length_t& index);
|
||||
void VectorizedLogScale(size_t row, size_t rowEnd);
|
||||
|
||||
|
@ -171,10 +171,10 @@ bool RendererBase::RandVec(vector<QTIsaac<ISAAC_SIZE, ISAAC_INT>>& randVec)
|
||||
/// </summary>
|
||||
/// <param name="pixels">The vector to allocate</param>
|
||||
/// <returns>True if the vector contains enough space to hold the output image</returns>
|
||||
bool RendererBase::PrepFinalAccumVector(vector<byte>& pixels)
|
||||
bool RendererBase::PrepFinalAccumVector(vector<v4F>& pixels)
|
||||
{
|
||||
EnterResize();
|
||||
size_t size = FinalBufferSize();
|
||||
size_t size = FinalDimensions();
|
||||
|
||||
if (m_ReclaimOnResize)
|
||||
{
|
||||
@ -374,27 +374,6 @@ void RendererBase::ReclaimOnResize(bool reclaimOnResize)
|
||||
ChangeVal([&] { m_ReclaimOnResize = reclaimOnResize; }, eProcessAction::FULL_RENDER);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get whether to use transparency in the alpha channel.
|
||||
/// This only applies when the number of channels is 4 and the output
|
||||
/// image is Png.
|
||||
/// Default: false.
|
||||
/// </summary>
|
||||
/// <returns>True if using transparency, else false.</returns>
|
||||
bool RendererBase::Transparency() const { return m_Transparency; }
|
||||
|
||||
/// <summary>
|
||||
/// Set whether to use transparency in the alpha channel.
|
||||
/// This only applies when the number of channels is 4 and the output
|
||||
/// image is Png.
|
||||
/// Set the render state to ACCUM_ONLY.
|
||||
/// </summary>
|
||||
/// <param name="transparency">True if using transparency, else false.</param>
|
||||
void RendererBase::Transparency(bool transparency)
|
||||
{
|
||||
ChangeVal([&] { m_Transparency = transparency; }, eProcessAction::ACCUM_ONLY);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the callback object.
|
||||
/// </summary>
|
||||
@ -474,40 +453,18 @@ void RendererBase::ThreadCount(size_t threads, const char* seedString)
|
||||
|
||||
/// <summary>
|
||||
/// Get the bytes per channel of the output image.
|
||||
/// The only acceptable values are 1 and 2, and 2 is only
|
||||
/// used when the output is Png.
|
||||
/// Default: 1.
|
||||
/// This will always be 4 since each channel is a 32-bit float.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <returns>The number of bytes per channel</returns>
|
||||
size_t RendererBase::BytesPerChannel() const { return m_BytesPerChannel; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the bytes per channel of the output image.
|
||||
/// The only acceptable values are 1 and 2, and 2 is only
|
||||
/// used when the output is Png.
|
||||
/// Set the render state to ACCUM_ONLY.
|
||||
/// </summary>
|
||||
/// <param name="bytesPerChannel">The bytes per channel.</param>
|
||||
void RendererBase::BytesPerChannel(size_t bytesPerChannel)
|
||||
{
|
||||
ChangeVal([&]
|
||||
{
|
||||
if (bytesPerChannel == 0 || bytesPerChannel > 2)
|
||||
m_BytesPerChannel = 1;
|
||||
else
|
||||
m_BytesPerChannel = bytesPerChannel;
|
||||
}, eProcessAction::ACCUM_ONLY);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of channels per pixel in the output image. 3 for RGB images
|
||||
/// like Bitmap and Jpeg, 4 for Png.
|
||||
/// Default is 3.
|
||||
/// Get the number of channels per pixel in the output image.
|
||||
/// This will always be 4 since each pixel is always RGBA.
|
||||
/// </summary>
|
||||
/// <returns>The number of channels per pixel in the output image</returns>
|
||||
size_t RendererBase::NumChannels() const { return m_NumChannels; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the priority used for the CPU rendering threads.
|
||||
/// This does not affect OpenCL rendering.
|
||||
@ -543,18 +500,6 @@ void RendererBase::InteractiveFilter(eInteractiveFilter filter)
|
||||
/// Virtual render properties, getters and setters.
|
||||
/// </summary>
|
||||
|
||||
/// <summary>
|
||||
/// Set the number of channels per pixel in the output image. 3 for RGB images
|
||||
/// like Bitmap and Jpeg, 4 for Png.
|
||||
/// Default is 3.
|
||||
/// Set the render state to ACCUM_ONLY.
|
||||
/// </summary>
|
||||
/// <param name="numChannels">The number of channels per pixel in the output image</param>
|
||||
void RendererBase::NumChannels(size_t numChannels)
|
||||
{
|
||||
ChangeVal([&] { m_NumChannels = numChannels; }, eProcessAction::ACCUM_ONLY);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of threads used when rendering.
|
||||
/// Default: use all avaliable cores.
|
||||
|
@ -105,7 +105,7 @@ public:
|
||||
size_t HistMemoryRequired(size_t strips);
|
||||
pair<size_t, size_t> MemoryRequired(size_t strips, bool includeFinal, bool threadedWrite);
|
||||
vector<QTIsaac<ISAAC_SIZE, ISAAC_INT>> RandVec();
|
||||
bool PrepFinalAccumVector(vector<byte>& pixels);
|
||||
bool PrepFinalAccumVector(vector<v4F>& pixels);
|
||||
|
||||
//Virtual processing functions.
|
||||
virtual bool Ok() const;
|
||||
@ -121,7 +121,7 @@ public:
|
||||
virtual void ComputeBounds() = 0;
|
||||
virtual void ComputeQuality() = 0;
|
||||
virtual void ComputeCamera() = 0;
|
||||
virtual eRenderStatus Run(vector<byte>& finalImage, double time = 0, size_t subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) = 0;
|
||||
virtual eRenderStatus Run(vector<v4F>& finalImage, double time = 0, size_t subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) = 0;
|
||||
virtual EmberImageComments ImageComments(const EmberStats& stats, size_t printEditDepth = 0, bool hexPalette = true) = 0;
|
||||
virtual DensityFilterBase* GetDensityFilter() = 0;
|
||||
|
||||
@ -152,12 +152,9 @@ public:
|
||||
void InsertPalette(bool insertPalette);
|
||||
bool ReclaimOnResize() const;
|
||||
void ReclaimOnResize(bool reclaimOnResize);
|
||||
bool Transparency() const;
|
||||
void Transparency(bool transparency);
|
||||
void Callback(RenderCallback* callback);
|
||||
void ThreadCount(size_t threads, const char* seedString = nullptr);
|
||||
size_t BytesPerChannel() const;
|
||||
void BytesPerChannel(size_t bytesPerChannel);
|
||||
size_t NumChannels() const;
|
||||
eThreadPriority Priority() const;
|
||||
void Priority(eThreadPriority priority);
|
||||
@ -165,7 +162,6 @@ public:
|
||||
void InteractiveFilter(eInteractiveFilter filter);
|
||||
|
||||
//Virtual render properties, getters and setters.
|
||||
virtual void NumChannels(size_t numChannels);
|
||||
virtual size_t ThreadCount() const;
|
||||
virtual eRendererType RendererType() const;
|
||||
|
||||
@ -200,7 +196,6 @@ public:
|
||||
protected:
|
||||
bool m_EarlyClip = false;
|
||||
bool m_YAxisUp = false;
|
||||
bool m_Transparency = false;
|
||||
bool m_LockAccum = false;
|
||||
bool m_InRender = false;
|
||||
bool m_InFinalAccum = false;
|
||||
@ -213,8 +208,8 @@ protected:
|
||||
size_t m_SuperSize = 0;
|
||||
size_t m_GutterWidth;
|
||||
size_t m_DensityFilterOffset;
|
||||
size_t m_NumChannels = 3;
|
||||
size_t m_BytesPerChannel = 1;
|
||||
size_t m_NumChannels = 4;
|
||||
size_t m_BytesPerChannel = 4;
|
||||
size_t m_ThreadsToUse;
|
||||
size_t m_VibGamCount;
|
||||
size_t m_LastTemporalSample = 0;
|
||||
|
@ -836,7 +836,6 @@ public:
|
||||
/// <returns>The percentage possible color values that were present in the final output image</returns>
|
||||
T TryColors(Ember<T>& ember, size_t colorResolution)
|
||||
{
|
||||
byte* p;
|
||||
size_t i, hits = 0, res = colorResolution;
|
||||
size_t pixTotal, res3 = res * res * res;
|
||||
T scalar;
|
||||
@ -862,14 +861,12 @@ public:
|
||||
|
||||
m_Hist.resize(res3);
|
||||
Memset(m_Hist);
|
||||
p = m_FinalImage.data();
|
||||
auto p = m_FinalImage.data();
|
||||
|
||||
for (i = 0; i < m_Renderer->FinalDimensions(); i++)
|
||||
{
|
||||
m_Hist[(p[0] * res / 256) +
|
||||
(p[1] * res / 256) * res +
|
||||
(p[2] * res / 256) * res * res]++;//A specific histogram index representing the sum of R,G,B values.
|
||||
p += m_Renderer->PixelSize();//Advance the pointer by 1 pixel.
|
||||
m_Hist[size_t((p->r * res) + (p->g * res) * res + (p->b * res) * res * res)]++;//A specific histogram index representing the sum of R,G,B values.
|
||||
p++;
|
||||
}
|
||||
|
||||
for (i = 0; i < res3; i++)
|
||||
@ -1352,7 +1349,7 @@ private:
|
||||
string m_Comment;
|
||||
|
||||
vector<Point<T>> m_Samples;
|
||||
vector<byte> m_FinalImage;
|
||||
vector<v4F> m_FinalImage;
|
||||
vector<uint> m_Hist;
|
||||
EmberToXml<T> m_EmberToXml;
|
||||
Iterator<T>* m_Iterator;
|
||||
|
@ -30,8 +30,7 @@ bool EmberAnimate(EmberOptions& opt)
|
||||
//Regular variables.
|
||||
Timing t;
|
||||
bool unsorted = false;
|
||||
uint channels;
|
||||
streamsize padding;
|
||||
uint padding;
|
||||
size_t i, firstUnsortedIndex = 0;
|
||||
string inputPath = GetPath(opt.Input());
|
||||
vector<Ember<T>> embers;
|
||||
@ -99,12 +98,6 @@ bool EmberAnimate(EmberOptions& opt)
|
||||
renderers[i]->ThreadCount(opt.ThreadCount(), ns.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (opt.BitsPerChannel() != 8)
|
||||
{
|
||||
cout << "Bits per channel cannot be anything other than 8 with OpenCL, setting to 8.\n";
|
||||
opt.BitsPerChannel(8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -153,24 +146,19 @@ bool EmberAnimate(EmberOptions& opt)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (opt.Format() != "jpg" &&
|
||||
opt.Format() != "png" &&
|
||||
opt.Format() != "bmp")
|
||||
if (!Find(opt.Format(), "jpg") &&
|
||||
!Find(opt.Format(), "png") &&
|
||||
#ifdef _WIN32
|
||||
!Find(opt.Format(), "bmp") &&
|
||||
#endif
|
||||
!Find(opt.Format(), "exr"))
|
||||
{
|
||||
cout << "Format must be jpg, png, or bmp not " << opt.Format() << ". Setting to jpg.\n";
|
||||
}
|
||||
|
||||
channels = opt.Format() == "png" ? 4 : 3;
|
||||
|
||||
if (opt.BitsPerChannel() == 16 && opt.Format() != "png")
|
||||
{
|
||||
cout << "Support for 16 bits per channel images is only present for the png format. Setting to 8.\n";
|
||||
opt.BitsPerChannel(8);
|
||||
}
|
||||
else if (opt.BitsPerChannel() != 8 && opt.BitsPerChannel() != 16)
|
||||
{
|
||||
cout << "Unexpected bits per channel specified " << opt.BitsPerChannel() << ". Setting to 8.\n";
|
||||
opt.BitsPerChannel(8);
|
||||
#ifdef _WIN32
|
||||
cout << "Format must be bmp, jpg, png, png16 or exr, not " << opt.Format() << ". Setting to png.\n";
|
||||
#else
|
||||
cout << "Format must be jpg, png, png16 or exr, not " << opt.Format() << ". Setting to png.\n";
|
||||
#endif
|
||||
opt.Format("png");
|
||||
}
|
||||
|
||||
if (opt.AspectRatio() < 0)
|
||||
@ -262,7 +250,7 @@ bool EmberAnimate(EmberOptions& opt)
|
||||
}
|
||||
|
||||
//Cast to double in case the value exceeds 2^32.
|
||||
double imageMem = double(channels) * double(ember.m_FinalRasW)
|
||||
double imageMem = 4 * double(ember.m_FinalRasW)
|
||||
* double(ember.m_FinalRasH) * double(renderers[0]->BytesPerChannel());
|
||||
double maxMem = pow(2.0, double((sizeof(void*) * 8) - 1));
|
||||
|
||||
@ -316,46 +304,131 @@ bool EmberAnimate(EmberOptions& opt)
|
||||
r->YAxisUp(opt.YAxisUp());
|
||||
r->LockAccum(opt.LockAccum());
|
||||
r->PixelAspectRatio(T(opt.AspectRatio()));
|
||||
r->Transparency(opt.Transparency());
|
||||
r->NumChannels(channels);
|
||||
r->BytesPerChannel(opt.BitsPerChannel() / 8);
|
||||
r->Priority(eThreadPriority(Clamp<intmax_t>(intmax_t(opt.Priority()), intmax_t(eThreadPriority::LOWEST), intmax_t(eThreadPriority::HIGHEST))));
|
||||
}
|
||||
|
||||
std::function<void (vector<byte>&, string, EmberImageComments, size_t, size_t, size_t)> saveFunc = [&](vector<byte>& finalImage,
|
||||
string filename,//These are copies because this will be launched in a thread.
|
||||
std::function<void (vector<v4F>&, string, EmberImageComments, size_t, size_t, size_t)> saveFunc = [&](vector<v4F>& finalImage,
|
||||
string baseFilename,//These are copies because this will be launched in a thread.
|
||||
EmberImageComments comments,
|
||||
size_t w,
|
||||
size_t h,
|
||||
size_t chan)
|
||||
{
|
||||
bool writeSuccess = false;
|
||||
byte* finalImagep = finalImage.data();
|
||||
auto finalImagep = finalImage.data();
|
||||
auto size = w * h;
|
||||
bool doBmp = Find(opt.Format(), "bmp");
|
||||
bool doJpg = Find(opt.Format(), "jpg");
|
||||
bool doExr = Find(opt.Format(), "exr");
|
||||
bool doPng8 = Find(opt.Format(), "png");
|
||||
bool doPng16 = Find(opt.Format(), "png16");
|
||||
bool doOnlyPng8 = doPng8 && !doPng16;
|
||||
vector<byte> rgb8Image;
|
||||
vector<std::thread> writeFileThreads;
|
||||
writeFileThreads.reserve(5);
|
||||
|
||||
if ((opt.Format() == "jpg" || opt.Format() == "bmp") && chan == 4)
|
||||
RgbaToRgb(finalImage, finalImage, w, h);
|
||||
if (doBmp || doJpg)
|
||||
{
|
||||
rgb8Image.resize(size * 3);
|
||||
Rgba32ToRgb8(finalImagep, rgb8Image.data(), w, h);
|
||||
|
||||
if (opt.Format() == "png")
|
||||
writeSuccess = WritePng(filename.c_str(), finalImagep, w, h, opt.BitsPerChannel() / 8, opt.PngComments(), comments, opt.Id(), opt.Url(), opt.Nick());
|
||||
else if (opt.Format() == "jpg")
|
||||
writeSuccess = WriteJpeg(filename.c_str(), finalImagep, w, h, int(opt.JpegQuality()), opt.JpegComments(), comments, opt.Id(), opt.Url(), opt.Nick());
|
||||
else if (opt.Format() == "bmp")
|
||||
writeSuccess = WriteBmp(filename.c_str(), finalImagep, w, h);
|
||||
if (doBmp)
|
||||
{
|
||||
writeFileThreads.push_back(std::thread([&]()
|
||||
{
|
||||
auto fn = baseFilename + ".bmp";
|
||||
VerbosePrint("Writing " + fn);
|
||||
auto writeSuccess = WriteBmp(fn.c_str(), rgb8Image.data(), w, h);
|
||||
|
||||
if (!writeSuccess)
|
||||
cout << "Error writing " << filename << "\n";
|
||||
if (!writeSuccess)
|
||||
cout << "Error writing " << fn << "\n";
|
||||
}));
|
||||
}
|
||||
|
||||
if (doJpg)
|
||||
{
|
||||
writeFileThreads.push_back(std::thread([&]()
|
||||
{
|
||||
auto fn = baseFilename + ".jpg";
|
||||
VerbosePrint("Writing " + fn);
|
||||
auto writeSuccess = WriteJpeg(fn.c_str(), rgb8Image.data(), w, h, int(opt.JpegQuality()), opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick());
|
||||
|
||||
if (!writeSuccess)
|
||||
cout << "Error writing " << fn << "\n";
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (doPng8)
|
||||
{
|
||||
bool doBothPng = doPng16 && (opt.Format().find("png") != opt.Format().rfind("png"));
|
||||
|
||||
if (doBothPng || doOnlyPng8)//8-bit PNG
|
||||
{
|
||||
writeFileThreads.push_back(std::thread([&]()
|
||||
{
|
||||
auto fn = baseFilename + ".png";
|
||||
VerbosePrint("Writing " + fn);
|
||||
vector<byte> rgba8Image(size * 4);
|
||||
Rgba32ToRgba8(finalImagep, rgba8Image.data(), w, h, opt.Transparency());
|
||||
auto writeSuccess = WritePng(fn.c_str(), rgba8Image.data(), w, h, 1, opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick());
|
||||
|
||||
if (!writeSuccess)
|
||||
cout << "Error writing " << fn << "\n";
|
||||
}));
|
||||
}
|
||||
|
||||
if (doPng16)
|
||||
{
|
||||
writeFileThreads.push_back(std::thread([&]()
|
||||
{
|
||||
auto suffix = opt.Suffix();
|
||||
auto fn = baseFilename;
|
||||
|
||||
if (doBothPng)//Add suffix if they specified both PNG.
|
||||
{
|
||||
VerbosePrint("Doing both PNG formats, so adding suffix _p16 to avoid overwriting the same file.");
|
||||
fn += "_p16";
|
||||
}
|
||||
|
||||
fn += ".png";
|
||||
VerbosePrint("Writing " + fn);
|
||||
vector<glm::uint16> rgba16Image(size * 4);
|
||||
Rgba32ToRgba16(finalImagep, rgba16Image.data(), w, h, opt.Transparency());
|
||||
auto writeSuccess = WritePng(fn.c_str(), (byte*)rgba16Image.data(), w, h, 2, opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick());
|
||||
|
||||
if (!writeSuccess)
|
||||
cout << "Error writing " << fn << "\n";
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (doExr)
|
||||
{
|
||||
writeFileThreads.push_back(std::thread([&]()
|
||||
{
|
||||
auto fn = baseFilename + ".exr";
|
||||
VerbosePrint("Writing " + fn);
|
||||
vector<Rgba> rgba32Image(size);
|
||||
Rgba32ToRgbaExr(finalImagep, rgba32Image.data(), w, h, opt.Transparency());
|
||||
auto writeSuccess = WriteExr(fn.c_str(), rgba32Image.data(), w, h, opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick());
|
||||
|
||||
if (!writeSuccess)
|
||||
cout << "Error writing " << fn << "\n";
|
||||
}));
|
||||
}
|
||||
|
||||
Join(writeFileThreads);
|
||||
};
|
||||
atomfTime.store(opt.FirstFrame());
|
||||
std::function<void(size_t)> iterFunc = [&](size_t index)
|
||||
{
|
||||
size_t ftime, finalImageIndex = 0;
|
||||
string filename, flameName;
|
||||
RendererBase* renderer = renderers[index].get();
|
||||
ostringstream fnstream, os;
|
||||
ostringstream os;
|
||||
EmberStats stats;
|
||||
EmberImageComments comments;
|
||||
Ember<T> centerEmber;
|
||||
vector<byte> finalImages[2];
|
||||
vector<v4F> finalImages[2];
|
||||
std::thread writeThread;
|
||||
os.imbue(std::locale(""));
|
||||
|
||||
@ -390,13 +463,9 @@ bool EmberAnimate(EmberOptions& opt)
|
||||
break;
|
||||
}
|
||||
|
||||
fnstream << inputPath << opt.Prefix() << setfill('0') << setprecision(0) << fixed << setw(padding) << ftime << opt.Suffix() << "." << opt.Format();
|
||||
filename = fnstream.str();
|
||||
fnstream.str("");
|
||||
|
||||
if (opt.WriteGenome())
|
||||
{
|
||||
flameName = filename.substr(0, filename.find_last_of('.')) + ".flame";
|
||||
auto flameName = MakeAnimFilename(inputPath, opt.Prefix(), opt.Suffix(), ".flame", padding, ftime);
|
||||
|
||||
if (opt.Verbose())
|
||||
{
|
||||
@ -425,21 +494,21 @@ bool EmberAnimate(EmberOptions& opt)
|
||||
cout << "Render time: " << t.Format(stats.m_RenderMs) << "\n";
|
||||
cout << "Pure iter time: " << t.Format(stats.m_IterMs) << "\n";
|
||||
cout << "Iters/sec: " << size_t(stats.m_Iters / (stats.m_IterMs / 1000.0)) << "\n";
|
||||
cout << "Writing " << filename << "\n\n";
|
||||
}
|
||||
|
||||
//Run image writing in a thread. Although doing it this way duplicates the final output memory, it saves a lot of time
|
||||
//when running with OpenCL. Call join() to ensure the previous thread call has completed.
|
||||
Join(writeThread);
|
||||
auto threadVecIndex = finalImageIndex;//Cache before launching thread.
|
||||
auto baseFilename = MakeAnimFilename(inputPath, opt.Prefix(), opt.Suffix(), "", padding, ftime);
|
||||
|
||||
if (opt.ThreadedWrite())//Copies are passed of all but the first parameter to saveFunc(), to avoid conflicting with those values changing when starting the render for the next image.
|
||||
if (opt.ThreadedWrite())//Copies of all but the first parameter are passed to saveFunc(), to avoid conflicting with those values changing when starting the render for the next image.
|
||||
{
|
||||
writeThread = std::thread(saveFunc, std::ref(finalImages[threadVecIndex]), filename, comments, renderer->FinalRasW(), renderer->FinalRasH(), renderer->NumChannels());
|
||||
writeThread = std::thread(saveFunc, std::ref(finalImages[threadVecIndex]), baseFilename, comments, renderer->FinalRasW(), renderer->FinalRasH(), renderer->NumChannels());
|
||||
finalImageIndex ^= 1;//Toggle the index.
|
||||
}
|
||||
else
|
||||
saveFunc(finalImages[threadVecIndex], filename, comments, renderer->FinalRasW(), renderer->FinalRasH(), renderer->NumChannels());//Will always use the first index, thereby not requiring more memory.
|
||||
saveFunc(finalImages[threadVecIndex], baseFilename, comments, renderer->FinalRasW(), renderer->FinalRasH(), renderer->NumChannels());//Will always use the first index, thereby not requiring more memory.
|
||||
}
|
||||
|
||||
Join(writeThread);//One final check to make sure all writing is done before exiting this thread.
|
||||
|
@ -147,13 +147,14 @@ static const char* CalcAlphaFunctionString =
|
||||
/// during final accumulation, which only takes floats.
|
||||
/// </summary>
|
||||
static const char* CurveAdjustFunctionString =
|
||||
"static inline void CurveAdjust(__constant real4reals_bucket* csa, float* a, uint index)\n"
|
||||
"static inline void CurveAdjust(__global real4reals_bucket* csa, float* a, uint index)\n"
|
||||
"{\n"
|
||||
" uint tempIndex = (uint)clamp(*a * (float)COLORMAP_LENGTH_MINUS_1, (float)0.0, (float)COLORMAP_LENGTH_MINUS_1);\n"
|
||||
" uint tempIndex2 = (uint)clamp((float)csa[tempIndex].m_Real4.x * (float)COLORMAP_LENGTH_MINUS_1, (float)0.0, (float)COLORMAP_LENGTH_MINUS_1);\n"
|
||||
" uint tempIndex = (uint)clamp(*a * CURVES_LENGTH_M1, 0.0f, CURVES_LENGTH_M1);\n"
|
||||
" uint tempIndex2 = (uint)clamp(csa[tempIndex].m_Real4.x * CURVES_LENGTH_M1, 0.0f, CURVES_LENGTH_M1);\n"
|
||||
"\n"
|
||||
" *a = (float)csa[tempIndex2].m_Reals[index];\n"
|
||||
"}\n";
|
||||
"}\n"
|
||||
"\n";
|
||||
|
||||
/// <summary>
|
||||
/// Use MWC 64 from David Thomas at the Imperial College of London for
|
||||
|
@ -85,6 +85,8 @@ static string ConstantDefinesString(bool doublePrecision)
|
||||
"#define SQRT5 2.2360679774997896964091736687313\n"
|
||||
"#define M_PHI 1.61803398874989484820458683436563\n"
|
||||
"#define DEG_2_RAD (MPI / 180)\n"
|
||||
"#define CURVES_LENGTH_M1 131071.0f\n"
|
||||
"#define ONE_OVER_CURVES_LENGTH_M1 7.62945273935e-6f\n"
|
||||
"\n"
|
||||
"//Index in each dimension of a thread within a block.\n"
|
||||
"#define THREAD_ID_X (get_local_id(0))\n"
|
||||
@ -314,10 +316,7 @@ struct ALIGN SpatialFilterCL
|
||||
uint m_FinalRasH;
|
||||
uint m_Supersample;
|
||||
uint m_FilterWidth;
|
||||
uint m_NumChannels;
|
||||
uint m_BytesPerChannel;
|
||||
uint m_DensityFilterOffset;
|
||||
uint m_Transparency;
|
||||
uint m_YAxisUp;
|
||||
T m_Vibrancy;
|
||||
T m_HighlightPower;
|
||||
@ -339,10 +338,7 @@ static const char* SpatialFilterCLStructString =
|
||||
" uint m_FinalRasH;\n"
|
||||
" uint m_Supersample;\n"
|
||||
" uint m_FilterWidth;\n"
|
||||
" uint m_NumChannels;\n"
|
||||
" uint m_BytesPerChannel;\n"
|
||||
" uint m_DensityFilterOffset;\n"
|
||||
" uint m_Transparency;\n"
|
||||
" uint m_YAxisUp;\n"
|
||||
" real_bucket_t m_Vibrancy;\n"
|
||||
" real_bucket_t m_HighlightPower;\n"
|
||||
|
@ -10,166 +10,58 @@ namespace EmberCLns
|
||||
FinalAccumOpenCLKernelCreator::FinalAccumOpenCLKernelCreator(bool doublePrecision)
|
||||
{
|
||||
m_DoublePrecision = doublePrecision;
|
||||
m_GammaCorrectionWithAlphaCalcKernel = CreateGammaCorrectionKernelString(true);
|
||||
m_GammaCorrectionWithoutAlphaCalcKernel = CreateGammaCorrectionKernelString(false);
|
||||
m_FinalAccumEarlyClipKernel = CreateFinalAccumKernelString(true, false, false);
|
||||
m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(true, true, true);
|
||||
m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(true, false, true);
|
||||
m_FinalAccumLateClipKernel = CreateFinalAccumKernelString(false, false, false);
|
||||
m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(false, true, true);
|
||||
m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(false, false, true);
|
||||
m_GammaCorrectionWithoutAlphaCalcKernel = CreateGammaCorrectionKernelString();
|
||||
m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(true);
|
||||
m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Kernel source and entry point properties, getters only.
|
||||
/// </summary>
|
||||
|
||||
const string& FinalAccumOpenCLKernelCreator::GammaCorrectionWithAlphaCalcKernel() const { return m_GammaCorrectionWithAlphaCalcKernel; }
|
||||
const string& FinalAccumOpenCLKernelCreator::GammaCorrectionWithAlphaCalcEntryPoint() const { return m_GammaCorrectionWithAlphaCalcEntryPoint; }
|
||||
const string& FinalAccumOpenCLKernelCreator::GammaCorrectionWithoutAlphaCalcKernel() const { return m_GammaCorrectionWithoutAlphaCalcKernel; }
|
||||
const string& FinalAccumOpenCLKernelCreator::GammaCorrectionWithoutAlphaCalcEntryPoint() const { return m_GammaCorrectionWithoutAlphaCalcEntryPoint; }
|
||||
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumEarlyClipKernel() const { return m_FinalAccumEarlyClipKernel; }
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumEarlyClipEntryPoint() const { return m_FinalAccumEarlyClipEntryPoint; }
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel() const { return m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel; }
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumEntryPoint() const { return m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumEntryPoint; }
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel() const { return m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel; }
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumEntryPoint() const { return m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumEntryPoint; }
|
||||
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumLateClipKernel() const { return m_FinalAccumLateClipKernel; }
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumLateClipEntryPoint() const { return m_FinalAccumLateClipEntryPoint; }
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel() const { return m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel; }
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumLateClipWithAlphaCalcWithAlphaAccumEntryPoint() const { return m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumEntryPoint; }
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel() const { return m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel; }
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumEntryPoint() const { return m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumEntryPoint; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the gamma correction entry point.
|
||||
/// </summary>
|
||||
/// <param name="channels">The number of channels used, 3 or 4.</param>
|
||||
/// <param name="transparency">True if channels equals 4 and using transparency, else false.</param>
|
||||
/// <returns>The name of the gamma correction entry point kernel function</returns>
|
||||
const string& FinalAccumOpenCLKernelCreator::GammaCorrectionEntryPoint(size_t channels, bool transparency) const
|
||||
{
|
||||
bool alphaCalc = ((channels > 3) && transparency);
|
||||
return alphaCalc ? m_GammaCorrectionWithAlphaCalcEntryPoint : m_GammaCorrectionWithoutAlphaCalcEntryPoint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the gamma correction kernel string.
|
||||
/// </summary>
|
||||
/// <param name="channels">The number of channels used, 3 or 4.</param>
|
||||
/// <param name="transparency">True if channels equals 4 and using transparency, else false.</param>
|
||||
/// <returns>The gamma correction kernel string</returns>
|
||||
const string& FinalAccumOpenCLKernelCreator::GammaCorrectionKernel(size_t channels, bool transparency) const
|
||||
{
|
||||
bool alphaCalc = ((channels > 3) && transparency);
|
||||
return alphaCalc ? m_GammaCorrectionWithAlphaCalcKernel : m_GammaCorrectionWithoutAlphaCalcKernel;
|
||||
}
|
||||
const string& FinalAccumOpenCLKernelCreator::GammaCorrectionEntryPoint() const { return m_GammaCorrectionWithoutAlphaCalcEntryPoint; }
|
||||
const string& FinalAccumOpenCLKernelCreator::GammaCorrectionKernel() const { return m_GammaCorrectionWithoutAlphaCalcKernel; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the final accumulation entry point.
|
||||
/// </summary>
|
||||
/// <param name="earlyClip">True if early clip is desired, else false.</param>
|
||||
/// <param name="channels">The number of channels used, 3 or 4.</param>
|
||||
/// <param name="transparency">True if channels equals 4 and using transparency, else false.</param>
|
||||
/// <param name="alphaBase">Storage for the alpha base value used in the kernel. 0 if transparency is true, else 255.</param>
|
||||
/// <param name="alphaScale">Storage for the alpha scale value used in the kernel. 255 if transparency is true, else 0.</param>
|
||||
/// <returns>The name of the final accumulation entry point kernel function</returns>
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumEntryPoint(bool earlyClip, size_t channels, bool transparency, double& alphaBase, double& alphaScale) const
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumEntryPoint(bool earlyClip) const
|
||||
{
|
||||
bool alphaCalc = ((channels > 3) && transparency);
|
||||
bool alphaAccum = channels > 3;
|
||||
|
||||
if (alphaAccum)
|
||||
{
|
||||
alphaBase = transparency ? 0 : 1;//See the table below.
|
||||
alphaScale = transparency ? 1 : 0;
|
||||
}
|
||||
|
||||
if (earlyClip)
|
||||
{
|
||||
if (!alphaCalc && !alphaAccum)//Rgb output, the most common case.
|
||||
return FinalAccumEarlyClipEntryPoint();
|
||||
else if (alphaCalc && alphaAccum)//Rgba output and Transparency.
|
||||
return FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumEntryPoint();
|
||||
else if (!alphaCalc && alphaAccum)//Rgba output and !Transparency.
|
||||
return FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumEntryPoint();
|
||||
else
|
||||
return m_Empty;//Cannot have alphaCalc and !alphaAccum, it makes no sense.
|
||||
}
|
||||
return FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumEntryPoint();
|
||||
else
|
||||
{
|
||||
if (!alphaCalc && !alphaAccum)//Rgb output, the most common case.
|
||||
return FinalAccumLateClipEntryPoint();
|
||||
else if (alphaCalc && alphaAccum)//Rgba output and Transparency.
|
||||
return FinalAccumLateClipWithAlphaCalcWithAlphaAccumEntryPoint();
|
||||
else if (!alphaCalc && alphaAccum)//Rgba output and !Transparency.
|
||||
return FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumEntryPoint();
|
||||
else
|
||||
return m_Empty;//Cannot have alphaCalc and !alphaAccum, it makes no sense.
|
||||
}
|
||||
return FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumEntryPoint();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the final accumulation kernel string.
|
||||
/// </summary>
|
||||
/// <param name="earlyClip">True if early clip is desired, else false.</param>
|
||||
/// <param name="channels">The number of channels used, 3 or 4.</param>
|
||||
/// <param name="transparency">True if channels equals 4 and using transparency, else false.</param>
|
||||
/// <returns>The final accumulation kernel string</returns>
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumKernel(bool earlyClip, size_t channels, bool transparency) const
|
||||
const string& FinalAccumOpenCLKernelCreator::FinalAccumKernel(bool earlyClip) const
|
||||
{
|
||||
bool alphaCalc = (channels > 3 && transparency);
|
||||
bool alphaAccum = channels > 3;
|
||||
|
||||
if (earlyClip)
|
||||
{
|
||||
if (!alphaCalc && !alphaAccum)//Rgb output, the most common case.
|
||||
return FinalAccumEarlyClipKernel();
|
||||
else if (alphaCalc && alphaAccum)//Rgba output and Transparency.
|
||||
return FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel();
|
||||
else if (!alphaCalc && alphaAccum)//Rgba output and !Transparency.
|
||||
return FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel();
|
||||
else
|
||||
return m_Empty;//Cannot have alphaCalc and !alphaAccum, it makes no sense.
|
||||
}
|
||||
return FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel();
|
||||
else
|
||||
{
|
||||
if (!alphaCalc && !alphaAccum)//Rgb output, the most common case.
|
||||
return FinalAccumLateClipKernel();
|
||||
else if (alphaCalc && alphaAccum)//Rgba output and Transparency.
|
||||
return FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel();
|
||||
else if (!alphaCalc && alphaAccum)//Rgba output and !Transparency.
|
||||
return FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel();
|
||||
else
|
||||
return m_Empty;//Cannot have alphaCalc and !alphaAccum, it makes no sense.
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper around CreateFinalAccumKernelString().
|
||||
/// </summary>
|
||||
/// <param name="earlyClip">True if early clip is desired, else false.</param>
|
||||
/// <param name="channels">The number of channels used, 3 or 4.</param>
|
||||
/// <param name="transparency">True if channels equals 4 and using transparency, else false.</param>
|
||||
/// <returns>The final accumulation kernel string</returns>
|
||||
string FinalAccumOpenCLKernelCreator::CreateFinalAccumKernelString(bool earlyClip, size_t channels, bool transparency)
|
||||
{
|
||||
return CreateFinalAccumKernelString(earlyClip, (channels > 3 && transparency), channels > 3);
|
||||
return FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the final accumulation kernel string
|
||||
/// </summary>
|
||||
/// <param name="earlyClip">True if early clip is desired, else false.</param>
|
||||
/// <param name="alphaCalc">True if channels equals 4 and transparency is desired, else false.</param>
|
||||
/// <param name="alphaAccum">True if channels equals 4</param>
|
||||
/// <returns>The final accumulation kernel string</returns>
|
||||
string FinalAccumOpenCLKernelCreator::CreateFinalAccumKernelString(bool earlyClip, bool alphaCalc, bool alphaAccum)
|
||||
string FinalAccumOpenCLKernelCreator::CreateFinalAccumKernelString(bool earlyClip)
|
||||
{
|
||||
ostringstream os;
|
||||
string channels = alphaAccum ? "4" : "3";
|
||||
os <<
|
||||
ConstantDefinesString(m_DoublePrecision) <<
|
||||
UnionCLStructString <<
|
||||
@ -181,29 +73,14 @@ string FinalAccumOpenCLKernelCreator::CreateFinalAccumKernelString(bool earlyCli
|
||||
|
||||
if (earlyClip)
|
||||
{
|
||||
if (!alphaCalc && !alphaAccum)//Rgb output, the most common case.
|
||||
os << "__kernel void " << m_FinalAccumEarlyClipEntryPoint << "(\n";
|
||||
else if (alphaCalc && alphaAccum)//Rgba output and Transparency.
|
||||
os << "__kernel void " << m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumEntryPoint << "(\n";
|
||||
else if (!alphaCalc && alphaAccum)//Rgba output and !Transparency.
|
||||
os << "__kernel void " << m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumEntryPoint << "(\n";
|
||||
else
|
||||
return "";//Cannot have alphaCalc and !alphaAccum, it makes no sense.
|
||||
os << "__kernel void " << m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumEntryPoint << "(\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
os <<
|
||||
CreateCalcNewRgbFunctionString(false) <<
|
||||
CreateGammaCorrectionFunctionString(false, alphaCalc, alphaAccum, true);
|
||||
|
||||
if (!alphaCalc && !alphaAccum)//Rgb output, the most common case.
|
||||
os << "__kernel void " << m_FinalAccumLateClipEntryPoint << "(\n";
|
||||
else if (alphaCalc && alphaAccum)//Rgba output and Transparency.
|
||||
os << "__kernel void " << m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumEntryPoint << "(\n";
|
||||
else if (!alphaCalc && alphaAccum)//Rgba output and !Transparency.
|
||||
os << "__kernel void " << m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumEntryPoint << "(\n";
|
||||
else
|
||||
return "";//Cannot have alphaCalc and !alphaAccum, it makes no sense.
|
||||
CreateGammaCorrectionFunctionString(false, true) <<
|
||||
"__kernel void " << m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumEntryPoint << "(\n";
|
||||
}
|
||||
|
||||
os <<
|
||||
@ -211,10 +88,8 @@ string FinalAccumOpenCLKernelCreator::CreateFinalAccumKernelString(bool earlyCli
|
||||
" __write_only image2d_t pixels,\n"
|
||||
" __constant SpatialFilterCL* spatialFilter,\n"
|
||||
" __constant real_bucket_t* filterCoefs,\n"
|
||||
" __constant real4reals_bucket* csa,\n"
|
||||
" const uint doCurves,\n"
|
||||
" const real_bucket_t alphaBase,\n"
|
||||
" const real_bucket_t alphaScale\n"
|
||||
" __global real4reals_bucket* csa,\n"
|
||||
" const uint doCurves\n"
|
||||
"\t)\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
@ -249,21 +124,13 @@ string FinalAccumOpenCLKernelCreator::CreateFinalAccumKernelString(bool earlyCli
|
||||
" }\n"
|
||||
"\n";
|
||||
|
||||
//Not supporting 2 bytes per channel on the GPU. If the user wants it, run on the CPU.
|
||||
if (earlyClip)//If early clip, simply assign values directly to the temp float4 since they've been gamma corrected already, then write it straight to the output image below.
|
||||
{
|
||||
os <<
|
||||
" finalColor.m_Float4.x = (float)newBucket.m_Real4.x;\n"//CPU side clamps, skip here because write_imagef() does the clamping for us.
|
||||
" finalColor.m_Float4.y = (float)newBucket.m_Real4.y;\n"
|
||||
" finalColor.m_Float4.z = (float)newBucket.m_Real4.z;\n";
|
||||
|
||||
if (alphaAccum)
|
||||
{
|
||||
if (alphaCalc)
|
||||
os << " finalColor.m_Float4.w = (float)newBucket.m_Real4.w;\n";
|
||||
else
|
||||
os << " finalColor.m_Float4.w = 1.0f;\n";
|
||||
}
|
||||
" finalColor.m_Float4.z = (float)newBucket.m_Real4.z;\n"
|
||||
" finalColor.m_Float4.w = (float)newBucket.m_Real4.w;\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -273,7 +140,7 @@ string FinalAccumOpenCLKernelCreator::CreateFinalAccumKernelString(bool earlyCli
|
||||
os <<
|
||||
" real4reals_bucket realFinal;\n"
|
||||
"\n"
|
||||
" GammaCorrectionFloats(&newBucket, &(spatialFilter->m_Background[0]), spatialFilter->m_Gamma, spatialFilter->m_LinRange, spatialFilter->m_Vibrancy, spatialFilter->m_HighlightPower, alphaBase, alphaScale, &(realFinal.m_Reals[0]));\n"
|
||||
" GammaCorrectionFloats(&newBucket, &(spatialFilter->m_Background[0]), spatialFilter->m_Gamma, spatialFilter->m_LinRange, spatialFilter->m_Vibrancy, spatialFilter->m_HighlightPower, &(realFinal.m_Reals[0]));\n"
|
||||
" finalColor.m_Float4.x = (float)realFinal.m_Real4.x;\n"
|
||||
" finalColor.m_Float4.y = (float)realFinal.m_Real4.y;\n"
|
||||
" finalColor.m_Float4.z = (float)realFinal.m_Real4.z;\n"
|
||||
@ -283,7 +150,7 @@ string FinalAccumOpenCLKernelCreator::CreateFinalAccumKernelString(bool earlyCli
|
||||
else
|
||||
{
|
||||
os <<
|
||||
" GammaCorrectionFloats(&newBucket, &(spatialFilter->m_Background[0]), spatialFilter->m_Gamma, spatialFilter->m_LinRange, spatialFilter->m_Vibrancy, spatialFilter->m_HighlightPower, alphaBase, alphaScale, &(finalColor.m_Floats[0]));\n";
|
||||
" GammaCorrectionFloats(&newBucket, &(spatialFilter->m_Background[0]), spatialFilter->m_Gamma, spatialFilter->m_LinRange, spatialFilter->m_Vibrancy, spatialFilter->m_HighlightPower, &(finalColor.m_Floats[0]));\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -308,81 +175,45 @@ string FinalAccumOpenCLKernelCreator::CreateFinalAccumKernelString(bool earlyCli
|
||||
/// This is not a full kernel, just a function that is used in the kernels.
|
||||
/// </summary>
|
||||
/// <param name="globalBucket">True if writing to a global buffer (early clip), else false (late clip).</param>
|
||||
/// <param name="alphaCalc">True if channels equals 4 and transparency is desired, else false.</param>
|
||||
/// <param name="alphaAccum">True if channels equals 4</param>
|
||||
/// <param name="finalOut">True if writing to global buffer (late clip), else false (early clip).</param>
|
||||
/// <returns>The gamma correction function string</returns>
|
||||
string FinalAccumOpenCLKernelCreator::CreateGammaCorrectionFunctionString(bool globalBucket, bool alphaCalc, bool alphaAccum, bool finalOut)
|
||||
string FinalAccumOpenCLKernelCreator::CreateGammaCorrectionFunctionString(bool globalBucket, bool finalOut)
|
||||
{
|
||||
ostringstream os;
|
||||
string dataType;
|
||||
string unionMember;
|
||||
dataType = "real_bucket_t";
|
||||
//Use real_t for all cases, early clip and final accum.
|
||||
os << "void GammaCorrectionFloats(" << (globalBucket ? "__global " : "") << "real4reals_bucket* bucket, __constant real_bucket_t* background, real_bucket_t g, real_bucket_t linRange, real_bucket_t vibrancy, real_bucket_t highlightPower, real_bucket_t alphaBase, real_bucket_t alphaScale, " << (finalOut ? "" : "__global") << " real_bucket_t* correctedChannels)\n";
|
||||
os
|
||||
<< "{\n"
|
||||
<< " real_bucket_t alpha, ls, tmp, a;\n"
|
||||
<< " real4reals_bucket newRgb;\n"
|
||||
<< "\n"
|
||||
<< " if (bucket->m_Reals[3] <= 0)\n"
|
||||
<< " {\n"
|
||||
<< " alpha = 0;\n"
|
||||
<< " ls = 0;\n"
|
||||
<< " }\n"
|
||||
<< " else\n"
|
||||
<< " {\n"
|
||||
<< " tmp = bucket->m_Reals[3];\n"
|
||||
<< " alpha = CalcAlpha(tmp, g, linRange);\n"
|
||||
<< " ls = vibrancy * alpha / tmp;\n"
|
||||
<< " alpha = clamp(alpha, (real_bucket_t)0.0, (real_bucket_t)1.0);\n"
|
||||
<< " }\n"
|
||||
<< "\n"
|
||||
<< " CalcNewRgb(bucket, ls, highlightPower, &newRgb);\n"
|
||||
<< "\n"
|
||||
<< " for (uint rgbi = 0; rgbi < 3; rgbi++)\n"
|
||||
<< " {\n"
|
||||
<< " a = newRgb.m_Reals[rgbi] + ((1.0 - vibrancy) * pow(fabs(bucket->m_Reals[rgbi]), g));\n"
|
||||
<< "\n";
|
||||
|
||||
if (!alphaCalc)
|
||||
{
|
||||
os <<
|
||||
" a += ((1.0 - alpha) * background[rgbi]);\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
os
|
||||
<< " if (alpha > 0)\n"
|
||||
<< " a /= alpha;\n"
|
||||
<< " else\n"
|
||||
<< " a = 0;\n";
|
||||
}
|
||||
|
||||
os <<
|
||||
"\n"
|
||||
" correctedChannels[rgbi] = (" << dataType << ")clamp(a, (real_bucket_t)0.0, (real_bucket_t)1.0);\n"
|
||||
" }\n"
|
||||
"\n";
|
||||
|
||||
//The CPU code has 3 cases for assigning alpha:
|
||||
//[3] = alpha.//Early clip.
|
||||
//[3] = alpha * 255.//Final Rgba with transparency.
|
||||
//[3] = 255.//Final Rgba without transparency.
|
||||
//Putting conditionals in GPU code is to be avoided. So do base + alpha * scale which will
|
||||
//work for all 3 cases without using a conditional, which should be faster on a GPU. This gives:
|
||||
//Base = 0, scale = 1. [3] = (0 + (alpha * 1)). [3] = alpha.
|
||||
//Base = 0, scale = 255. [3] = (0 + (alpha * 255)). [3] = alpha * 255.
|
||||
//Base = 255, scale = 0. [3] = (255 + (alpha * 0)). [3] = 255.
|
||||
if (alphaAccum)
|
||||
{
|
||||
os
|
||||
<< " correctedChannels[3] = (" << dataType << ")(alphaBase + (alpha * alphaScale));\n";
|
||||
}
|
||||
|
||||
os <<
|
||||
"}\n"
|
||||
"\n";
|
||||
os << "void GammaCorrectionFloats(" << (globalBucket ? "__global " : "") << "real4reals_bucket* bucket, __constant real_bucket_t* background, real_bucket_t g, real_bucket_t linRange, real_bucket_t vibrancy, real_bucket_t highlightPower, " << (finalOut ? "" : "__global") << " real_bucket_t* correctedChannels)\n";
|
||||
os << "{\n"
|
||||
<< " real_bucket_t alpha, ls, tmp, a;\n"
|
||||
<< " real4reals_bucket newRgb;\n"
|
||||
<< "\n"
|
||||
<< " if (bucket->m_Reals[3] <= 0)\n"
|
||||
<< " {\n"
|
||||
<< " alpha = 0;\n"
|
||||
<< " ls = 0;\n"
|
||||
<< " }\n"
|
||||
<< " else\n"
|
||||
<< " {\n"
|
||||
<< " tmp = bucket->m_Reals[3];\n"
|
||||
<< " alpha = CalcAlpha(tmp, g, linRange);\n"
|
||||
<< " ls = vibrancy * alpha / tmp;\n"
|
||||
<< " alpha = clamp(alpha, (real_bucket_t)0.0, (real_bucket_t)1.0);\n"
|
||||
<< " }\n"
|
||||
<< "\n"
|
||||
<< " CalcNewRgb(bucket, ls, highlightPower, &newRgb);\n"
|
||||
<< "\n"
|
||||
<< " for (uint rgbi = 0; rgbi < 3; rgbi++)\n"
|
||||
<< " {\n"
|
||||
<< " a = newRgb.m_Reals[rgbi] + ((1.0 - vibrancy) * pow(fabs(bucket->m_Reals[rgbi]), g));\n"
|
||||
<< " a += ((1.0 - alpha) * background[rgbi]);\n"
|
||||
<< " correctedChannels[rgbi] = (" << dataType << ")clamp(a, (real_bucket_t)0.0, (real_bucket_t)1.0);\n"
|
||||
<< " }\n"
|
||||
<< "\n"
|
||||
<< " correctedChannels[3] = (" << dataType << ")alpha;\n"
|
||||
<< "}\n"
|
||||
<< "\n";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
@ -451,9 +282,8 @@ string FinalAccumOpenCLKernelCreator::CreateCalcNewRgbFunctionString(bool global
|
||||
/// <summary>
|
||||
/// Create the gamma correction kernel string used for early clipping.
|
||||
/// </summary>
|
||||
/// <param name="alphaCalc">True if channels equals 4 and transparency is desired, else false.</param>
|
||||
/// <returns>The gamma correction kernel string used for early clipping</returns>
|
||||
string FinalAccumOpenCLKernelCreator::CreateGammaCorrectionKernelString(bool alphaCalc)
|
||||
string FinalAccumOpenCLKernelCreator::CreateGammaCorrectionKernelString()
|
||||
{
|
||||
ostringstream os;
|
||||
string dataType;
|
||||
@ -465,8 +295,8 @@ string FinalAccumOpenCLKernelCreator::CreateGammaCorrectionKernelString(bool alp
|
||||
CalcAlphaFunctionString <<
|
||||
CreateCalcNewRgbFunctionString(true) <<
|
||||
SpatialFilterCLStructString <<
|
||||
CreateGammaCorrectionFunctionString(true, alphaCalc, true, false);//Will only be used with float in this case, early clip. Will always alpha accum.
|
||||
os << "__kernel void " << (alphaCalc ? m_GammaCorrectionWithAlphaCalcEntryPoint : m_GammaCorrectionWithoutAlphaCalcEntryPoint) << "(\n" <<
|
||||
CreateGammaCorrectionFunctionString(true, false);//Will only be used with float in this case, early clip. Will always alpha accum.
|
||||
os << "__kernel void " << m_GammaCorrectionWithoutAlphaCalcEntryPoint << "(\n" <<
|
||||
" __global real4reals_bucket* accumulator,\n"
|
||||
" __constant SpatialFilterCL* spatialFilter\n"
|
||||
")\n"
|
||||
@ -478,8 +308,7 @@ string FinalAccumOpenCLKernelCreator::CreateGammaCorrectionKernelString(bool alp
|
||||
"\n"
|
||||
" uint superIndex = (GLOBAL_ID_Y * spatialFilter->m_SuperRasW) + GLOBAL_ID_X;\n"
|
||||
" __global real4reals_bucket* bucket = accumulator + superIndex;\n"
|
||||
//Pass in an alphaBase and alphaScale of 0, 1 which means to just directly assign the computed alpha value.
|
||||
" GammaCorrectionFloats(bucket, &(spatialFilter->m_Background[0]), spatialFilter->m_Gamma, spatialFilter->m_LinRange, spatialFilter->m_Vibrancy, spatialFilter->m_HighlightPower, 0.0, 1.0, &(bucket->m_Reals[0]));\n"
|
||||
" GammaCorrectionFloats(bucket, &(spatialFilter->m_Background[0]), spatialFilter->m_Gamma, spatialFilter->m_LinRange, spatialFilter->m_Vibrancy, spatialFilter->m_HighlightPower, &(bucket->m_Reals[0]));\n"
|
||||
"}\n"
|
||||
;
|
||||
return os.str();
|
||||
|
@ -17,64 +17,35 @@ namespace EmberCLns
|
||||
/// with all conditionals and unnecessary calculations stripped out.
|
||||
/// The conditionals are:
|
||||
/// Early clip/late clip
|
||||
/// Alpha channel, no alpha channel
|
||||
/// Alpha with/without transparency
|
||||
/// </summary>
|
||||
class EMBERCL_API FinalAccumOpenCLKernelCreator
|
||||
{
|
||||
public:
|
||||
FinalAccumOpenCLKernelCreator(bool doublePrecision);
|
||||
|
||||
const string& GammaCorrectionWithAlphaCalcKernel() const;
|
||||
const string& GammaCorrectionWithAlphaCalcEntryPoint() const;
|
||||
|
||||
const string& GammaCorrectionWithoutAlphaCalcKernel() const;
|
||||
const string& GammaCorrectionWithoutAlphaCalcEntryPoint() const;
|
||||
|
||||
const string& FinalAccumEarlyClipKernel() const;
|
||||
const string& FinalAccumEarlyClipEntryPoint() const;
|
||||
const string& FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel() const;
|
||||
const string& FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumEntryPoint() const;
|
||||
const string& FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel() const;
|
||||
const string& FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumEntryPoint() const;
|
||||
|
||||
const string& FinalAccumLateClipKernel() const;
|
||||
const string& FinalAccumLateClipEntryPoint() const;
|
||||
const string& FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel() const;
|
||||
const string& FinalAccumLateClipWithAlphaCalcWithAlphaAccumEntryPoint() const;
|
||||
const string& FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel() const;
|
||||
const string& FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumEntryPoint() const;
|
||||
const string& GammaCorrectionEntryPoint(size_t channels, bool transparency) const;
|
||||
const string& GammaCorrectionKernel(size_t channels, bool transparency) const;
|
||||
const string& FinalAccumEntryPoint(bool earlyClip, size_t channels, bool transparency, double& alphaBase, double& alphaScale) const;
|
||||
const string& FinalAccumKernel(bool earlyClip, size_t channels, bool transparency) const;
|
||||
const string& GammaCorrectionEntryPoint() const;
|
||||
const string& GammaCorrectionKernel() const;
|
||||
const string& FinalAccumEntryPoint(bool earlyClip) const;
|
||||
const string& FinalAccumKernel(bool earlyClip) const;
|
||||
|
||||
private:
|
||||
string CreateFinalAccumKernelString(bool earlyClip, size_t channels, bool transparency);
|
||||
string CreateGammaCorrectionKernelString(bool alphaCalc);
|
||||
string CreateFinalAccumKernelString(bool earlyClip);
|
||||
string CreateGammaCorrectionKernelString();
|
||||
|
||||
string CreateFinalAccumKernelString(bool earlyClip, bool alphaCalc, bool alphaAccum);
|
||||
string CreateGammaCorrectionFunctionString(bool globalBucket, bool alphaCalc, bool alphaAccum, bool finalOut);
|
||||
string CreateGammaCorrectionFunctionString(bool globalBucket, bool finalOut);
|
||||
string CreateCalcNewRgbFunctionString(bool globalBucket);
|
||||
|
||||
string m_GammaCorrectionWithAlphaCalcKernel;
|
||||
string m_GammaCorrectionWithAlphaCalcEntryPoint = "GammaCorrectionWithAlphaCalcKernel";
|
||||
|
||||
string m_GammaCorrectionWithoutAlphaCalcKernel;
|
||||
string m_GammaCorrectionWithoutAlphaCalcEntryPoint = "GammaCorrectionWithoutAlphaCalcKernel";
|
||||
|
||||
string m_FinalAccumEarlyClipKernel;//False, false.
|
||||
string m_FinalAccumEarlyClipEntryPoint = "FinalAccumEarlyClipKernel";
|
||||
string m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel;//True, true.
|
||||
string m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel";
|
||||
string m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel;//False, true.
|
||||
string m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel;
|
||||
string m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel";
|
||||
|
||||
string m_FinalAccumLateClipKernel;//False, false.
|
||||
string m_FinalAccumLateClipEntryPoint = "FinalAccumLateClipKernel";
|
||||
string m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel;//True, true.
|
||||
string m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel";
|
||||
string m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel;//False, true.
|
||||
string m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel;
|
||||
string m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel";
|
||||
|
||||
string m_Empty;
|
||||
|
@ -40,7 +40,6 @@ void RendererCL<T, bucketT>::Init()
|
||||
{
|
||||
m_Init = false;
|
||||
m_DoublePrecision = typeid(T) == typeid(double);
|
||||
m_NumChannels = 4;
|
||||
//Buffer names.
|
||||
m_EmberBufferName = "Ember";
|
||||
m_XformsBufferName = "Xforms";
|
||||
@ -73,7 +72,7 @@ void RendererCL<T, bucketT>::Init()
|
||||
m_PaletteFormat.image_channel_order = CL_RGBA;
|
||||
m_PaletteFormat.image_channel_data_type = CL_FLOAT;
|
||||
m_FinalFormat.image_channel_order = CL_RGBA;
|
||||
m_FinalFormat.image_channel_data_type = CL_UNORM_INT8;//Change if this ever supports 2BPC outputs for PNG.
|
||||
m_FinalFormat.image_channel_data_type = CL_FLOAT;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -386,7 +385,7 @@ const string& RendererCL<T, bucketT>::DEKernel() const { return m_DEOpenCLKernel
|
||||
/// </summary>
|
||||
/// <returns>The string representation of the kernel for the last built final accumulation program.</returns>
|
||||
template <typename T, typename bucketT>
|
||||
const string& RendererCL<T, bucketT>::FinalAccumKernel() const { return m_FinalAccumOpenCLKernelCreator.FinalAccumKernel(EarlyClip(), Renderer<T, bucketT>::NumChannels(), Transparency()); }
|
||||
const string& RendererCL<T, bucketT>::FinalAccumKernel() const { return m_FinalAccumOpenCLKernelCreator.FinalAccumKernel(EarlyClip()); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the a const referece to the devices this renderer will use.
|
||||
@ -407,7 +406,7 @@ const vector<unique_ptr<RendererClDevice>>& RendererCL<T, bucketT>::Devices() co
|
||||
/// <param name="pixels">The host side buffer to read into</param>
|
||||
/// <returns>True if success, else false.</returns>
|
||||
template <typename T, typename bucketT>
|
||||
bool RendererCL<T, bucketT>::ReadFinal(byte* pixels)
|
||||
bool RendererCL<T, bucketT>::ReadFinal(v4F* pixels)
|
||||
{
|
||||
if (pixels && !m_Devices.empty())
|
||||
return m_Devices[0]->m_Wrapper.ReadImage(m_FinalImageName, FinalRasW(), FinalRasH(), 0, m_Devices[0]->m_Wrapper.Shared(), pixels);
|
||||
@ -423,7 +422,7 @@ bool RendererCL<T, bucketT>::ReadFinal(byte* pixels)
|
||||
template <typename T, typename bucketT>
|
||||
bool RendererCL<T, bucketT>::ClearFinal()
|
||||
{
|
||||
vector<byte> v;
|
||||
vector<v4F> v;
|
||||
|
||||
if (!m_Devices.empty())
|
||||
{
|
||||
@ -470,17 +469,6 @@ bool RendererCL<T, bucketT>::Ok() const
|
||||
return !m_Devices.empty() && m_Init;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to force num channels to be 4 because RGBA is always used for OpenCL
|
||||
/// since the output is actually an image rather than just a buffer.
|
||||
/// </summary>
|
||||
/// <param name="numChannels">The number of channels, ignored.</param>
|
||||
template <typename T, typename bucketT>
|
||||
void RendererCL<T, bucketT>::NumChannels(size_t numChannels)
|
||||
{
|
||||
m_NumChannels = 4;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear the error report for this class as well as the OpenCLWrapper members of each device.
|
||||
/// </summary>
|
||||
@ -771,7 +759,7 @@ eRenderStatus RendererCL<T, bucketT>::GaussianDensityFilter()
|
||||
/// <param name="finalOffset">Offset in the buffer to store the pixels to</param>
|
||||
/// <returns>True if success and not aborted, else false.</returns>
|
||||
template <typename T, typename bucketT>
|
||||
eRenderStatus RendererCL<T, bucketT>::AccumulatorToFinalImage(byte* pixels, size_t finalOffset)
|
||||
eRenderStatus RendererCL<T, bucketT>::AccumulatorToFinalImage(v4F* pixels, size_t finalOffset)
|
||||
{
|
||||
auto status = RunFinalAccum();
|
||||
|
||||
@ -877,17 +865,6 @@ EmberStats RendererCL<T, bucketT>::Iterate(size_t iterCount, size_t temporalSamp
|
||||
return stats;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override which just passes false to the base.
|
||||
/// This is because curves are scaled from 0-1 to 0-255 or 0-65535 on the CPU, but need to be kept as 0-1 for OpenCL because the texture expects normalized values.
|
||||
/// </summary>
|
||||
/// <param name="scale">Ignored</param>
|
||||
template <typename T, typename bucketT>
|
||||
void RendererCL<T, bucketT>::ComputeCurves(bool scale)
|
||||
{
|
||||
Renderer<T, bucketT>::ComputeCurves(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private functions for making and running OpenCL programs.
|
||||
/// </summary>
|
||||
@ -1304,9 +1281,7 @@ eRenderStatus RendererCL<T, bucketT>::RunFinalAccum()
|
||||
{
|
||||
//Timing t(4);
|
||||
bool b = true;
|
||||
double alphaBase;
|
||||
double alphaScale;
|
||||
int accumKernelIndex = MakeAndGetFinalAccumProgram(alphaBase, alphaScale);
|
||||
int accumKernelIndex = MakeAndGetFinalAccumProgram();
|
||||
cl_uint argIndex;
|
||||
size_t gridW;
|
||||
size_t gridH;
|
||||
@ -1323,7 +1298,7 @@ eRenderStatus RendererCL<T, bucketT>::RunFinalAccum()
|
||||
|
||||
if (b && !(b = wrapper.AddAndWriteBuffer(m_SpatialFilterParamsBufferName, reinterpret_cast<void*>(&m_SpatialFilterCL), sizeof(m_SpatialFilterCL)))) { AddToReport(loc); }
|
||||
|
||||
if (b && !(b = wrapper.AddAndWriteBuffer(m_CurvesCsaName, m_Csa.data(), SizeOf(m_Csa)))) { AddToReport(loc); }
|
||||
if (b && !(b = wrapper.AddAndWriteBuffer(m_CurvesCsaName, m_Csa.data(), SizeOf(m_Csa)))) { AddToReport(loc); }
|
||||
|
||||
//Since early clip requires gamma correcting the entire accumulator first,
|
||||
//it can't be done inside of the normal final accumulation kernel, so
|
||||
@ -1373,10 +1348,6 @@ eRenderStatus RendererCL<T, bucketT>::RunFinalAccum()
|
||||
|
||||
if (b && !(b = wrapper.SetArg (accumKernelIndex, argIndex++, curvesSet))) { AddToReport(loc); }//Do curves.
|
||||
|
||||
if (b && !(b = wrapper.SetArg (accumKernelIndex, argIndex++, bucketT(alphaBase)))) { AddToReport(loc); }//Alpha base.
|
||||
|
||||
if (b && !(b = wrapper.SetArg (accumKernelIndex, argIndex++, bucketT(alphaScale)))) { AddToReport(loc); }//Alpha scale.
|
||||
|
||||
if (b && wrapper.Shared())
|
||||
if (b && !(b = wrapper.EnqueueAcquireGLObjects(m_FinalImageName))) { AddToReport(loc); }
|
||||
|
||||
@ -1534,26 +1505,22 @@ int RendererCL<T, bucketT>::MakeAndGetDensityFilterProgram(size_t ss, uint filte
|
||||
|
||||
/// <summary>
|
||||
/// Make the final accumulation on the primary device program and return its index.
|
||||
/// There are many different kernels for final accum, depending on early clip, alpha channel, and transparency.
|
||||
/// Loading all of these in the beginning is too much, so only load the one for the current case being worked with.
|
||||
/// </summary>
|
||||
/// <param name="alphaBase">Storage for the alpha base value used in the kernel. 0 if transparency is true, else 255.</param>
|
||||
/// <param name="alphaScale">Storage for the alpha scale value used in the kernel. 255 if transparency is true, else 0.</param>
|
||||
/// <returns>The kernel index if successful, else -1.</returns>
|
||||
template <typename T, typename bucketT>
|
||||
int RendererCL<T, bucketT>::MakeAndGetFinalAccumProgram(double& alphaBase, double& alphaScale)
|
||||
int RendererCL<T, bucketT>::MakeAndGetFinalAccumProgram()
|
||||
{
|
||||
int kernelIndex = -1;
|
||||
|
||||
if (!m_Devices.empty())
|
||||
{
|
||||
auto& wrapper = m_Devices[0]->m_Wrapper;
|
||||
auto& finalAccumEntryPoint = m_FinalAccumOpenCLKernelCreator.FinalAccumEntryPoint(EarlyClip(), Renderer<T, bucketT>::NumChannels(), Transparency(), alphaBase, alphaScale);
|
||||
auto& finalAccumEntryPoint = m_FinalAccumOpenCLKernelCreator.FinalAccumEntryPoint(EarlyClip());
|
||||
const char* loc = __FUNCTION__;
|
||||
|
||||
if ((kernelIndex = wrapper.FindKernelIndex(finalAccumEntryPoint)) == -1)//Has not been built yet.
|
||||
{
|
||||
auto& kernel = m_FinalAccumOpenCLKernelCreator.FinalAccumKernel(EarlyClip(), Renderer<T, bucketT>::NumChannels(), Transparency());
|
||||
auto& kernel = m_FinalAccumOpenCLKernelCreator.FinalAccumKernel(EarlyClip());
|
||||
|
||||
if (wrapper.AddProgram(finalAccumEntryPoint, kernel, finalAccumEntryPoint, m_DoublePrecision))
|
||||
kernelIndex = wrapper.FindKernelIndex(finalAccumEntryPoint);//Try to find it again, it will be present if successfully built.
|
||||
@ -1575,13 +1542,13 @@ int RendererCL<T, bucketT>::MakeAndGetGammaCorrectionProgram()
|
||||
if (!m_Devices.empty())
|
||||
{
|
||||
auto& wrapper = m_Devices[0]->m_Wrapper;
|
||||
auto& gammaEntryPoint = m_FinalAccumOpenCLKernelCreator.GammaCorrectionEntryPoint(Renderer<T, bucketT>::NumChannels(), Transparency());
|
||||
auto& gammaEntryPoint = m_FinalAccumOpenCLKernelCreator.GammaCorrectionEntryPoint();
|
||||
int kernelIndex = wrapper.FindKernelIndex(gammaEntryPoint);
|
||||
const char* loc = __FUNCTION__;
|
||||
|
||||
if (kernelIndex == -1)//Has not been built yet.
|
||||
{
|
||||
auto& kernel = m_FinalAccumOpenCLKernelCreator.GammaCorrectionKernel(Renderer<T, bucketT>::NumChannels(), Transparency());
|
||||
auto& kernel = m_FinalAccumOpenCLKernelCreator.GammaCorrectionKernel();
|
||||
bool b = wrapper.AddProgram(gammaEntryPoint, kernel, gammaEntryPoint, m_DoublePrecision);
|
||||
|
||||
if (b)
|
||||
@ -1735,10 +1702,7 @@ void RendererCL<T, bucketT>::ConvertSpatialFilter()
|
||||
m_SpatialFilterCL.m_FinalRasH = uint(FinalRasH());
|
||||
m_SpatialFilterCL.m_Supersample = uint(Supersample());
|
||||
m_SpatialFilterCL.m_FilterWidth = uint(m_SpatialFilter->FinalFilterWidth());
|
||||
m_SpatialFilterCL.m_NumChannels = uint(Renderer<T, bucketT>::NumChannels());
|
||||
m_SpatialFilterCL.m_BytesPerChannel = uint(BytesPerChannel());
|
||||
m_SpatialFilterCL.m_DensityFilterOffset = uint(DensityFilterOffset());
|
||||
m_SpatialFilterCL.m_Transparency = Transparency();
|
||||
m_SpatialFilterCL.m_YAxisUp = uint(m_YAxisUp);
|
||||
m_SpatialFilterCL.m_Vibrancy = vibrancy;
|
||||
m_SpatialFilterCL.m_HighlightPower = HighlightPower();
|
||||
|
@ -19,7 +19,7 @@ class EMBERCL_API RendererCLBase
|
||||
{
|
||||
public:
|
||||
virtual ~RendererCLBase() { }
|
||||
virtual bool ReadFinal(byte* pixels) = 0;
|
||||
virtual bool ReadFinal(v4F* pixels) = 0;
|
||||
virtual bool ClearFinal() = 0;
|
||||
};
|
||||
|
||||
@ -43,7 +43,6 @@ class EMBERCL_API RendererCL : public Renderer<T, bucketT>, public RendererCLBas
|
||||
{
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::Abort;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::EarlyClip;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::Transparency;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::EnterResize;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::LeaveResize;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::FinalRasW;
|
||||
@ -60,7 +59,6 @@ class EMBERCL_API RendererCL : public Renderer<T, bucketT>, public RendererCLBas
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::m_YAxisUp;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::m_LockAccum;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::m_Abort;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::m_NumChannels;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::m_LastIter;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::m_LastIterPercent;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::m_Stats;
|
||||
@ -141,13 +139,12 @@ public:
|
||||
const vector<unique_ptr<RendererClDevice>>& Devices() const;
|
||||
|
||||
//Virtual functions overridden from RendererCLBase.
|
||||
virtual bool ReadFinal(byte* pixels);
|
||||
virtual bool ReadFinal(v4F* pixels);
|
||||
virtual bool ClearFinal();
|
||||
|
||||
//Public virtual functions overridden from Renderer or RendererBase.
|
||||
virtual size_t MemoryAvailable() override;
|
||||
virtual bool Ok() const override;
|
||||
virtual void NumChannels(size_t numChannels) override;
|
||||
virtual void ClearErrorReport() override;
|
||||
virtual size_t SubBatchSize() const override;
|
||||
virtual size_t ThreadCount() const override;
|
||||
@ -166,9 +163,8 @@ protected:
|
||||
virtual bool ResetBuckets(bool resetHist = true, bool resetAccum = true) override;
|
||||
virtual eRenderStatus LogScaleDensityFilter(bool forceOutput = false) override;
|
||||
virtual eRenderStatus GaussianDensityFilter() override;
|
||||
virtual eRenderStatus AccumulatorToFinalImage(byte* pixels, size_t finalOffset) override;
|
||||
virtual eRenderStatus AccumulatorToFinalImage(v4F* pixels, size_t finalOffset) override;
|
||||
virtual EmberStats Iterate(size_t iterCount, size_t temporalSample) override;
|
||||
virtual void ComputeCurves(bool scale) override;
|
||||
|
||||
#ifndef TEST_CL
|
||||
private:
|
||||
@ -183,7 +179,7 @@ private:
|
||||
bool ClearBuffer(size_t device, const string& bufferName, uint width, uint height, uint elementSize);
|
||||
bool RunDensityFilterPrivate(size_t kernelIndex, size_t gridW, size_t gridH, size_t blockW, size_t blockH, uint chunkSizeW, uint chunkSizeH, uint colChunkPass, uint rowChunkPass);
|
||||
int MakeAndGetDensityFilterProgram(size_t ss, uint filterWidth);
|
||||
int MakeAndGetFinalAccumProgram(double& alphaBase, double& alphaScale);
|
||||
int MakeAndGetFinalAccumProgram();
|
||||
int MakeAndGetGammaCorrectionProgram();
|
||||
bool CreateHostBuffer();
|
||||
bool SumDeviceHist();
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "EmberCommonPch.h"
|
||||
#include "EmberOptions.h"
|
||||
|
||||
/// <summary>
|
||||
/// Global utility classes and functions that are common to all programs that use
|
||||
@ -168,26 +169,133 @@ void FormatName(Ember<T>& result, ostringstream& os, streamsize padding)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert an RGBA buffer to an RGB buffer.
|
||||
/// Convert an RGBA 32-bit float buffer to an RGB 8-bit buffer.
|
||||
/// The two buffers can point to the same memory location if needed.
|
||||
/// </summary>
|
||||
/// <param name="rgba">The RGBA buffer</param>
|
||||
/// <param name="rgb">The RGB buffer</param>
|
||||
/// <param name="rgba">The RGBA 32-bit float buffer</param>
|
||||
/// <param name="rgb">The RGB 8-bit buffer</param>
|
||||
/// <param name="width">The width of the image in pixels</param>
|
||||
/// <param name="height">The height of the image in pixels</param>
|
||||
static void RgbaToRgb(vector<byte>& rgba, vector<byte>& rgb, size_t width, size_t height)
|
||||
static void Rgba32ToRgb8(v4F* rgba, byte* rgb, size_t width, size_t height)
|
||||
{
|
||||
if (rgba.data() != rgb.data())//Only resize the destination buffer if they are different.
|
||||
rgb.resize(width * height * 3);
|
||||
|
||||
for (size_t i = 0, j = 0; i < (width * height * 4); i += 4, j += 3)
|
||||
for (size_t i = 0, j = 0; i < (width * height); i++)
|
||||
{
|
||||
rgb[j] = rgba[i];
|
||||
rgb[j + 1] = rgba[i + 1];
|
||||
rgb[j + 2] = rgba[i + 2];
|
||||
rgb[j++] = byte(Clamp<float>(rgba[i].r * 255.0f, 0.0f, 255.0f));
|
||||
rgb[j++] = byte(Clamp<float>(rgba[i].g * 255.0f, 0.0f, 255.0f));
|
||||
rgb[j++] = byte(Clamp<float>(rgba[i].b * 255.0f, 0.0f, 255.0f));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert an RGBA 32-bit float buffer to an RGBA 8-bit buffer.
|
||||
/// The two buffers can point to the same memory location if needed.
|
||||
/// </summary>
|
||||
/// <param name="rgba">The RGBA 32-bit float buffer</param>
|
||||
/// <param name="rgb">The RGBA 8-bit buffer</param>
|
||||
/// <param name="width">The width of the image in pixels</param>
|
||||
/// <param name="height">The height of the image in pixels</param>
|
||||
/// <param name="doAlpha">True to use alpha transparency, false to assign the max alpha value to make each pixel fully visible</param>
|
||||
static void Rgba32ToRgba8(v4F* rgba, byte* rgb, size_t width, size_t height, bool doAlpha)
|
||||
{
|
||||
for (size_t i = 0, j = 0; i < (width * height); i++)
|
||||
{
|
||||
rgb[j++] = byte(Clamp<float>(rgba[i].r * 255.0f, 0.0f, 255.0f));
|
||||
rgb[j++] = byte(Clamp<float>(rgba[i].g * 255.0f, 0.0f, 255.0f));
|
||||
rgb[j++] = byte(Clamp<float>(rgba[i].b * 255.0f, 0.0f, 255.0f));
|
||||
rgb[j++] = doAlpha ? byte(Clamp<float>(rgba[i].a * 255.0f, 0.0f, 255.0f)) : 255;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert an RGBA 32-bit float buffer to an RGBA 16-bit buffer.
|
||||
/// The two buffers can point to the same memory location if needed.
|
||||
/// </summary>
|
||||
/// <param name="rgba">The RGBA 32-bit float buffer</param>
|
||||
/// <param name="rgb">The RGBA 16-bit buffer</param>
|
||||
/// <param name="width">The width of the image in pixels</param>
|
||||
/// <param name="height">The height of the image in pixels</param>
|
||||
/// <param name="doAlpha">True to use alpha transparency, false to assign the max alpha value to make each pixel fully visible</param>
|
||||
static void Rgba32ToRgba16(v4F* rgba, glm::uint16* rgb, size_t width, size_t height, bool doAlpha)
|
||||
{
|
||||
for (size_t i = 0, j = 0; i < (width * height); i++)
|
||||
{
|
||||
rgb[j++] = glm::uint16(Clamp<float>(rgba[i].r * 65535.0f, 0.0f, 65535.0f));
|
||||
rgb[j++] = glm::uint16(Clamp<float>(rgba[i].g * 65535.0f, 0.0f, 65535.0f));
|
||||
rgb[j++] = glm::uint16(Clamp<float>(rgba[i].b * 65535.0f, 0.0f, 65535.0f));
|
||||
rgb[j++] = doAlpha ? glm::uint16(Clamp<float>(rgba[i].a * 65535.0f, 0.0f, 65535.0f)) : glm::uint16(65535);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert an RGBA 32-bit float buffer to an EXR RGBA 32-bit float buffer.
|
||||
/// The two buffers can point to the same memory location if needed.
|
||||
/// </summary>
|
||||
/// <param name="rgba">The RGBA 32-bit float buffer</param>
|
||||
/// <param name="rgb">The EXR RGBA 32-bit float buffer</param>
|
||||
/// <param name="width">The width of the image in pixels</param>
|
||||
/// <param name="height">The height of the image in pixels</param>
|
||||
/// <param name="doAlpha">True to use alpha transparency, false to assign the max alpha value to make each pixel fully visible</param>
|
||||
static void Rgba32ToRgbaExr(v4F* rgba, Rgba* ilmfRgba, size_t width, size_t height, bool doAlpha)
|
||||
{
|
||||
for (size_t i = 0; i < (width * height); i++)
|
||||
{
|
||||
ilmfRgba[i].r = Clamp<float>(rgba[i].r, 0.0f, 1.0f);
|
||||
ilmfRgba[i].g = Clamp<float>(rgba[i].g, 0.0f, 1.0f);
|
||||
ilmfRgba[i].b = Clamp<float>(rgba[i].b, 0.0f, 1.0f);
|
||||
ilmfRgba[i].a = doAlpha ? Clamp<float>(rgba[i].a * 1.0f, 0.0f, 1.0f) : 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make a filename for a single render. This is used in EmberRender.
|
||||
/// </summary>
|
||||
/// <param name="path">The path portion of where to save the file</param>
|
||||
/// <param name="out">The full name and path to override everything else</param>
|
||||
/// <param name="finalName">The name to use when useFinalName is true</param>
|
||||
/// <param name="prefix">The prefix to prepend to the filename</param>
|
||||
/// <param name="suffix">True suffix to append to the filename</param>
|
||||
/// <param name="format">The format extention. This must not contain a period.</param>
|
||||
/// <param name="padding">The width padding to use, which will be zero filled.</param>
|
||||
/// <param name="i">The numerical value to use for the filename when useFinalName is false and out is empty</param>
|
||||
/// <param name="useFinalName">Whether to use the name included in the flame. The i parameter is ignored in this case.</param>
|
||||
static string MakeSingleFilename(const string& path, const string& out, const string& finalName, const string& prefix, const string& suffix, const string& format, glm::uint padding, size_t i, bool useFinalName)
|
||||
{
|
||||
string filename;
|
||||
|
||||
if (!out.empty())
|
||||
{
|
||||
filename = out;
|
||||
}
|
||||
else if (useFinalName)
|
||||
{
|
||||
filename = path + prefix + finalName + suffix + "." + format;
|
||||
}
|
||||
else
|
||||
{
|
||||
ostringstream fnstream;
|
||||
fnstream << path << prefix << setfill('0') << setprecision(0) << fixed << setw(padding) << i << suffix << "." << format;
|
||||
filename = fnstream.str();
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make a filename for a frame of an animation render. This is used in EmberAnimate.
|
||||
/// </summary>
|
||||
/// <param name="path">The path portion of where to save the file</param>
|
||||
/// <param name="prefix">The prefix to prepend to the filename</param>
|
||||
/// <param name="suffix">True suffix to append to the filename</param>
|
||||
/// <param name="format">The format extention. This must contain a period.</param>
|
||||
/// <param name="padding">The width padding to use, which will be zero filled.</param>
|
||||
/// <param name="ftime">The numerical value to use for the filename</param>
|
||||
static string MakeAnimFilename(const string& path, const string& prefix, const string& suffix, const string& format, glm::uint padding, size_t ftime)
|
||||
{
|
||||
ostringstream fnstream;
|
||||
fnstream << path << prefix << setfill('0') << setprecision(0) << fixed << setw(padding) << ftime << suffix << format;
|
||||
return fnstream.str();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the number of strips required if the needed amount of memory
|
||||
/// is greater than the system memory, or greater than what the user wants to allow.
|
||||
@ -439,7 +547,7 @@ static vector<unique_ptr<Renderer<T, float>>> CreateRenderers(eRendererType rend
|
||||
/// <param name="allStripsFinished">Function called when all strips successfully finish rendering</param>
|
||||
/// <returns>True if all rendering was successful, else false.</returns>
|
||||
template <typename T>
|
||||
static bool StripsRender(RendererBase* renderer, Ember<T>& ember, vector<byte>& finalImage, double time, size_t strips, bool yAxisUp,
|
||||
static bool StripsRender(RendererBase* renderer, Ember<T>& ember, vector<v4F>& finalImage, double time, size_t strips, bool yAxisUp,
|
||||
std::function<void(size_t strip)> perStripStart,
|
||||
std::function<void(size_t strip)> perStripFinish,
|
||||
std::function<void(size_t strip)> perStripError,
|
||||
|
@ -57,5 +57,17 @@
|
||||
#include "SimpleGlob.h"
|
||||
#include "SimpleOpt.h"
|
||||
|
||||
//Exr
|
||||
#ifdef _WIN32
|
||||
#define OPENEXR_DLL 1
|
||||
#endif
|
||||
|
||||
#include <ImfRgbaFile.h>
|
||||
#include <ImfStringAttribute.h>
|
||||
#include <half.h>
|
||||
|
||||
using namespace Imf;
|
||||
using namespace Imath;
|
||||
|
||||
using namespace EmberNs;
|
||||
using namespace EmberCLns;
|
||||
|
@ -58,8 +58,7 @@ enum class eOptionIDs : et
|
||||
OPT_INT_PALETTE,
|
||||
OPT_HEX_PALETTE,
|
||||
OPT_INSERT_PALETTE,
|
||||
OPT_JPEG_COMMENTS,
|
||||
OPT_PNG_COMMENTS,
|
||||
OPT_ENABLE_COMMENTS,
|
||||
OPT_WRITE_GENOME,
|
||||
OPT_THREADED_WRITE,
|
||||
OPT_ENCLOSED,
|
||||
@ -75,7 +74,6 @@ enum class eOptionIDs : et
|
||||
OPT_STRIPS,
|
||||
OPT_SUPERSAMPLE,
|
||||
OPT_TEMPSAMPLES,
|
||||
OPT_BPC,
|
||||
OPT_PRINT_EDIT_DEPTH,
|
||||
OPT_JPEG,
|
||||
OPT_BEGIN,
|
||||
@ -363,8 +361,7 @@ public:
|
||||
INITBOOLOPTION(NameEnable, Eob(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_NAME_ENABLE, _T("--name_enable"), false, SO_NONE, " --name_enable Use the name attribute contained in the Xml as the output filename [default: false].\n"));
|
||||
INITBOOLOPTION(HexPalette, Eob(eOptionUse::OPT_ANIM_GENOME, eOptionIDs::OPT_HEX_PALETTE, _T("--hex_palette"), true, SO_OPT, " --hex_palette Force palette RGB values to be hex when saving to Xml [default: true].\n"));
|
||||
INITBOOLOPTION(InsertPalette, Eob(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_INSERT_PALETTE, _T("--insert_palette"), false, SO_NONE, " --insert_palette Insert the palette into the image for debugging purposes. Disabled when running with OpenCL [default: false].\n"));
|
||||
INITBOOLOPTION(JpegComments, Eob(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_JPEG_COMMENTS, _T("--enable_jpg_comments"), false, SO_NONE, " --enable_jpg_comments Enables embedding the flame parameters and user identifying information in the jpeg header [default: false].\n"));
|
||||
INITBOOLOPTION(PngComments, Eob(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_PNG_COMMENTS, _T("--enable_png_comments"), false, SO_NONE, " --enable_png_comments Enables embedding the flame parameters and user identifying information in the png header [default: false].\n"));
|
||||
INITBOOLOPTION(EnableComments, Eob(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_ENABLE_COMMENTS, _T("--enable_comments"), false, SO_NONE, " --enable_comments Enables embedding the flame parameters and user identifying information in the header of a jpg, png or exr [default: false].\n"));
|
||||
INITBOOLOPTION(WriteGenome, Eob(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_WRITE_GENOME, _T("--write_genome"), false, SO_NONE, " --write_genome Write out flame associated with center of motion blur window [default: false].\n"));
|
||||
INITBOOLOPTION(ThreadedWrite, Eob(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_THREADED_WRITE, _T("--threaded_write"), true, SO_OPT, " --threaded_write Use a separate thread to write images to disk. This gives better performance, but doubles the memory required for the final output buffer. [default: true].\n"));
|
||||
INITBOOLOPTION(Enclosed, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_ENCLOSED, _T("--enclosed"), true, SO_OPT, " --enclosed Use enclosing Xml tags [default: true].\n"));
|
||||
@ -388,7 +385,6 @@ public:
|
||||
INITUINTOPTION(Strips, Eou(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_STRIPS, _T("--nstrips"), 1, SO_REQ_SEP, " --nstrips=<val> The number of fractions to split a single render frame into. Useful for print size renders or low memory systems [default: 1].\n"));
|
||||
INITUINTOPTION(Supersample, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_SUPERSAMPLE, _T("--supersample"), 0, SO_REQ_SEP, " --supersample=<val> The supersample value used to override the one specified in the file [default: 0 (use value from file), Range: 0 - 4].\n"));
|
||||
INITUINTOPTION(TemporalSamples, Eou(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_TEMPSAMPLES, _T("--ts"), 0, SO_REQ_SEP, " --ts=<val> The temporal samples value used to override all of the temporal sample values specified in the file when animating [default: 0 (use value from file)].\n"));
|
||||
INITUINTOPTION(BitsPerChannel, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_BPC, _T("--bpc"), 8, SO_REQ_SEP, " --bpc=<val> Bits per channel. 8 or 16 for PNG, 8 for all others, always 8 with OpenCL [default: 8].\n"));
|
||||
INITUINTOPTION(PrintEditDepth, Eou(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PRINT_EDIT_DEPTH, _T("--print_edit_depth"), 0, SO_REQ_SEP, " --print_edit_depth=<val> Depth to truncate <edit> tag structure when converting a flame to Xml. 0 prints all <edit> tags [default: 0].\n"));
|
||||
INITUINTOPTION(JpegQuality, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_JPEG, _T("--jpeg"), 95, SO_REQ_SEP, " --jpeg=<val> Jpeg quality 0-100 for compression [default: 95].\n"));
|
||||
INITUINTOPTION(FirstFrame, Eou(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_BEGIN, _T("--begin"), UINT_MAX, SO_REQ_SEP, " --begin=<val> Time of first frame to render [default: first time specified in file].\n"));
|
||||
@ -431,7 +427,11 @@ public:
|
||||
INITSTRINGOPTION(Out, Eos(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_OUT, _T("--out"), "", SO_REQ_SEP, " --out=<val> Name of a single output file. Not recommended when rendering more than one image.\n"));
|
||||
INITSTRINGOPTION(Prefix, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_PREFIX, _T("--prefix"), "", SO_REQ_SEP, " --prefix=<val> Prefix to prepend to all output files.\n"));
|
||||
INITSTRINGOPTION(Suffix, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_SUFFIX, _T("--suffix"), "", SO_REQ_SEP, " --suffix=<val> Suffix to append to all output files.\n"));
|
||||
INITSTRINGOPTION(Format, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_FORMAT, _T("--format"), "png", SO_REQ_SEP, " --format=<val> Format of the output file. Valid values are: bmp, jpg, png [default: png].\n"));
|
||||
#ifdef _WIN32
|
||||
INITSTRINGOPTION(Format, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_FORMAT, _T("--format"), "png", SO_REQ_SEP, " --format=<val> Format of the output file. Valid values are: bmp, jpg, png or exr [default: png].\n"));
|
||||
#else
|
||||
INITSTRINGOPTION(Format, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_FORMAT, _T("--format"), "png", SO_REQ_SEP, " --format=<val> Format of the output file. Valid values are: jpg, png or exr [default: png].\n"));
|
||||
#endif
|
||||
INITSTRINGOPTION(PalettePath, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PALETTE_FILE, _T("--flam3_palettes"), "flam3-palettes.xml", SO_REQ_SEP, " --flam3_palettes=<val> Path and name of the palette file [default: flam3-palettes.xml].\n"));
|
||||
INITSTRINGOPTION(Id, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_ID, _T("--id"), "", SO_REQ_SEP, " --id=<val> ID to use in <edit> tags / image comments.\n"));
|
||||
INITSTRINGOPTION(Url, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_URL, _T("--url"), "", SO_REQ_SEP, " --url=<val> URL to use in <edit> tags / image comments.\n"));
|
||||
@ -519,8 +519,7 @@ public:
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_NAME_ENABLE, NameEnable);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_HEX_PALETTE, HexPalette);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_INSERT_PALETTE, InsertPalette);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_JPEG_COMMENTS, JpegComments);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_PNG_COMMENTS, PngComments);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_ENABLE_COMMENTS, EnableComments);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_WRITE_GENOME, WriteGenome);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_THREADED_WRITE, ThreadedWrite);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_ENCLOSED, Enclosed);
|
||||
@ -538,7 +537,6 @@ public:
|
||||
PARSEOPTION(eOptionIDs::OPT_STRIPS, Strips);
|
||||
PARSEOPTION(eOptionIDs::OPT_SUPERSAMPLE, Supersample);
|
||||
PARSEOPTION(eOptionIDs::OPT_TEMPSAMPLES, TemporalSamples);
|
||||
PARSEOPTION(eOptionIDs::OPT_BPC, BitsPerChannel);
|
||||
PARSEOPTION(eOptionIDs::OPT_PRINT_EDIT_DEPTH, PrintEditDepth);
|
||||
PARSEOPTION(eOptionIDs::OPT_JPEG, JpegQuality);
|
||||
PARSEOPTION(eOptionIDs::OPT_BEGIN, FirstFrame);
|
||||
@ -723,18 +721,18 @@ public:
|
||||
{
|
||||
cout << "Usage:\n"
|
||||
#ifdef _WIN32
|
||||
"\tEmberRender.exe --in=test.flame [--out=outfile --format=png --verbose --progress --opencl]\n\n";
|
||||
"\tEmberRender.exe --in=test.flame [--out=outfile --verbose --progress --opencl]\n\n";
|
||||
#else
|
||||
"\temberrender --in=test.flame [--out=outfile --format=png --verbose --progress --opencl]\n\n";
|
||||
"\temberrender --in=test.flame [--out=outfile --verbose --progress --opencl]\n\n";
|
||||
#endif
|
||||
}
|
||||
else if (optUsage == eOptionUse::OPT_USE_ANIMATE)
|
||||
{
|
||||
cout << "Usage:\n"
|
||||
#ifdef _WIN32
|
||||
"\tEmberAnimate.exe --in=sequence.flame [--format=png --verbose --progress --opencl]\n\n";
|
||||
"\tEmberAnimate.exe --in=sequence.flame [--verbose --progress --opencl]\n\n";
|
||||
#else
|
||||
"\temberanimate --in=sequence.flame [--format=png --verbose --progress --opencl]\n\n";
|
||||
"\temberanimate --in=sequence.flame [--verbose --progress --opencl]\n\n";
|
||||
#endif
|
||||
}
|
||||
else if (optUsage == eOptionUse::OPT_USE_GENOME)
|
||||
@ -808,8 +806,7 @@ public:
|
||||
Eob NameEnable;
|
||||
Eob HexPalette;
|
||||
Eob InsertPalette;
|
||||
Eob JpegComments;
|
||||
Eob PngComments;
|
||||
Eob EnableComments;
|
||||
Eob WriteGenome;
|
||||
Eob ThreadedWrite;
|
||||
Eob Enclosed;
|
||||
@ -828,7 +825,6 @@ public:
|
||||
Eou Strips;
|
||||
Eou Supersample;
|
||||
Eou TemporalSamples;
|
||||
Eou BitsPerChannel;
|
||||
Eou Bits;
|
||||
Eou PrintEditDepth;
|
||||
Eou JpegQuality;
|
||||
|
@ -136,28 +136,28 @@ static bool WritePng(const char* filename, byte* image, size_t width, size_t hei
|
||||
glm::uint16 testbe = 1;
|
||||
vector<byte*> rows(height);
|
||||
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
text[0].key = const_cast<png_charp>("flam3_version");
|
||||
text[0].key = const_cast<png_charp>("ember_version");
|
||||
text[0].text = const_cast<png_charp>(EmberVersion());
|
||||
text[1].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
text[1].key = const_cast<png_charp>("flam3_nickname");
|
||||
text[1].key = const_cast<png_charp>("ember_nickname");
|
||||
text[1].text = const_cast<png_charp>(nick.c_str());
|
||||
text[2].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
text[2].key = const_cast<png_charp>("flam3_url");
|
||||
text[2].key = const_cast<png_charp>("ember_url");
|
||||
text[2].text = const_cast<png_charp>(url.c_str());
|
||||
text[3].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
text[3].key = const_cast<png_charp>("flam3_id");
|
||||
text[3].key = const_cast<png_charp>("ember_id");
|
||||
text[3].text = const_cast<png_charp>(id.c_str());
|
||||
text[4].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
text[4].key = const_cast<png_charp>("flam3_error_rate");
|
||||
text[4].key = const_cast<png_charp>("ember_error_rate");
|
||||
text[4].text = const_cast<png_charp>(comments.m_Badvals.c_str());
|
||||
text[5].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
text[5].key = const_cast<png_charp>("flam3_samples");
|
||||
text[5].key = const_cast<png_charp>("ember_samples");
|
||||
text[5].text = const_cast<png_charp>(comments.m_NumIters.c_str());
|
||||
text[6].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
text[6].key = const_cast<png_charp>("flam3_time");
|
||||
text[6].key = const_cast<png_charp>("ember_time");
|
||||
text[6].text = const_cast<png_charp>(comments.m_Runtime.c_str());
|
||||
text[7].compression = PNG_TEXT_COMPRESSION_zTXt;
|
||||
text[7].key = const_cast<png_charp>("flam3_genome");
|
||||
text[7].key = const_cast<png_charp>("ember_genome");
|
||||
text[7].text = const_cast<png_charp>(comments.m_Genome.c_str());
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
@ -326,3 +326,50 @@ static bool WriteBmp(const char* filename, byte* image, size_t width, size_t hei
|
||||
b = SaveBmp(filename, bgrBuf.data(), width, height, newSize);
|
||||
return b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write an EXR file.
|
||||
/// This is used for extreme color precision because it uses
|
||||
/// floats for each color channel.
|
||||
/// </summary>
|
||||
/// <param name="filename">The full path and name of the file</param>
|
||||
/// <param name="image">Pointer to the image data to write</param>
|
||||
/// <param name="width">Width of the image in pixels</param>
|
||||
/// <param name="height">Height of the image in pixels</param>
|
||||
/// <param name="enableComments">True to embed comments, else false</param>
|
||||
/// <param name="comments">The comment string to embed</param>
|
||||
/// <param name="id">Id of the author</param>
|
||||
/// <param name="url">Url of the author</param>
|
||||
/// <param name="nick">Nickname of the author</param>
|
||||
/// <returns>True if success, else false</returns>
|
||||
static bool WriteExr(const char* filename, Rgba* image, size_t width, size_t height, bool enableComments, const EmberImageComments& comments, const string& id, const string& url, const string& nick)
|
||||
{
|
||||
try
|
||||
{
|
||||
int iw = int(width);
|
||||
int ih = int(height);
|
||||
RgbaOutputFile file(filename, iw, ih, WRITE_RGBA);
|
||||
|
||||
if (enableComments)
|
||||
{
|
||||
auto& header = const_cast<Imf::Header&>(file.header());
|
||||
header.insert("ember_version", StringAttribute(EmberVersion()));
|
||||
header.insert("ember_nickname", StringAttribute(nick));
|
||||
header.insert("ember_url", StringAttribute(url));
|
||||
header.insert("ember_id", StringAttribute(id));
|
||||
header.insert("ember_error_rate", StringAttribute(comments.m_Badvals));
|
||||
header.insert("ember_samples", StringAttribute(comments.m_NumIters));
|
||||
header.insert("ember_time", StringAttribute(comments.m_Runtime));
|
||||
header.insert("ember_genome", StringAttribute(comments.m_Genome));
|
||||
}
|
||||
|
||||
file.setFrameBuffer(image, 1, iw);
|
||||
file.writePixels(ih);
|
||||
return true;
|
||||
}
|
||||
catch (std::exception e)
|
||||
{
|
||||
cout << e.what() << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -171,13 +171,15 @@ bool EmberGenome(EmberOptions& opt)
|
||||
bool exactTimeMatch, randomMode, didColor, seqFlag, random = false;
|
||||
size_t i, i0, i1, rep, val, frame, frameCount, count = 0;
|
||||
size_t ftime, firstFrame, lastFrame;
|
||||
size_t n, tot, totb, totw;
|
||||
T avgPix, fractionBlack, fractionWhite, blend, spread, mix0, mix1;
|
||||
double tot;
|
||||
size_t n, totb, totw;
|
||||
double avgPix;
|
||||
T fractionBlack, fractionWhite, blend, spread, mix0, mix1;
|
||||
string token, filename;
|
||||
ostringstream os, os2;
|
||||
vector<Ember<T>> embers, embers2, templateEmbers;
|
||||
vector<eVariationId> vars, noVars;
|
||||
vector<byte> finalImage;
|
||||
vector<v4F> finalImage;
|
||||
eCrossMode crossMeth;
|
||||
eMutateMode mutMeth;
|
||||
Ember<T> orig, save, selp0, selp1, parent0, parent1;
|
||||
@ -598,7 +600,6 @@ bool EmberGenome(EmberOptions& opt)
|
||||
renderer->YAxisUp(opt.YAxisUp());
|
||||
renderer->LockAccum(opt.LockAccum());
|
||||
renderer->PixelAspectRatio(T(opt.AspectRatio()));
|
||||
renderer->Transparency(opt.Transparency());
|
||||
|
||||
if (opt.Repeat() == 0)
|
||||
{
|
||||
@ -786,19 +787,20 @@ bool EmberGenome(EmberOptions& opt)
|
||||
return false;
|
||||
}
|
||||
|
||||
tot = totb = totw = 0;
|
||||
tot = 0;
|
||||
totb = totw = 0;
|
||||
n = orig.m_FinalRasW * orig.m_FinalRasH;
|
||||
|
||||
for (i = 0; i < 3 * n; i += 3)
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
tot += (finalImage[i] + finalImage[i + 1] + finalImage[i + 2]);
|
||||
tot += (finalImage[i].r + finalImage[i].g + finalImage[i].b);
|
||||
|
||||
if (0 == finalImage[i] && 0 == finalImage[i + 1] && 0 == finalImage[i + 2]) totb++;
|
||||
if (0 == finalImage[i].r && 0 == finalImage[i].g && 0 == finalImage[i].b) totb++;
|
||||
|
||||
if (255 == finalImage[i] && 255 == finalImage[i + 1] && 255 == finalImage[i + 2]) totw++;
|
||||
if (1 == finalImage[i].r && 1 == finalImage[i].g && 1 == finalImage[i].g) totw++;
|
||||
}
|
||||
|
||||
avgPix = (tot / T(3 * n));
|
||||
avgPix = (tot / (3 * n));
|
||||
fractionBlack = totb / T(n);
|
||||
fractionWhite = totw / T(n);
|
||||
|
||||
|
@ -29,17 +29,15 @@ bool EmberRender(EmberOptions& opt)
|
||||
VerbosePrint("Using " << (sizeof(T) == sizeof(float) ? "single" : "double") << " precision.");
|
||||
Timing t;
|
||||
bool writeSuccess = false;
|
||||
byte* finalImagep;
|
||||
uint padding;
|
||||
size_t i, channels;
|
||||
size_t i;
|
||||
size_t strips;
|
||||
size_t iterCount;
|
||||
string filename;
|
||||
string inputPath = GetPath(opt.Input());
|
||||
ostringstream os;
|
||||
pair<size_t, size_t> p;
|
||||
vector<Ember<T>> embers;
|
||||
vector<byte> finalImage;
|
||||
vector<v4F> finalImage;
|
||||
EmberStats stats;
|
||||
EmberReport emberReport;
|
||||
EmberImageComments comments;
|
||||
@ -102,12 +100,6 @@ bool EmberRender(EmberOptions& opt)
|
||||
opt.ThreadCount(1);
|
||||
renderer->ThreadCount(opt.ThreadCount(), opt.IsaacSeed() != "" ? opt.IsaacSeed().c_str() : nullptr);
|
||||
|
||||
if (opt.BitsPerChannel() != 8)
|
||||
{
|
||||
cout << "Bits per channel cannot be anything other than 8 with OpenCL, setting to 8.\n";
|
||||
opt.BitsPerChannel(8);
|
||||
}
|
||||
|
||||
if (opt.InsertPalette())
|
||||
{
|
||||
cout << "Inserting palette not supported with OpenCL, insertion will not take place.\n";
|
||||
@ -115,24 +107,19 @@ bool EmberRender(EmberOptions& opt)
|
||||
}
|
||||
}
|
||||
|
||||
if (opt.Format() != "jpg" &&
|
||||
opt.Format() != "png" &&
|
||||
opt.Format() != "bmp")
|
||||
if (!Find(opt.Format(), "jpg") &&
|
||||
!Find(opt.Format(), "png") &&
|
||||
#ifdef _WIN32
|
||||
!Find(opt.Format(), "bmp") &&
|
||||
#endif
|
||||
!Find(opt.Format(), "exr"))
|
||||
{
|
||||
cout << "Format must be jpg, png, or bmp not " << opt.Format() << ". Setting to jpg.\n";
|
||||
}
|
||||
|
||||
channels = opt.Format() == "png" ? 4 : 3;
|
||||
|
||||
if (opt.BitsPerChannel() == 16 && opt.Format() != "png")
|
||||
{
|
||||
cout << "Support for 16 bits per channel images is only present for the png format. Setting to 8.\n";
|
||||
opt.BitsPerChannel(8);
|
||||
}
|
||||
else if (opt.BitsPerChannel() != 8 && opt.BitsPerChannel() != 16)
|
||||
{
|
||||
cout << "Unexpected bits per channel specified " << opt.BitsPerChannel() << ". Setting to 8.\n";
|
||||
opt.BitsPerChannel(8);
|
||||
#ifdef _WIN32
|
||||
cout << "Format must be bmp, jpg, png, png16 or exr, not " << opt.Format() << ". Setting to png.\n";
|
||||
#else
|
||||
cout << "Format must be jpg, png, png16 or exr, not " << opt.Format() << ". Setting to png.\n";
|
||||
#endif
|
||||
opt.Format("png");
|
||||
}
|
||||
|
||||
if (opt.AspectRatio() < 0)
|
||||
@ -156,9 +143,6 @@ bool EmberRender(EmberOptions& opt)
|
||||
renderer->LockAccum(opt.LockAccum());
|
||||
renderer->InsertPalette(opt.InsertPalette());
|
||||
renderer->PixelAspectRatio(T(opt.AspectRatio()));
|
||||
renderer->Transparency(opt.Transparency());
|
||||
renderer->NumChannels(channels);
|
||||
renderer->BytesPerChannel(opt.BitsPerChannel() / 8);
|
||||
renderer->Priority(eThreadPriority(Clamp<intmax_t>(intmax_t(opt.Priority()), intmax_t(eThreadPriority::LOWEST), intmax_t(eThreadPriority::HIGHEST))));
|
||||
renderer->Callback(opt.DoProgress() ? progress.get() : nullptr);
|
||||
|
||||
@ -282,21 +266,6 @@ bool EmberRender(EmberOptions& opt)
|
||||
//Only write once all strips for this image are finished.
|
||||
[&](Ember<T>& finalEmber)
|
||||
{
|
||||
if (!opt.Out().empty())
|
||||
{
|
||||
filename = opt.Out();
|
||||
}
|
||||
else if (opt.NameEnable() && !finalEmber.m_Name.empty())
|
||||
{
|
||||
filename = inputPath + opt.Prefix() + finalEmber.m_Name + opt.Suffix() + "." + opt.Format();
|
||||
}
|
||||
else
|
||||
{
|
||||
ostringstream fnstream;
|
||||
fnstream << inputPath << opt.Prefix() << setfill('0') << setprecision(0) << fixed << setw(padding) << i << opt.Suffix() << "." << opt.Format();
|
||||
filename = fnstream.str();
|
||||
}
|
||||
|
||||
//TotalIterCount() is actually using ScaledQuality() which does not get reset upon ember assignment,
|
||||
//so it ends up using the correct value for quality * strips.
|
||||
iterCount = renderer->TotalIterCount(1);
|
||||
@ -305,28 +274,116 @@ bool EmberRender(EmberOptions& opt)
|
||||
os << comments.m_NumIters << " / " << iterCount << " (" << std::fixed << std::setprecision(2) << ((double(stats.m_Iters) / double(iterCount)) * 100) << "%)";
|
||||
VerbosePrint("\nIters ran/requested: " + os.str());
|
||||
|
||||
if (!opt.EmberCL()) VerbosePrint("Bad values: " << stats.m_Badvals);
|
||||
if (!opt.EmberCL())
|
||||
VerbosePrint("Bad values: " << stats.m_Badvals);
|
||||
|
||||
VerbosePrint("Render time: " + t.Format(stats.m_RenderMs));
|
||||
VerbosePrint("Pure iter time: " + t.Format(stats.m_IterMs));
|
||||
VerbosePrint("Iters/sec: " << size_t(stats.m_Iters / (stats.m_IterMs / 1000.0)) << "\n");
|
||||
VerbosePrint("Writing " + filename);
|
||||
bool useName = opt.NameEnable() && !finalEmber.m_Name.empty();
|
||||
auto finalImagep = finalImage.data();
|
||||
auto size = finalEmber.m_FinalRasW * finalEmber.m_FinalRasH;
|
||||
bool doBmp = Find(opt.Format(), "bmp");
|
||||
bool doJpg = Find(opt.Format(), "jpg");
|
||||
bool doExr = Find(opt.Format(), "exr");
|
||||
bool doPng8 = Find(opt.Format(), "png");
|
||||
bool doPng16 = Find(opt.Format(), "png16");
|
||||
bool doOnlyPng8 = doPng8 && !doPng16;
|
||||
vector<byte> rgb8Image;
|
||||
vector<std::thread> writeFileThreads;
|
||||
writeFileThreads.reserve(5);
|
||||
|
||||
if ((opt.Format() == "jpg" || opt.Format() == "bmp") && renderer->NumChannels() == 4)
|
||||
RgbaToRgb(finalImage, finalImage, renderer->FinalRasW(), renderer->FinalRasH());
|
||||
if (doBmp || doJpg)
|
||||
{
|
||||
rgb8Image.resize(size * 3);
|
||||
Rgba32ToRgb8(finalImagep, rgb8Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH);
|
||||
|
||||
finalImagep = finalImage.data();
|
||||
writeSuccess = false;
|
||||
if (doBmp)
|
||||
{
|
||||
writeFileThreads.push_back(std::thread([&]()
|
||||
{
|
||||
auto filename = MakeSingleFilename(inputPath, opt.Out(), finalEmber.m_Name, opt.Prefix(), opt.Suffix(), "bmp", padding, i, useName);
|
||||
VerbosePrint("Writing " + filename);
|
||||
writeSuccess = WriteBmp(filename.c_str(), rgb8Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH);
|
||||
|
||||
if (opt.Format() == "png")
|
||||
writeSuccess = WritePng(filename.c_str(), finalImagep, finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, opt.BitsPerChannel() / 8, opt.PngComments(), comments, opt.Id(), opt.Url(), opt.Nick());
|
||||
else if (opt.Format() == "jpg")
|
||||
writeSuccess = WriteJpeg(filename.c_str(), finalImagep, finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, int(opt.JpegQuality()), opt.JpegComments(), comments, opt.Id(), opt.Url(), opt.Nick());
|
||||
else if (opt.Format() == "bmp")
|
||||
writeSuccess = WriteBmp(filename.c_str(), finalImagep, finalEmber.m_FinalRasW, finalEmber.m_FinalRasH);
|
||||
if (!writeSuccess)
|
||||
cout << "Error writing " << filename << "\n";
|
||||
}));
|
||||
}
|
||||
|
||||
if (!writeSuccess)
|
||||
cout << "Error writing " << filename << "\n";
|
||||
if (doJpg)
|
||||
{
|
||||
writeFileThreads.push_back(std::thread([&]()
|
||||
{
|
||||
auto filename = MakeSingleFilename(inputPath, opt.Out(), finalEmber.m_Name, opt.Prefix(), opt.Suffix(), "jpg", padding, i, useName);
|
||||
VerbosePrint("Writing " + filename);
|
||||
writeSuccess = WriteJpeg(filename.c_str(), rgb8Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, int(opt.JpegQuality()), opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick());
|
||||
|
||||
if (!writeSuccess)
|
||||
cout << "Error writing " << filename << "\n";
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (doPng8)
|
||||
{
|
||||
bool doBothPng = doPng16 && (opt.Format().find("png") != opt.Format().rfind("png"));
|
||||
|
||||
if (doBothPng || doOnlyPng8)//8-bit PNG
|
||||
{
|
||||
writeFileThreads.push_back(std::thread([&]()
|
||||
{
|
||||
auto filename = MakeSingleFilename(inputPath, opt.Out(), finalEmber.m_Name, opt.Prefix(), opt.Suffix(), "png", padding, i, useName);
|
||||
VerbosePrint("Writing " + filename);
|
||||
vector<byte> rgba8Image(size * 4);
|
||||
Rgba32ToRgba8(finalImagep, rgba8Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, opt.Transparency());
|
||||
writeSuccess = WritePng(filename.c_str(), rgba8Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, 1, opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick());
|
||||
|
||||
if (!writeSuccess)
|
||||
cout << "Error writing " << filename << "\n";
|
||||
}));
|
||||
}
|
||||
|
||||
if (doPng16)
|
||||
{
|
||||
writeFileThreads.push_back(std::thread([&]()
|
||||
{
|
||||
auto suffix = opt.Suffix();
|
||||
|
||||
if (doBothPng)//Add suffix if they specified both PNG.
|
||||
{
|
||||
VerbosePrint("Doing both PNG formats, so adding suffix _p16 to avoid overwriting the same file.");
|
||||
suffix += "_p16";
|
||||
}
|
||||
|
||||
auto filename = MakeSingleFilename(inputPath, opt.Out(), finalEmber.m_Name, opt.Prefix(), suffix, "png", padding, i, useName);
|
||||
VerbosePrint("Writing " + filename);
|
||||
vector<glm::uint16> rgba16Image(size * 4);
|
||||
Rgba32ToRgba16(finalImagep, rgba16Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, opt.Transparency());
|
||||
writeSuccess = WritePng(filename.c_str(), (byte*)rgba16Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, 2, opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick());
|
||||
|
||||
if (!writeSuccess)
|
||||
cout << "Error writing " << filename << "\n";
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (doExr)
|
||||
{
|
||||
writeFileThreads.push_back(std::thread([&]()
|
||||
{
|
||||
auto filename = MakeSingleFilename(inputPath, opt.Out(), finalEmber.m_Name, opt.Prefix(), opt.Suffix(), "exr", padding, i, useName);
|
||||
VerbosePrint("Writing " + filename);
|
||||
vector<Rgba> rgba32Image(size);
|
||||
Rgba32ToRgbaExr(finalImagep, rgba32Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, opt.Transparency());
|
||||
writeSuccess = WriteExr(filename.c_str(), rgba32Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick());
|
||||
|
||||
if (!writeSuccess)
|
||||
cout << "Error writing " << filename << "\n";
|
||||
}));
|
||||
}
|
||||
|
||||
Join(writeFileThreads);
|
||||
});
|
||||
|
||||
if (opt.EmberCL() && opt.DumpKernel())
|
||||
|
@ -5,6 +5,25 @@
|
||||
#include <list>
|
||||
#include <deque>
|
||||
|
||||
#include <ImfRgbaFile.h>
|
||||
//#include <ImfStringAttribute.h>
|
||||
//#include <ImfMatrixAttribute.h>
|
||||
//#include <ImfArray.h>
|
||||
//#include <ImfChannelList.h>
|
||||
|
||||
//#include "drawImage.h"
|
||||
//
|
||||
//#include <iostream>
|
||||
//#include <algorithm>
|
||||
//
|
||||
//
|
||||
//#include <ImfNamespace.h>
|
||||
//
|
||||
//namespace IMF = Imf;
|
||||
//
|
||||
using namespace Imf;
|
||||
using namespace Imath;
|
||||
|
||||
/// <summary>
|
||||
/// EmberTester is a scratch area used for on the fly testing.
|
||||
/// It may become a more formalized automated testing system
|
||||
@ -17,6 +36,43 @@ using namespace EmberCommon;
|
||||
|
||||
//#define DO_NVIDIA 1
|
||||
|
||||
void writeRgba1(const char filename[],
|
||||
const Rgba* pixels,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
//
|
||||
// Write an RGBA image using class RgbaOutputFile.
|
||||
//
|
||||
// - open the file
|
||||
// - describe the memory layout of the pixels
|
||||
// - store the pixels in the file
|
||||
//
|
||||
//auto& chl = file.header().channels();
|
||||
//chl.findChannel("R")->type = PixelType::FLOAT;
|
||||
//Header header(width, height);
|
||||
//header.channels().insert("R", Channel(IMF::FLOAT));
|
||||
//header.channels().insert("G", Channel(IMF::FLOAT));
|
||||
//header.channels().insert("B", Channel(IMF::FLOAT));
|
||||
////header.channels().insert("A", Channel(IMF::FLOAT));
|
||||
//FrameBuffer frameBuffer;
|
||||
//frameBuffer.insert("Z", // name
|
||||
// Slice(IMF::FLOAT, // type
|
||||
// (char *)zPixels, // base
|
||||
// sizeof(*zPixels) * 1, // xStride
|
||||
// sizeof(*zPixels) * width)); // yStride
|
||||
try
|
||||
{
|
||||
RgbaOutputFile file(filename, width, height, WRITE_RGBA);
|
||||
file.setFrameBuffer(pixels, 1, width);
|
||||
file.writePixels(height);
|
||||
}
|
||||
catch (std::exception e)
|
||||
{
|
||||
cout << e.what() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SaveFinalImage(Renderer<T, T>& renderer, vector<byte>& pixels, char* suffix)
|
||||
{
|
||||
@ -1981,6 +2037,20 @@ int _tmain(int argc, _TCHAR* argv[])
|
||||
vector<Ember<double>> dv;
|
||||
list<Ember<float>> fl;
|
||||
list<Ember<double>> dl;
|
||||
int w = 1000, h = 1000;
|
||||
string filename = ".\\testexr.exr";
|
||||
vector<Rgba> pixels;
|
||||
pixels.resize(w * h);
|
||||
|
||||
for (auto& pix : pixels)
|
||||
{
|
||||
pix.r = 1.0;
|
||||
pix.b = 0.0;
|
||||
pix.a = 1.0;
|
||||
//pix.r = std::numeric_limits<float>::max();
|
||||
}
|
||||
|
||||
writeRgba1(filename.c_str(), pixels.data(), w, h);
|
||||
/* TestFuncs();
|
||||
string line = "title=\"cj_aerie\" smooth=no", delim = " =\"";
|
||||
auto vec = Split(line, delim, true);
|
||||
@ -2008,25 +2078,24 @@ int _tmain(int argc, _TCHAR* argv[])
|
||||
return 1;
|
||||
*/
|
||||
//MakeTestAllVarsRegPrePostComboFile("testallvarsout.flame");
|
||||
/* return 0;
|
||||
return 0;
|
||||
/*
|
||||
TestThreadedKernel();
|
||||
|
||||
auto palf = PaletteList<float>::Instance();
|
||||
Palette<float>* pal = palf->GetRandomPalette();
|
||||
|
||||
TestThreadedKernel();
|
||||
cout << pal->Size() << endl;
|
||||
|
||||
auto palf = PaletteList<float>::Instance();
|
||||
Palette<float>* pal = palf->GetRandomPalette();
|
||||
double d = 1;
|
||||
|
||||
cout << pal->Size() << endl;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
cout << "log10(" << d << ") = " << std::max<uint>(1u, uint(std::log10(d)) + 1u) << endl;
|
||||
d *= 10;
|
||||
}
|
||||
|
||||
double d = 1;
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
cout << "log10(" << d << ") = " << std::max<uint>(1u, uint(std::log10(d)) + 1u) << endl;
|
||||
d *= 10;
|
||||
}
|
||||
|
||||
return 0;*/
|
||||
return 0;*/
|
||||
/*
|
||||
uint i, iters = (uint)10e7;
|
||||
size_t total = 0;
|
||||
|
@ -58,7 +58,7 @@
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="center">Fractorium 1.0.0.4</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><a href="http://fractorium.com"><span style=" text-decoration: underline; color:#0000ff;">fractorium.com</span></a><span style=" font-size:10pt;"><br/>Lead: Matt Feemster<br/>Contributors: Simon Detheridge, Michel Mastriani</span></p></body></html></string>
|
||||
<string><html><head/><body><p align="center">Fractorium 1.0.0.5</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><a href="http://fractorium.com"><span style=" text-decoration: underline; color:#0000ff;">fractorium.com</span></a><span style=" font-size:10pt;"><br/>Lead: Matt Feemster<br/>Contributors: Simon Detheridge, Michel Mastriani</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
|
@ -169,7 +169,7 @@ void DoubleSpinBox::OnTimeout()
|
||||
/// <returns>false</returns>
|
||||
bool DoubleSpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
{
|
||||
QMouseEvent* me = dynamic_cast<QMouseEvent*>(e);
|
||||
auto me = dynamic_cast<QMouseEvent*>(e);
|
||||
|
||||
if (isEnabled() && me)
|
||||
{
|
||||
@ -287,3 +287,124 @@ void DoubleSpinBox::StopTimer()
|
||||
s_Timer.stop();
|
||||
disconnect(&s_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that passes agruments to the base and assigns the m_Param and m_Variation members.
|
||||
/// It also sets up the context menu for special numerical values.
|
||||
/// </summary>
|
||||
/// <param name="p">The parent widget</param>
|
||||
/// <param name="widgetItem">The widget item this spinner is contained in</param>
|
||||
/// <param name="id">The variation this spinner is for</param>
|
||||
/// <param name="param">The name of the parameter this is for</param>
|
||||
/// <param name="h">The height of the spin box. Default: 16.</param>
|
||||
/// <param name="step">The step used to increment/decrement the spin box when using the mouse wheel. Default: 0.05.</param>
|
||||
VariationTreeDoubleSpinBox::VariationTreeDoubleSpinBox(QWidget* p, VariationTreeWidgetItem* widgetItem, eVariationId id, const string& param, int h, double step)
|
||||
: DoubleSpinBox(p, h, step)
|
||||
{
|
||||
m_WidgetItem = widgetItem;
|
||||
m_Param = param;
|
||||
m_Id = id;
|
||||
setDecimals(3);
|
||||
//PI
|
||||
auto piAction = new QAction("PI", this);
|
||||
connect(piAction, SIGNAL(triggered(bool)), this, SLOT(PiActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(piAction);
|
||||
//PI * 2
|
||||
auto twoPiAction = new QAction("2 PI", this);
|
||||
connect(twoPiAction, SIGNAL(triggered(bool)), this, SLOT(TwoPiActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(twoPiAction);
|
||||
//PI / 2
|
||||
auto piOver2Action = new QAction("PI / 2", this);
|
||||
connect(piOver2Action, SIGNAL(triggered(bool)), this, SLOT(PiOver2ActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(piOver2Action);
|
||||
//PI / 3
|
||||
auto piOver3Action = new QAction("PI / 3", this);
|
||||
connect(piOver3Action, SIGNAL(triggered(bool)), this, SLOT(PiOver3ActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(piOver3Action);
|
||||
//PI / 4
|
||||
auto piOver4Action = new QAction("PI / 4", this);
|
||||
connect(piOver4Action, SIGNAL(triggered(bool)), this, SLOT(PiOver4ActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(piOver4Action);
|
||||
//PI / 6
|
||||
auto piOver6Action = new QAction("PI / 6", this);
|
||||
connect(piOver6Action, SIGNAL(triggered(bool)), this, SLOT(PiOver6ActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(piOver6Action);
|
||||
//1 / PI
|
||||
auto oneOverPiAction = new QAction("1 / PI", this);
|
||||
connect(oneOverPiAction, SIGNAL(triggered(bool)), this, SLOT(OneOverPiActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(oneOverPiAction);
|
||||
//2 / PI
|
||||
auto twoOverPiAction = new QAction("2 / PI", this);
|
||||
connect(twoOverPiAction, SIGNAL(triggered(bool)), this, SLOT(TwoOverPiActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(twoOverPiAction);
|
||||
//3 / PI
|
||||
auto threeOverPiAction = new QAction("3 / PI", this);
|
||||
connect(threeOverPiAction, SIGNAL(triggered(bool)), this, SLOT(ThreeOverPiActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(threeOverPiAction);
|
||||
//4 / PI
|
||||
auto fourOverPiAction = new QAction("4 / PI", this);
|
||||
connect(fourOverPiAction, SIGNAL(triggered(bool)), this, SLOT(FourOverPiActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(fourOverPiAction);
|
||||
//Sqrt(2)
|
||||
auto sqrtTwoAction = new QAction("Sqrt(2)", this);
|
||||
connect(sqrtTwoAction, SIGNAL(triggered(bool)), this, SLOT(SqrtTwoActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(sqrtTwoAction);
|
||||
//Sqrt(2)
|
||||
auto sqrtThreeAction = new QAction("Sqrt(3)", this);
|
||||
connect(sqrtThreeAction, SIGNAL(triggered(bool)), this, SLOT(SqrtThreeActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(sqrtThreeAction);
|
||||
//Need this for it to show up properly.
|
||||
this->setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||
}
|
||||
|
||||
void VariationTreeDoubleSpinBox::PiActionTriggered(bool checked) { setValue(M_PI); }
|
||||
void VariationTreeDoubleSpinBox::TwoPiActionTriggered(bool checked) { setValue(M_PI * 2); }
|
||||
void VariationTreeDoubleSpinBox::PiOver2ActionTriggered(bool checked) { setValue(M_PI_2); }
|
||||
void VariationTreeDoubleSpinBox::PiOver3ActionTriggered(bool checked) { setValue(M_PI / 3); }
|
||||
void VariationTreeDoubleSpinBox::PiOver4ActionTriggered(bool checked) { setValue(M_PI / 4); }
|
||||
void VariationTreeDoubleSpinBox::PiOver6ActionTriggered(bool checked) { setValue(M_PI / 6); }
|
||||
void VariationTreeDoubleSpinBox::OneOverPiActionTriggered(bool checked) { setValue(1 / M_PI); }
|
||||
void VariationTreeDoubleSpinBox::TwoOverPiActionTriggered(bool checked) { setValue(2 / M_PI); }
|
||||
void VariationTreeDoubleSpinBox::ThreeOverPiActionTriggered(bool checked) { setValue(3 / M_PI); }
|
||||
void VariationTreeDoubleSpinBox::FourOverPiActionTriggered(bool checked) { setValue(4 / M_PI); }
|
||||
void VariationTreeDoubleSpinBox::SqrtTwoActionTriggered(bool checked) { setValue(M_SQRT2); }
|
||||
void VariationTreeDoubleSpinBox::SqrtThreeActionTriggered(bool checked) { setValue(std::sqrt(3.0)); }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that sets up the context menu for special numerical values specific to affine spinners.
|
||||
/// </summary>
|
||||
/// <param name="p">The parent widget</param>
|
||||
/// <param name="h">The height of the spin box. Default: 20.</param>
|
||||
/// <param name="step">The step used to increment/decrement the spin box when using the mouse wheel. Default: 0.01.</param>
|
||||
AffineDoubleSpinBox::AffineDoubleSpinBox(QWidget* p, int h, double step)
|
||||
: DoubleSpinBox(p, h, step)
|
||||
{
|
||||
//-1
|
||||
auto neg1Action = new QAction("-1", this);
|
||||
connect(neg1Action, SIGNAL(triggered(bool)), this, SLOT(NegOneActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(neg1Action);
|
||||
//0
|
||||
auto zeroAction = new QAction("0", this);
|
||||
connect(zeroAction, SIGNAL(triggered(bool)), this, SLOT(ZeroActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(zeroAction);
|
||||
//1
|
||||
auto oneAction = new QAction("1", this);
|
||||
connect(oneAction, SIGNAL(triggered(bool)), this, SLOT(OneActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(oneAction);
|
||||
//45
|
||||
auto fortyFiveAction = new QAction("45", this);
|
||||
connect(fortyFiveAction, SIGNAL(triggered(bool)), this, SLOT(FortyFiveActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(fortyFiveAction);
|
||||
//-45
|
||||
auto negFortyFiveAction = new QAction("-45", this);
|
||||
connect(negFortyFiveAction, SIGNAL(triggered(bool)), this, SLOT(NegFortyFiveActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(negFortyFiveAction);
|
||||
//Need this for it to show up properly.
|
||||
this->setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||
}
|
||||
|
||||
void AffineDoubleSpinBox::NegOneActionTriggered(bool checked) { setValue(-1); }
|
||||
void AffineDoubleSpinBox::ZeroActionTriggered(bool checked) { setValue(0); }
|
||||
void AffineDoubleSpinBox::OneActionTriggered(bool checked) { setValue(1); }
|
||||
void AffineDoubleSpinBox::FortyFiveActionTriggered(bool checked) { setValue(0.707107); }
|
||||
void AffineDoubleSpinBox::NegFortyFiveActionTriggered(bool checked) { setValue(-0.707107); }
|
||||
|
@ -71,33 +71,52 @@ class VariationTreeWidgetItem;
|
||||
/// </summary>
|
||||
class VariationTreeDoubleSpinBox : public DoubleSpinBox
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor that passes agruments to the base and assigns the m_Param and m_Variation members.
|
||||
/// </summary>
|
||||
/// <param name="p">The parent widget</param>
|
||||
/// <param name="widgetItem">The widget item this spinner is contained in</param>
|
||||
/// <param name="id">The variation this spinner is for</param>
|
||||
/// <param name="param">The name of the parameter this is for</param>
|
||||
/// <param name="h">The height of the spin box. Default: 16.</param>
|
||||
/// <param name="step">The step used to increment/decrement the spin box when using the mouse wheel. Default: 0.05.</param>
|
||||
explicit VariationTreeDoubleSpinBox(QWidget* p, VariationTreeWidgetItem* widgetItem, eVariationId id, const string& param, int h = 16, double step = 0.05)
|
||||
: DoubleSpinBox(p, h, step)
|
||||
{
|
||||
m_WidgetItem = widgetItem;
|
||||
m_Param = param;
|
||||
m_Id = id;
|
||||
setDecimals(3);
|
||||
}
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VariationTreeDoubleSpinBox(QWidget* p, VariationTreeWidgetItem* widgetItem, eVariationId id, const string& param, int h = 16, double step = 0.05);
|
||||
virtual ~VariationTreeDoubleSpinBox() { }
|
||||
bool IsParam() { return !m_Param.empty(); }
|
||||
string ParamName() { return m_Param; }
|
||||
eVariationId GetVariationId() { return m_Id; }
|
||||
VariationTreeWidgetItem* WidgetItem() { return m_WidgetItem; }
|
||||
|
||||
public slots:
|
||||
void PiActionTriggered(bool checked = false);
|
||||
void TwoPiActionTriggered(bool checked = false);
|
||||
void PiOver2ActionTriggered(bool checked = false);
|
||||
void PiOver3ActionTriggered(bool checked = false);
|
||||
void PiOver4ActionTriggered(bool checked = false);
|
||||
void PiOver6ActionTriggered(bool checked = false);
|
||||
void OneOverPiActionTriggered(bool checked = false);
|
||||
void TwoOverPiActionTriggered(bool checked = false);
|
||||
void ThreeOverPiActionTriggered(bool checked = false);
|
||||
void FourOverPiActionTriggered(bool checked = false);
|
||||
void SqrtTwoActionTriggered(bool checked = false);
|
||||
void SqrtThreeActionTriggered(bool checked = false);
|
||||
|
||||
private:
|
||||
string m_Param;
|
||||
eVariationId m_Id;
|
||||
VariationTreeWidgetItem* m_WidgetItem;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Derivation for the double spin boxes that are in the
|
||||
/// affine controls.
|
||||
/// </summary>
|
||||
class AffineDoubleSpinBox : public DoubleSpinBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AffineDoubleSpinBox(QWidget* p, int h = 20, double step = 0.01);
|
||||
virtual ~AffineDoubleSpinBox() { }
|
||||
|
||||
public slots:
|
||||
void NegOneActionTriggered(bool checked = false);
|
||||
void ZeroActionTriggered(bool checked = false);
|
||||
void OneActionTriggered(bool checked = false);
|
||||
void FortyFiveActionTriggered(bool checked = false);
|
||||
void NegFortyFiveActionTriggered(bool checked = false);
|
||||
};
|
||||
|
@ -34,10 +34,10 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
//~EmberTreeWidgetItemBase()
|
||||
//{
|
||||
// qDebug() << "~EmberTreeWidgetItemBase()";
|
||||
//}
|
||||
~EmberTreeWidgetItemBase()
|
||||
{
|
||||
//qDebug() << "~EmberTreeWidgetItemBase()";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the preview image for the tree widget item.
|
||||
|
@ -52,8 +52,12 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(QWidget* p, Qt::WindowF
|
||||
m_ItersCellIndex = row++;//Iters.
|
||||
m_PathCellIndex = row;
|
||||
QStringList comboList;
|
||||
#ifndef _WIN32
|
||||
comboList.append("bmp");
|
||||
#endif
|
||||
comboList.append("jpg");
|
||||
comboList.append("png");
|
||||
comboList.append("exr");
|
||||
m_Tbcw = new TwoButtonComboWidget("...", "Open", comboList, 22, 40, 22, table);
|
||||
table->setCellWidget(row, 1, m_Tbcw);
|
||||
table->item(row++, 1)->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
@ -116,6 +120,7 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(QWidget* p, Qt::WindowF
|
||||
ui.FinalRenderSaveXmlCheckBox->setChecked( m_Settings->FinalSaveXml());
|
||||
ui.FinalRenderDoAllCheckBox->setChecked( m_Settings->FinalDoAll());
|
||||
ui.FinalRenderDoSequenceCheckBox->setChecked( m_Settings->FinalDoSequence());
|
||||
ui.FinalRenderPng16BitCheckBox->setChecked( m_Settings->FinalPng16Bit());
|
||||
ui.FinalRenderKeepAspectCheckBox->setChecked( m_Settings->FinalKeepAspect());
|
||||
ui.FinalRenderThreadCountSpin->setValue( m_Settings->FinalThreadCount());
|
||||
#ifdef _WIN32
|
||||
@ -136,11 +141,27 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(QWidget* p, Qt::WindowF
|
||||
m_SupersampleSpin->setValue(m_Settings->FinalSupersample());
|
||||
m_StripsSpin->setValue(int(m_Settings->FinalStrips()));
|
||||
Scale(eScaleType(m_Settings->FinalScale()));
|
||||
int index = 0;
|
||||
#ifdef _WIN32
|
||||
|
||||
if (m_Settings->FinalExt() == "jpg")
|
||||
m_Tbcw->m_Combo->setCurrentIndex(0);
|
||||
else
|
||||
m_Tbcw->m_Combo->setCurrentIndex(1);
|
||||
if (m_Settings->FinalExt().endsWith("bmp", Qt::CaseInsensitive))
|
||||
m_Tbcw->m_Combo->setCurrentIndex(index);
|
||||
|
||||
index++;
|
||||
#endif
|
||||
|
||||
if (m_Settings->FinalExt().endsWith("jpg", Qt::CaseInsensitive))
|
||||
m_Tbcw->m_Combo->setCurrentIndex(index);
|
||||
|
||||
index++;
|
||||
|
||||
if (m_Settings->FinalExt().endsWith("png", Qt::CaseInsensitive))
|
||||
m_Tbcw->m_Combo->setCurrentIndex(index);
|
||||
|
||||
index++;
|
||||
|
||||
if (m_Settings->FinalExt().endsWith("exr", Qt::CaseInsensitive))
|
||||
m_Tbcw->m_Combo->setCurrentIndex(index);
|
||||
|
||||
//Explicitly call these to enable/disable the appropriate controls.
|
||||
OnOpenCLCheckBoxStateChanged(ui.FinalRenderOpenCLCheckBox->isChecked());
|
||||
@ -150,23 +171,20 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(QWidget* p, Qt::WindowF
|
||||
int desktopHeight = qApp->desktop()->availableGeometry().height();
|
||||
s.setHeight(std::min(s.height(), int(double(desktopHeight * 0.90))));
|
||||
setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, s, qApp->desktop()->availableGeometry()));
|
||||
ui.FinalRenderThreadHorizontalLayout->setAlignment(Qt::AlignLeft);
|
||||
ui.FinalRenderThreadHorizontalLayout->setAlignment(ui.FinalRenderThreadCountSpin, Qt::AlignLeft);
|
||||
ui.FinalRenderThreadHorizontalLayout->setAlignment(ui.FinalRenderThreadPriorityLabel, Qt::AlignLeft);
|
||||
ui.FinalRenderThreadHorizontalLayout->setAlignment(ui.FinalRenderThreadPriorityComboBox, Qt::AlignLeft);
|
||||
QWidget* w = SetTabOrder(this, ui.FinalRenderEarlyClipCheckBox, ui.FinalRenderYAxisUpCheckBox);
|
||||
//Update these with new controls.
|
||||
QWidget* w = SetTabOrder(this, ui.FinalRenderEarlyClipCheckBox, ui.FinalRenderYAxisUpCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderTransparencyCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderOpenCLCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderPng16BitCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderDoublePrecisionCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderSaveXmlCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderDoAllCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderDoSequenceCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderCurrentSpin);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderDeviceTable);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderApplyToAllCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderThreadCountSpin);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderThreadPriorityComboBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderApplyToAllCheckBox);
|
||||
w = SetTabOrder(this, w, m_WidthScaleSpin);
|
||||
w = SetTabOrder(this, w, m_HeightScaleSpin);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderScaleNoneRadioButton);
|
||||
@ -215,9 +233,10 @@ bool FractoriumFinalRenderDialog::Double() { return ui.FinalRenderDoublePrecisio
|
||||
bool FractoriumFinalRenderDialog::SaveXml() { return ui.FinalRenderSaveXmlCheckBox->isChecked(); }
|
||||
bool FractoriumFinalRenderDialog::DoAll() { return ui.FinalRenderDoAllCheckBox->isChecked(); }
|
||||
bool FractoriumFinalRenderDialog::DoSequence() { return ui.FinalRenderDoSequenceCheckBox->isChecked(); }
|
||||
bool FractoriumFinalRenderDialog::Png16Bit() { return ui.FinalRenderPng16BitCheckBox->isChecked(); }
|
||||
bool FractoriumFinalRenderDialog::KeepAspect() { return ui.FinalRenderKeepAspectCheckBox->isChecked(); }
|
||||
bool FractoriumFinalRenderDialog::ApplyToAll() { return ui.FinalRenderApplyToAllCheckBox->isChecked(); }
|
||||
QString FractoriumFinalRenderDialog::Ext() { return m_Tbcw->m_Combo->currentIndex() == 0 ? "jpg" : "png"; }
|
||||
QString FractoriumFinalRenderDialog::Ext() { return m_Tbcw->m_Combo->currentText(); }
|
||||
QString FractoriumFinalRenderDialog::Path() { return ui.FinalRenderParamsTable->item(m_PathCellIndex, 1)->text(); }
|
||||
void FractoriumFinalRenderDialog::Path(const QString& s) { ui.FinalRenderParamsTable->item(m_PathCellIndex, 1)->setText(s); }
|
||||
QString FractoriumFinalRenderDialog::Prefix() { return m_PrefixEdit->text(); }
|
||||
@ -261,6 +280,7 @@ FinalRenderGuiState FractoriumFinalRenderDialog::State()
|
||||
state.m_SaveXml = SaveXml();
|
||||
state.m_DoAll = DoAll();
|
||||
state.m_DoSequence = DoSequence();
|
||||
state.m_Png16Bit = Png16Bit();
|
||||
state.m_KeepAspect = KeepAspect();
|
||||
state.m_Scale = Scale();
|
||||
state.m_Path = Path();
|
||||
|
@ -60,6 +60,7 @@ public:
|
||||
bool SaveXml();
|
||||
bool DoAll();
|
||||
bool DoSequence();
|
||||
bool Png16Bit();
|
||||
bool KeepAspect();
|
||||
bool ApplyToAll();
|
||||
eScaleType Scale();
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>519</width>
|
||||
<height>941</height>
|
||||
<width>573</width>
|
||||
<height>751</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -63,8 +63,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>507</width>
|
||||
<height>929</height>
|
||||
<width>561</width>
|
||||
<height>739</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
@ -83,96 +83,12 @@
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="FinalRenderGridLayout" columnstretch="0,0">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderEarlyClipCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: clip colors and gamma correct after density filtering.</p><p>Unchecked: do it after spatial filtering.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Early Clip</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderYAxisUpCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: Positive Y direction is up.</p><p>Unchecked: Positive Y direction is down.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Positive Y Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderOpenCLCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use OpenCL to render if your video card supports it.</p><p>This is highly recommended as it will dramatically speed up render time.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use OpenCL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderTransparencyCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use transparency in the final image.</p><p>Only supported for Png format.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Transparency</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderDoublePrecisionCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: use 64-bit double precision numbers (slower, but better image quality).</p><p>Unchecked: use 32-bit single precision numbers (faster, but worse image quality).</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use Double Precision</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderSaveXmlCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Save an Xml parameter file for each flame rendered</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save Xml</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderDoAllCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Render all open flames instead of just the current one</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Render All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderDoSequenceCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Use temporal samples value to achieve motion blur effect between flames</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Render as Animation Sequence</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="FinalRenderGridLayout2">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetNoConstraint</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="FinalRenderPreviewLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
@ -215,7 +131,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="0" column="2">
|
||||
<widget class="QSpinBox" name="FinalRenderCurrentSpin">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
@ -237,6 +153,100 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="FinalRenderGridLayout" columnstretch="0,0">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderEarlyClipCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: clip colors and gamma correct after density filtering.</p><p>Unchecked: do it after spatial filtering.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Early Clip</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderYAxisUpCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: Positive Y direction is up.</p><p>Unchecked: Positive Y direction is down.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Positive Y Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderOpenCLCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use OpenCL to render if your video card supports it.</p><p>This is highly recommended as it will dramatically speed up render time.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use OpenCL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderTransparencyCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use transparency in the final image.</p><p>Only supported for Png format.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Transparency</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderDoublePrecisionCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: use 64-bit double precision numbers (slower, but better image quality).</p><p>Unchecked: use 32-bit single precision numbers (faster, but worse image quality).</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use Double Precision</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderSaveXmlCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Save an Xml parameter file for each flame rendered</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save Xml</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderDoAllCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Render all open flames instead of just the current one</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Render All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderDoSequenceCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Use temporal samples value to achieve motion blur effect between flames</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Render as Animation Sequence</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderPng16BitCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Save each RGBA component as 16-bits when saving Png files.</p><p>This leads to greater color precision for use in high end rendering and display on HDR monitors, however it makes the file size larger.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save 16-bit Png</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@ -328,7 +338,10 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="FinalRenderThreadHorizontalLayout" stretch="0,0,0">
|
||||
<layout class="QHBoxLayout" name="FinalRenderThreadHorizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="FinalRenderThreadCountSpin">
|
||||
<property name="sizePolicy">
|
||||
@ -405,6 +418,19 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@ -928,6 +954,146 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="FinalRenderTextOutput">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="FinalRenderGridLayout3" rowstretch="0,0,0,0" columnstretch="1,4">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item row="2" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderFilteringProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="FinalRenderIterationProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Iteration:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="FinalRenderAccumProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Final Accumulation:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderIterationProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderAccumProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="FinalRenderFilteringProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Density Filtering:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="FinalRenderTotalProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Total Progress:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderTotalProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="FinalRenderImageCountLabel">
|
||||
<property name="text">
|
||||
@ -938,142 +1104,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="FinalRenderGridLayout3" rowstretch="0,0,0,0" columnstretch="1,4">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item row="2" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderFilteringProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="FinalRenderIterationProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Iteration:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="FinalRenderAccumProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Final Accumulation:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderIterationProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderAccumProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="FinalRenderFilteringProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Density Filtering:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="FinalRenderTotalProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Total Progress:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderTotalProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="FinalRenderTextOutput">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="FinalRenderButtonHBoxLayout">
|
||||
<property name="spacing">
|
||||
@ -1160,13 +1190,22 @@
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>FinalRenderEarlyClipCheckBox</tabstop>
|
||||
<tabstop>FinalRenderDoublePrecisionCheckBox</tabstop>
|
||||
<tabstop>FinalRenderYAxisUpCheckBox</tabstop>
|
||||
<tabstop>FinalRenderSaveXmlCheckBox</tabstop>
|
||||
<tabstop>FinalRenderTransparencyCheckBox</tabstop>
|
||||
<tabstop>FinalRenderDoAllCheckBox</tabstop>
|
||||
<tabstop>FinalRenderOpenCLCheckBox</tabstop>
|
||||
<tabstop>FinalRenderParamsTable</tabstop>
|
||||
<tabstop>FinalRenderTextOutput</tabstop>
|
||||
<tabstop>FinalRenderStartButton</tabstop>
|
||||
<tabstop>FinalRenderDoSequenceCheckBox</tabstop>
|
||||
<tabstop>FinalRenderPng16BitCheckBox</tabstop>
|
||||
<tabstop>FinalRenderCurrentSpin</tabstop>
|
||||
<tabstop>FinalRenderStopButton</tabstop>
|
||||
<tabstop>FinalRenderStartButton</tabstop>
|
||||
<tabstop>FinalRenderScaleWidthRadioButton</tabstop>
|
||||
<tabstop>FinalRenderScaleHeightRadioButton</tabstop>
|
||||
<tabstop>FinalRenderScaleNoneRadioButton</tabstop>
|
||||
<tabstop>FinalRenderKeepAspectCheckBox</tabstop>
|
||||
<tabstop>FinalRenderTextOutput</tabstop>
|
||||
<tabstop>FinalRenderCloseButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
|
@ -80,7 +80,7 @@ bool FinalRenderEmberControllerBase::CreateRendererFromGUI()
|
||||
bool useOpenCL = m_Info->Ok() && m_FinalRenderDialog->OpenCL();
|
||||
auto v = Devices(m_FinalRenderDialog->Devices());
|
||||
return CreateRenderer((useOpenCL && !v.empty()) ? eRendererType::OPENCL_RENDERER : eRendererType::CPU_RENDERER,
|
||||
v, false); //Not shared.
|
||||
v, false, false); //Not shared.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -178,7 +178,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
size_t ftime;
|
||||
size_t finalImageIndex = 0;
|
||||
std::thread writeThread;
|
||||
vector<byte> finalImages[2];
|
||||
vector<v4F> finalImages[2];
|
||||
EmberStats stats;
|
||||
EmberImageComments comments;
|
||||
Timing renderTimer;
|
||||
@ -225,8 +225,8 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
finalImages[threadFinalImageIndex],
|
||||
renderer->FinalRasW(),
|
||||
renderer->FinalRasH(),
|
||||
renderer->NumChannels(),
|
||||
renderer->BytesPerChannel());
|
||||
m_FinalRenderDialog->Png16Bit(),
|
||||
m_FinalRenderDialog->Transparency());
|
||||
}, ftime, finalImageIndex);
|
||||
m_FinishedImageCount.fetch_add(1);
|
||||
RenderComplete(*m_EmberFile.Get(ftime), stats, renderTimer);
|
||||
@ -422,10 +422,9 @@ bool FinalRenderEmberController<T>::Render()
|
||||
/// <param name="shared">True if shared with OpenGL, else false. Always false in this case.</param>
|
||||
/// <returns>True if nothing went wrong, else false.</returns>
|
||||
template <typename T>
|
||||
bool FinalRenderEmberController<T>::CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared)
|
||||
bool FinalRenderEmberController<T>::CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool updatePreviews, bool shared)
|
||||
{
|
||||
bool ok = true;
|
||||
//uint channels = m_FinalRenderDialog->Ext().endsWith("png", Qt::CaseInsensitive) ? 4 : 3;
|
||||
bool renderTypeMismatch = (m_Renderer.get() && (m_Renderer->RendererType() != renderType)) ||
|
||||
(!m_Renderers.empty() && (m_Renderers[0]->RendererType() != renderType));
|
||||
CancelRender();
|
||||
@ -542,35 +541,24 @@ template <typename T>
|
||||
bool FinalRenderEmberController<T>::SyncGuiToRenderer()
|
||||
{
|
||||
bool ok = true;
|
||||
uint channels = m_FinalRenderDialog->Ext().endsWith("png", Qt::CaseInsensitive) ? 4 : 3;
|
||||
|
||||
if (m_Renderer.get())
|
||||
{
|
||||
if (m_Renderer->RendererType() == eRendererType::OPENCL_RENDERER)
|
||||
channels = 4;//Always using 4 since the GL texture is RGBA.
|
||||
|
||||
m_Renderer->Callback(this);
|
||||
m_Renderer->NumChannels(channels);
|
||||
m_Renderer->EarlyClip(m_FinalRenderDialog->EarlyClip());
|
||||
m_Renderer->YAxisUp(m_FinalRenderDialog->YAxisUp());
|
||||
m_Renderer->ThreadCount(m_FinalRenderDialog->ThreadCount());
|
||||
m_Renderer->Priority((eThreadPriority)m_FinalRenderDialog->ThreadPriority());
|
||||
m_Renderer->Transparency(m_FinalRenderDialog->Transparency());
|
||||
}
|
||||
else if (!m_Renderers.empty())
|
||||
{
|
||||
for (size_t i = 0; i < m_Renderers.size(); i++)
|
||||
{
|
||||
if (m_Renderers[i]->RendererType() == eRendererType::OPENCL_RENDERER)
|
||||
channels = 4;//Always using 4 since the GL texture is RGBA.
|
||||
|
||||
m_Renderers[i]->Callback(!i ? this : nullptr);
|
||||
m_Renderers[i]->NumChannels(channels);
|
||||
m_Renderers[i]->EarlyClip(m_FinalRenderDialog->EarlyClip());
|
||||
m_Renderers[i]->YAxisUp(m_FinalRenderDialog->YAxisUp());
|
||||
m_Renderers[i]->ThreadCount(m_FinalRenderDialog->ThreadCount());
|
||||
m_Renderers[i]->Priority((eThreadPriority)m_FinalRenderDialog->ThreadPriority());
|
||||
m_Renderers[i]->Transparency(m_FinalRenderDialog->Transparency());
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -627,11 +615,11 @@ void FinalRenderEmberController<T>::ResetProgress(bool total)
|
||||
/// specified in the widgets and compute the amount of memory required to render.
|
||||
/// This includes the memory needed for the final output image.
|
||||
/// </summary>
|
||||
/// <returns>If successful, memory required in bytes, else zero.</returns>
|
||||
/// <returns>If successful, a tuple specifying the memory required in bytes for the histogram int he first element, the total memory in the second, and the iter count in the last, else zero.</returns>
|
||||
template <typename T>
|
||||
tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemory()
|
||||
{
|
||||
size_t iterCount;
|
||||
size_t iterCount = 0;
|
||||
pair<size_t, size_t> p(0, 0);
|
||||
size_t strips;
|
||||
uint channels = m_FinalRenderDialog->Ext() == "png" ? 4 : 3;//4 channels for Png, else 3.
|
||||
@ -642,7 +630,6 @@ tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemor
|
||||
strips = VerifyStrips(m_Ember->m_FinalRasH, m_FinalRenderDialog->Strips(),
|
||||
[&](const string & s) {}, [&](const string & s) {}, [&](const string & s) {});
|
||||
m_Renderer->SetEmber(*m_Ember, eProcessAction::FULL_RENDER, true);
|
||||
m_Renderer->NumChannels(channels);
|
||||
m_FinalPreviewRenderer->Render(UINT_MAX, UINT_MAX);
|
||||
p = m_Renderer->MemoryRequired(strips, true, m_FinalRenderDialog->DoSequence());
|
||||
iterCount = m_Renderer->TotalIterCount(strips);
|
||||
@ -652,7 +639,6 @@ tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemor
|
||||
for (auto& renderer : m_Renderers)
|
||||
{
|
||||
renderer->SetEmber(*m_Ember, eProcessAction::FULL_RENDER, true);
|
||||
renderer->NumChannels(channels);
|
||||
}
|
||||
|
||||
m_FinalPreviewRenderer->Render(UINT_MAX, UINT_MAX);
|
||||
@ -711,24 +697,24 @@ template<typename T>
|
||||
void FinalRenderEmberController<T>::SaveCurrentRender(Ember<T>& ember)
|
||||
{
|
||||
auto comments = m_Renderer->ImageComments(m_Stats, 0, true);
|
||||
SaveCurrentRender(ember, comments, m_FinalImage, m_Renderer->FinalRasW(), m_Renderer->FinalRasH(), m_Renderer->NumChannels(), m_Renderer->BytesPerChannel());
|
||||
SaveCurrentRender(ember, comments, m_FinalImage, m_Renderer->FinalRasW(), m_Renderer->FinalRasH(), m_FinalRenderDialog->Png16Bit(), m_FinalRenderDialog->Transparency());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the output of the render.
|
||||
/// </summary>
|
||||
/// <param name="ember">The ember whose rendered output will be saved</param>
|
||||
/// <param name="comments">The comments to save in the png or jpg</param>
|
||||
/// <param name="comments">The comments to save in the png, jpg or exr</param>
|
||||
/// <param name="pixels">The buffer containing the pixels</param>
|
||||
/// <param name="width">The width in pixels of the image</param>
|
||||
/// <param name="height">The height in pixels of the image</param>
|
||||
/// <param name="channels">The number of channels, 3 or 4.</param>
|
||||
/// <param name="bpc">The bytes per channel, almost always 1.</param>
|
||||
/// <param name="png16Bit">Whether to use 16 bits per channel per pixel when saving as Png.</param>
|
||||
/// <param name="transparency">Whether to use alpha when saving as Png or Exr.</param>
|
||||
template<typename T>
|
||||
void FinalRenderEmberController<T>::SaveCurrentRender(Ember<T>& ember, const EmberImageComments& comments, vector<byte>& pixels, size_t width, size_t height, size_t channels, size_t bpc)
|
||||
void FinalRenderEmberController<T>::SaveCurrentRender(Ember<T>& ember, const EmberImageComments& comments, vector<v4F>& pixels, size_t width, size_t height, bool png16Bit, bool transparency)
|
||||
{
|
||||
QString filename = ComposePath(QString::fromStdString(ember.m_Name));
|
||||
FractoriumEmberControllerBase::SaveCurrentRender(filename, comments, pixels, width, height, channels, bpc);
|
||||
FractoriumEmberControllerBase::SaveCurrentRender(filename, comments, pixels, width, height, png16Bit, transparency);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -806,6 +792,7 @@ void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember, const EmberS
|
||||
m_Settings->FinalSaveXml(m_GuiState.m_SaveXml);
|
||||
m_Settings->FinalDoAll(m_GuiState.m_DoAll);
|
||||
m_Settings->FinalDoSequence(m_GuiState.m_DoSequence);
|
||||
m_Settings->FinalPng16Bit(m_GuiState.m_Png16Bit);
|
||||
m_Settings->FinalKeepAspect(m_GuiState.m_KeepAspect);
|
||||
m_Settings->FinalScale(uint(m_GuiState.m_Scale));
|
||||
m_Settings->FinalExt(m_GuiState.m_Ext);
|
||||
@ -960,6 +947,7 @@ void FinalRenderPreviewRenderer<T>::PreviewRenderFunc(uint start, uint end)
|
||||
QLabel* widget = d->ui.FinalRenderPreviewLabel;
|
||||
//Determine how to scale the scaled ember to fit in the label with a max of 100x100.
|
||||
auto e = m_Controller->m_Ember;
|
||||
auto settings = FractoriumSettings::Instance();
|
||||
|
||||
if (e->m_FinalRasW >= e->m_FinalRasH)
|
||||
scalePercentage = T(maxDim) / e->m_FinalRasW;
|
||||
@ -974,9 +962,7 @@ void FinalRenderPreviewRenderer<T>::PreviewRenderFunc(uint start, uint end)
|
||||
m_PreviewEmber.m_PixelsPerUnit = scalePercentage * e->m_PixelsPerUnit;
|
||||
m_PreviewRenderer.EarlyClip(d->EarlyClip());
|
||||
m_PreviewRenderer.YAxisUp(d->YAxisUp());
|
||||
m_PreviewRenderer.Transparency(d->Transparency());
|
||||
m_PreviewRenderer.Callback(nullptr);
|
||||
m_PreviewRenderer.NumChannels(4);
|
||||
m_PreviewRenderer.SetEmber(m_PreviewEmber);
|
||||
m_PreviewRenderer.PrepFinalAccumVector(m_PreviewFinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
|
||||
auto strips = VerifyStrips(m_PreviewEmber.m_FinalRasH, d->Strips(),
|
||||
@ -987,8 +973,10 @@ void FinalRenderPreviewRenderer<T>::PreviewRenderFunc(uint start, uint end)
|
||||
[&](size_t strip) {},//Error.
|
||||
[&](Ember<T>& finalEmber)//Final strip.
|
||||
{
|
||||
m_PreviewVec.resize(finalEmber.m_FinalRasW * finalEmber.m_FinalRasH * 4);
|
||||
Rgba32ToRgba8(m_PreviewFinalImage.data(), m_PreviewVec.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, d->Transparency());
|
||||
QImage image(int(finalEmber.m_FinalRasW), int(finalEmber.m_FinalRasH), QImage::Format_RGBA8888);//The label wants RGBA.
|
||||
memcpy(image.scanLine(0), m_PreviewFinalImage.data(), finalEmber.m_FinalRasW * finalEmber.m_FinalRasH * 4);//Memcpy the data in.
|
||||
memcpy(image.scanLine(0), m_PreviewVec.data(), SizeOf(m_PreviewVec));//Memcpy the data in.
|
||||
QPixmap pixmap(QPixmap::fromImage(image));
|
||||
QMetaObject::invokeMethod(widget, "setPixmap", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap));
|
||||
});
|
||||
|
@ -28,6 +28,7 @@ struct FinalRenderGuiState
|
||||
bool m_Double;
|
||||
bool m_SaveXml;
|
||||
bool m_DoAll;
|
||||
bool m_Png16Bit;
|
||||
bool m_DoSequence;
|
||||
bool m_KeepAspect;
|
||||
eScaleType m_Scale;
|
||||
@ -111,7 +112,7 @@ public:
|
||||
#endif
|
||||
virtual void SetEmber(size_t index, bool verbatim) override;
|
||||
virtual bool Render() override;
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared = true) override;
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool updatePreviews, bool shared = true) override;
|
||||
virtual int ProgressFunc(Ember<T>& ember, void* foo, double fraction, int stage, double etaMs) override;
|
||||
virtual size_t Index() const override { return m_Ember->m_Index; }
|
||||
virtual uint SizeOfT() const override { return sizeof(T); }
|
||||
@ -134,7 +135,7 @@ public:
|
||||
protected:
|
||||
void HandleFinishedProgress();
|
||||
void SaveCurrentRender(Ember<T>& ember);
|
||||
void SaveCurrentRender(Ember<T>& ember, const EmberImageComments& comments, vector<byte>& pixels, size_t width, size_t height, size_t channels, size_t bpc);
|
||||
void SaveCurrentRender(Ember<T>& ember, const EmberImageComments& comments, vector<v4F>& pixels, size_t width, size_t height, bool png16Bit, bool transparency);
|
||||
void RenderComplete(Ember<T>& ember);
|
||||
void RenderComplete(Ember<T>& ember, const EmberStats& stats, Timing& renderTimer);
|
||||
void SyncGuiToEmber(Ember<T>& ember, size_t widthOverride = 0, size_t heightOverride = 0);
|
||||
@ -158,6 +159,7 @@ class FinalRenderPreviewRenderer : public PreviewRenderer<T>
|
||||
{
|
||||
public:
|
||||
using PreviewRenderer<T>::m_PreviewRun;
|
||||
using PreviewRenderer<T>::m_PreviewVec;
|
||||
using PreviewRenderer<T>::m_PreviewEmber;
|
||||
using PreviewRenderer<T>::m_PreviewRenderer;
|
||||
using PreviewRenderer<T>::m_PreviewFinalImage;
|
||||
|
@ -26,6 +26,7 @@ Fractorium::Fractorium(QWidget* p)
|
||||
qRegisterMetaType<size_t>("size_t");
|
||||
qRegisterMetaType<QVector<int>>("QVector<int>");//For previews.
|
||||
qRegisterMetaType<vector<byte>>("vector<byte>");
|
||||
qRegisterMetaType<vv4F>("vv4F");
|
||||
qRegisterMetaType<EmberTreeWidgetItemBase*>("EmberTreeWidgetItemBase*");
|
||||
setDockOptions(DockOption::AllowNestedDocks | DockOption::AllowTabbedDocks);
|
||||
setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::TabPosition::North);
|
||||
@ -505,7 +506,7 @@ void Fractorium::SetFixedTableHeader(QHeaderView* header, QHeaderView::ResizeMod
|
||||
/// Setup and show the open XML dialog.
|
||||
/// This will perform lazy instantiation.
|
||||
/// </summary>
|
||||
/// <returns>The filename selected</returns>
|
||||
/// <returns>The list of filenames selected</returns>
|
||||
QStringList Fractorium::SetupOpenXmlDialog()
|
||||
{
|
||||
#ifndef __APPLE__
|
||||
@ -522,7 +523,7 @@ QStringList Fractorium::SetupOpenXmlDialog()
|
||||
connect(m_FileDialog, &QFileDialog::filterSelected, [&](const QString & filter) { m_Settings->OpenXmlExt(filter); });
|
||||
m_FileDialog->setFileMode(QFileDialog::ExistingFiles);
|
||||
m_FileDialog->setAcceptMode(QFileDialog::AcceptOpen);
|
||||
m_FileDialog->setNameFilter("Flam3 (*.flam3);;Flame (*.flame);;Xml (*.xml)");
|
||||
m_FileDialog->setNameFilter("*.flam3;;*.flame;;*.xml");
|
||||
m_FileDialog->setWindowTitle("Open Flame");
|
||||
m_FileDialog->setDirectory(m_Settings->OpenFolder());
|
||||
m_FileDialog->selectNameFilter(m_Settings->OpenXmlExt());
|
||||
@ -567,30 +568,23 @@ QString Fractorium::SetupSaveXmlDialog(const QString& defaultFilename)
|
||||
|
||||
QString filename;
|
||||
m_FileDialog->disconnect(SIGNAL(filterSelected(const QString&)));
|
||||
connect(m_FileDialog, &QFileDialog::filterSelected, [&](const QString & filter) { m_Settings->SaveXmlExt(filter); });
|
||||
connect(m_FileDialog, &QFileDialog::filterSelected, [&](const QString & filter)
|
||||
{
|
||||
m_Settings->SaveXmlExt(filter);
|
||||
m_FileDialog->setDefaultSuffix(filter);
|
||||
});
|
||||
//This must come first because it clears various internal states which allow the file text to be properly set.
|
||||
//This is most likely a bug in QFileDialog.
|
||||
m_FileDialog->setAcceptMode(QFileDialog::AcceptSave);
|
||||
m_FileDialog->selectFile(defaultFilename);
|
||||
m_FileDialog->setNameFilter("Flam3 (*.flam3);;Flame (*.flame);;Xml (*.xml)");
|
||||
m_FileDialog->setNameFilter(".flam3;;.flame;;.xml");
|
||||
m_FileDialog->setWindowTitle("Save flame as xml");
|
||||
m_FileDialog->setDirectory(m_Settings->SaveFolder());
|
||||
m_FileDialog->selectNameFilter(m_Settings->SaveXmlExt());
|
||||
m_FileDialog->setDefaultSuffix(m_Settings->SaveXmlExt());
|
||||
|
||||
if (m_FileDialog->exec() == QDialog::Accepted)
|
||||
{
|
||||
filename = m_FileDialog->selectedFiles().value(0);
|
||||
//For some reason, linux doesn't automatically append this, but Windows does. Force it to be safe.
|
||||
auto filt = m_FileDialog->selectedNameFilter().split('*');//Qt makes it very hard to get the actual extension used.
|
||||
|
||||
if (filt.size() > 1)//Should always be true.
|
||||
{
|
||||
auto s = filt[1].replace(")", "");
|
||||
|
||||
if (!filename.endsWith(s))
|
||||
filename.append(s);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
auto defaultFilter(m_Settings->SaveXmlExt());
|
||||
@ -619,7 +613,11 @@ QString Fractorium::SetupSaveImageDialog(const QString& defaultFilename)
|
||||
|
||||
QString filename;
|
||||
m_FileDialog->disconnect(SIGNAL(filterSelected(const QString&)));
|
||||
connect(m_FileDialog, &QFileDialog::filterSelected, [&](const QString & filter) { m_Settings->SaveImageExt(filter); });
|
||||
connect(m_FileDialog, &QFileDialog::filterSelected, [&](const QString & filter)
|
||||
{
|
||||
m_Settings->SaveImageExt(filter);
|
||||
m_FileDialog->setDefaultSuffix(filter);
|
||||
});
|
||||
//This must come first because it clears various internal states which allow the file text to be properly set.
|
||||
//This is most likely a bug in QFileDialog.
|
||||
m_FileDialog->setAcceptMode(QFileDialog::AcceptSave);
|
||||
@ -627,17 +625,22 @@ QString Fractorium::SetupSaveImageDialog(const QString& defaultFilename)
|
||||
m_FileDialog->setFileMode(QFileDialog::AnyFile);
|
||||
m_FileDialog->setOption(QFileDialog::ShowDirsOnly, false);
|
||||
m_FileDialog->setOption(QFileDialog::DontUseNativeDialog, false);
|
||||
m_FileDialog->setNameFilter("Jpeg (*.jpg);;Png (*.png);;Bmp (*.bmp)");
|
||||
#ifdef _WIN32
|
||||
m_FileDialog->setNameFilter(".bmp;;.jpg;;.png;;.exr");
|
||||
#else
|
||||
m_FileDialog->setNameFilter(".jpg;;.png;;.exr");
|
||||
#endif
|
||||
m_FileDialog->setWindowTitle("Save image");
|
||||
m_FileDialog->setDirectory(m_Settings->SaveFolder());
|
||||
m_FileDialog->selectNameFilter(m_Settings->SaveImageExt());
|
||||
m_FileDialog->setDefaultSuffix(m_Settings->SaveImageExt());
|
||||
|
||||
if (m_FileDialog->exec() == QDialog::Accepted)
|
||||
filename = m_FileDialog->selectedFiles().value(0);
|
||||
|
||||
#else
|
||||
auto defaultFilter(m_Settings->SaveImageExt());
|
||||
auto filename = QFileDialog::getSaveFileName(this, tr("Save image"), m_Settings->SaveFolder() + "/" + defaultFilename, tr("Jpeg (*.jpg);;Png (*.png);;Bmp (*.bmp)"), &defaultFilter);
|
||||
auto filename = QFileDialog::getSaveFileName(this, tr("Save image"), m_Settings->SaveFolder() + "/" + defaultFilename, tr("Jpg (*.jpg);;Png (*.png);;Exr (*.exr)"), &defaultFilter);
|
||||
m_Settings->SaveImageExt(defaultFilter);
|
||||
#endif
|
||||
return filename;
|
||||
|
@ -339,18 +339,18 @@ public slots:
|
||||
void OnSummaryTreeHeaderSectionClicked(int logicalIndex);
|
||||
|
||||
//Rendering/progress.
|
||||
void StartRenderTimer();
|
||||
void StartRenderTimer(bool updatePreviews);
|
||||
void IdleTimer();
|
||||
bool ControllersOk();
|
||||
void ShowCritical(const QString& title, const QString& text, bool invokeRequired = false);
|
||||
|
||||
//Can't have a template function be a slot.
|
||||
void SetLibraryTreeItemData(EmberTreeWidgetItemBase* item, vector<byte>& v, uint w, uint h);
|
||||
void SetLibraryTreeItemData(EmberTreeWidgetItemBase* item, vv4F& v, uint w, uint h);
|
||||
|
||||
public:
|
||||
//template<typename spinType, typename valType>//See below.
|
||||
//static void SetupSpinner(QTableWidget* table, const QObject* receiver, int& row, int col, spinType*& spinBox, int height, valType min, valType max, valType step, const char* signal, const char* slot, bool incRow = true, valType val = 0, valType doubleClickZero = -999, valType doubleClickNonZero = -999);
|
||||
static void SetupAffineSpinner(QTableWidget* table, const QObject* receiver, int row, int col, DoubleSpinBox*& spinBox, int height, double min, double max, double step, double prec, const char* signal, const char* slot);
|
||||
static void SetupAffineSpinner(QTableWidget* table, const QObject* receiver, int row, int col, AffineDoubleSpinBox*& spinBox, int height, double min, double max, double step, double prec, const char* signal, const char* slot);
|
||||
static void SetupCombo(QTableWidget* table, const QObject* receiver, int& row, int col, StealthComboBox*& comboBox, const vector<string>& vals, const char* signal, const char* slot, Qt::ConnectionType connectionType = Qt::QueuedConnection);
|
||||
static void SetFixedTableHeader(QHeaderView* header, QHeaderView::ResizeMode mode = QHeaderView::Fixed);
|
||||
|
||||
@ -422,8 +422,8 @@ private:
|
||||
void ErrorReportToQTextEdit(const vector<string>& errors, QTextEdit* textEdit, bool clear = true);
|
||||
|
||||
//Rendering/progress.
|
||||
void ShutdownAndRecreateFromOptions();
|
||||
bool CreateRendererFromOptions();
|
||||
void ShutdownAndRecreateFromOptions(bool updatePreviews);
|
||||
bool CreateRendererFromOptions(bool updatePreviews);
|
||||
bool CreateControllerFromOptions();
|
||||
void EnableRenderControls(bool enable);
|
||||
|
||||
@ -489,22 +489,22 @@ private:
|
||||
DoubleSpinBox* m_XformDirectColorSpin;
|
||||
|
||||
//Xforms Affine.
|
||||
DoubleSpinBox* m_PreX1Spin;//Pre.
|
||||
DoubleSpinBox* m_PreX2Spin;
|
||||
DoubleSpinBox* m_PreY1Spin;
|
||||
DoubleSpinBox* m_PreY2Spin;
|
||||
DoubleSpinBox* m_PreO1Spin;
|
||||
DoubleSpinBox* m_PreO2Spin;
|
||||
AffineDoubleSpinBox* m_PreX1Spin;//Pre.
|
||||
AffineDoubleSpinBox* m_PreX2Spin;
|
||||
AffineDoubleSpinBox* m_PreY1Spin;
|
||||
AffineDoubleSpinBox* m_PreY2Spin;
|
||||
AffineDoubleSpinBox* m_PreO1Spin;
|
||||
AffineDoubleSpinBox* m_PreO2Spin;
|
||||
|
||||
DoubleSpinBox* m_PostX1Spin;//Post.
|
||||
DoubleSpinBox* m_PostX2Spin;
|
||||
DoubleSpinBox* m_PostY1Spin;
|
||||
DoubleSpinBox* m_PostY2Spin;
|
||||
DoubleSpinBox* m_PostO1Spin;
|
||||
DoubleSpinBox* m_PostO2Spin;
|
||||
AffineDoubleSpinBox* m_PostX1Spin;//Post.
|
||||
AffineDoubleSpinBox* m_PostX2Spin;
|
||||
AffineDoubleSpinBox* m_PostY1Spin;
|
||||
AffineDoubleSpinBox* m_PostY2Spin;
|
||||
AffineDoubleSpinBox* m_PostO1Spin;
|
||||
AffineDoubleSpinBox* m_PostO2Spin;
|
||||
|
||||
DoubleSpinBox* m_PreSpins[6];
|
||||
DoubleSpinBox* m_PostSpins[6];
|
||||
AffineDoubleSpinBox* m_PreSpins[6];
|
||||
AffineDoubleSpinBox* m_PostSpins[6];
|
||||
|
||||
//Xaos.
|
||||
DoubleSpinBox* m_XaosSpinBox;
|
||||
@ -555,6 +555,7 @@ private:
|
||||
int m_VarSortMode;
|
||||
int m_PaletteSortMode;
|
||||
int m_PreviousPaletteRow;
|
||||
vector<byte> m_PreviewVec;
|
||||
shared_ptr<OpenCLInfo> m_Info;
|
||||
unique_ptr<FractoriumEmberControllerBase> m_Controller;
|
||||
Ui::FractoriumClass ui;
|
||||
|
@ -18,7 +18,7 @@ FractoriumEmberControllerBase::FractoriumEmberControllerBase(Fractorium* fractor
|
||||
m_RenderTimer->setInterval(0);
|
||||
m_Fractorium->connect(m_RenderTimer.get(), SIGNAL(timeout()), SLOT(IdleTimer()));
|
||||
m_RenderRestartTimer = make_unique<QTimer>(m_Fractorium);
|
||||
m_Fractorium->connect(m_RenderRestartTimer.get(), SIGNAL(timeout()), SLOT(StartRenderTimer()));
|
||||
m_Fractorium->connect(m_RenderRestartTimer.get(), &QTimer::timeout, [&]() { m_Fractorium->StartRenderTimer(false); });//It's ok to pass false for the first shot because creating the controller will start the preview renders.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -368,7 +368,6 @@ void TreePreviewRenderer<T>::PreviewRenderFunc(uint start, uint end)
|
||||
auto f = m_Controller->m_Fractorium;
|
||||
m_PreviewRenderer.EarlyClip(f->m_Settings->EarlyClip());
|
||||
m_PreviewRenderer.YAxisUp(f->m_Settings->YAxisUp());
|
||||
m_PreviewRenderer.Transparency(f->m_Settings->Transparency());
|
||||
m_PreviewRenderer.ThreadCount(std::max(1u, Timing::ProcessorCount() - 1));//Leave one processor free so the GUI can breathe.
|
||||
|
||||
if (auto top = m_Tree->topLevelItem(0))
|
||||
@ -394,7 +393,7 @@ void TreePreviewRenderer<T>::PreviewRenderFunc(uint start, uint end)
|
||||
//until the update is complete.
|
||||
QMetaObject::invokeMethod(f, "SetLibraryTreeItemData", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(EmberTreeWidgetItemBase*, treeItem),
|
||||
Q_ARG(vector<byte>&, m_PreviewFinalImage),
|
||||
Q_ARG(vv4F&, m_PreviewFinalImage),
|
||||
Q_ARG(uint, PREVIEW_SIZE),
|
||||
Q_ARG(uint, PREVIEW_SIZE));
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ public:
|
||||
virtual void AffineInterpTypeChanged(int i) { }
|
||||
virtual void InterpTypeChanged(int i) { }
|
||||
virtual void BackgroundChanged(const QColor& color) { }
|
||||
virtual void ClearColorCurves() { }
|
||||
virtual void ClearColorCurves(int i) { }
|
||||
virtual void ColorCurveChanged(int curveIndex, int pointInxed, const QPointF& point) { }
|
||||
|
||||
//Xforms.
|
||||
@ -240,7 +240,7 @@ public:
|
||||
|
||||
//Rendering/progress.
|
||||
virtual bool Render() { return false; }
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared = true) { return false; }
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool updatePreviews, bool shared = true) { return false; }
|
||||
virtual uint SizeOfT() const { return 0; }
|
||||
virtual void ClearUndo() { }
|
||||
virtual GLEmberControllerBase* GLController() { return nullptr; }
|
||||
@ -252,10 +252,10 @@ public:
|
||||
void Shutdown();
|
||||
void UpdateRender(eProcessAction action = eProcessAction::FULL_RENDER);
|
||||
void DeleteRenderer();
|
||||
void SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector<byte>& pixels, size_t width, size_t height, size_t channels, size_t bpc);
|
||||
void SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector<v4F>& pixels, size_t width, size_t height, bool png16Bit, bool transparency);
|
||||
RendererBase* Renderer() { return m_Renderer.get(); }
|
||||
vector<byte>* FinalImage() { return &(m_FinalImage); }
|
||||
vector<byte>* PreviewFinalImage() { return &m_PreviewFinalImage; }
|
||||
vector<v4F>* FinalImage() { return &(m_FinalImage); }
|
||||
vector<v4F>* PreviewFinalImage() { return &m_PreviewFinalImage; }
|
||||
EmberStats Stats() { return m_Stats; }
|
||||
|
||||
protected:
|
||||
@ -286,8 +286,8 @@ protected:
|
||||
string m_CurrentPaletteFilePath;
|
||||
std::recursive_mutex m_Cs;
|
||||
std::thread m_WriteThread;
|
||||
vector<byte> m_FinalImage;
|
||||
vector<byte> m_PreviewFinalImage;
|
||||
vector<v4F> m_FinalImage;
|
||||
vector<v4F> m_PreviewFinalImage;
|
||||
vector<eProcessAction> m_ProcessActions;
|
||||
vector<eVariationId> m_FilteredVariations;
|
||||
unique_ptr<EmberNs::RendererBase> m_Renderer;
|
||||
@ -436,7 +436,7 @@ public:
|
||||
virtual void AffineInterpTypeChanged(int index) override;
|
||||
virtual void InterpTypeChanged(int index) override;
|
||||
virtual void BackgroundChanged(const QColor& col) override;
|
||||
virtual void ClearColorCurves() override;
|
||||
virtual void ClearColorCurves(int i) override;
|
||||
virtual void ColorCurveChanged(int curveIndex, int pointInxed, const QPointF& point) override;
|
||||
|
||||
//Xforms.
|
||||
@ -510,7 +510,7 @@ public:
|
||||
|
||||
//Rendering/progress.
|
||||
virtual bool Render() override;
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared = true) override;
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool updatePreviews, bool shared = true) override;
|
||||
virtual uint SizeOfT() const override { return sizeof(T); }
|
||||
virtual int ProgressFunc(Ember<T>& ember, void* foo, double fraction, int stage, double etaMs) override;
|
||||
virtual void ClearUndo() override;
|
||||
@ -607,11 +607,6 @@ public:
|
||||
return m_PreviewRenderer.YAxisUp();
|
||||
}
|
||||
|
||||
bool Transparency()
|
||||
{
|
||||
return m_PreviewRenderer.Transparency();
|
||||
}
|
||||
|
||||
bool Running()
|
||||
{
|
||||
return m_PreviewRun || m_PreviewResult.isRunning();
|
||||
@ -622,7 +617,8 @@ public:
|
||||
protected:
|
||||
volatile bool m_PreviewRun = false;
|
||||
Ember<T> m_PreviewEmber;
|
||||
vector<byte> m_PreviewFinalImage;
|
||||
vector<byte> m_PreviewVec;
|
||||
vv4F m_PreviewFinalImage;
|
||||
EmberNs::Renderer<T, float> m_PreviewRenderer;
|
||||
|
||||
private:
|
||||
@ -639,6 +635,7 @@ class TreePreviewRenderer : public PreviewRenderer<T>
|
||||
public:
|
||||
using PreviewRenderer<T>::m_PreviewRun;
|
||||
using PreviewRenderer<T>::m_PreviewEmber;
|
||||
using PreviewRenderer<T>::m_PreviewVec;
|
||||
using PreviewRenderer<T>::m_PreviewRenderer;
|
||||
using PreviewRenderer<T>::m_PreviewFinalImage;
|
||||
|
||||
@ -655,10 +652,8 @@ public:
|
||||
{
|
||||
auto f = m_Controller->m_Fractorium;
|
||||
m_PreviewRenderer.Callback(nullptr);
|
||||
m_PreviewRenderer.NumChannels(4);
|
||||
m_PreviewRenderer.EarlyClip(f->m_Settings->EarlyClip());
|
||||
m_PreviewRenderer.YAxisUp(f->m_Settings->YAxisUp());
|
||||
m_PreviewRenderer.Transparency(f->m_Settings->Transparency());
|
||||
}
|
||||
|
||||
virtual void PreviewRenderFunc(uint start, uint end) override;
|
||||
|
@ -96,15 +96,18 @@ vector<pair<size_t, QTreeWidgetItem*>> Fractorium::GetCurrentEmberIndex()
|
||||
/// <param name="v">The vector holding the RGBA bitmap</param>
|
||||
/// <param name="w">The width of the bitmap</param>
|
||||
/// <param name="h">The height of the bitmap</param>
|
||||
void Fractorium::SetLibraryTreeItemData(EmberTreeWidgetItemBase* item, vector<byte>& v, uint w, uint h)
|
||||
void Fractorium::SetLibraryTreeItemData(EmberTreeWidgetItemBase* item, vv4F& v, uint w, uint h)
|
||||
{
|
||||
item->SetImage(v, w, h);
|
||||
m_PreviewVec.resize(w * h * 4);
|
||||
Rgba32ToRgba8(v.data(), m_PreviewVec.data(), w, h, m_Settings->Transparency());
|
||||
item->SetImage(m_PreviewVec, w, h);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set all libary tree entries to the name of the corresponding ember they represent.
|
||||
/// Set all libary tree entries to point to the underlying ember they represent.
|
||||
/// </summary>
|
||||
/// <param name="update">A bitfield representing the type of synchronizing to do. Update one or more of index, name or pointer.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::SyncLibrary(eLibraryUpdate update)
|
||||
{
|
||||
|
@ -349,9 +349,10 @@ void Fractorium::OnActionSaveCurrentScreen(bool checked)
|
||||
auto filename = SetupSaveImageDialog(m_Controller->Name());
|
||||
auto renderer = m_Controller->Renderer();
|
||||
auto& pixels = *m_Controller->FinalImage();
|
||||
auto rendererCL = dynamic_cast<RendererCLBase*>(m_Controller->Renderer());
|
||||
auto rendererCL = dynamic_cast<RendererCLBase*>(renderer);
|
||||
auto stats = m_Controller->Stats();
|
||||
auto comments = renderer->ImageComments(stats, 0, true);
|
||||
auto settings = FractoriumSettings::Instance();
|
||||
|
||||
if (rendererCL && renderer->PrepFinalAccumVector(pixels))
|
||||
{
|
||||
@ -362,7 +363,7 @@ void Fractorium::OnActionSaveCurrentScreen(bool checked)
|
||||
}
|
||||
}
|
||||
|
||||
m_Controller->SaveCurrentRender(filename, comments, pixels, renderer->FinalRasW(), renderer->FinalRasH(), renderer->NumChannels(), renderer->BytesPerChannel());
|
||||
m_Controller->SaveCurrentRender(filename, comments, pixels, renderer->FinalRasW(), renderer->FinalRasH(), settings->Png16Bit(), settings->Transparency());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -879,7 +880,7 @@ void Fractorium::OnActionFinalRender(bool checked)
|
||||
void Fractorium::OnFinalRenderClose(int result)
|
||||
{
|
||||
m_RenderStatusLabel->setText("Renderer starting...");
|
||||
StartRenderTimer();//Re-create the renderer and start rendering again.
|
||||
StartRenderTimer(false);//Re-create the renderer and start rendering again.
|
||||
ui.ActionStartStopRenderer->setChecked(false);//Re-enable any controls that might have been disabled.
|
||||
OnActionStartStopRenderer(false);
|
||||
}
|
||||
@ -892,10 +893,17 @@ void Fractorium::OnFinalRenderClose(int result)
|
||||
/// <param name="checked">Ignored</param>
|
||||
void Fractorium::OnActionOptions(bool checked)
|
||||
{
|
||||
bool ec = m_Settings->EarlyClip();
|
||||
bool yup = m_Settings->YAxisUp();
|
||||
bool trans = m_Settings->Transparency();
|
||||
|
||||
if (m_OptionsDialog->exec())
|
||||
{
|
||||
bool updatePreviews = ec != m_Settings->EarlyClip() ||
|
||||
yup != m_Settings->YAxisUp() ||
|
||||
trans != m_Settings->Transparency();
|
||||
SyncOptionsToToolbar();//This won't trigger a recreate, the call below handles it.
|
||||
ShutdownAndRecreateFromOptions();//This will recreate the controller and/or the renderer from the options if necessary, then start the render timer.
|
||||
ShutdownAndRecreateFromOptions(updatePreviews);//This will recreate the controller and/or the renderer from the options if necessary, then start the render timer.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -491,21 +491,38 @@ void Fractorium::SetPaletteFileComboIndex(const string& filename)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the color curve values in the current ember to their default state and also update the curves control.
|
||||
/// Reset the color curve values for the selected curve in the current ember to their default state and also update the curves control.
|
||||
/// Called when ResetCurvesButton is clicked.
|
||||
/// Note if they click Reset Curves when the "All" radio button is selected, then it clears all curves.
|
||||
/// Resets the rendering process at either ACCUM_ONLY by default, or FILTER_AND_ACCUM when using early clip.
|
||||
/// </summary>
|
||||
/// <param name="i">The index of the curve to be cleared, 0 to clear all.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::ClearColorCurves()
|
||||
void FractoriumEmberController<T>::ClearColorCurves(int i)
|
||||
{
|
||||
Update([&]
|
||||
{
|
||||
m_Ember.m_Curves.Init();
|
||||
if (i)
|
||||
m_Ember.m_Curves.Init(i);
|
||||
else
|
||||
m_Ember.m_Curves.Init(0);
|
||||
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY);
|
||||
FillCurvesControl();
|
||||
}
|
||||
|
||||
void Fractorium::OnResetCurvesButtonClicked(bool checked) { m_Controller->ClearColorCurves(); }
|
||||
void Fractorium::OnResetCurvesButtonClicked(bool checked)
|
||||
{
|
||||
if (ui.CurvesAllRadio->isChecked())
|
||||
m_Controller->ClearColorCurves(0);
|
||||
else if (ui.CurvesRedRadio->isChecked())
|
||||
m_Controller->ClearColorCurves(1);
|
||||
else if (ui.CurvesGreenRadio->isChecked())
|
||||
m_Controller->ClearColorCurves(2);
|
||||
else if (ui.CurvesBlueRadio->isChecked())
|
||||
m_Controller->ClearColorCurves(3);
|
||||
else
|
||||
m_Controller->ClearColorCurves(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the coordinate of the curve point.
|
||||
|
@ -115,16 +115,16 @@
|
||||
#include <QWidget>
|
||||
#include <QWidgetAction>
|
||||
|
||||
#define GLM_FORCE_RADIANS 1
|
||||
#define GLM_ENABLE_EXPERIMENTAL 1
|
||||
//#define GLM_FORCE_RADIANS 1
|
||||
//#define GLM_ENABLE_EXPERIMENTAL 1
|
||||
|
||||
#ifndef __APPLE__
|
||||
#define GLM_FORCE_INLINE 1
|
||||
#endif
|
||||
|
||||
#include "glm/glm.hpp"
|
||||
#include "glm/gtc/matrix_transform.hpp"
|
||||
#include "glm/gtc/type_ptr.hpp"
|
||||
//#ifndef __APPLE__
|
||||
// #define GLM_FORCE_INLINE 1
|
||||
//#endif
|
||||
//
|
||||
//#include "glm/glm.hpp"
|
||||
//#include "glm/gtc/matrix_transform.hpp"
|
||||
//#include "glm/gtc/type_ptr.hpp"
|
||||
|
||||
#ifndef _WIN32
|
||||
#undef Bool
|
||||
|
@ -111,49 +111,66 @@ void FractoriumEmberControllerBase::DeleteRenderer()
|
||||
/// This will embed the id, url and nick fields from the options in the image comments.
|
||||
/// </summary>
|
||||
/// <param name="filename">The full path and filename</param>
|
||||
/// <param name="comments">The comments to save in the png or jpg</param>
|
||||
/// <param name="comments">The comments to save in the png, jpg or exr</param>
|
||||
/// <param name="pixels">The buffer containing the pixels</param>
|
||||
/// <param name="width">The width in pixels of the image</param>
|
||||
/// <param name="height">The height in pixels of the image</param>
|
||||
/// <param name="channels">The number of channels, 3 or 4.</param>
|
||||
/// <param name="bpc">The bytes per channel, almost always 1.</param>
|
||||
void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector<byte>& pixels, size_t width, size_t height, size_t channels, size_t bpc)
|
||||
/// <param name="png16Bit">Whether to use 16 bits per channel per pixel when saving as Png.</param>
|
||||
/// <param name="transparency">Whether to use alpha when saving as Png or Exr.</param>
|
||||
void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector<v4F>& pixels, size_t width, size_t height, bool png16Bit, bool transparency)
|
||||
{
|
||||
if (filename != "")
|
||||
{
|
||||
bool b = false;
|
||||
byte* data = nullptr;
|
||||
vector<byte> vecRgb;
|
||||
auto size = width * height;
|
||||
auto settings = m_Fractorium->m_Settings;
|
||||
QFileInfo fileInfo(filename);
|
||||
QString suffix = fileInfo.suffix();
|
||||
auto settings = m_Fractorium->m_Settings;
|
||||
|
||||
//Ensure dimensions are valid.
|
||||
if (pixels.size() < (width * height * channels * bpc))
|
||||
{
|
||||
m_Fractorium->ShowCritical("Save Failed", "Dimensions didn't match, not saving.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
data = pixels.data();//Png and channels == 4.
|
||||
|
||||
if ((suffix == "jpg" || suffix == "bmp") && channels)
|
||||
{
|
||||
RgbaToRgb(pixels, vecRgb, width, height);
|
||||
data = vecRgb.data();
|
||||
}
|
||||
|
||||
string s = filename.toStdString();
|
||||
string id = settings->Id().toStdString();
|
||||
string url = settings->Url().toStdString();
|
||||
string nick = settings->Nick().toStdString();
|
||||
|
||||
if (suffix == "png")
|
||||
b = WritePng(s.c_str(), data, width, height, 1, true, comments, id, url, nick);
|
||||
else if (suffix == "jpg")
|
||||
b = WriteJpeg(s.c_str(), data, width, height, 100, true, comments, id, url, nick);
|
||||
else if (suffix == "bmp")
|
||||
b = WriteBmp(s.c_str(), data, width, height);
|
||||
//Ensure dimensions are valid.
|
||||
if (pixels.size() < size)
|
||||
{
|
||||
m_Fractorium->ShowCritical("Save Failed", "Dimensions didn't match, not saving.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
auto data = pixels.data();
|
||||
|
||||
if (suffix.endsWith("bmp", Qt::CaseInsensitive) || suffix.endsWith("jpg", Qt::CaseInsensitive))
|
||||
{
|
||||
vector<byte> rgb8Image(size * 3);
|
||||
Rgba32ToRgb8(data, rgb8Image.data(), width, height);
|
||||
|
||||
if (suffix.endsWith("bmp", Qt::CaseInsensitive))
|
||||
b = WriteBmp(s.c_str(), rgb8Image.data(), width, height);
|
||||
else if (suffix.endsWith("jpg", Qt::CaseInsensitive))
|
||||
b = WriteJpeg(s.c_str(), rgb8Image.data(), width, height, 100, true, comments, id, url, nick);
|
||||
}
|
||||
else if (suffix.endsWith("png", Qt::CaseInsensitive))
|
||||
{
|
||||
if (!png16Bit)
|
||||
{
|
||||
vector<byte> rgba8Image(size * 4);
|
||||
Rgba32ToRgba8(data, rgba8Image.data(), width, height, transparency);
|
||||
b = WritePng(s.c_str(), rgba8Image.data(), width, height, 1, true, comments, id, url, nick);//Put an opt here for 1 or 2 bytes.//TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<glm::uint16> rgba16Image(size * 4);
|
||||
Rgba32ToRgba16(data, rgba16Image.data(), width, height, transparency);
|
||||
b = WritePng(s.c_str(), (byte*)rgba16Image.data(), width, height, 2, true, comments, id, url, nick);//Put an opt here for 1 or 2 bytes.//TODO
|
||||
}
|
||||
}
|
||||
else if (suffix.endsWith("exr", Qt::CaseInsensitive))
|
||||
{
|
||||
vector<Rgba> rgba32Image(size);
|
||||
Rgba32ToRgbaExr(data, rgba32Image.data(), width, height, transparency);
|
||||
b = WriteExr(s.c_str(), rgba32Image.data(), width, height, true, comments, id, url, nick);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Fractorium->ShowCritical("Save Failed", "Unrecognized format " + suffix + ", not saving.", true);
|
||||
@ -452,7 +469,7 @@ bool FractoriumEmberController<T>::Render()
|
||||
//Update it on finish because the rendering process is completely done.
|
||||
if (update || ProcessState() == eProcessState::ACCUM_DONE)
|
||||
{
|
||||
if (m_FinalImage.size() == m_Renderer->FinalBufferSize())//Make absolutely sure the correct amount of data is passed.
|
||||
if (m_FinalImage.size() == m_Renderer->FinalDimensions())//Make absolutely sure the correct amount of data is passed.
|
||||
gl->update();
|
||||
|
||||
if (ProcessState() == eProcessState::ACCUM_DONE)
|
||||
@ -509,10 +526,11 @@ bool FractoriumEmberController<T>::Render()
|
||||
/// </summary>
|
||||
/// <param name="renderType">The type of render to create</param>
|
||||
/// <param name="devices">The platform,device index pairs of the devices to use</param>
|
||||
/// <param name="updatePreviews">True to re-render the library previews, else false.</param>
|
||||
/// <param name="shared">True if shared with OpenGL, else false. Default: true.</param>
|
||||
/// <returns>True if nothing went wrong, else false.</returns>
|
||||
template <typename T>
|
||||
bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared)
|
||||
bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool updatePreviews, bool shared)
|
||||
{
|
||||
bool ok = true;
|
||||
auto s = m_Fractorium->m_Settings;
|
||||
@ -565,7 +583,6 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
|
||||
}
|
||||
|
||||
m_Renderer->Callback(this);
|
||||
m_Renderer->NumChannels(4);//Always using 4 since the GL texture is RGBA.
|
||||
m_Renderer->ReclaimOnResize(true);
|
||||
//Give it an initial ember, will be updated many times later.
|
||||
//Even though the bounds are computed when starting the next render. The OpenGL draw calls use these values, which might get called before the render starts.
|
||||
@ -573,17 +590,15 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
|
||||
m_Renderer->EarlyClip(s->EarlyClip());
|
||||
m_Renderer->YAxisUp(s->YAxisUp());
|
||||
m_Renderer->ThreadCount(s->ThreadCount());
|
||||
m_Renderer->Transparency(s->Transparency());
|
||||
|
||||
if (m_Renderer->RendererType() == eRendererType::CPU_RENDERER)
|
||||
m_Renderer->InteractiveFilter(s->CpuDEFilter() ? eInteractiveFilter::FILTER_DE : eInteractiveFilter::FILTER_LOG);
|
||||
else
|
||||
m_Renderer->InteractiveFilter(s->OpenCLDEFilter() ? eInteractiveFilter::FILTER_DE : eInteractiveFilter::FILTER_LOG);
|
||||
|
||||
if ((m_Renderer->EarlyClip() != m_LibraryPreviewRenderer->EarlyClip()) ||
|
||||
(m_Renderer->YAxisUp() != m_LibraryPreviewRenderer->YAxisUp()) ||
|
||||
(m_Renderer->Transparency() != m_LibraryPreviewRenderer->Transparency()))
|
||||
if (updatePreviews)
|
||||
{
|
||||
m_LibraryPreviewRenderer = make_unique<TreePreviewRenderer<T>>(this, m_Fractorium->ui.LibraryTree, m_EmberFile);//Will take the same settings as the main renderer.
|
||||
RenderLibraryPreviews();
|
||||
}
|
||||
|
||||
@ -618,26 +633,28 @@ void Fractorium::EnableRenderControls(bool enable)
|
||||
/// <summary>
|
||||
/// Wrapper to stop the timer, shutdown the controller and recreate, then restart the controller and renderer from the options.
|
||||
/// </summary>
|
||||
void Fractorium::ShutdownAndRecreateFromOptions()
|
||||
/// <param name="updatePreviews">True to re-render the library previews, else false.</param>
|
||||
void Fractorium::ShutdownAndRecreateFromOptions(bool updatePreviews)
|
||||
{
|
||||
//First completely stop what the current rendering process is doing.
|
||||
m_Controller->Shutdown();
|
||||
StartRenderTimer();//This will recreate the controller and/or the renderer from the options if necessary, then start the render timer.
|
||||
StartRenderTimer(updatePreviews);//This will recreate the controller and/or the renderer from the options if necessary, then start the render timer.
|
||||
m_Settings->sync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new renderer from the options.
|
||||
/// </summary>
|
||||
/// <param name="updatePreviews">True to re-render the library previews, else false.</param>
|
||||
/// <returns>True if nothing went wrong, else false.</returns>
|
||||
bool Fractorium::CreateRendererFromOptions()
|
||||
bool Fractorium::CreateRendererFromOptions(bool updatePreviews)
|
||||
{
|
||||
bool ok = true;
|
||||
bool useOpenCL = m_Info->Ok() && m_Settings->OpenCL();
|
||||
auto v = Devices(m_Settings->Devices());
|
||||
|
||||
//The most important option to process is what kind of renderer is desired, so do it first.
|
||||
if (!m_Controller->CreateRenderer((useOpenCL && !v.empty()) ? eRendererType::OPENCL_RENDERER : eRendererType::CPU_RENDERER, v))
|
||||
if (!m_Controller->CreateRenderer((useOpenCL && !v.empty()) ? eRendererType::OPENCL_RENDERER : eRendererType::CPU_RENDERER, v, updatePreviews))
|
||||
{
|
||||
//If using OpenCL, will only get here if creating RendererCL failed, but creating a backup CPU Renderer succeeded.
|
||||
ShowCritical("Renderer Creation Error", "Error creating renderer, most likely a GPU problem. Using CPU instead.");
|
||||
@ -735,25 +752,30 @@ bool Fractorium::CreateControllerFromOptions()
|
||||
m_PaletteFrequencySpin->SetValueStealth(freq);
|
||||
m_Controller->PaletteAdjust();//Applies the adjustments to temp and saves in m_Ember.m_Palette, then fills in the palette preview widget.
|
||||
}
|
||||
|
||||
return m_Controller.get();
|
||||
}
|
||||
|
||||
return m_Controller.get();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the render timer.
|
||||
/// If a renderer has not been created yet, or differs form the options, it will first be created from the options.
|
||||
/// </summary>
|
||||
void Fractorium::StartRenderTimer()
|
||||
/// <param name="updatePreviews">True to re-render the library previews, else false.</param>
|
||||
void Fractorium::StartRenderTimer(bool updatePreviews)
|
||||
{
|
||||
//Starting the render timer, either for the first time
|
||||
//or from a paused state, such as resizing or applying new options.
|
||||
CreateControllerFromOptions();
|
||||
bool newController = CreateControllerFromOptions();
|
||||
|
||||
if (m_Controller.get())
|
||||
{
|
||||
//On program startup, the renderer does not get initialized until now.
|
||||
CreateRendererFromOptions();
|
||||
//If a new controller was created, then previews will have started, so only start the previews if a new controller
|
||||
//was *not* created and updatePreviews is true.
|
||||
CreateRendererFromOptions(updatePreviews && !newController);
|
||||
|
||||
if (m_Controller->Renderer())
|
||||
m_Controller->StartRenderTimer();
|
||||
|
@ -61,16 +61,16 @@ void FractoriumSettings::EnsureDefaults()
|
||||
FinalScale(0);
|
||||
|
||||
if (OpenXmlExt() == "")
|
||||
OpenXmlExt("Flame (*.flame)");
|
||||
OpenXmlExt("*.flame");
|
||||
|
||||
if (SaveXmlExt() == "")
|
||||
SaveXmlExt("Flame (*.flame)");
|
||||
SaveXmlExt(".flame");
|
||||
|
||||
if (OpenImageExt() == "")
|
||||
OpenImageExt("Png (*.png)");
|
||||
OpenImageExt("*.png");
|
||||
|
||||
if (SaveImageExt() == "")
|
||||
SaveImageExt("Png (*.png)");
|
||||
SaveImageExt(".png");
|
||||
|
||||
if (FinalExt() != "jpg" && FinalExt() != "png")
|
||||
FinalExt("png");
|
||||
@ -121,6 +121,9 @@ void FractoriumSettings::ShowGrid(bool b) { setValue(SHOW
|
||||
bool FractoriumSettings::ToggleType() { return value(TOGGLETYPE).toBool(); }
|
||||
void FractoriumSettings::ToggleType(bool b) { setValue(TOGGLETYPE, b); }
|
||||
|
||||
bool FractoriumSettings::Png16Bit() { return value(PNG16BIT).toBool(); }
|
||||
void FractoriumSettings::Png16Bit(bool b) { setValue(PNG16BIT, b); }
|
||||
|
||||
bool FractoriumSettings::ContinuousUpdate() { return value(CONTUPDATE).toBool(); }
|
||||
void FractoriumSettings::ContinuousUpdate(bool b) { setValue(CONTUPDATE, b); }
|
||||
|
||||
@ -229,6 +232,9 @@ void FractoriumSettings::FinalDoAll(bool b) { setValue(FINALDOALL, b);
|
||||
bool FractoriumSettings::FinalDoSequence() { return value(FINALDOSEQUENCE).toBool(); }
|
||||
void FractoriumSettings::FinalDoSequence(bool b) { setValue(FINALDOSEQUENCE, b); }
|
||||
|
||||
bool FractoriumSettings::FinalPng16Bit() { return value(FINALPNG16BIT).toBool(); }
|
||||
void FractoriumSettings::FinalPng16Bit(bool b) { setValue(FINALPNG16BIT, b); }
|
||||
|
||||
bool FractoriumSettings::FinalKeepAspect() { return value(FINALKEEPASPECT).toBool(); }
|
||||
void FractoriumSettings::FinalKeepAspect(bool b) { setValue(FINALKEEPASPECT, b); }
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#define SHOWXFORMS "render/showxforms"
|
||||
#define SHOWGRID "render/showgrid"
|
||||
#define TOGGLETYPE "render/toggletype"
|
||||
#define PNG16BIT "render/png16bit"
|
||||
#define DEVICES "render/devices"
|
||||
#define THREADCOUNT "render/threadcount"
|
||||
#define CPUDEFILTER "render/cpudefilter"
|
||||
@ -50,6 +51,7 @@
|
||||
#define FINALSAVEXML "finalrender/savexml"
|
||||
#define FINALDOALL "finalrender/doall"
|
||||
#define FINALDOSEQUENCE "finalrender/dosequence"
|
||||
#define FINALPNG16BIT "finalrender/png16bit"
|
||||
#define FINALKEEPASPECT "finalrender/keepaspect"
|
||||
#define FINALSCALE "finalrender/scale"
|
||||
#define FINALEXT "finalrender/ext"
|
||||
@ -124,6 +126,9 @@ public:
|
||||
bool ToggleType();
|
||||
void ToggleType(bool b);
|
||||
|
||||
bool Png16Bit();
|
||||
void Png16Bit(bool b);
|
||||
|
||||
bool ContinuousUpdate();
|
||||
void ContinuousUpdate(bool b);
|
||||
|
||||
@ -220,6 +225,9 @@ public:
|
||||
bool FinalDoSequence();
|
||||
void FinalDoSequence(bool b);
|
||||
|
||||
bool FinalPng16Bit();
|
||||
void FinalPng16Bit(bool b);
|
||||
|
||||
bool FinalKeepAspect();
|
||||
void FinalKeepAspect(bool b);
|
||||
|
||||
|
@ -43,7 +43,7 @@ void Fractorium::OnActionCpu(bool checked)
|
||||
if (checked && m_Settings->OpenCL())
|
||||
{
|
||||
m_Settings->OpenCL(false);
|
||||
ShutdownAndRecreateFromOptions();
|
||||
ShutdownAndRecreateFromOptions(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ void Fractorium::OnActionCL(bool checked)
|
||||
if (checked && !m_Settings->OpenCL())
|
||||
{
|
||||
m_Settings->OpenCL(true);
|
||||
ShutdownAndRecreateFromOptions();
|
||||
ShutdownAndRecreateFromOptions(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ void Fractorium::OnActionSP(bool checked)
|
||||
if (checked && m_Settings->Double())
|
||||
{
|
||||
m_Settings->Double(false);
|
||||
ShutdownAndRecreateFromOptions();
|
||||
ShutdownAndRecreateFromOptions(true);//Pass true, but it's not needed because creating a new controller will force a library tree re-render.
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ void Fractorium::OnActionDP(bool checked)
|
||||
if (checked && !m_Settings->Double())
|
||||
{
|
||||
m_Settings->Double(true);
|
||||
ShutdownAndRecreateFromOptions();
|
||||
ShutdownAndRecreateFromOptions(true);//Pass true, but it's not needed because creating a new controller will force a library tree re-render.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,7 +251,7 @@ void FractoriumEmberController<T>::AffineSetHelper(double d, int index, bool pre
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
DoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
|
||||
AffineDoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
|
||||
|
||||
if (m_Fractorium->ui.PolarAffineCheckBox->isChecked())
|
||||
{
|
||||
@ -618,7 +618,7 @@ void FractoriumEmberController<T>::FillBothAffines()
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FillAffineWithXform(Xform<T>* xform, bool pre)
|
||||
{
|
||||
DoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
|
||||
AffineDoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
|
||||
if (m_Fractorium->ui.PolarAffineCheckBox->isChecked())
|
||||
@ -715,9 +715,9 @@ void Fractorium::OnPolarAffineCheckBoxStateChanged(int state)
|
||||
/// <param name="prec">The precision of the spinner</param>
|
||||
/// <param name="signal">The signal the spinner emits</param>
|
||||
/// <param name="slot">The slot to receive the signal</param>
|
||||
void Fractorium::SetupAffineSpinner(QTableWidget* table, const QObject* receiver, int row, int col, DoubleSpinBox*& spinBox, int height, double min, double max, double step, double prec, const char* signal, const char* slot)
|
||||
void Fractorium::SetupAffineSpinner(QTableWidget* table, const QObject* receiver, int row, int col, AffineDoubleSpinBox*& spinBox, int height, double min, double max, double step, double prec, const char* signal, const char* slot)
|
||||
{
|
||||
spinBox = new DoubleSpinBox(table, height, step);
|
||||
spinBox = new AffineDoubleSpinBox(table, height, step);
|
||||
spinBox->setRange(min, max);
|
||||
spinBox->setDecimals(prec);
|
||||
table->setCellWidget(row, col, spinBox);
|
||||
|
@ -375,5 +375,5 @@ void Fractorium::OnVariationsFilterClearButtonClicked(bool checked)
|
||||
template class FractoriumEmberController<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template class FractoriumEmberController<double>;
|
||||
template class FractoriumEmberController<double>;
|
||||
#endif
|
||||
|
@ -54,8 +54,6 @@ void GLWidget::InitGL()
|
||||
void GLWidget::DrawQuad()
|
||||
{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
auto renderer = m_Fractorium->m_Controller->Renderer();
|
||||
auto finalImage = m_Fractorium->m_Controller->FinalImage();
|
||||
|
||||
@ -65,7 +63,7 @@ void GLWidget::DrawQuad()
|
||||
glBindTexture(GL_TEXTURE_2D, m_OutputTexID);//The texture to draw to.
|
||||
|
||||
//Only draw if the dimensions match exactly.
|
||||
if (m_TexWidth == width() && m_TexHeight == height() && ((m_TexWidth * m_TexHeight * 4) == GLint(finalImage->size())))
|
||||
if (m_TexWidth == width() && m_TexHeight == height() && ((m_TexWidth * m_TexHeight) == GLint(finalImage->size())))
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
@ -77,7 +75,7 @@ void GLWidget::DrawQuad()
|
||||
|
||||
//Copy data from CPU to OpenGL if using a CPU renderer. This is not needed when using OpenCL.
|
||||
if (renderer->RendererType() == eRendererType::CPU_RENDERER)
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_TexWidth, m_TexHeight, GL_RGBA, GL_UNSIGNED_BYTE, finalImage->data());
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_TexWidth, m_TexHeight, GL_RGBA, GL_FLOAT, finalImage->data());
|
||||
|
||||
glBegin(GL_QUADS);//This will need to be converted to a shader at some point in the future.
|
||||
glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
|
||||
@ -94,7 +92,6 @@ void GLWidget::DrawQuad()
|
||||
glBindTexture(GL_TEXTURE_2D, 0);//Stop using this texture.
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
@ -267,10 +264,10 @@ void GLEmberController<T>::DrawImage()
|
||||
|
||||
if (SizesMatch())//Ensure all sizes are correct. If not, do nothing.
|
||||
{
|
||||
vector<byte>* finalImage = m_FractoriumEmberController->FinalImage();
|
||||
auto finalImage = m_FractoriumEmberController->FinalImage();
|
||||
|
||||
if ((renderer->RendererType() == eRendererType::OPENCL_RENDERER) || finalImage)//Final image only matters for CPU renderer.
|
||||
if ((renderer->RendererType() == eRendererType::OPENCL_RENDERER) || finalImage->size() == renderer->FinalBufferSize())
|
||||
if ((renderer->RendererType() == eRendererType::OPENCL_RENDERER) || finalImage->size() == renderer->FinalDimensions())
|
||||
m_GL->DrawQuad();//Output image is drawn here.
|
||||
}
|
||||
|
||||
@ -757,7 +754,7 @@ bool GLWidget::Allocate(bool force)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TexWidth, m_TexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_TexWidth, m_TexHeight, 0, GL_RGBA, GL_FLOAT, nullptr);
|
||||
alloc = true;
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@ bool FractoriumOptionsDialog::OpenCL() { return ui.OpenCLCheckBox->isChecked();
|
||||
bool FractoriumOptionsDialog::Double() { return ui.DoublePrecisionCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::ShowAllXforms() { return ui.ShowAllXformsCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::ToggleType() { return ui.ToggleTypeCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::Png16Bit() { return ui.Png16BitCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::AutoUnique() { return ui.AutoUniqueCheckBox->isChecked(); }
|
||||
uint FractoriumOptionsDialog::ThreadCount() { return ui.ThreadCountSpin->value(); }
|
||||
uint FractoriumOptionsDialog::RandomCount() { return ui.RandomCountSpin->value(); }
|
||||
@ -174,6 +175,7 @@ void FractoriumOptionsDialog::GuiToData()
|
||||
m_Settings->Double(Double());
|
||||
m_Settings->ShowAllXforms(ShowAllXforms());
|
||||
m_Settings->ToggleType(ToggleType());
|
||||
m_Settings->Png16Bit(Png16Bit());
|
||||
m_Settings->ThreadCount(ThreadCount());
|
||||
m_Settings->RandomCount(RandomCount());
|
||||
m_Settings->CpuSubBatch(ui.CpuSubBatchSpin->value());
|
||||
@ -207,6 +209,7 @@ void FractoriumOptionsDialog::DataToGui()
|
||||
ui.DoublePrecisionCheckBox->setChecked(m_Settings->Double());
|
||||
ui.ShowAllXformsCheckBox->setChecked(m_Settings->ShowAllXforms());
|
||||
ui.ToggleTypeCheckBox->setChecked(m_Settings->ToggleType());
|
||||
ui.Png16BitCheckBox->setChecked(m_Settings->Png16Bit());
|
||||
ui.ThreadCountSpin->setValue(m_Settings->ThreadCount());
|
||||
ui.RandomCountSpin->setValue(m_Settings->RandomCount());
|
||||
ui.CpuSubBatchSpin->setValue(m_Settings->CpuSubBatch());
|
||||
|
@ -39,13 +39,13 @@ protected:
|
||||
private:
|
||||
bool EarlyClip();
|
||||
bool YAxisUp();
|
||||
bool AlphaChannel();
|
||||
bool Transparency();
|
||||
bool ContinuousUpdate();
|
||||
bool OpenCL();
|
||||
bool Double();
|
||||
bool ShowAllXforms();
|
||||
bool ToggleType();
|
||||
bool Png16Bit();
|
||||
bool AutoUnique();
|
||||
uint ThreadCount();
|
||||
uint RandomCount();
|
||||
|
@ -424,6 +424,16 @@ in interactive mode for each mouse movement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="Png16BitCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Save each RGBA component as 16-bits when saving Png files.</p><p>This leads to greater color precision for use in high end rendering and display on HDR monitors, however it makes the file size larger.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save 16-bit Png</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="OptionsXmlSavingTab">
|
||||
@ -846,6 +856,8 @@ in interactive mode for each mouse movement</string>
|
||||
<tabstop>TransparencyCheckBox</tabstop>
|
||||
<tabstop>ShowAllXformsCheckBox</tabstop>
|
||||
<tabstop>ContinuousUpdateCheckBox</tabstop>
|
||||
<tabstop>ToggleTypeCheckBox</tabstop>
|
||||
<tabstop>Png16BitCheckBox</tabstop>
|
||||
<tabstop>RandomCountSpin</tabstop>
|
||||
<tabstop>ThreadCountSpin</tabstop>
|
||||
<tabstop>CpuSubBatchSpin</tabstop>
|
||||
|
@ -496,7 +496,11 @@ QStringList PaletteEditor::SetupOpenImagesDialog()
|
||||
m_FileDialog->setViewMode(QFileDialog::List);
|
||||
m_FileDialog->setFileMode(QFileDialog::ExistingFile);
|
||||
m_FileDialog->setAcceptMode(QFileDialog::AcceptOpen);
|
||||
#ifdef _WIN32
|
||||
m_FileDialog->setNameFilter("Image Files (*.png *.jpg *.bmp)");
|
||||
#else
|
||||
m_FileDialog->setNameFilter("Image Files ( *.jpg *.png)");
|
||||
#endif
|
||||
m_FileDialog->setWindowTitle("Open Image");
|
||||
m_FileDialog->setDirectory(settings->OpenPaletteImageFolder());
|
||||
m_FileDialog->selectNameFilter("*.jpg");
|
||||
@ -515,7 +519,7 @@ QStringList PaletteEditor::SetupOpenImagesDialog()
|
||||
}
|
||||
|
||||
#else
|
||||
auto filename = QFileDialog::getOpenFileName(this, tr("Open Image"), settings->OpenPaletteImageFolder(), tr("Image Files (*.png *.jpg *.bmp)"));
|
||||
auto filename = QFileDialog::getOpenFileName(this, tr("Open Image"), settings->OpenPaletteImageFolder(), tr("Image Files (*.jpg *.png)"));
|
||||
|
||||
if (filename.size() > 0)
|
||||
{
|
||||
|
@ -146,7 +146,7 @@ void SpinBox::OnTimeout()
|
||||
/// <returns>false</returns>
|
||||
bool SpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
{
|
||||
QMouseEvent* me = dynamic_cast<QMouseEvent*>(e);
|
||||
auto me = dynamic_cast<QMouseEvent*>(e);
|
||||
|
||||
if (isEnabled() && me)
|
||||
{
|
||||
|
@ -52,4 +52,5 @@ copy X64\Release\tbb.dll ..\..\..\fractorium\Deps
|
||||
copy X64\Release\tbb.lib ..\..\..\fractorium\Deps
|
||||
cd ..\..\..
|
||||
|
||||
cd fractorium
|
||||
openexr.cmd
|
||||
|
||||
|
46
openexr.cmd
Normal file
46
openexr.cmd
Normal file
@ -0,0 +1,46 @@
|
||||
ECHO building OpenEXR
|
||||
|
||||
cd..
|
||||
if not exist ".\openexr" ^
|
||||
mkdir openexr
|
||||
|
||||
git clone git://github.com/meshula/openexr.git
|
||||
|
||||
cd openexr
|
||||
git pull
|
||||
|
||||
SET current=%cd%
|
||||
|
||||
if not exist ".\output" mkdir .\output
|
||||
|
||||
cd IlmBase
|
||||
|
||||
cmake -G "Visual Studio 14 2015 Win64"^
|
||||
-DCMAKE_PREFIX_PATH="%current%\output"^
|
||||
-DCMAKE_INSTALL_PREFIX="%current%\output"^
|
||||
.\
|
||||
|
||||
cmake --build . --target install --config Release -- /maxcpucount:8
|
||||
|
||||
cd ..\OpenEXR
|
||||
|
||||
cmake -G "Visual Studio 14 2015 Win64"^
|
||||
-DCMAKE_PREFIX_PATH="%current%\output"^
|
||||
-DCMAKE_INSTALL_PREFIX="%current%\output"^
|
||||
-DILMBASE_PACKAGE_PREFIX="%current%\output" ^
|
||||
-DZLIB_ROOT="%current%\..\zlib"^
|
||||
.\
|
||||
|
||||
cmake --build . --target install --config Release
|
||||
|
||||
cd %current%
|
||||
|
||||
copy %current%\output\lib\Half.lib %current%\..\fractorium\Deps\Half.lib
|
||||
copy %current%\output\lib\Iex-2_2.lib %current%\..\fractorium\Deps\Iex.lib
|
||||
copy %current%\output\lib\IexMath-2_2.lib %current%\..\fractorium\Deps\IexMath.lib
|
||||
copy %current%\output\lib\IlmImf-2_2.lib %current%\..\fractorium\Deps\IlmImf.lib
|
||||
copy %current%\output\lib\IlmImfUtil-2_2.lib %current%\..\fractorium\Deps\IlmImfUtil.lib
|
||||
copy %current%\output\lib\IlmThread-2_2.lib %current%\..\fractorium\Deps\IlmThread.lib
|
||||
copy %current%\output\lib\Imath-2_2.lib %current%\..\fractorium\Deps\Imath.lib
|
||||
xcopy %current%\output\Include %current%\..\fractorium\Deps\Include\ /S /Y
|
||||
xcopy %current%\output\lib\*.dll %current%\..\fractorium\Deps\ /Y
|
Loading…
Reference in New Issue
Block a user