Compare commits
No commits in common. "1031ba580855827a76a4fea5971aef07f27a19c9" and "53c6a4fbe530752c6d4a62dd8574be596141ffdf" have entirely different histories.
1031ba5808
...
53c6a4fbe5
|
@ -361,4 +361,3 @@ MigrationBackup/
|
||||||
|
|
||||||
# Fody - auto-generated XML schema
|
# Fody - auto-generated XML schema
|
||||||
FodyWeavers.xsd
|
FodyWeavers.xsd
|
||||||
/UnitTest/Qt.x64.runsettings
|
|
||||||
|
|
|
@ -4,76 +4,26 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
VisualStudioVersion = 17.2.32519.379
|
VisualStudioVersion = 17.2.32519.379
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ArchitectureColoredPainting", "ArchitectureColoredPainting\ArchitectureColoredPainting.vcxproj", "{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ArchitectureColoredPainting", "ArchitectureColoredPainting\ArchitectureColoredPainting.vcxproj", "{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}"
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FramelessHelperCore", "FramelessHelper\qmake\FramelessHelperCore\FramelessHelperCore.vcxproj", "{954D3D24-DF86-33A3-8867-D1735CCBDB10}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FramelessHelperWidgets", "FramelessHelper\qmake\FramelessHelperWidgets\FramelessHelperWidgets.vcxproj", "{E7A71E05-4AA5-31DB-A17D-542FC7BD83A3}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest", "UnitTest\UnitTest.vcxproj", "{C81742B7-2428-4329-BEA8-01E4B985810A}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709} = {3FE96A33-2BB7-4686-A710-3EB8E3BBD709}
|
{B982E745-C0B1-46B3-A27B-743AF105F2D0} = {B982E745-C0B1-46B3-A27B-743AF105F2D0}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "components", "qt-material-widgets\components\components.vcxproj", "{8F360763-A045-3808-87A9-3FAE38E69819}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QGoodWindow", "QGoodWindow\QGoodWindow.vcxproj", "{B982E745-C0B1-46B3-A27B-743AF105F2D0}"
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "examples", "qt-material-widgets\examples\examples.vcxproj", "{2CF18346-77C1-3A0A-B9ED-8B38C828491B}"
|
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
Debug|x86 = Debug|x86
|
|
||||||
Release|x64 = Release|x64
|
Release|x64 = Release|x64
|
||||||
Release|x86 = Release|x86
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Debug|x64.ActiveCfg = Debug|x64
|
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Debug|x64.Build.0 = Debug|x64
|
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Debug|x64.Build.0 = Debug|x64
|
||||||
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Debug|x86.ActiveCfg = Debug|x64
|
|
||||||
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Debug|x86.Build.0 = Debug|x64
|
|
||||||
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Release|x64.ActiveCfg = Release|x64
|
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Release|x64.ActiveCfg = Release|x64
|
||||||
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Release|x64.Build.0 = Release|x64
|
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Release|x64.Build.0 = Release|x64
|
||||||
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Release|x86.ActiveCfg = Release|x64
|
{B982E745-C0B1-46B3-A27B-743AF105F2D0}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Release|x86.Build.0 = Release|x64
|
{B982E745-C0B1-46B3-A27B-743AF105F2D0}.Debug|x64.Build.0 = Debug|x64
|
||||||
{954D3D24-DF86-33A3-8867-D1735CCBDB10}.Debug|x64.ActiveCfg = Debug|x64
|
{B982E745-C0B1-46B3-A27B-743AF105F2D0}.Release|x64.ActiveCfg = Release|x64
|
||||||
{954D3D24-DF86-33A3-8867-D1735CCBDB10}.Debug|x64.Build.0 = Debug|x64
|
{B982E745-C0B1-46B3-A27B-743AF105F2D0}.Release|x64.Build.0 = Release|x64
|
||||||
{954D3D24-DF86-33A3-8867-D1735CCBDB10}.Debug|x86.ActiveCfg = Debug|x64
|
|
||||||
{954D3D24-DF86-33A3-8867-D1735CCBDB10}.Debug|x86.Build.0 = Debug|x64
|
|
||||||
{954D3D24-DF86-33A3-8867-D1735CCBDB10}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{954D3D24-DF86-33A3-8867-D1735CCBDB10}.Release|x64.Build.0 = Release|x64
|
|
||||||
{954D3D24-DF86-33A3-8867-D1735CCBDB10}.Release|x86.ActiveCfg = Release|x64
|
|
||||||
{954D3D24-DF86-33A3-8867-D1735CCBDB10}.Release|x86.Build.0 = Release|x64
|
|
||||||
{E7A71E05-4AA5-31DB-A17D-542FC7BD83A3}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{E7A71E05-4AA5-31DB-A17D-542FC7BD83A3}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{E7A71E05-4AA5-31DB-A17D-542FC7BD83A3}.Debug|x86.ActiveCfg = Debug|x64
|
|
||||||
{E7A71E05-4AA5-31DB-A17D-542FC7BD83A3}.Debug|x86.Build.0 = Debug|x64
|
|
||||||
{E7A71E05-4AA5-31DB-A17D-542FC7BD83A3}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{E7A71E05-4AA5-31DB-A17D-542FC7BD83A3}.Release|x64.Build.0 = Release|x64
|
|
||||||
{E7A71E05-4AA5-31DB-A17D-542FC7BD83A3}.Release|x86.ActiveCfg = Release|x64
|
|
||||||
{E7A71E05-4AA5-31DB-A17D-542FC7BD83A3}.Release|x86.Build.0 = Release|x64
|
|
||||||
{C81742B7-2428-4329-BEA8-01E4B985810A}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{C81742B7-2428-4329-BEA8-01E4B985810A}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{C81742B7-2428-4329-BEA8-01E4B985810A}.Debug|x86.ActiveCfg = Debug|x64
|
|
||||||
{C81742B7-2428-4329-BEA8-01E4B985810A}.Debug|x86.Build.0 = Debug|x64
|
|
||||||
{C81742B7-2428-4329-BEA8-01E4B985810A}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{C81742B7-2428-4329-BEA8-01E4B985810A}.Release|x64.Build.0 = Release|x64
|
|
||||||
{C81742B7-2428-4329-BEA8-01E4B985810A}.Release|x86.ActiveCfg = Release|x64
|
|
||||||
{C81742B7-2428-4329-BEA8-01E4B985810A}.Release|x86.Build.0 = Release|x64
|
|
||||||
{8F360763-A045-3808-87A9-3FAE38E69819}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{8F360763-A045-3808-87A9-3FAE38E69819}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{8F360763-A045-3808-87A9-3FAE38E69819}.Debug|x86.ActiveCfg = Debug|x64
|
|
||||||
{8F360763-A045-3808-87A9-3FAE38E69819}.Debug|x86.Build.0 = Debug|x64
|
|
||||||
{8F360763-A045-3808-87A9-3FAE38E69819}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{8F360763-A045-3808-87A9-3FAE38E69819}.Release|x64.Build.0 = Release|x64
|
|
||||||
{8F360763-A045-3808-87A9-3FAE38E69819}.Release|x86.ActiveCfg = Release|x64
|
|
||||||
{8F360763-A045-3808-87A9-3FAE38E69819}.Release|x86.Build.0 = Release|x64
|
|
||||||
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Debug|x86.ActiveCfg = Debug|x64
|
|
||||||
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Debug|x86.Build.0 = Debug|x64
|
|
||||||
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Release|x64.Build.0 = Release|x64
|
|
||||||
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Release|x86.ActiveCfg = Release|x64
|
|
||||||
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Release|x86.Build.0 = Release|x64
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
|
||||||
<QtInstall>5.15.2_msvc2019_64</QtInstall>
|
<QtInstall>5.15.2_msvc2019_64</QtInstall>
|
||||||
<QtModules>core;xml;gui;svg;widgets;core-private;gui-private;widgets-private</QtModules>
|
<QtModules>core;xml;gui;svg;widgets;winextras</QtModules>
|
||||||
<QtBuildConfig>debug</QtBuildConfig>
|
<QtBuildConfig>debug</QtBuildConfig>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
|
||||||
|
@ -55,7 +55,7 @@
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||||
<IncludePath>$(IncludePath)</IncludePath>
|
<IncludePath>$(SolutionDir)include;$(IncludePath)</IncludePath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -67,22 +67,16 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
<AdditionalIncludeDirectories>$(ProjectDir)include;$(SolutionDir)ArchitectureColoredPainting\src\Editor\RightBar;$(SolutionDir)ArchitectureColoredPainting\src\Editor\;$(SolutionDir)FramelessHelper\include;$(SolutionDir)FramelessHelper\qmake\inc\core;$(SolutionDir)FramelessHelper\include\FramelessHelper\Core;$(SolutionDir)qt-material-widgets\components;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)ArchitectureColoredPainting\src\Editor\RightBar;$(SolutionDir)ArchitectureColoredPainting\src\Editor\;$(SolutionDir)QGoodWindow;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>FRAMELESSHELPER_WIDGETS_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<WarningLevel>Level1</WarningLevel>
|
|
||||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
|
@ -104,144 +98,116 @@
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\Editor\EditorWidget.cpp" />
|
|
||||||
<ClCompile Include="src\CaptionButton.cpp" />
|
<ClCompile Include="src\CaptionButton.cpp" />
|
||||||
<ClCompile Include="src\Editor\EditorWidgetItem.cpp" />
|
<ClCompile Include="src\Editor\EditorWidget.cpp" />
|
||||||
<ClCompile Include="src\Editor\ElementManager.cpp" />
|
<ClCompile Include="src\Editor\ElementManager.cpp" />
|
||||||
<ClCompile Include="src\Editor\GraphicElement.cpp" />
|
<ClCompile Include="src\Editor\GraphicElement.cpp" />
|
||||||
<ClCompile Include="src\Editor\LayerManager.cpp" />
|
<ClCompile Include="src\Editor\LayerManager.cpp" />
|
||||||
<ClCompile Include="src\Editor\LayerStyle.cpp" />
|
|
||||||
<ClCompile Include="src\Editor\LayerWrapper.cpp" />
|
<ClCompile Include="src\Editor\LayerWrapper.cpp" />
|
||||||
<ClCompile Include="src\Editor\PixelPath.cpp" />
|
|
||||||
<ClCompile Include="src\Editor\PreviewWindow.cpp" />
|
<ClCompile Include="src\Editor\PreviewWindow.cpp" />
|
||||||
<ClCompile Include="src\Editor\RightBar\InfoDisplayWidget.cpp" />
|
<ClCompile Include="src\Editor\RightBar\InfoDisplayWidget.cpp" />
|
||||||
<ClCompile Include="src\Editor\RightBar\LayerTreeWidget.cpp" />
|
<ClCompile Include="src\Editor\RightBar\LayerTreeWidget.cpp" />
|
||||||
<ClCompile Include="src\Editor\ThirdPartyLib\qquick\qquicksvgparser.cpp" />
|
<ClCompile Include="src\Editor\third-party modules\qquick\qquicksvgparser.cpp" />
|
||||||
<ClCompile Include="src\Editor\ThirdPartyLib\SvgHelper.cpp" />
|
<ClCompile Include="src\Editor\third-party modules\util\SvgFileLoader.cpp" />
|
||||||
<ClCompile Include="src\Editor\util\PainterPathUtil.cpp" />
|
|
||||||
<ClCompile Include="src\Editor\util\SvgFileLoader.cpp" />
|
|
||||||
<ClCompile Include="src\gl.c" />
|
|
||||||
<ClCompile Include="src\IconWidget.cpp" />
|
<ClCompile Include="src\IconWidget.cpp" />
|
||||||
<ClCompile Include="src\main.cpp" />
|
<ClCompile Include="src\main.cpp" />
|
||||||
<ClCompile Include="src\MainWindow.cpp" />
|
<ClCompile Include="src\MainWindow.cpp" />
|
||||||
<ClCompile Include="src\NavigationBarWidget.cpp" />
|
<ClCompile Include="src\NavigationBarWidget.cpp" />
|
||||||
<ClCompile Include="src\Renderer\IblUtils.cpp" />
|
|
||||||
<ClCompile Include="src\Renderer\Painting\BaseStyle.cpp" />
|
|
||||||
<ClCompile Include="src\Renderer\Painting\BvhTree.cpp" />
|
<ClCompile Include="src\Renderer\Painting\BvhTree.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Camera.cpp" />
|
<ClCompile Include="src\Renderer\Camera.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Painting\CubicBezier.cpp" />
|
<ClCompile Include="src\Renderer\Painting\CubicBezier.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Painting\CubicBezierSignedDistance.cpp" />
|
<ClCompile Include="src\Renderer\Painting\CubicBezierSignedDistance.cpp" />
|
||||||
|
<ClCompile Include="src\Renderer\Painting\CubicMonotonization.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Light.cpp" />
|
<ClCompile Include="src\Renderer\Light.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Painting\Element.cpp" />
|
<ClCompile Include="src\Renderer\Painting\Element.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Painting\ElementStyle.cpp" />
|
<ClCompile Include="src\Renderer\Painting\ElementStyle.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Painting\MaterialStyleFill.cpp" />
|
|
||||||
<ClCompile Include="src\Renderer\Painting\Line.cpp" />
|
<ClCompile Include="src\Renderer\Painting\Line.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Mesh.cpp" />
|
<ClCompile Include="src\Renderer\Mesh.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Model.cpp" />
|
<ClCompile Include="src\Renderer\Model.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Painting\LineTree.cpp" />
|
<ClCompile Include="src\Renderer\Painting\LineTree.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Painting\MaterialStyleStroke.cpp" />
|
|
||||||
<ClCompile Include="src\Renderer\Painting\Painting.cpp" />
|
<ClCompile Include="src\Renderer\Painting\Painting.cpp" />
|
||||||
|
<ClCompile Include="src\Renderer\Painting\PaintingHelper.cpp" />
|
||||||
<ClCompile Include="src\Renderer\PaintingMesh.cpp" />
|
<ClCompile Include="src\Renderer\PaintingMesh.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Preview\ElementRenderer.cpp" />
|
|
||||||
<ClCompile Include="src\Renderer\RendererGLWidget.cpp" />
|
<ClCompile Include="src\Renderer\RendererGLWidget.cpp" />
|
||||||
<ClCompile Include="src\Renderer\RendererWidget.cpp" />
|
<ClCompile Include="src\Renderer\RendererWidget.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Painting\ShortCutTree.cpp" />
|
<ClCompile Include="src\Renderer\Painting\ShortCutTree.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Painting\StraightLine.cpp" />
|
<ClCompile Include="src\Renderer\Painting\StraightLine.cpp" />
|
||||||
<ClCompile Include="src\Renderer\VirtualTextureManager.cpp" />
|
|
||||||
<ClCompile Include="src\SvgParser.cpp" />
|
<ClCompile Include="src\SvgParser.cpp" />
|
||||||
<ClCompile Include="src\TitleWidget.cpp" />
|
<ClCompile Include="src\TitleWidget.cpp" />
|
||||||
<QtUic Include="EditorWidgetItem.ui" />
|
<ClCompile Include="src\Editor\third-party modules\SvgHelper.cpp" />
|
||||||
|
<QtRcc Include="MainWindow.qrc" />
|
||||||
|
<QtUic Include="EditorWidget.ui" />
|
||||||
<QtUic Include="FramelessWindow.ui" />
|
<QtUic Include="FramelessWindow.ui" />
|
||||||
<QtUic Include="MainWindow.ui" />
|
<QtUic Include="MainWindow.ui" />
|
||||||
<QtUic Include="NavigationBarWidget.ui" />
|
<QtUic Include="NavigationBarWidget.ui" />
|
||||||
<QtUic Include="RendererWidget.ui" />
|
<QtUic Include="RendererWidget.ui" />
|
||||||
<QtUic Include="EditorWidget.ui" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\data.json" />
|
<None Include="..\data.json" />
|
||||||
<None Include="res\Shaders\brdf_lut.comp" />
|
<None Include="darkstyle.qss" />
|
||||||
<None Include="res\Shaders\cubemap.frag" />
|
<None Include="lightstyle.qss" />
|
||||||
<None Include="res\Shaders\cubemap.vert" />
|
<None Include="Shaders\depth_init.comp" />
|
||||||
<None Include="res\Shaders\cubemap_prefilter.frag" />
|
<None Include="Shaders\depth_mipmap.comp" />
|
||||||
<None Include="res\Shaders\depth_init.comp" />
|
<None Include="Shaders\final.frag" />
|
||||||
<None Include="res\Shaders\depth_mipmap.comp" />
|
<None Include="Shaders\final.vert" />
|
||||||
<None Include="res\Shaders\element.comp" />
|
<None Include="Shaders\model.frag" />
|
||||||
<None Include="res\Shaders\final.frag" />
|
<None Include="Shaders\model.vert" />
|
||||||
<None Include="res\Shaders\final.vert" />
|
<None Include="Shaders\model_shadow.frag" />
|
||||||
<None Include="res\Shaders\irradiance_convolution.frag" />
|
<None Include="Shaders\model_shadow.geom" />
|
||||||
<None Include="res\Shaders\model.frag" />
|
<None Include="Shaders\model_shadow.vert" />
|
||||||
<None Include="res\Shaders\model.vert" />
|
<None Include="Shaders\painting.comp" />
|
||||||
<None Include="res\Shaders\model_shadow.frag" />
|
<None Include="Shaders\painting.frag" />
|
||||||
<None Include="res\Shaders\model_shadow.geom" />
|
<None Include="Shaders\painting.vert" />
|
||||||
<None Include="res\Shaders\model_shadow.vert" />
|
<None Include="Shaders\shader.frag" />
|
||||||
<None Include="res\Shaders\pageId_downsample.comp" />
|
<None Include="Shaders\shader.vert" />
|
||||||
<None Include="res\Shaders\painting.comp" />
|
<None Include="Shaders\shadow_mapping.comp" />
|
||||||
<None Include="res\Shaders\painting.frag" />
|
<None Include="Shaders\ssgi.comp" />
|
||||||
<None Include="res\Shaders\painting.vert" />
|
|
||||||
<None Include="res\Shaders\shader.frag" />
|
|
||||||
<None Include="res\Shaders\shader.vert" />
|
|
||||||
<None Include="res\Shaders\shadow_mapping.comp" />
|
|
||||||
<None Include="res\Shaders\skybox.frag" />
|
|
||||||
<None Include="res\Shaders\skybox.vert" />
|
|
||||||
<None Include="res\Shaders\ssgi.comp" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtMoc Include="src\Editor\RightBar\LayerTreeWidget.h" />
|
<QtMoc Include="src\Editor\RightBar\LayerTreeWidget.h" />
|
||||||
<QtMoc Include="src\Editor\RightBar\InfoDisplayWidget.h" />
|
<QtMoc Include="src\Editor\RightBar\InfoDisplayWidget.h" />
|
||||||
|
<ClInclude Include="src\Editor\third-party modules\qquick\qtquickglobal.h" />
|
||||||
|
<ClInclude Include="src\Editor\third-party modules\qquick\qtquickglobal_p.h" />
|
||||||
|
<ClInclude Include="src\Editor\third-party modules\qquick\qquicksvgparser_p.h" />
|
||||||
|
<ClInclude Include="src\Editor\third-party modules\SvgHelper.h" />
|
||||||
<QtMoc Include="src\MainWindow.h" />
|
<QtMoc Include="src\MainWindow.h" />
|
||||||
<QtMoc Include="src\Editor\EditorWidget.h" />
|
|
||||||
<ClInclude Include="src\Editor\ElementManager.h" />
|
<ClInclude Include="src\Editor\ElementManager.h" />
|
||||||
<ClInclude Include="src\Editor\GraphicElement.h" />
|
<ClInclude Include="src\Editor\GraphicElement.h" />
|
||||||
<ClInclude Include="src\Editor\LayerManager.h" />
|
<ClInclude Include="src\Editor\LayerManager.h" />
|
||||||
<ClInclude Include="src\Editor\LayerStyle.h" />
|
<ClInclude Include="src\Editor\LayerStyle.h" />
|
||||||
|
<ClInclude Include="src\Editor\LayerWrapper.h" />
|
||||||
<QtMoc Include="src\Editor\PreviewWindow.h" />
|
<QtMoc Include="src\Editor\PreviewWindow.h" />
|
||||||
<ClInclude Include="src\Editor\PixelPath.h" />
|
<ClInclude Include="src\Editor\third-party modules\util\SvgFileLoader.h" />
|
||||||
<ClInclude Include="src\Editor\ThirdPartyLib\qquick\qquicksvgparser_p.h" />
|
|
||||||
<ClInclude Include="src\Editor\ThirdPartyLib\qquick\qtquickglobal.h" />
|
|
||||||
<ClInclude Include="src\Editor\ThirdPartyLib\qquick\qtquickglobal_p.h" />
|
|
||||||
<ClInclude Include="src\Editor\ThirdPartyLib\SvgHelper.h" />
|
|
||||||
<ClInclude Include="src\Editor\util\PainterPathUtil.h" />
|
|
||||||
<ClInclude Include="src\Editor\util\SvgFileLoader.h" />
|
|
||||||
<ClInclude Include="src\Renderer\IblUtils.h" />
|
|
||||||
<ClInclude Include="src\Renderer\Painting\BaseStyle.h" />
|
|
||||||
<ClInclude Include="src\Renderer\Painting\CubicBezierSignedDistance.h" />
|
<ClInclude Include="src\Renderer\Painting\CubicBezierSignedDistance.h" />
|
||||||
<ClInclude Include="src\Renderer\Painting\Element.h" />
|
<ClInclude Include="src\Renderer\Painting\Element.h" />
|
||||||
<ClInclude Include="src\Renderer\Painting\ElementStyle.h" />
|
<ClInclude Include="src\Renderer\Painting\ElementStyle.h" />
|
||||||
<ClInclude Include="src\Renderer\Painting\MaterialStyleFill.h" />
|
|
||||||
<ClInclude Include="src\Renderer\Painting\LineTree.h" />
|
<ClInclude Include="src\Renderer\Painting\LineTree.h" />
|
||||||
<ClInclude Include="src\Renderer\Painting\MaterialStyleStroke.h" />
|
|
||||||
<ClInclude Include="src\Renderer\Painting\Painting.h" />
|
<ClInclude Include="src\Renderer\Painting\Painting.h" />
|
||||||
<ClInclude Include="src\Renderer\Preview\ElementRenderer.h" />
|
|
||||||
<ClInclude Include="src\Renderer\VirtualTextureManager.h" />
|
|
||||||
<ClInclude Include="src\SvgParser.h" />
|
<ClInclude Include="src\SvgParser.h" />
|
||||||
<QtMoc Include="src\TitleWidget.h" />
|
<QtMoc Include="src\TitleWidget.h" />
|
||||||
<QtMoc Include="src\IconWidget.h" />
|
<QtMoc Include="src\IconWidget.h" />
|
||||||
<QtMoc Include="src\CaptionButton.h" />
|
<QtMoc Include="src\CaptionButton.h" />
|
||||||
<QtMoc Include="src\NavigationBarWidget.h" />
|
<QtMoc Include="src\NavigationBarWidget.h" />
|
||||||
<QtMoc Include="src\Renderer\RendererWidget.h" />
|
<QtMoc Include="src\Renderer\RendererWidget.h" />
|
||||||
<QtMoc Include="src\Editor\EditorWidgetItem.h" />
|
<QtMoc Include="src\Editor\EditorWidget.h" />
|
||||||
<ClInclude Include="src\Renderer\Painting\BvhTree.h" />
|
<ClInclude Include="src\Renderer\Painting\BvhTree.h" />
|
||||||
<ClInclude Include="src\Renderer\Camera.h" />
|
<ClInclude Include="src\Renderer\Camera.h" />
|
||||||
<ClInclude Include="src\Renderer\Painting\CubicBezier.h" />
|
<ClInclude Include="src\Renderer\Painting\CubicBezier.h" />
|
||||||
|
<ClInclude Include="src\Renderer\Painting\CubicMonotonization.h" />
|
||||||
<ClInclude Include="src\Renderer\Drawable.h" />
|
<ClInclude Include="src\Renderer\Drawable.h" />
|
||||||
<ClInclude Include="src\Renderer\Light.h" />
|
<ClInclude Include="src\Renderer\Light.h" />
|
||||||
<ClInclude Include="src\Renderer\Painting\Line.h" />
|
<ClInclude Include="src\Renderer\Painting\Line.h" />
|
||||||
<ClInclude Include="src\Renderer\Mesh.h" />
|
<ClInclude Include="src\Renderer\Mesh.h" />
|
||||||
<ClInclude Include="src\Renderer\Model.h" />
|
<ClInclude Include="src\Renderer\Model.h" />
|
||||||
|
<ClInclude Include="src\Renderer\Painting\PaintingHelper.h" />
|
||||||
<ClInclude Include="src\Renderer\PaintingMesh.h" />
|
<ClInclude Include="src\Renderer\PaintingMesh.h" />
|
||||||
<ClInclude Include="src\Renderer\Painting\ShortCutTree.h" />
|
<ClInclude Include="src\Renderer\Painting\ShortCutTree.h" />
|
||||||
<ClInclude Include="src\Renderer\Painting\StraightLine.h" />
|
<ClInclude Include="src\Renderer\Painting\StraightLine.h" />
|
||||||
<QtMoc Include="src\Renderer\RendererGLWidget.h" />
|
<QtMoc Include="src\Renderer\RendererGLWidget.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtRcc Include="res\MainWindow.qrc" />
|
<ProjectReference Include="..\QGoodWindow\QGoodWindow.vcxproj">
|
||||||
</ItemGroup>
|
<Project>{b982e745-c0b1-46b3-a27b-743af105f2d0}</Project>
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\FramelessHelper\qmake\FramelessHelperWidgets\FramelessHelperWidgets.vcxproj">
|
|
||||||
<Project>{e7a71e05-4aa5-31db-a17d-542fc7bd83a3}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\qt-material-widgets\components\components.vcxproj">
|
|
||||||
<Project>{8f360763-a045-3808-87a9-3fae38e69819}</Project>
|
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
|
|
@ -41,29 +41,23 @@
|
||||||
<Filter Include="Header Files\Renderer\Painting">
|
<Filter Include="Header Files\Renderer\Painting">
|
||||||
<UniqueIdentifier>{22909273-2b23-49fa-84ab-444cefb09656}</UniqueIdentifier>
|
<UniqueIdentifier>{22909273-2b23-49fa-84ab-444cefb09656}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="Header Files\Editor\ThirdPartyLib">
|
|
||||||
<UniqueIdentifier>{11f273e9-b41f-4982-b4ca-12851a03aaae}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Header Files\Editor\util">
|
<Filter Include="Header Files\Editor\util">
|
||||||
<UniqueIdentifier>{727fd876-d2b0-4928-80a7-2da7cafe1519}</UniqueIdentifier>
|
<UniqueIdentifier>{e3c323ec-d150-4876-8618-5800c87a4941}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="Header Files\Editor\ThirdPartyLib\qquick">
|
<Filter Include="Header Files\Editor\third-party modules">
|
||||||
<UniqueIdentifier>{169687a8-6807-4571-802c-c4a95858db3a}</UniqueIdentifier>
|
<UniqueIdentifier>{30b46cf2-d980-47be-94c4-d2ec1dcc54ed}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="Source Files\Editor\ThirdPartyLib">
|
<Filter Include="Header Files\Editor\third-party modules\qquick">
|
||||||
<UniqueIdentifier>{0567e730-5508-4380-8304-86ded8ea3b2f}</UniqueIdentifier>
|
<UniqueIdentifier>{5028c879-8b07-4033-81ac-e538a873a837}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="Source Files\Editor\ThirdPartyLib\qquick">
|
<Filter Include="Source Files\Editor\third-party modules">
|
||||||
<UniqueIdentifier>{cfa316d0-97e0-49b0-9911-baebfea49236}</UniqueIdentifier>
|
<UniqueIdentifier>{555d169f-4fa2-4501-b67c-695197b9e6ae}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files\Editor\third-party modules\qquick">
|
||||||
|
<UniqueIdentifier>{0b29331b-03b9-44fe-916f-28f5061b4147}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="Source Files\Editor\util">
|
<Filter Include="Source Files\Editor\util">
|
||||||
<UniqueIdentifier>{96f98afe-4250-44cb-a505-682a1d5932c3}</UniqueIdentifier>
|
<UniqueIdentifier>{d7c7ab61-0d05-4e67-9e89-852f3e56fa2f}</UniqueIdentifier>
|
||||||
</Filter>
|
|
||||||
<Filter Include="Source Files\Renderer\Preview">
|
|
||||||
<UniqueIdentifier>{2a8e109f-7791-46ad-8c86-fe22a651cbe7}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Header Files\Renderer\Preview">
|
|
||||||
<UniqueIdentifier>{7ead1a66-586a-4584-ae80-9e7a4e667364}</UniqueIdentifier>
|
|
||||||
</Filter>
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -76,12 +70,9 @@
|
||||||
<QtUic Include="FramelessWindow.ui">
|
<QtUic Include="FramelessWindow.ui">
|
||||||
<Filter>Form Files</Filter>
|
<Filter>Form Files</Filter>
|
||||||
</QtUic>
|
</QtUic>
|
||||||
<QtUic Include="EditorWidget.ui">
|
|
||||||
<Filter>Form Files</Filter>
|
|
||||||
</QtUic>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\Editor\EditorWidgetItem.cpp">
|
<ClCompile Include="src\Editor\EditorWidget.cpp">
|
||||||
<Filter>Source Files\Editor</Filter>
|
<Filter>Source Files\Editor</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="src\Renderer\Camera.cpp">
|
<ClCompile Include="src\Renderer\Camera.cpp">
|
||||||
|
@ -132,6 +123,12 @@
|
||||||
<ClCompile Include="src\Renderer\Painting\CubicBezier.cpp">
|
<ClCompile Include="src\Renderer\Painting\CubicBezier.cpp">
|
||||||
<Filter>Source Files\Renderer\Painting</Filter>
|
<Filter>Source Files\Renderer\Painting</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Renderer\Painting\CubicMonotonization.cpp">
|
||||||
|
<Filter>Source Files\Renderer\Painting</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Renderer\Painting\PaintingHelper.cpp">
|
||||||
|
<Filter>Source Files\Renderer\Painting</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="src\Renderer\Painting\ShortCutTree.cpp">
|
<ClCompile Include="src\Renderer\Painting\ShortCutTree.cpp">
|
||||||
<Filter>Source Files\Renderer\Painting</Filter>
|
<Filter>Source Files\Renderer\Painting</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -168,6 +165,16 @@
|
||||||
<ClCompile Include="src\Renderer\Painting\CubicBezierSignedDistance.cpp">
|
<ClCompile Include="src\Renderer\Painting\CubicBezierSignedDistance.cpp">
|
||||||
<Filter>Source Files\Renderer\Painting</Filter>
|
<Filter>Source Files\Renderer\Painting</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Editor\third-party modules\qquick\qquicksvgparser.cpp">
|
||||||
|
<Filter>Source Files\Editor\third-party modules\qquick</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Editor\third-party modules\util\SvgFileLoader.cpp">
|
||||||
|
<Filter>Source Files\Editor\util</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Editor\third-party modules\SvgHelper.cpp">
|
||||||
|
<Filter>Source Files\Editor\third-party modules</Filter>
|
||||||
|
<Filter>Source Files\Editor\third-party modules</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="src\Editor\RightBar\LayerTreeWidget.cpp">
|
<ClCompile Include="src\Editor\RightBar\LayerTreeWidget.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -177,54 +184,12 @@
|
||||||
<ClCompile Include="src\Renderer\Painting\ElementStyle.cpp">
|
<ClCompile Include="src\Renderer\Painting\ElementStyle.cpp">
|
||||||
<Filter>Source Files\Renderer\Painting</Filter>
|
<Filter>Source Files\Renderer\Painting</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="src\Renderer\Painting\MaterialStyleFill.cpp">
|
|
||||||
<Filter>Source Files\Renderer\Painting</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Renderer\Painting\BaseStyle.cpp">
|
|
||||||
<Filter>Source Files\Renderer\Painting</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Renderer\Painting\MaterialStyleStroke.cpp">
|
|
||||||
<Filter>Source Files\Renderer\Painting</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Editor\ThirdPartyLib\qquick\qquicksvgparser.cpp">
|
|
||||||
<Filter>Source Files\Editor\ThirdPartyLib\qquick</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Editor\ThirdPartyLib\SvgHelper.cpp">
|
|
||||||
<Filter>Source Files\Editor\ThirdPartyLib</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Editor\util\SvgFileLoader.cpp">
|
|
||||||
<Filter>Source Files\Editor\util</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Editor\util\PainterPathUtil.cpp">
|
|
||||||
<Filter>Source Files\Editor\util</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Renderer\Preview\ElementRenderer.cpp">
|
|
||||||
<Filter>Source Files\Renderer\Preview</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Editor\LayerStyle.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Renderer\IblUtils.cpp">
|
|
||||||
<Filter>Source Files\Renderer</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Renderer\VirtualTextureManager.cpp">
|
|
||||||
<Filter>Source Files\Renderer</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\gl.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Editor\PixelPath.cpp">
|
|
||||||
<Filter>Source Files\Editor</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Editor\EditorWidget.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtMoc Include="src\Renderer\RendererGLWidget.h">
|
<QtMoc Include="src\Renderer\RendererGLWidget.h">
|
||||||
<Filter>Header Files\Renderer</Filter>
|
<Filter>Header Files\Renderer</Filter>
|
||||||
</QtMoc>
|
</QtMoc>
|
||||||
<QtMoc Include="src\Editor\EditorWidgetItem.h">
|
<QtMoc Include="src\Editor\EditorWidget.h">
|
||||||
<Filter>Header Files\Editor</Filter>
|
<Filter>Header Files\Editor</Filter>
|
||||||
</QtMoc>
|
</QtMoc>
|
||||||
<QtMoc Include="src\Renderer\RendererWidget.h">
|
<QtMoc Include="src\Renderer\RendererWidget.h">
|
||||||
|
@ -254,90 +219,66 @@
|
||||||
<QtMoc Include="src\Editor\RightBar\InfoDisplayWidget.h">
|
<QtMoc Include="src\Editor\RightBar\InfoDisplayWidget.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</QtMoc>
|
</QtMoc>
|
||||||
<QtMoc Include="src\Editor\EditorWidget.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</QtMoc>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<None Include="Shaders\shader.frag">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\shader.vert">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\model.frag">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\model.vert">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\final.vert">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\final.frag">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\painting.frag">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\painting.vert">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\painting.comp">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\model_shadow.frag">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\model_shadow.vert">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\depth_mipmap.comp">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\depth_init.comp">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\model_shadow.geom">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\shadow_mapping.comp">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Shaders\ssgi.comp">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="darkstyle.qss">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="lightstyle.qss">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</None>
|
||||||
<None Include="..\data.json" />
|
<None Include="..\data.json" />
|
||||||
<None Include="res\Shaders\depth_init.comp">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\depth_mipmap.comp">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\element.comp">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\final.frag">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\final.vert">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\model.frag">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\model.vert">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\model_shadow.frag">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\model_shadow.geom">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\model_shadow.vert">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\painting.comp">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\painting.frag">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\painting.vert">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\shader.frag">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\shader.vert">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\shadow_mapping.comp">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\ssgi.comp">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\cubemap.vert">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\cubemap.frag">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\skybox.vert">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\skybox.frag">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\irradiance_convolution.frag">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\cubemap_prefilter.frag">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\brdf_lut.comp">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="res\Shaders\pageId_downsample.comp">
|
|
||||||
<Filter>Resource Files\Shaders</Filter>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtUic Include="EditorWidgetItem.ui">
|
<QtUic Include="EditorWidget.ui">
|
||||||
<Filter>Form Files</Filter>
|
<Filter>Form Files</Filter>
|
||||||
</QtUic>
|
</QtUic>
|
||||||
<QtUic Include="RendererWidget.ui">
|
<QtUic Include="RendererWidget.ui">
|
||||||
|
@ -372,9 +313,15 @@
|
||||||
<ClInclude Include="src\Renderer\Painting\CubicBezier.h">
|
<ClInclude Include="src\Renderer\Painting\CubicBezier.h">
|
||||||
<Filter>Header Files\Renderer\Painting</Filter>
|
<Filter>Header Files\Renderer\Painting</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Renderer\Painting\CubicMonotonization.h">
|
||||||
|
<Filter>Header Files\Renderer\Painting</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="src\Renderer\Painting\Line.h">
|
<ClInclude Include="src\Renderer\Painting\Line.h">
|
||||||
<Filter>Header Files\Renderer\Painting</Filter>
|
<Filter>Header Files\Renderer\Painting</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Renderer\Painting\PaintingHelper.h">
|
||||||
|
<Filter>Header Files\Renderer\Painting</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="src\Renderer\Painting\ShortCutTree.h">
|
<ClInclude Include="src\Renderer\Painting\ShortCutTree.h">
|
||||||
<Filter>Header Files\Renderer\Painting</Filter>
|
<Filter>Header Files\Renderer\Painting</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -405,54 +352,34 @@
|
||||||
<ClInclude Include="src\Renderer\Painting\CubicBezierSignedDistance.h">
|
<ClInclude Include="src\Renderer\Painting\CubicBezierSignedDistance.h">
|
||||||
<Filter>Header Files\Renderer\Painting</Filter>
|
<Filter>Header Files\Renderer\Painting</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\Renderer\Painting\ElementStyle.h">
|
<ClInclude Include="src\Editor\third-party modules\SvgHelper.h">
|
||||||
<Filter>Header Files\Renderer\Painting</Filter>
|
<Filter>Header Files\Editor\third-party modules</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\Editor\ThirdPartyLib\qquick\qquicksvgparser_p.h">
|
<ClInclude Include="src\Editor\third-party modules\qquick\qquicksvgparser_p.h">
|
||||||
<Filter>Header Files\Editor\ThirdPartyLib\qquick</Filter>
|
<Filter>Header Files\Editor\third-party modules\qquick</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\Editor\ThirdPartyLib\qquick\qtquickglobal.h">
|
<ClInclude Include="src\Editor\third-party modules\qquick\qtquickglobal.h">
|
||||||
<Filter>Header Files\Editor\ThirdPartyLib\qquick</Filter>
|
<Filter>Header Files\Editor\third-party modules\qquick</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\Editor\ThirdPartyLib\qquick\qtquickglobal_p.h">
|
<ClInclude Include="src\Editor\third-party modules\qquick\qtquickglobal_p.h">
|
||||||
<Filter>Header Files\Editor\ThirdPartyLib\qquick</Filter>
|
<Filter>Header Files\Editor\third-party modules\qquick</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\Editor\ThirdPartyLib\SvgHelper.h">
|
<ClInclude Include="src\Editor\third-party modules\util\SvgFileLoader.h">
|
||||||
<Filter>Header Files\Editor\ThirdPartyLib</Filter>
|
<Filter>Header Files\Editor\util</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\Editor\util\SvgFileLoader.h">
|
<ClInclude Include="src\Editor\LayerWrapper.h">
|
||||||
|
<Filter>Header Files\Editor</Filter>
|
||||||
|
<Filter>Header Files\Editor\third-party modules\qquick</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Editor\third-party modules\util\SvgFileLoader.h">
|
||||||
<Filter>Header Files\Editor\util</Filter>
|
<Filter>Header Files\Editor\util</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\Renderer\Painting\ElementStyle.h">
|
<ClInclude Include="src\Renderer\Painting\ElementStyle.h">
|
||||||
<Filter>Header Files\Renderer\Painting</Filter>
|
<Filter>Header Files\Renderer\Painting</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\Renderer\Painting\MaterialStyleFill.h">
|
|
||||||
<Filter>Header Files\Renderer\Painting</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Renderer\Painting\MaterialStyleStroke.h">
|
|
||||||
<Filter>Header Files\Renderer\Painting</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Editor\util\PainterPathUtil.h">
|
|
||||||
<Filter>Header Files\Editor\util</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Renderer\Preview\ElementRenderer.h">
|
|
||||||
<Filter>Header Files\Renderer\Preview</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Editor\PixelPath.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Renderer\IblUtils.h">
|
|
||||||
<Filter>Header Files\Renderer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Renderer\Painting\BaseStyle.h">
|
|
||||||
<Filter>Header Files\Renderer\Painting</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\Renderer\VirtualTextureManager.h">
|
|
||||||
<Filter>Header Files\Renderer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtRcc Include="res\MainWindow.qrc">
|
<QtRcc Include="MainWindow.qrc">
|
||||||
<Filter>Resource Files</Filter>
|
<Filter>Resource Files</Filter>
|
||||||
</QtRcc>
|
</QtRcc>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -1,176 +1,108 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>EditorWidget</class>
|
<class>EditorWidgetClass</class>
|
||||||
<widget class="QWidget" name="EditorWidget">
|
<widget class="QWidget" name="EditorWidgetClass">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1139</width>
|
<width>1124</width>
|
||||||
<height>685</height>
|
<height>695</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Form</string>
|
<string>RendererWidget</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,1,1,20">
|
|
||||||
<property name="topMargin">
|
<property name="topMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<property name="rightMargin">
|
||||||
<spacer name="horizontalSpacer_2">
|
<number>0</number>
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="bottomMargin">
|
||||||
<size>
|
<number>0</number>
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="widget" native="true">
|
<widget class="QWidget" name="MainWindow" native="true">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,30">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<widget class="QLabel" name="Title">
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="createButton">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>80</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>80</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>新建</string>
|
<string>纹理编辑</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="openButton">
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,18,5">
|
||||||
<property name="minimumSize">
|
<item>
|
||||||
<size>
|
<widget class="QWidget" name="LeftBar" native="true"/>
|
||||||
<width>80</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>80</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>打开</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="saveButton">
|
<widget class="PreviewWindow" name="Preview"/>
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>80</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>80</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>保存</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="saveAsButton">
|
<widget class="QWidget" name="RightBar" native="true">
|
||||||
<property name="minimumSize">
|
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="1,2">
|
||||||
<size>
|
|
||||||
<width>80</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>80</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>另存为</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="closeButton">
|
<widget class="QTabWidget" name="DisplayTab">
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>80</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>80</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>关闭</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</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>
|
|
||||||
<item>
|
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>1</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="tab">
|
<widget class="InfoDisplayWidget" name="LayerDisplay">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Tab 1</string>
|
<string>Layer</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab_2">
|
<widget class="QWidget" name="ElementDisplay">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Tab 2</string>
|
<string>Element</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="LayerTreeWidget" name="LayerTree">
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::CustomContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>PreviewWindow</class>
|
||||||
|
<extends>QOpenGLWidget</extends>
|
||||||
|
<header>PreviewWindow.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>LayerTreeWidget</class>
|
||||||
|
<extends>QTreeWidget</extends>
|
||||||
|
<header location="global">LayerTreeWidget.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>InfoDisplayWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header location="global">InfoDisplayWidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
|
@ -1,113 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>EditorWidgetItem</class>
|
|
||||||
<widget class="QWidget" name="EditorWidgetItem">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>1124</width>
|
|
||||||
<height>695</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>RendererWidget</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QWidget" name="MainWindow" native="true">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,30">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="Title">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,18,5">
|
|
||||||
<item>
|
|
||||||
<widget class="QWidget" name="LeftBar" native="true"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="PreviewWindow" name="Preview"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QWidget" name="RightBar" native="true">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="1,2">
|
|
||||||
<item>
|
|
||||||
<widget class="QTabWidget" name="DisplayTab">
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<widget class="InfoDisplayWidget" name="LayerDisplay">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Layer</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="ElementDisplay">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Element</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="LayerTreeWidget" name="LayerTree">
|
|
||||||
<property name="contextMenuPolicy">
|
|
||||||
<enum>Qt::CustomContextMenu</enum>
|
|
||||||
</property>
|
|
||||||
<column>
|
|
||||||
<property name="text">
|
|
||||||
<string notr="true">1</string>
|
|
||||||
</property>
|
|
||||||
</column>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>PreviewWindow</class>
|
|
||||||
<extends>QOpenGLWidget</extends>
|
|
||||||
<header>PreviewWindow.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>LayerTreeWidget</class>
|
|
||||||
<extends>QTreeWidget</extends>
|
|
||||||
<header location="global">LayerTreeWidget.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>InfoDisplayWidget</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header location="global">InfoDisplayWidget.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
|
@ -38,7 +38,7 @@
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
<string notr="true"/>
|
<string notr="true">#windowFrame{ background-color:palette(Window);}</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
|
@ -56,13 +56,108 @@
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="TitleWidget" name="windowTitlebar" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="autoFillBackground">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">#windowTitlebar{border: 0px none palette(base); border-top-left-radius:5px; border-top-right-radius:5px; background-color:palette(shadow); height:20px;}</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,0,0,0">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="spacer">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>4</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>4</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="IconWidget" name="icon" native="true">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>16</width>
|
||||||
|
<height>16</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16</width>
|
||||||
|
<height>16</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::NoContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">#icon {background-color:palette(shadow);}</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="TitleWidget" name="titleWidget" native="true"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="CaptionButton" name="minimizeButton" native="true"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="CaptionButton" name="restoreButton" native="true"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="CaptionButton" name="maximizeButton" native="true"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="CaptionButton" name="closeButton" native="true"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="windowContent" native="true">
|
<widget class="QWidget" name="windowContent" native="true">
|
||||||
<property name="autoFillBackground">
|
<property name="autoFillBackground">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
<string notr="true"/>
|
<string notr="true">#windowContent{
|
||||||
|
border: 0px none palette(base);
|
||||||
|
border-radius:0px 0px 5px 5px;
|
||||||
|
}</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
|
@ -89,6 +184,25 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>CaptionButton</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>CaptionButton.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>IconWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>IconWidget.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>TitleWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>TitleWidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
|
@ -23,15 +23,6 @@
|
||||||
<file>images/icon_window_restore.png</file>
|
<file>images/icon_window_restore.png</file>
|
||||||
<file>darkstyle.qss</file>
|
<file>darkstyle.qss</file>
|
||||||
<file>lightstyle.qss</file>
|
<file>lightstyle.qss</file>
|
||||||
<file>Shaders/element.comp</file>
|
|
||||||
<file>Shaders/cubemap.frag</file>
|
|
||||||
<file>Shaders/cubemap.vert</file>
|
|
||||||
<file>Shaders/skybox.frag</file>
|
|
||||||
<file>Shaders/skybox.vert</file>
|
|
||||||
<file>Shaders/irradiance_convolution.frag</file>
|
|
||||||
<file>Shaders/cubemap_prefilter.frag</file>
|
|
||||||
<file>Shaders/brdf_lut.comp</file>
|
|
||||||
<file>Shaders/pageId_downsample.comp</file>
|
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/qt/etc">
|
<qresource prefix="/qt/etc">
|
||||||
<file>qt.conf</file>
|
<file>qt.conf</file>
|
|
@ -59,19 +59,18 @@
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
<string notr="true">
|
<string notr="true">QTabBar::tab {
|
||||||
QTabBar::tab.rendererWidget {
|
|
||||||
height: 0px;
|
height: 0px;
|
||||||
margin-top:0px;
|
margin-top:0px;
|
||||||
}
|
}
|
||||||
QTabWidget::tab-bar.rendererWidget
|
QTabWidget::tab-bar
|
||||||
{
|
{
|
||||||
height: 0px;
|
height: 0px;
|
||||||
top:0px;
|
top:0px;
|
||||||
}
|
}
|
||||||
QTabWidget::pane.rendererWidget {
|
QTabWidget::pane {
|
||||||
border: 0px;
|
border: 0px;
|
||||||
background-color: transparent;
|
background-color: rgba(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
</string>
|
</string>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
@ -13,10 +13,7 @@
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>RendererWidget</string>
|
<string>RendererWidget</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,1">
|
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
|
||||||
<property name="spacing">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -30,74 +27,20 @@
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<spacer name="verticalSpacer">
|
||||||
<property name="sizeConstraint">
|
|
||||||
<enum>QLayout::SetDefaultConstraint</enum>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="openButton">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>打开</string>
|
|
||||||
</property>
|
|
||||||
<property name="flat">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>40</width>
|
<width>20</width>
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QMenuBar" name="menuBar">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Ignored">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<widget class="QMenu" name="menu">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="title">
|
</spacer>
|
||||||
<string>打开</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<addaction name="menu"/>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
|
||||||
|
@ -115,20 +58,11 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
<property name="spacing">
|
|
||||||
<number>12</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>12</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>12</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSlider" name="horizontalSlider">
|
<widget class="QSlider" name="horizontalSlider">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
|
@ -137,7 +71,7 @@
|
||||||
<number>180</number>
|
<number>180</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -147,23 +81,7 @@
|
||||||
<number>360</number>
|
<number>360</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSlider" name="exposureSlider">
|
|
||||||
<property name="minimum">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>200</number>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
#version 450 core
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
in vec2 TexCoords;
|
||||||
|
|
||||||
|
uniform sampler2D gBaseColor;
|
||||||
|
uniform sampler2D gNormal;
|
||||||
|
uniform sampler2D gPosition;
|
||||||
|
uniform sampler2D gMetallicRoughness;
|
||||||
|
uniform sampler2D gDepth;
|
||||||
|
uniform sampler2D gDirectLight;
|
||||||
|
uniform sampler2D gIndirectLight;
|
||||||
|
|
||||||
|
uniform vec3 mainLightDirection;
|
||||||
|
uniform vec3 mainLightRadiance;
|
||||||
|
|
||||||
|
uniform vec3 camPos;
|
||||||
|
|
||||||
|
const float PI = 3.14159265359;
|
||||||
|
|
||||||
|
float DistributionGGX(vec3 N, vec3 H, float roughness)
|
||||||
|
{
|
||||||
|
float a = roughness*roughness;
|
||||||
|
float a2 = a*a;
|
||||||
|
float NdotH = max(dot(N, H), 0.0);
|
||||||
|
float NdotH2 = NdotH*NdotH;
|
||||||
|
|
||||||
|
float nom = a2;
|
||||||
|
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
||||||
|
denom = PI * denom * denom;
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||||
|
{
|
||||||
|
float r = (roughness + 1.0);
|
||||||
|
float k = (r*r) / 8.0;
|
||||||
|
|
||||||
|
float nom = NdotV;
|
||||||
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
||||||
|
{
|
||||||
|
float NdotV = max(dot(N, V), 0.0);
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||||
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||||
|
|
||||||
|
return ggx1 * ggx2;
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
||||||
|
{
|
||||||
|
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
|
||||||
|
//FragColor = vec4(vec3(textureLod(gDepth, TexCoords, 1).x), 1.0);
|
||||||
|
//FragColor -= vec4(vec3(textureLod(gDepth, TexCoords, 0).x), 1.0);
|
||||||
|
//ivec2 depthCoords = ivec2(TexCoords*(textureSize(gDepth,0)-ivec2(1)) + vec2(0.5));
|
||||||
|
//float depth = texelFetch(gDepth, depthCoords/64, 6).x;
|
||||||
|
//depth -= texelFetch(gDepth, depthCoords, 0).x;
|
||||||
|
//FragColor = vec4(vec3(depth*10000),1);
|
||||||
|
//FragColor = vec4(vec3(textureSize(gShadowMap, 0)-vec3(1)),1);
|
||||||
|
//FragColor = vec4(texture(gRadiance, TexCoords).rgb, 1);
|
||||||
|
vec3 albedo = pow(texture(gBaseColor, TexCoords).rgb, vec3(2.2));
|
||||||
|
vec3 color = albedo * texture(gIndirectLight, TexCoords).rgb + texture(gDirectLight, TexCoords).rgb;
|
||||||
|
color = color / (color + vec3(1.0));
|
||||||
|
color = pow(color, vec3(1.0/2.2));
|
||||||
|
FragColor = vec4(color, 1.0);
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
float metallic = texture(gMetallicRoughness, TexCoords).r;
|
||||||
|
float roughness = texture(gMetallicRoughness, TexCoords).g;
|
||||||
|
|
||||||
|
|
||||||
|
vec3 N = texture(gNormal, TexCoords).xyz;
|
||||||
|
vec3 WorldPos = texture(gPosition, TexCoords).xyz;
|
||||||
|
|
||||||
|
if(N==vec3(0))
|
||||||
|
{
|
||||||
|
vec3 color = mainLightRadiance;
|
||||||
|
|
||||||
|
color = color / (color + vec3(1.0));
|
||||||
|
color = pow(color, vec3(1.0/2.2));
|
||||||
|
|
||||||
|
FragColor = vec4(color, 1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 V = normalize(camPos - WorldPos);
|
||||||
|
|
||||||
|
vec3 F0 = vec3(0.04);
|
||||||
|
F0 = mix(F0, albedo, metallic);
|
||||||
|
|
||||||
|
// reflectance equation
|
||||||
|
vec3 Lo = vec3(0.0);
|
||||||
|
|
||||||
|
|
||||||
|
// calculate per-light radiance
|
||||||
|
vec3 L = normalize(mainLightDirection);
|
||||||
|
vec3 H = normalize(V + L);
|
||||||
|
//float distance = length(lightPositions[i] - WorldPos);
|
||||||
|
//float attenuation = 1.0 / (distance * distance);
|
||||||
|
vec3 radiance = mainLightRadiance ;//* attenuation;
|
||||||
|
|
||||||
|
// cook-torrance brdf
|
||||||
|
float NDF = DistributionGGX(N, H, roughness);
|
||||||
|
float G = GeometrySmith(N, V, L, roughness);
|
||||||
|
vec3 F = fresnelSchlick(clamp(dot(H, V),0.,1.), F0);
|
||||||
|
//F = clamp(F,vec3(0),vec3(1));
|
||||||
|
|
||||||
|
vec3 kS = F;
|
||||||
|
vec3 kD = vec3(1.0) - kS;
|
||||||
|
kD *= 1.0 - metallic;
|
||||||
|
|
||||||
|
vec3 nominator = NDF * G * F;
|
||||||
|
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001;
|
||||||
|
vec3 specular = nominator / denominator;
|
||||||
|
|
||||||
|
// add to outgoing radiance Lo
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
Lo += (kD * albedo / PI + specular) * radiance * NdotL;
|
||||||
|
|
||||||
|
vec3 ambient = vec3(0.03) * albedo;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//vec4 FragPosLightSpace = lightSpaceMatrix * vec4(WorldPos, 1.0);
|
||||||
|
//float bias = 0.08 * max(0.05 * (1.0 - dot(N, L)), 0.005);
|
||||||
|
//int debugLayer;
|
||||||
|
//float shadow = ShadowCalculation(WorldPos, N, debugLayer);
|
||||||
|
|
||||||
|
//vec3 color = ambient + Lo;
|
||||||
|
//vec3 color = indirect*1;
|
||||||
|
float directLight = texture(gDirectLight, TexCoords).r;
|
||||||
|
color = ambient + directLight * Lo;
|
||||||
|
//color*=mix(mix(vec3(1,0,0), vec3(0,1,0), float(debugLayer)/shadowCascadeCount/0.5),
|
||||||
|
//mix(vec3(0,1,0), vec3(0,0,1), float(debugLayer)/(shadowCascadeCount)/0.5-1), float(debugLayer)/(shadowCascadeCount));
|
||||||
|
//vec3 color = (1.0 - shadow) * Lo;
|
||||||
|
//vec3 color = (1.0 - shadow) * Lo + indirect*10;
|
||||||
|
color = color / (color + vec3(1.0));
|
||||||
|
color = pow(color, vec3(1.0/2.2));
|
||||||
|
|
||||||
|
FragColor = vec4(color, 1.0);
|
||||||
|
//FragColor = vec4(vec3(shadow), 1);
|
||||||
|
//FragColor = vec4(texture(gShadowNormal, TexCoords).rgb, 1.0);
|
||||||
|
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ layout (location = 0) out vec4 gBaseColor;
|
||||||
layout (location = 1) out vec3 gNormal;
|
layout (location = 1) out vec3 gNormal;
|
||||||
layout (location = 2) out vec3 gPosition;
|
layout (location = 2) out vec3 gPosition;
|
||||||
layout (location = 3) out vec2 gMetallicRoughness;
|
layout (location = 3) out vec2 gMetallicRoughness;
|
||||||
layout (location = 4) out uvec2 gPaintingIndex;
|
layout (location = 4) out uint gPaintingIndex;
|
||||||
|
|
||||||
in vec2 TexCoords;
|
in vec2 TexCoords;
|
||||||
in vec3 WorldPos;
|
in vec3 WorldPos;
|
||||||
|
@ -36,22 +36,13 @@ vec3 getNormalFromMap()
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
if(textureSize(texture_basecolor,0)!=vec2(0))
|
//gBaseColor = vec4(1,0,0,1);
|
||||||
gBaseColor = texture(texture_basecolor, TexCoords);
|
gBaseColor = texture(texture_basecolor, TexCoords);
|
||||||
else
|
|
||||||
gBaseColor = vec4(1);
|
|
||||||
if(gBaseColor.a<0.4)
|
if(gBaseColor.a<0.4)
|
||||||
discard;
|
discard;
|
||||||
gPosition = WorldPos;
|
gPosition = WorldPos;
|
||||||
if(textureSize(texture_normal,0)!=vec2(0))
|
|
||||||
gNormal = getNormalFromMap();
|
gNormal = getNormalFromMap();
|
||||||
else
|
|
||||||
gNormal = Normal;
|
|
||||||
if(textureSize(texture_metallic_roughness,0)!=vec2(0))
|
|
||||||
gMetallicRoughness = texture(texture_metallic_roughness, TexCoords).bg;
|
gMetallicRoughness = texture(texture_metallic_roughness, TexCoords).bg;
|
||||||
else
|
gPaintingIndex = 0;
|
||||||
gMetallicRoughness = vec2(0,1);
|
|
||||||
|
|
||||||
gPaintingIndex = uvec2(0);
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
#version 450 core
|
||||||
|
|
||||||
|
uniform sampler2D texture_basecolor;
|
||||||
|
|
||||||
|
in vec2 TexCoords;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
//gBaseColor = vec4(1,0,0,1);
|
||||||
|
vec4 baseColor = texture(texture_basecolor, TexCoords);
|
||||||
|
if(baseColor.a<0.4)
|
||||||
|
discard;
|
||||||
|
}
|
|
@ -2,35 +2,43 @@
|
||||||
|
|
||||||
layout (local_size_x = 8, local_size_y = 8) in;
|
layout (local_size_x = 8, local_size_y = 8) in;
|
||||||
|
|
||||||
layout(location = 0) uniform ivec2 pixelOffset;
|
|
||||||
|
|
||||||
layout(rgba8, binding = 0) uniform image2D gBaseColor;
|
layout(rgba8, binding = 0) uniform image2D gBaseColor;
|
||||||
layout(rg8, binding = 1) uniform image2D gMetallicRoughness;
|
layout(rg8, binding = 1) uniform image2D gMetallicRoughness;
|
||||||
|
layout(r16ui, binding = 2) uniform uimage2D gPaintingIndex;
|
||||||
|
layout(rg32f, binding = 3) uniform image2D gPaintingTexCoord;
|
||||||
|
|
||||||
layout(std430, binding = 0) buffer bvhBuffer
|
layout(std430, binding = 1) buffer paintingOffsetBuffer
|
||||||
|
{
|
||||||
|
/**********************
|
||||||
|
** @x paintingBvhRoot
|
||||||
|
** @y paintingBvhLength
|
||||||
|
**********************/
|
||||||
|
uvec2 paintingOffsets[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 2) buffer bvhBuffer
|
||||||
{
|
{
|
||||||
uvec2 bvhChildren[];
|
uvec2 bvhChildren[];
|
||||||
};
|
};
|
||||||
layout(std430, binding = 1) buffer bvhBoundBuffer
|
layout(std430, binding = 3) buffer bvhBoundBuffer
|
||||||
{
|
{
|
||||||
vec4 bvhBound[];
|
vec4 bvhBound[];
|
||||||
};
|
};
|
||||||
layout(std430, binding = 2) buffer elementOffsetBuffer
|
layout(std430, binding = 4) buffer elementOffsetBuffer
|
||||||
{
|
{
|
||||||
/**
|
/**********************
|
||||||
* @[0] elementBvhRoot
|
** @[0] elementBvhRoot
|
||||||
* @[1] styleOffset
|
** @[1] styleOffset
|
||||||
* @[2] pointsOffset
|
** @[2] pointsOffset
|
||||||
* @[3] linesOffset
|
** @[3] linesOffset
|
||||||
|
**********************/
|
||||||
*/
|
uvec4 elementOffset[];
|
||||||
uint elementOffset[][5];
|
|
||||||
};
|
};
|
||||||
layout(std430, binding = 3) buffer elementIndexBuffer
|
layout(std430, binding = 5) buffer elementIndexBuffer
|
||||||
{
|
{
|
||||||
uint elementIndexs[]; //ÏߺÍÃæ
|
uint elementIndexs[]; //ÏߺÍÃæ
|
||||||
};
|
};
|
||||||
layout(std430, binding = 4) buffer elementDataBuffer
|
layout(std430, binding = 6) buffer elementDataBuffer
|
||||||
{
|
{
|
||||||
float elementData[]; //µãºÍStyle
|
float elementData[]; //µãºÍStyle
|
||||||
};
|
};
|
||||||
|
@ -244,51 +252,65 @@ int cubic_bezier_int_test(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
|
||||||
return n_ints;
|
return n_ints;
|
||||||
}
|
}
|
||||||
|
|
||||||
bvec3 segment_sign_test(vec2 uv, vec2 p0, vec2 p1)
|
|
||||||
{
|
|
||||||
p0 -= uv;
|
|
||||||
p1 -= uv;
|
|
||||||
bvec3 ret;
|
|
||||||
vec2 nor = p0 - p1;
|
|
||||||
nor = vec2(nor.y, -nor.x);
|
|
||||||
|
|
||||||
float sgn;
|
|
||||||
|
|
||||||
if (p0.y > p1.y)
|
|
||||||
{
|
|
||||||
sgn = 1.;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sgn = -1.;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dot(nor, p0) * sgn < 0.)
|
|
||||||
{
|
|
||||||
if (p0.y * p1.y < 0.)
|
|
||||||
ret.y = false;
|
|
||||||
else
|
|
||||||
ret.y = false;
|
|
||||||
ret.xz = bvec2(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (p0.y * p1.y < 0.)
|
|
||||||
ret.y = true;
|
|
||||||
else
|
|
||||||
ret.y = false;
|
|
||||||
ret.xz = bvec2(true);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bvec3 cubic_bezier_sign_test(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
|
bvec3 cubic_bezier_sign_test(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
|
||||||
{
|
{
|
||||||
// if(abs(p3.y-p0.y)< 1e-4)
|
// float cu = (-p0.y + 3. * p1.y - 3. * p2.y + p3.y);
|
||||||
|
// float qu = (3. * p0.y - 6. * p1.y + 3. * p2.y);
|
||||||
|
// float li = (-3. * p0.y + 3. * p1.y);
|
||||||
|
// float co = p0.y - uv.y;
|
||||||
|
|
||||||
|
// vec3 roots = vec3(1e38);
|
||||||
|
// int n_roots;
|
||||||
|
|
||||||
|
// int n_ints = 0;
|
||||||
|
// bvec3 result = bvec3(false);
|
||||||
|
|
||||||
|
// if (uv.x < min(min(p0.x, p1.x), min(p2.x, p3.x)))
|
||||||
// {
|
// {
|
||||||
// return segment_sign_test(uv, p0,p3);
|
// if (uv.y >= min(p0.y, p3.y) && uv.y <= max(p0.y, p3.y))
|
||||||
|
// {
|
||||||
|
// n_ints = 1;
|
||||||
|
// result[1] = !result[1];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
|
||||||
|
// if (abs(cu) < .0001)
|
||||||
|
// {
|
||||||
|
// n_roots = solve_quadric(vec2(co / qu, li / qu), roots.xy);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// n_roots = solve_cubic(vec3(co / cu, li / cu, qu / cu), roots);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// for (int i = 0; i < n_roots; i++)
|
||||||
|
// {
|
||||||
|
// //if (roots[i] >= 0. && roots[i] <= 1.)
|
||||||
|
// {
|
||||||
|
// float x_pos = -p0.x + 3. * p1.x - 3. * p2.x + p3.x;
|
||||||
|
// x_pos = x_pos * roots[i] + 3. * p0.x - 6. * p1.x + 3. * p2.x;
|
||||||
|
// x_pos = x_pos * roots[i] + -3. * p0.x + 3. * p1.x;
|
||||||
|
// x_pos = x_pos * roots[i] + p0.x;
|
||||||
|
|
||||||
|
// if (x_pos > uv.x)
|
||||||
|
// {
|
||||||
|
// if(roots[i] >= 0. && roots[i] <= 1.){
|
||||||
|
// result[1] = !result[1];
|
||||||
|
// }
|
||||||
|
// else if(roots[i] < 0.)
|
||||||
|
// {
|
||||||
|
// result[0]=!result[0];
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// result[2]=!result[2];
|
||||||
|
// //n_ints++;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return result;
|
||||||
float cu = (-p0.y + 3. * p1.y - 3. * p2.y + p3.y);
|
float cu = (-p0.y + 3. * p1.y - 3. * p2.y + p3.y);
|
||||||
float qu = (3. * p0.y - 6. * p1.y + 3. * p2.y);
|
float qu = (3. * p0.y - 6. * p1.y + 3. * p2.y);
|
||||||
float li = (-3. * p0.y + 3. * p1.y);
|
float li = (-3. * p0.y + 3. * p1.y);
|
||||||
|
@ -811,134 +833,26 @@ float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEn
|
||||||
return sqrt(d0);
|
return sqrt(d0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int cubic_bezier_int_test2(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool reverse)
|
|
||||||
{
|
|
||||||
float cu = (-p0.y + 3. * p1.y - 3. * p2.y + p3.y);
|
|
||||||
float qu = (3. * p0.y - 6. * p1.y + 3. * p2.y);
|
|
||||||
float li = (-3. * p0.y + 3. * p1.y);
|
|
||||||
float co = p0.y - uv.y;
|
|
||||||
|
|
||||||
vec3 roots = vec3(1e38);
|
|
||||||
int n_roots;
|
|
||||||
|
|
||||||
int n_ints = 0;
|
|
||||||
|
|
||||||
if (reverse? uv.x > max(max(p0.x, p1.x), max(p2.x, p3.x)): uv.x < min(min(p0.x, p1.x), min(p2.x, p3.x)))
|
|
||||||
{
|
|
||||||
if (uv.y >= min(p0.y, p3.y) && uv.y <= max(p0.y, p3.y))
|
|
||||||
n_ints = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (abs(cu) < .0001) n_roots = solve_quadric(vec2(co / qu, li / qu), roots.xy);
|
|
||||||
else n_roots = solve_cubic(vec3(co / cu, li / cu, qu / cu), roots);
|
|
||||||
|
|
||||||
for (int i = 0; i < n_roots; i++)
|
|
||||||
{
|
|
||||||
if (roots[i] >= 0. && roots[i] <= 1.)
|
|
||||||
{
|
|
||||||
float x_pos = -p0.x + 3. * p1.x - 3. * p2.x + p3.x;
|
|
||||||
x_pos = x_pos * roots[i] + 3. * p0.x - 6. * p1.x + 3. * p2.x;
|
|
||||||
x_pos = x_pos * roots[i] + -3. * p0.x + 3. * p1.x;
|
|
||||||
x_pos = x_pos * roots[i] + p0.x;
|
|
||||||
|
|
||||||
if (reverse? x_pos < uv.x: x_pos > uv.x) n_ints++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n_ints;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ray_int_test(vec2 uv, vec2 p0, vec2 direction, bool reverse)
|
|
||||||
{
|
|
||||||
p0 -= uv;
|
|
||||||
if (-p0.y * direction.y > 0.)
|
|
||||||
{
|
|
||||||
vec2 nor = -direction;
|
|
||||||
nor = vec2(nor.y, -nor.x);
|
|
||||||
float sgn = p0.y > direction.y? 1.: -1.;
|
|
||||||
if(reverse) sgn = -sgn;
|
|
||||||
return dot(nor, p0) * sgn < 0.? 0: 1;
|
|
||||||
}
|
|
||||||
else return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 bezierTangent(float t, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
|
|
||||||
{
|
|
||||||
float u = 1 - t;
|
|
||||||
float uu = u * u;
|
|
||||||
float tu = t * u;
|
|
||||||
float tt = t * t;
|
|
||||||
|
|
||||||
vec2 P = p0 * 3 * uu * (-1.0);
|
|
||||||
P += p1 * 3 * (uu - 2 * tu);
|
|
||||||
P += p2 * 3 * (2 * tu - tt);
|
|
||||||
P += p3 * 3 * tt;
|
|
||||||
|
|
||||||
//返回单位向量
|
|
||||||
return normalize(P);
|
|
||||||
}
|
|
||||||
|
|
||||||
//判断两向量夹角(向量A逆时针到向量B)是否大于180°,大于180°返回真,否则返回假
|
|
||||||
bool angleLargeThanPi(vec2 a, vec2 b)
|
|
||||||
{
|
|
||||||
return a.x * b.y - b.x * a.y < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawLine(in float d, in uint styleIndex, out vec4 elementColor, out vec2 metallicRoughness)
|
void drawLine(in float d, in uint styleIndex, out vec4 elementColor, out vec2 metallicRoughness)
|
||||||
{
|
{
|
||||||
elementColor = vec4(1);
|
elementColor = vec4(1);
|
||||||
metallicRoughness = vec2(0.8);
|
metallicRoughness = vec2(0.8);
|
||||||
uint headUint = floatBitsToUint(elementData[styleIndex+1]);
|
switch(int(elementData[styleIndex+3]))
|
||||||
vec4 head = unpackUnorm4x8(headUint);
|
|
||||||
switch (int(head.a*100)%10)
|
|
||||||
//switch (2)
|
|
||||||
{
|
{
|
||||||
/// Plain
|
case 0:
|
||||||
case 0: {
|
{
|
||||||
metallicRoughness = head.rg;
|
elementColor = vec4(elementData[styleIndex+7],elementData[styleIndex+8],elementData[styleIndex+9],1);
|
||||||
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+2])).rgb, 1);
|
metallicRoughness = vec2(elementData[styleIndex+10],elementData[styleIndex+11]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/// RadialGradient
|
case 1:
|
||||||
case 1: {
|
|
||||||
uint size = headUint%(1<<15);
|
|
||||||
bool gradual = (headUint&(1<<15))!=0;
|
|
||||||
|
|
||||||
uint lastData = floatBitsToUint(elementData[styleIndex+2+0*2]);
|
|
||||||
float lastLevel = 0;
|
|
||||||
vec2 lastMetallicRoughness = unpackUnorm4x8(lastData).rg;
|
|
||||||
vec4 lastColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+3+0*2])).rgb, 1);
|
|
||||||
|
|
||||||
for(uint i = 0; i < size; i++)
|
|
||||||
{
|
{
|
||||||
uint data = floatBitsToUint(elementData[styleIndex+2+i*2]);
|
elementColor = vec4(mix(vec3(0), vec3(1), d), 1);
|
||||||
float level = unpackUnorm2x16(data).y;
|
metallicRoughness = vec2(0,0.8);
|
||||||
vec4 currentColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+3+i*2])).rgb, 1);
|
|
||||||
vec2 currentMetallicRoughness = unpackUnorm4x8(data).rg;
|
|
||||||
if (d <= level)
|
|
||||||
{
|
|
||||||
if(gradual)
|
|
||||||
{
|
|
||||||
float a = (d-lastLevel)/(level-lastLevel);
|
|
||||||
elementColor = mix(lastColor, currentColor, a);
|
|
||||||
metallicRoughness = mix(lastMetallicRoughness, currentMetallicRoughness, a);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
elementColor = currentColor;
|
|
||||||
metallicRoughness = currentMetallicRoughness;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
lastMetallicRoughness = currentMetallicRoughness;
|
case 2:
|
||||||
lastColor = currentColor;
|
{
|
||||||
lastLevel = level;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
float levels[] = {0.25,0.5,0.75};
|
float levels[] = {0.25,0.5,0.75};
|
||||||
vec3 colors[] = {vec3(1,0,0), vec3(0,1,0), vec3(0,0,1), vec3(1,1,0)};
|
vec3 colors[] = {vec3(1,0,0), vec3(0,1,0), vec3(0,0,1), vec3(1,1,0)};
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -962,14 +876,14 @@ void drawLine(in float d, in uint styleIndex, out vec4 elementColor, out vec2 me
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, out vec2 metallicRoughness, inout vec3 debugBVH = vec3(0))
|
bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metallicRoughness, inout vec3 debugBVH = vec3(0))
|
||||||
{
|
{
|
||||||
bool hitElement = false;
|
bool hitElement = false;
|
||||||
vec4 elementColor = vec4(-1);
|
vec4 elementColor = vec4(-1);
|
||||||
metallicRoughness = vec2(0, 0.8);
|
|
||||||
|
|
||||||
uint currentOffset[] = elementOffset[elementIndex];
|
uvec4 currentOffset = elementOffset[elementIndex];
|
||||||
uint elementBvhRoot = currentOffset[0];
|
uint elementBvhRoot = currentOffset[0];
|
||||||
|
//uint elementBvhLength = currentOffset[1];
|
||||||
uint styleIndex = currentOffset[1];
|
uint styleIndex = currentOffset[1];
|
||||||
uint elementBvhLength = 0x80000000;
|
uint elementBvhLength = 0x80000000;
|
||||||
uint pointsOffset = currentOffset[2];
|
uint pointsOffset = currentOffset[2];
|
||||||
|
@ -996,10 +910,9 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
|
||||||
}
|
}
|
||||||
//uint styleIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y;
|
//uint styleIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y;
|
||||||
//uint elementType = bvhChildren[elementBvhRoot + elementBvhIndex].y;
|
//uint elementType = bvhChildren[elementBvhRoot + elementBvhIndex].y;
|
||||||
//float elementType = elementData[styleIndex];
|
float elementType = elementData[styleIndex];
|
||||||
bool isFillStyle = elementData[styleIndex]<=0;
|
|
||||||
// for(int i = 0; i<200;i++)
|
// for(int i = 0; i<200;i++)
|
||||||
if (isFillStyle) //面
|
if (elementType == 0) //Ãæ
|
||||||
{
|
{
|
||||||
uint contourIndex = linesOffset + leftChild - 0x80000000;
|
uint contourIndex = linesOffset + leftChild - 0x80000000;
|
||||||
|
|
||||||
|
@ -1010,9 +923,17 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
|
||||||
for ( uint contourIterator = contourIndex + 1;contourIterator < contourIndex + 1 + lineCount; contourIterator++)
|
for ( uint contourIterator = contourIndex + 1;contourIterator < contourIndex + 1 + lineCount; contourIterator++)
|
||||||
{
|
{
|
||||||
uint lineIndex = elementIndexs[contourIterator];
|
uint lineIndex = elementIndexs[contourIterator];
|
||||||
uint pLocation = linesOffset + 2 * lineIndex;
|
uint pLocation = linesOffset + 4 * lineIndex;
|
||||||
uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation]>>16, elementIndexs[pLocation]&0xFFFF, elementIndexs[pLocation+1]>>16, elementIndexs[pLocation+1]&0xFFFF);
|
uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation], elementIndexs[pLocation+1], elementIndexs[pLocation+2], elementIndexs[pLocation+3]);
|
||||||
uvec4 pyIndex = uvec4(1)+pxIndex;
|
uvec4 pyIndex = uvec4(1)+pxIndex;
|
||||||
|
// vec2 p0 = vec2(elementData[pxIndex[0]],
|
||||||
|
// elementData[pyIndex[0]]);
|
||||||
|
// vec2 p1 = vec2(elementData[pxIndex[1]],
|
||||||
|
// elementData[pyIndex[1]]);
|
||||||
|
// vec2 p2 = vec2(elementData[pxIndex[2]],
|
||||||
|
// elementData[pyIndex[2]]);
|
||||||
|
// vec2 p3 = vec2(elementData[pxIndex[3]],
|
||||||
|
// elementData[pyIndex[3]]);
|
||||||
mat4x2 p = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]],
|
mat4x2 p = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]],
|
||||||
elementData[pxIndex[1]], elementData[pyIndex[1]],
|
elementData[pxIndex[1]], elementData[pyIndex[1]],
|
||||||
elementData[pxIndex[2]],elementData[pyIndex[2]],
|
elementData[pxIndex[2]],elementData[pyIndex[2]],
|
||||||
|
@ -1040,44 +961,38 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
|
||||||
{
|
{
|
||||||
hitElement = true;
|
hitElement = true;
|
||||||
elementColor = vec4(1,1,0,0);
|
elementColor = vec4(1,1,0,0);
|
||||||
|
if(elementData[styleIndex+1]==0)
|
||||||
vec4 head = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex]));
|
|
||||||
if(head.z==0)
|
|
||||||
{
|
{
|
||||||
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+1])).rgb,0);
|
elementColor = vec4(elementData[styleIndex+2],elementData[styleIndex+3],elementData[styleIndex+4],0);
|
||||||
metallicRoughness = head.xy;
|
metallicRoughness = vec2(elementData[styleIndex+5],elementData[styleIndex+6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else //线
|
else if (elementType == 1) //Ïß
|
||||||
{
|
{
|
||||||
float strokeWidth = elementData[styleIndex];
|
float strokeWidth = elementData[styleIndex+1];
|
||||||
float widthHeightRatio = uintBitsToFloat(currentOffset[4]);
|
|
||||||
|
|
||||||
vec2 size = normalize(vec2(widthHeightRatio, 1)) + vec2(2 * strokeWidth);
|
|
||||||
vec2 ratio = widthHeightRatio < 1 ? vec2(widthHeightRatio, 1) : vec2(1, 1 / widthHeightRatio);
|
|
||||||
localUV *= ratio;
|
|
||||||
|
|
||||||
|
|
||||||
uint contourIndex = linesOffset + leftChild - 0x80000000;
|
uint contourIndex = linesOffset + leftChild - 0x80000000;
|
||||||
float minDistance = 1e38;
|
float d = 1e38;
|
||||||
|
bool signTmp=false;
|
||||||
|
uint lineCountTmp=0;
|
||||||
|
uint lastPIndex = -1;
|
||||||
|
bool lastSign = false;
|
||||||
uint lineCount = elementIndexs[contourIndex];
|
uint lineCount = elementIndexs[contourIndex];
|
||||||
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+1]));
|
uint reverseFlag = 0;
|
||||||
float lineType = floor(styleHead.b*10);
|
for ( uint contourIterator = contourIndex + 1;contourIterator < contourIndex + 1 + lineCount; contourIterator++)
|
||||||
//float lineType = 2;
|
|
||||||
vec2 p3Last = vec2(1e38);
|
|
||||||
vec2 p2Last = vec2(1e38);
|
|
||||||
int debugBegin = 0;
|
|
||||||
for ( uint contourIterator_ = contourIndex + 1;contourIterator_ <= contourIndex + 1 + lineCount; contourIterator_++)
|
|
||||||
{
|
{
|
||||||
uint contourIterator = contourIterator_;
|
|
||||||
if(contourIterator_==contourIndex + 1 + lineCount)
|
|
||||||
contourIterator = contourIndex + 1;
|
|
||||||
uint lineIndex = elementIndexs[contourIterator];
|
uint lineIndex = elementIndexs[contourIterator];
|
||||||
uint pLocation = linesOffset + 3 * lineIndex;
|
bool reverse = false;
|
||||||
uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation]>>16, elementIndexs[pLocation]&0xFFFF, elementIndexs[pLocation+1]>>16, elementIndexs[pLocation+1]&0xFFFF);
|
if(lineIndex>=0x80000000)
|
||||||
|
{
|
||||||
|
reverse = true;
|
||||||
|
lineIndex -= 0x80000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint pLocation = linesOffset + 4 * lineIndex;
|
||||||
|
uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation], elementIndexs[pLocation+1], elementIndexs[pLocation+2], elementIndexs[pLocation+3]);
|
||||||
uvec4 pyIndex = uvec4(1)+pxIndex;
|
uvec4 pyIndex = uvec4(1)+pxIndex;
|
||||||
|
|
||||||
mat4x2 p = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]],
|
mat4x2 p = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]],
|
||||||
|
@ -1085,81 +1000,97 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
|
||||||
elementData[pxIndex[2]], elementData[pyIndex[2]],
|
elementData[pxIndex[2]], elementData[pyIndex[2]],
|
||||||
elementData[pxIndex[3]], elementData[pyIndex[3]]);
|
elementData[pxIndex[3]], elementData[pyIndex[3]]);
|
||||||
|
|
||||||
p[0] *= ratio;
|
bvec3 signTestResult = cubic_bezier_sign_test(localUV, p[0], p[1], p[2], p[3]);
|
||||||
p[1] *= ratio;
|
|
||||||
p[2] *= ratio;
|
|
||||||
p[3] *= ratio;
|
|
||||||
|
|
||||||
if(p[0]==p[1]&&p[2]==p[3])
|
if(lastPIndex!=pxIndex[0])
|
||||||
{
|
{
|
||||||
p[1] = (p[0]+p[3])/2;
|
if(lastSign)
|
||||||
p[2] = p[1];
|
signTmp = !signTmp;
|
||||||
}
|
float lineType = elementData[styleIndex+4];
|
||||||
|
/*if(d<=0.001)
|
||||||
if(distance(localUV,p[0])<=0.001)
|
|
||||||
{
|
|
||||||
if(p3Last==p[0]) debugBegin = 2;
|
|
||||||
else debugBegin = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true);
|
|
||||||
if(d<=strokeWidth)
|
|
||||||
{
|
|
||||||
bool onBegin = distance(localUV,p[0])<=strokeWidth&&p3Last==p[0];
|
|
||||||
bool fill = true;
|
|
||||||
if(onBegin)
|
|
||||||
{
|
|
||||||
vec2 normalLast = normalize(mat2(0,1,-1,0)*(p3Last-p2Last));
|
|
||||||
vec2 normalNow = normalize(mat2(0,1,-1,0)*(p[1]-p[0]));
|
|
||||||
vec2 normal = normalLast+normalNow;
|
|
||||||
fill = angleLargeThanPi(normal, localUV-p[0]);
|
|
||||||
}
|
|
||||||
if(onBegin?fill:d<minDistance)
|
|
||||||
{
|
|
||||||
minDistance = min(minDistance, d);
|
|
||||||
|
|
||||||
bool reverse = p[3].y-p[0].y<0.;
|
|
||||||
|
|
||||||
vec2 tangentBegin = normalize(p[0]-p[1]);
|
|
||||||
vec2 tangentEnd = normalize(p[3]-p[2]);
|
|
||||||
if(tangentBegin.y==0.) tangentBegin.y=reverse?eps:-eps;
|
|
||||||
if(tangentEnd.y==0.) tangentEnd.y=reverse?-eps:eps;
|
|
||||||
int intTest = cubic_bezier_int_test2(localUV, p[0], p[1], p[2], p[3], reverse)
|
|
||||||
+ ray_int_test(localUV, p[0], tangentBegin, reverse)
|
|
||||||
+ ray_int_test(localUV, p[3], tangentEnd, reverse);
|
|
||||||
if(lineType==2 || intTest%2==int(lineType))
|
|
||||||
{
|
{
|
||||||
hitElement = true;
|
hitElement = true;
|
||||||
drawLine(minDistance/strokeWidth, styleIndex, elementColor, metallicRoughness);
|
elementColor = vec4(0,0,0,1);
|
||||||
}
|
}
|
||||||
else if(p3Last==p[0]) hitElement = false;
|
else*/ if(d<=strokeWidth && (lineType==2 || signTmp==(lineType==1-reverseFlag)))
|
||||||
// if(distance(localUV,p[0])<=strokeWidth&&p3Last==p[0]&&fill)
|
{
|
||||||
// {
|
d/=strokeWidth;
|
||||||
// hitElement = true;
|
hitElement = true;
|
||||||
// elementColor = vec4(0,0,1,1);
|
drawLine(d, styleIndex, elementColor, metallicRoughness);
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
if(reverse)
|
||||||
|
reverseFlag = 1;
|
||||||
|
d = 1e38;
|
||||||
|
signTmp=signTestResult[0];
|
||||||
|
lineCountTmp = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
p3Last = p[3];
|
lastPIndex = pxIndex[3];
|
||||||
p2Last = p[2];
|
lastSign = signTestResult[2];
|
||||||
|
lineCountTmp++;
|
||||||
|
float lineType = elementData[styleIndex+4];
|
||||||
|
d = min(d, cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], elementData[styleIndex+2]==0));
|
||||||
|
if(signTestResult[1])
|
||||||
|
signTmp = !signTmp;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
if(lastSign)
|
||||||
|
signTmp = !signTmp;
|
||||||
|
float lineType = elementData[styleIndex+4];
|
||||||
|
/*if(d<=0.001)
|
||||||
|
{
|
||||||
|
hitElement = true;
|
||||||
|
elementColor = vec4(0,0,0,1);
|
||||||
|
}
|
||||||
|
else*/ if(d<=strokeWidth && (lineType==2 || signTmp==(lineType==1-reverseFlag)))
|
||||||
|
{
|
||||||
|
d/=strokeWidth;
|
||||||
|
hitElement = true;
|
||||||
|
drawLine(d, styleIndex, elementColor, metallicRoughness);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(minDistance<=0.001)
|
// float strokeWidth = elementData[styleIndex+1];
|
||||||
|
// uint lineIndex = leftChild - 0x80000000;
|
||||||
|
// uint p0Index = elementIndexs[linesOffset + 4 * lineIndex];
|
||||||
|
// uint p1Index = elementIndexs[linesOffset + 4 * lineIndex + 1];
|
||||||
|
// uint p2Index = elementIndexs[linesOffset + 4 * lineIndex + 2];
|
||||||
|
// uint p3Index = elementIndexs[linesOffset + 4 * lineIndex + 3];
|
||||||
|
|
||||||
|
// vec2 p0 = vec2(elementData[pointsOffset + 2 * p0Index],
|
||||||
|
// elementData[pointsOffset + 2 * p0Index + 1]);
|
||||||
|
// vec2 p1 = vec2(elementData[pointsOffset + 2 * p1Index],
|
||||||
|
// elementData[pointsOffset + 2 * p1Index + 1]);
|
||||||
|
// vec2 p2 = vec2(elementData[pointsOffset + 2 * p2Index],
|
||||||
|
// elementData[pointsOffset + 2 * p2Index + 1]);
|
||||||
|
// vec2 p3 = vec2(elementData[pointsOffset + 2 * p3Index],
|
||||||
|
// elementData[pointsOffset + 2 * p3Index + 1]);
|
||||||
|
|
||||||
|
// // if(p0.y==p3.y)
|
||||||
|
// // {
|
||||||
|
// // p2.y-=0.0000001;
|
||||||
|
// // p3.y-=0.0000001;
|
||||||
|
// // }
|
||||||
|
// float lineType = elementData[styleIndex+4];
|
||||||
|
// if(cubic_bezier_dis(localUV, p0, p1, p2, p3, true)<=0.001)
|
||||||
// {
|
// {
|
||||||
// hitElement = true;
|
// hitElement = true;
|
||||||
// elementColor = vec4(0,0,0,1);
|
// elementColor = vec4(0,0,0,1);
|
||||||
// if(debugBegin==1)
|
|
||||||
// elementColor = vec4(1,1,0,1);
|
|
||||||
// else if(debugBegin==2)
|
|
||||||
// elementColor = vec4(0,1,0,1);
|
|
||||||
// }
|
// }
|
||||||
|
// else if(cubic_bezier_dis(localUV, p0, p1, p2, p3, elementData[styleIndex+2]==0)<=strokeWidth
|
||||||
|
// &&(lineType==2 || cubic_bezier_sign_test(localUV, p0, p1, p2, p3)==(lineType==1)))
|
||||||
|
// {
|
||||||
|
// hitElement = true;
|
||||||
|
// elementColor = vec4(1);
|
||||||
|
// if(elementData[styleIndex+3]==0)
|
||||||
|
// {
|
||||||
|
// elementColor = vec4(elementData[styleIndex+7],elementData[styleIndex+8],elementData[styleIndex+9],1);
|
||||||
|
// metallicRoughness = vec2(elementData[styleIndex+10],elementData[styleIndex+11]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
elementBvhIndex = elementBvhLength;
|
elementBvhIndex = elementBvhLength;
|
||||||
color = elementColor.xyz;
|
|
||||||
return hitElement;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1185,13 +1116,13 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ivec2 pixelLocation = ivec2(pixelOffset + gl_GlobalInvocationID.xy);
|
//ivec2 pixelLocation = ivec2(((gl_LocalInvocationID.xy)*imageSize(gPaintingIndex)/gl_WorkGroupSize.xy + gl_WorkGroupID.xy).xy);
|
||||||
vec2 uv = (pixelLocation + vec2(0.5)) / imageSize(gBaseColor);
|
ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy);
|
||||||
//imageStore(gBaseColor, pixelLocation, vec4(uv,1,1));
|
uint paintingIndex = imageLoad(gPaintingIndex, pixelLocation).r;
|
||||||
//imageStore(gMetallicRoughness, pixelLocation, vec4(uv,1,1));
|
if(paintingIndex==0)
|
||||||
//return;
|
return;
|
||||||
uv = vec2(1)-uv*2;
|
|
||||||
//vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg;
|
vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg;
|
||||||
|
|
||||||
vec3 debugBVH = vec3(0);
|
vec3 debugBVH = vec3(0);
|
||||||
//bool debugHit = false;
|
//bool debugHit = false;
|
||||||
|
@ -1210,28 +1141,24 @@ void main()
|
||||||
uint leftChild = bvhChildren[index].x;
|
uint leftChild = bvhChildren[index].x;
|
||||||
if (leftChild >= bvhLength)
|
if (leftChild >= bvhLength)
|
||||||
{
|
{
|
||||||
uint zIndex = bvhChildren[index].y >> 18;
|
uint zIndex = bvhChildren[index].y / 65535;
|
||||||
bvec2 flip = bvec2(bvhChildren[index].y & (1<<16), bvhChildren[index].y & (1<<17));
|
float angle = (float(bvhChildren[index].y) / 65535.0 - zIndex) * 2 * PI;
|
||||||
float angle = (float(bvhChildren[index].y&((1<<16)-1)) / 65535.0) * 2 * PI;
|
|
||||||
mat2 rotation = {{cos(angle), -sin(angle)}, {sin(angle), cos(angle)}};
|
mat2 rotation = {{cos(angle), -sin(angle)}, {sin(angle), cos(angle)}};
|
||||||
vec2 localUV = uv - (bound.xy + bound.zw) / 2;
|
vec2 localUV = uv - (bound.xy + bound.zw) / 2;
|
||||||
localUV = rotation * localUV;
|
localUV = rotation * localUV;
|
||||||
vec2 scale = (bound.zw - bound.xy) / 2;
|
localUV /= (bound.zw - bound.xy) / 2;
|
||||||
localUV /= scale;
|
|
||||||
if (all(lessThan(vec2(-1), localUV)) && all(lessThan(localUV, vec2(1))) && zIndex>color.w)
|
if (all(lessThan(vec2(-1), localUV)) && all(lessThan(localUV, vec2(1))) && zIndex>color.w)
|
||||||
{
|
{
|
||||||
//if (any(greaterThan(bound.xy+vec2(0.005), uv)) || any(greaterThan(uv, bound.zw-vec2(0.005))))
|
if (any(greaterThan(bound.xy+vec2(0.005), uv)) || any(greaterThan(uv, bound.zw-vec2(0.005))))
|
||||||
if (any(greaterThan(vec2(-1)+vec2(0.005), localUV)) || any(greaterThan(localUV, vec2(1)-vec2(0.005))))
|
|
||||||
debugBVH.g += 0.3;
|
debugBVH.g += 0.3;
|
||||||
//uint elementIndex = leftChild - bvhLength;
|
//uint elementIndex = leftChild - bvhLength;
|
||||||
//debugBVH.bg += 0.5 * (localUV + vec2(1));
|
//debugBVH.bg += 0.5 * (localUV + vec2(1));
|
||||||
|
|
||||||
//debugBVH = vec3(0);
|
//debugBVH = vec3(0);
|
||||||
if(flip.x) localUV.x = -localUV.x;
|
|
||||||
if(flip.y) localUV.y = -localUV.y;
|
|
||||||
vec3 elementColor;
|
vec3 elementColor;
|
||||||
vec2 elementMetallicRoughness;
|
vec2 elementMetallicRoughness;
|
||||||
if(drawElement(leftChild - 0x80000000, localUV, scale, elementColor, elementMetallicRoughness, debugBVH))
|
if(drawElement(leftChild - 0x80000000, localUV, elementColor, elementMetallicRoughness, debugBVH))
|
||||||
{
|
{
|
||||||
color = vec4(elementColor, zIndex);
|
color = vec4(elementColor, zIndex);
|
||||||
metallicRoughness = elementMetallicRoughness;
|
metallicRoughness = elementMetallicRoughness;
|
|
@ -0,0 +1,647 @@
|
||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 gBaseColor;
|
||||||
|
layout(location = 1) out vec3 gNormal;
|
||||||
|
layout(location = 2) out vec3 gPosition;
|
||||||
|
layout(location = 3) out vec2 gMetallicRoughness;
|
||||||
|
layout(location = 4) out uint gPaintingIndex;
|
||||||
|
layout(location = 5) out vec2 gPaintingTexCoord;
|
||||||
|
|
||||||
|
in vec2 TexCoords;
|
||||||
|
in vec3 WorldPos;
|
||||||
|
in vec3 Normal;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
|
||||||
|
gBaseColor = vec4( vec3(1),1 );
|
||||||
|
// mainImage(gBaseColor, vec2(1.,1.)-TexCoords);
|
||||||
|
gPosition = WorldPos;
|
||||||
|
gNormal = normalize(Normal);
|
||||||
|
// gMetallicRoughness = vec2(1, 46./255);
|
||||||
|
gMetallicRoughness = vec2(0);
|
||||||
|
gPaintingIndex = 1;
|
||||||
|
gPaintingTexCoord = vec2(1., 1.) - TexCoords * 2;
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
layout(std430, binding = 1) buffer bvhBuffer
|
||||||
|
{
|
||||||
|
uint bvhLength;
|
||||||
|
uvec2 bvhChildren[];
|
||||||
|
};
|
||||||
|
layout(std430, binding = 2) buffer bvhBoundBuffer
|
||||||
|
{
|
||||||
|
vec4 bvhBound[];
|
||||||
|
};
|
||||||
|
layout(std430, binding = 3) buffer elementOffsetBuffer
|
||||||
|
{
|
||||||
|
/**********************
|
||||||
|
** @x elementBvhRoot
|
||||||
|
** @y elementBvhLength
|
||||||
|
** @z pointsOffset
|
||||||
|
** @w linesOffset
|
||||||
|
**********************/
|
||||||
|
uvec4 elementOffset[];
|
||||||
|
};
|
||||||
|
layout(std430, binding = 4) buffer elementIndexBuffer
|
||||||
|
{
|
||||||
|
uint elementIndexs[]; //ÏߺÍÃæ
|
||||||
|
};
|
||||||
|
layout(std430, binding = 5) buffer elementDataBuffer
|
||||||
|
{
|
||||||
|
float elementData[]; //µãºÍStyle
|
||||||
|
};
|
||||||
|
|
||||||
|
const float PI = 3.14159265358979;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
float border = 0;
|
||||||
|
|
||||||
|
mat2 inv(mat2 m)
|
||||||
|
{
|
||||||
|
return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / (m[0][0] * m[1][1] - m[1][0] * m[0][1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
float abs_min(float a, float b)
|
||||||
|
{
|
||||||
|
if (abs(a) < abs(b))
|
||||||
|
{
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int i_mod(int a, int m)
|
||||||
|
{
|
||||||
|
return int(mod(float(a), float(m)));
|
||||||
|
}
|
||||||
|
|
||||||
|
float line_dist(vec2 uv, const vec2 p0, vec2 p1)
|
||||||
|
{
|
||||||
|
vec2 tang = p1 - p0;
|
||||||
|
vec2 nor = normalize(vec2(tang.y, -tang.x));
|
||||||
|
|
||||||
|
if (dot(tang, uv) < dot(tang, p0))
|
||||||
|
{
|
||||||
|
return distance(p0, uv);
|
||||||
|
}
|
||||||
|
else if (dot(tang, uv) > dot(tang, p1))
|
||||||
|
{
|
||||||
|
return distance(p1, uv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return dot(nor, uv) - dot(nor, p0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool int_test(vec2 uv, vec2 last_point, vec2 p0, vec2 p1)
|
||||||
|
{
|
||||||
|
last_point -= uv;
|
||||||
|
p0 -= uv;
|
||||||
|
p1 -= uv;
|
||||||
|
|
||||||
|
bool ret;
|
||||||
|
if (p0.y == 0.)
|
||||||
|
{
|
||||||
|
ret = (p0.x >= 0. && p1.y * last_point.y < 0.);
|
||||||
|
}
|
||||||
|
else if (p1.y == 0.)
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
else if (p0.y * p1.y < 0.)
|
||||||
|
{
|
||||||
|
if (p0.x >= 0. && p1.x >= 0.)
|
||||||
|
{
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
else if (p0.x < 0. && p1.x < 0.)
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec2 nor;
|
||||||
|
if (p0.y > p1.y)
|
||||||
|
{
|
||||||
|
nor = p0 - p1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nor = p1 - p0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nor = vec2(nor.y, -nor.x);
|
||||||
|
if (dot(nor, p0) < 0.)
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tri_test(vec2 uv, vec2 p0, vec2 p1, vec2 p2, bool inside)
|
||||||
|
{
|
||||||
|
vec2 nor1 = normalize(p0 - p1);
|
||||||
|
nor1 = vec2(nor1.y, -nor1.x);
|
||||||
|
vec2 nor2 = normalize(p1 - p2);
|
||||||
|
nor2 = vec2(nor2.y, -nor2.x);
|
||||||
|
vec2 tan3 = normalize(p2 - p0);
|
||||||
|
vec2 nor3 = vec2(tan3.y, -tan3.x);
|
||||||
|
|
||||||
|
if (inside)
|
||||||
|
{
|
||||||
|
if (dot(tan3, p0) >= dot(tan3, uv) || dot(tan3, p2) <= dot(tan3, uv))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float brd = max(dot(nor3, nor1), dot(nor3, nor2)) * border;
|
||||||
|
return (dot(uv, nor1) >= dot(p0, nor1) && dot(uv, nor2) >= dot(p1, nor2) &&
|
||||||
|
dot(uv, nor3) >= dot(p2, nor3) + brd) ||
|
||||||
|
(dot(uv, nor1) <= dot(p0, nor1) && dot(uv, nor2) <= dot(p1, nor2) &&
|
||||||
|
dot(uv, nor3) <= dot(p2, nor3) - brd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float brd1 = dot(nor1, tan3) * border;
|
||||||
|
float brd2 = dot(nor2, tan3) * border;
|
||||||
|
|
||||||
|
if (dot(tan3, p0) >= dot(tan3, uv) - brd1 || dot(tan3, p2) <= dot(tan3, uv) - brd2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (dot(uv, nor1) >= dot(p0, nor1) - border && dot(uv, nor2) >= dot(p1, nor2) - border &&
|
||||||
|
dot(uv, nor3) >= dot(p2, nor3)) ||
|
||||||
|
(dot(uv, nor1) <= dot(p0, nor1) + border && dot(uv, nor2) <= dot(p1, nor2) + border &&
|
||||||
|
dot(uv, nor3) <= dot(p2, nor3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float bezier_sd(vec2 uv, vec2 p0, vec2 p1, vec2 p2)
|
||||||
|
{
|
||||||
|
|
||||||
|
const mat2 trf1 = mat2(-1, 2, 1, 2);
|
||||||
|
mat2 trf2 = inv(mat2(p0 - p1, p2 - p1));
|
||||||
|
mat2 trf = trf1 * trf2;
|
||||||
|
|
||||||
|
uv -= p1;
|
||||||
|
vec2 xy = trf * uv;
|
||||||
|
xy.y -= 1.;
|
||||||
|
|
||||||
|
vec2 gradient;
|
||||||
|
gradient.x = 2. * trf[0][0] * (trf[0][0] * uv.x + trf[1][0] * uv.y) - trf[0][1];
|
||||||
|
gradient.y = 2. * trf[1][0] * (trf[0][0] * uv.x + trf[1][0] * uv.y) - trf[1][1];
|
||||||
|
|
||||||
|
return (xy.x * xy.x - xy.y) / length(gradient);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
// Modified from http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c
|
||||||
|
// Credits to Doublefresh for hinting there
|
||||||
|
int solve_quadric(vec2 coeffs, inout vec2 roots)
|
||||||
|
{
|
||||||
|
|
||||||
|
// normal form: x^2 + px + q = 0
|
||||||
|
float p = coeffs[1] / 2.;
|
||||||
|
float q = coeffs[0];
|
||||||
|
|
||||||
|
float D = p * p - q;
|
||||||
|
|
||||||
|
if (D < 0.)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
roots[0] = -sqrt(D) - p;
|
||||||
|
roots[1] = sqrt(D) - p;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// From Trisomie21
|
||||||
|
// But instead of his cancellation fix i'm using a newton iteration
|
||||||
|
int solve_cubic(vec3 coeffs, inout vec3 r)
|
||||||
|
{
|
||||||
|
|
||||||
|
float a = coeffs[2];
|
||||||
|
float b = coeffs[1];
|
||||||
|
float c = coeffs[0];
|
||||||
|
|
||||||
|
float p = b - a * a / 3.0;
|
||||||
|
float q = a * (2.0 * a * a - 9.0 * b) / 27.0 + c;
|
||||||
|
float p3 = p * p * p;
|
||||||
|
float d = q * q + 4.0 * p3 / 27.0;
|
||||||
|
float offset = -a / 3.0;
|
||||||
|
if (d >= 0.0)
|
||||||
|
{ // Single solution
|
||||||
|
float z = sqrt(d);
|
||||||
|
float u = (-q + z) / 2.0;
|
||||||
|
float v = (-q - z) / 2.0;
|
||||||
|
u = sign(u) * pow(abs(u), 1.0 / 3.0);
|
||||||
|
v = sign(v) * pow(abs(v), 1.0 / 3.0);
|
||||||
|
r[0] = offset + u + v;
|
||||||
|
|
||||||
|
// Single newton iteration to account for cancellation
|
||||||
|
float f = ((r[0] + a) * r[0] + b) * r[0] + c;
|
||||||
|
float f1 = (3. * r[0] + 2. * a) * r[0] + b;
|
||||||
|
|
||||||
|
r[0] -= f / f1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
float u = sqrt(-p / 3.0);
|
||||||
|
float v = acos(-sqrt(-27.0 / p3) * q / 2.0) / 3.0;
|
||||||
|
float m = cos(v), n = sin(v) * 1.732050808;
|
||||||
|
|
||||||
|
// Single newton iteration to account for cancellation
|
||||||
|
//(once for every root)
|
||||||
|
r[0] = offset + u * (m + m);
|
||||||
|
r[1] = offset - u * (n + m);
|
||||||
|
r[2] = offset + u * (n - m);
|
||||||
|
|
||||||
|
vec3 f = ((r + a) * r + b) * r + c;
|
||||||
|
vec3 f1 = (3. * r + 2. * a) * r + b;
|
||||||
|
|
||||||
|
r -= f / f1;
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
float cubic_bezier_normal_iteration(float t, vec2 a0, vec2 a1, vec2 a2, vec2 a3)
|
||||||
|
{
|
||||||
|
// horner's method
|
||||||
|
vec2 a_2 = a2 + t * a3;
|
||||||
|
vec2 a_1 = a1 + t * a_2;
|
||||||
|
vec2 b_2 = a_2 + t * a3;
|
||||||
|
|
||||||
|
vec2 uv_to_p = a0 + t * a_1;
|
||||||
|
vec2 tang = a_1 + t * b_2;
|
||||||
|
|
||||||
|
float l_tang = dot(tang, tang);
|
||||||
|
return t - dot(tang, uv_to_p) / l_tang;
|
||||||
|
}
|
||||||
|
|
||||||
|
float cubic_bezier_dis_approx_sq(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
|
||||||
|
{
|
||||||
|
vec2 a3 = (-p0 + 3. * p1 - 3. * p2 + p3);
|
||||||
|
vec2 a2 = (3. * p0 - 6. * p1 + 3. * p2);
|
||||||
|
vec2 a1 = (-3. * p0 + 3. * p1);
|
||||||
|
vec2 a0 = p0 - uv;
|
||||||
|
|
||||||
|
float d0 = 1e38;
|
||||||
|
|
||||||
|
float t;
|
||||||
|
vec3 params = vec3(0, .5, 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
t = params[i];
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
{
|
||||||
|
t = cubic_bezier_normal_iteration(t, a0, a1, a2, a3);
|
||||||
|
}
|
||||||
|
t = clamp(t, 0., 1.);
|
||||||
|
vec2 uv_to_p = ((a3 * t + a2) * t + a1) * t + a0;
|
||||||
|
d0 = min(d0, dot(uv_to_p, uv_to_p));
|
||||||
|
}
|
||||||
|
|
||||||
|
return d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// segment_dis_sq by iq
|
||||||
|
float length2(vec2 v)
|
||||||
|
{
|
||||||
|
return dot(v, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
float segment_dis_sq(vec2 p, vec2 a, vec2 b)
|
||||||
|
{
|
||||||
|
vec2 pa = p - a, ba = b - a;
|
||||||
|
float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
|
||||||
|
return length2(pa - ba * h);
|
||||||
|
}
|
||||||
|
|
||||||
|
int segment_int_test(vec2 uv, vec2 p0, vec2 p1)
|
||||||
|
{
|
||||||
|
p0 -= uv;
|
||||||
|
p1 -= uv;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (p0.y * p1.y < 0.)
|
||||||
|
{
|
||||||
|
vec2 nor = p0 - p1;
|
||||||
|
nor = vec2(nor.y, -nor.x);
|
||||||
|
|
||||||
|
float sgn;
|
||||||
|
|
||||||
|
if (p0.y > p1.y)
|
||||||
|
{
|
||||||
|
sgn = 1.;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sgn = -1.;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dot(nor, p0) * sgn < 0.)
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cubic_bezier_int_test(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
|
||||||
|
{
|
||||||
|
|
||||||
|
float cu = (-p0.y + 3. * p1.y - 3. * p2.y + p3.y);
|
||||||
|
float qu = (3. * p0.y - 6. * p1.y + 3. * p2.y);
|
||||||
|
float li = (-3. * p0.y + 3. * p1.y);
|
||||||
|
float co = p0.y - uv.y;
|
||||||
|
|
||||||
|
vec3 roots = vec3(1e38);
|
||||||
|
int n_roots;
|
||||||
|
|
||||||
|
int n_ints = 0;
|
||||||
|
|
||||||
|
if (uv.x < min(min(p0.x, p1.x), min(p2.x, p3.x)))
|
||||||
|
{
|
||||||
|
if (uv.y >= min(p0.y, p3.y) && uv.y <= max(p0.y, p3.y))
|
||||||
|
{
|
||||||
|
n_ints = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
if (abs(cu) < .0001)
|
||||||
|
{
|
||||||
|
n_roots = solve_quadric(vec2(co / qu, li / qu), roots.xy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n_roots = solve_cubic(vec3(co / cu, li / cu, qu / cu), roots);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < n_roots; i++)
|
||||||
|
{
|
||||||
|
if (roots[i] >= 0. && roots[i] <= 1.)
|
||||||
|
{
|
||||||
|
float x_pos = -p0.x + 3. * p1.x - 3. * p2.x + p3.x;
|
||||||
|
x_pos = x_pos * roots[i] + 3. * p0.x - 6. * p1.x + 3. * p2.x;
|
||||||
|
x_pos = x_pos * roots[i] + -3. * p0.x + 3. * p1.x;
|
||||||
|
x_pos = x_pos * roots[i] + p0.x;
|
||||||
|
|
||||||
|
if (x_pos > uv.x)
|
||||||
|
{
|
||||||
|
n_ints++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n_ints;
|
||||||
|
}
|
||||||
|
|
||||||
|
float path2_dis_sq(vec2 uv)
|
||||||
|
{
|
||||||
|
float dis_sq = 1e38;
|
||||||
|
|
||||||
|
int num_its = 0;
|
||||||
|
|
||||||
|
vec2[45] p = vec2[](vec2(-0.124919, 0.0496896), vec2(-0.127105, 0.0391554), vec2(-0.127105, 0.0405467),
|
||||||
|
vec2(-0.127105, 0.0463107), vec2(-0.131876, 0.0506833), vec2(-0.143205, 0.0506833),
|
||||||
|
vec2(-0.177789, 0.0506833), vec2(-0.194286, 0.00795032), vec2(-0.194286, -0.018882),
|
||||||
|
vec2(-0.194286, -0.0425342), vec2(-0.181366, -0.0508821), vec2(-0.167851, -0.0508821),
|
||||||
|
vec2(-0.153739, -0.0508821), vec2(-0.144397, -0.0417392), vec2(-0.138236, -0.0325963),
|
||||||
|
vec2(-0.137043, -0.0445217), vec2(-0.129888, -0.0508821), vec2(-0.118758, -0.0508821),
|
||||||
|
vec2(-0.108025, -0.0508821), vec2(-0.0901364, -0.0465093), vec2(-0.0788071, -0.0141118),
|
||||||
|
vec2(-0.087155, -0.0141118), vec2(-0.0901364, -0.0240497), vec2(-0.0955028, -0.0327951),
|
||||||
|
vec2(-0.103254, -0.0327951), vec2(-0.10882, -0.0327951), vec2(-0.111403, -0.0298137),
|
||||||
|
vec2(-0.111403, -0.0242485), vec2(-0.111403, -0.0224597), vec2(-0.111205, -0.0204721),
|
||||||
|
vec2(-0.110609, -0.0178882), vec2(-0.0962985, 0.0496896), vec2(-0.137043, 0.0383603),
|
||||||
|
vec2(-0.130683, 0.0383603), vec2(-0.128894, 0.0331926), vec2(-0.128894, 0.0308075),
|
||||||
|
vec2(-0.138435, -0.0141118), vec2(-0.14082, -0.0256398), vec2(-0.149168, -0.0316026),
|
||||||
|
vec2(-0.154931, -0.0316026), vec2(-0.158509, -0.0316026), vec2(-0.164869, -0.0314042),
|
||||||
|
vec2(-0.164869, -0.0160994), vec2(-0.164869, 0.00258385), vec2(-0.153938, 0.0383603));
|
||||||
|
|
||||||
|
ivec2[6] seg = ivec2[](ivec2(0, 1), ivec2(1, 2), ivec2(20, 21), ivec2(30, 31), ivec2(31, 0), ivec2(35, 36));
|
||||||
|
|
||||||
|
ivec4[13] c_bez =
|
||||||
|
ivec4[](ivec4(2, 3, 4, 5), ivec4(5, 6, 7, 8), ivec4(8, 9, 10, 11), ivec4(11, 12, 13, 14), ivec4(14, 15, 16, 17),
|
||||||
|
ivec4(17, 18, 19, 20), ivec4(21, 22, 23, 24), ivec4(24, 25, 26, 27), ivec4(27, 28, 29, 30),
|
||||||
|
ivec4(32, 33, 34, 35), ivec4(36, 37, 38, 39), ivec4(39, 40, 41, 42), ivec4(42, 43, 44, 32));
|
||||||
|
|
||||||
|
if (all(lessThan(uv, vec2(-0.0788071, 0.0506833) + border)) &&
|
||||||
|
all(greaterThan(uv, vec2(-0.194286, -0.0508821) - border)))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
dis_sq = min(dis_sq, segment_dis_sq(uv, p[seg[i][0]], p[seg[i][1]]));
|
||||||
|
num_its += segment_int_test(uv, p[seg[i][0]], p[seg[i][1]]);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 13; i++)
|
||||||
|
{
|
||||||
|
dis_sq = min(
|
||||||
|
dis_sq, cubic_bezier_dis_approx_sq(uv, p[c_bez[i][0]], p[c_bez[i][1]], p[c_bez[i][2]], p[c_bez[i][3]]));
|
||||||
|
num_its += cubic_bezier_int_test(uv, p[c_bez[i][0]], p[c_bez[i][1]], p[c_bez[i][2]], p[c_bez[i][3]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float sgn = 1.;
|
||||||
|
|
||||||
|
if (num_its % 2 == 1)
|
||||||
|
{
|
||||||
|
sgn = -1.;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sgn * dis_sq;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage(out vec3 fragColor, in vec2 fragCoord)
|
||||||
|
{
|
||||||
|
border = 0.01;
|
||||||
|
vec2 uv = fragCoord;
|
||||||
|
uv -= .5;
|
||||||
|
|
||||||
|
float dis_sq = 1e38;
|
||||||
|
|
||||||
|
if (all(lessThan(uv, vec2(0.4, 0.0993791) + border)) && all(greaterThan(uv, vec2(-0.4, -0.0993791) - border)))
|
||||||
|
{
|
||||||
|
dis_sq = min(dis_sq, path2_dis_sq(uv));
|
||||||
|
}
|
||||||
|
|
||||||
|
float dis = sign(dis_sq) * sqrt(abs(dis_sq));
|
||||||
|
|
||||||
|
fragColor = vec3(smoothstep(0., border, dis));
|
||||||
|
if (dis > 0 && dis <= border)
|
||||||
|
fragColor = vec3(1, 1, 0);
|
||||||
|
}
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
const uint STACK_SIZE = 40;
|
||||||
|
|
||||||
|
struct Stack
|
||||||
|
{
|
||||||
|
uint top;
|
||||||
|
uint data[STACK_SIZE];
|
||||||
|
|
||||||
|
bool empty()
|
||||||
|
{
|
||||||
|
return top == 0;
|
||||||
|
}
|
||||||
|
bool full()
|
||||||
|
{
|
||||||
|
return top == STACK_SIZE;
|
||||||
|
}
|
||||||
|
bool getTop(out uint x)
|
||||||
|
{
|
||||||
|
if (empty())
|
||||||
|
return false;
|
||||||
|
x = data[top - 1];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool pop()
|
||||||
|
{
|
||||||
|
if (empty())
|
||||||
|
return false;
|
||||||
|
top--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool push(in uint x)
|
||||||
|
{
|
||||||
|
if (full())
|
||||||
|
return false;
|
||||||
|
data[top] = x;
|
||||||
|
top++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} stack, elementStack;
|
||||||
|
|
||||||
|
vec3 drawElement(uint elementIndex, vec2 localUV, inout vec3 debugBVH = vec3(0))
|
||||||
|
{
|
||||||
|
vec4 elementColor = vec4(0);
|
||||||
|
|
||||||
|
uvec4 currentOffset = elementOffset[elementIndex];
|
||||||
|
uint elementBvhRoot = currentOffset.x;
|
||||||
|
uint elementBvhLength = currentOffset.y;
|
||||||
|
uint pointsOffset = currentOffset.z;
|
||||||
|
uint linesOffset = currentOffset.w;
|
||||||
|
|
||||||
|
elementStack.top = 0;
|
||||||
|
uint elementBvhIndex = 0;
|
||||||
|
while (elementBvhIndex < elementBvhLength || !elementStack.empty())
|
||||||
|
{
|
||||||
|
|
||||||
|
while (elementBvhIndex < elementBvhLength)
|
||||||
|
{
|
||||||
|
vec4 bound = bvhBound[elementBvhRoot + elementBvhIndex];
|
||||||
|
uint leftChild = bvhChildren[elementBvhRoot + elementBvhIndex].x;
|
||||||
|
|
||||||
|
if (all(lessThan(bound.xy, localUV)) && all(lessThan(localUV, bound.zw)))
|
||||||
|
{
|
||||||
|
if (leftChild >= elementBvhLength)
|
||||||
|
{
|
||||||
|
debugBVH.g += 0.5;
|
||||||
|
|
||||||
|
uint styleIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y - elementBvhLength;
|
||||||
|
// for(int i = 0; i<200;i++)
|
||||||
|
if (elementData[styleIndex] == 0.) //Ãæ
|
||||||
|
{
|
||||||
|
|
||||||
|
uint lineCount = elementIndexs[leftChild - elementBvhLength];
|
||||||
|
uint num_its = 0;
|
||||||
|
|
||||||
|
for (uint contourIterator = leftChild - elementBvhLength + 1;
|
||||||
|
contourIterator <= leftChild - elementBvhLength + lineCount; contourIterator++)
|
||||||
|
{
|
||||||
|
uint lineIndex = elementIndexs[contourIterator];
|
||||||
|
uint p0Index = elementIndexs[linesOffset + 4 * lineIndex];
|
||||||
|
uint p1Index = elementIndexs[linesOffset + 4 * lineIndex + 1];
|
||||||
|
uint p2Index = elementIndexs[linesOffset + 4 * lineIndex + 2];
|
||||||
|
uint p3Index = elementIndexs[linesOffset + 4 * lineIndex + 3];
|
||||||
|
|
||||||
|
vec2 p0 = vec2(elementData[pointsOffset + 2 * p0Index],
|
||||||
|
elementData[pointsOffset + 2 * p0Index + 1]);
|
||||||
|
vec2 p1 = vec2(elementData[pointsOffset + 2 * p1Index],
|
||||||
|
elementData[pointsOffset + 2 * p1Index + 1]);
|
||||||
|
vec2 p2 = vec2(elementData[pointsOffset + 2 * p2Index],
|
||||||
|
elementData[pointsOffset + 2 * p2Index + 1]);
|
||||||
|
vec2 p3 = vec2(elementData[pointsOffset + 2 * p3Index],
|
||||||
|
elementData[pointsOffset + 2 * p3Index + 1]);
|
||||||
|
|
||||||
|
if (p0 == p1 && p2 == p3)
|
||||||
|
{
|
||||||
|
num_its += segment_int_test(localUV, p0, p3);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
num_its += cubic_bezier_int_test(localUV, p0, p1, p2, p3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_its % 2 == 1)
|
||||||
|
{
|
||||||
|
elementColor = vec4(1);
|
||||||
|
//debugHit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (elementData[styleIndex] == 1) //Ïß
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
elementBvhIndex = elementBvhLength;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// debugBVH.b += 0.2;
|
||||||
|
elementStack.push(elementBvhIndex);
|
||||||
|
elementBvhIndex = leftChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
elementBvhIndex = elementBvhLength;
|
||||||
|
}
|
||||||
|
if (!elementStack.empty())
|
||||||
|
{
|
||||||
|
elementStack.getTop(elementBvhIndex);
|
||||||
|
elementStack.pop();
|
||||||
|
elementBvhIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return elementColor.xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
|
||||||
|
uniform sampler2D texture_basecolor;
|
||||||
|
uniform sampler2D texture_metallic_roughness;
|
||||||
|
uniform sampler2D texture_normal;
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
in vec2 TexCoords;
|
||||||
|
in vec3 WorldPos;
|
||||||
|
in vec3 Normal;
|
||||||
|
|
||||||
|
// lights
|
||||||
|
uniform vec3 lightPositions[4];
|
||||||
|
uniform vec3 lightColors[4];
|
||||||
|
|
||||||
|
uniform vec3 camPos;
|
||||||
|
|
||||||
|
const float PI = 3.14159265359;
|
||||||
|
|
||||||
|
vec3 getNormalFromMap()
|
||||||
|
{
|
||||||
|
vec3 tangentNormal = texture(texture_normal, TexCoords).xyz * 2.0 - 1.0;
|
||||||
|
|
||||||
|
vec3 Q1 = dFdx(WorldPos);
|
||||||
|
vec3 Q2 = dFdy(WorldPos);
|
||||||
|
vec2 st1 = dFdx(TexCoords);
|
||||||
|
vec2 st2 = dFdy(TexCoords);
|
||||||
|
|
||||||
|
vec3 N = normalize(Normal);
|
||||||
|
vec3 T = normalize(Q1*st2.t - Q2*st1.t);
|
||||||
|
vec3 B = -normalize(cross(N, T));
|
||||||
|
mat3 TBN = mat3(T, B, N);
|
||||||
|
|
||||||
|
return normalize(TBN * tangentNormal);
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
float DistributionGGX(vec3 N, vec3 H, float roughness)
|
||||||
|
{
|
||||||
|
float a = roughness*roughness;
|
||||||
|
float a2 = a*a;
|
||||||
|
float NdotH = max(dot(N, H), 0.0);
|
||||||
|
float NdotH2 = NdotH*NdotH;
|
||||||
|
|
||||||
|
float nom = a2;
|
||||||
|
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
||||||
|
denom = PI * denom * denom;
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||||
|
{
|
||||||
|
float r = (roughness + 1.0);
|
||||||
|
float k = (r*r) / 8.0;
|
||||||
|
|
||||||
|
float nom = NdotV;
|
||||||
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
||||||
|
{
|
||||||
|
float NdotV = max(dot(N, V), 0.0);
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||||
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||||
|
|
||||||
|
return ggx1 * ggx2;
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
||||||
|
{
|
||||||
|
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
||||||
|
}
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 baseColor = texture(texture_basecolor, TexCoords);
|
||||||
|
if(baseColor.a<0.4)
|
||||||
|
discard;
|
||||||
|
|
||||||
|
vec3 albedo = pow(baseColor.rgb, vec3(2.2));
|
||||||
|
float metallic = texture(texture_metallic_roughness, TexCoords).b;
|
||||||
|
float roughness = texture(texture_metallic_roughness, TexCoords).g;
|
||||||
|
|
||||||
|
|
||||||
|
vec3 N = getNormalFromMap();
|
||||||
|
vec3 V = normalize(camPos - WorldPos);
|
||||||
|
|
||||||
|
vec3 F0 = vec3(0.04);
|
||||||
|
F0 = mix(F0, albedo, metallic);
|
||||||
|
|
||||||
|
// reflectance equation
|
||||||
|
vec3 Lo = vec3(0.0);
|
||||||
|
for(int i = 0; i < 1; ++i)
|
||||||
|
{
|
||||||
|
// calculate per-light radiance
|
||||||
|
vec3 L = normalize(lightPositions[i] - WorldPos);
|
||||||
|
vec3 H = normalize(V + L);
|
||||||
|
float distance = length(lightPositions[i] - WorldPos);
|
||||||
|
float attenuation = 1.0 / (distance * distance);
|
||||||
|
vec3 radiance = lightColors[i] * attenuation;
|
||||||
|
|
||||||
|
// cook-torrance brdf
|
||||||
|
float NDF = DistributionGGX(N, H, roughness);
|
||||||
|
float G = GeometrySmith(N, V, L, roughness);
|
||||||
|
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
|
||||||
|
F = clamp(F,vec3(0),vec3(1));
|
||||||
|
|
||||||
|
vec3 kS = F;
|
||||||
|
vec3 kD = vec3(1.0) - kS;
|
||||||
|
kD *= 1.0 - metallic;
|
||||||
|
|
||||||
|
vec3 nominator = NDF * G * F;
|
||||||
|
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001;
|
||||||
|
vec3 specular = nominator / denominator;
|
||||||
|
|
||||||
|
// add to outgoing radiance Lo
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
Lo += (kD * albedo / PI + specular) * radiance * NdotL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ambient = vec3(0.03) * albedo;
|
||||||
|
vec3 color = ambient + Lo;
|
||||||
|
|
||||||
|
color = color / (color + vec3(1.0));
|
||||||
|
color = pow(color, vec3(1.0/2.2));
|
||||||
|
|
||||||
|
FragColor = vec4(color, 1.0);
|
||||||
|
|
||||||
|
}
|
|
@ -2,16 +2,11 @@
|
||||||
|
|
||||||
layout (local_size_x = 8, local_size_y = 8) in;
|
layout (local_size_x = 8, local_size_y = 8) in;
|
||||||
|
|
||||||
layout(rgba8, binding = 0) uniform image2D gBaseColor;
|
uniform sampler2D gBaseColor;
|
||||||
uniform sampler2D gNormal;
|
uniform sampler2D gNormal;
|
||||||
uniform sampler2D gPosition;
|
uniform sampler2D gPosition;
|
||||||
uniform sampler2D gMetallicRoughness;
|
uniform sampler2D gMetallicRoughness;
|
||||||
uniform sampler2DArray gShadowMap;
|
uniform sampler2DArray gShadowMap;
|
||||||
|
|
||||||
uniform samplerCube irradianceMap;
|
|
||||||
uniform samplerCube prefilterMap;
|
|
||||||
uniform sampler2D brdfLUT;
|
|
||||||
|
|
||||||
layout(rgba16f, binding = 1) uniform image2D gDirectLight;
|
layout(rgba16f, binding = 1) uniform image2D gDirectLight;
|
||||||
layout (std140, binding = 0) uniform LightSpaceMatrices
|
layout (std140, binding = 0) uniform LightSpaceMatrices
|
||||||
{
|
{
|
||||||
|
@ -70,34 +65,6 @@ vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
||||||
{
|
{
|
||||||
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
||||||
}
|
}
|
||||||
vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)
|
|
||||||
{
|
|
||||||
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 ambientLighting(vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness, float ao)
|
|
||||||
{
|
|
||||||
// ambient lighting (we now use IBL as the ambient term)
|
|
||||||
vec3 F = fresnelSchlickRoughness(clamp(dot(N, V),0.,1.), F0, roughness);
|
|
||||||
|
|
||||||
vec3 kS = F;
|
|
||||||
vec3 kD = 1.0 - kS;
|
|
||||||
kD *= 1.0 - metallic;
|
|
||||||
|
|
||||||
vec3 irradiance = texture(irradianceMap, N).rgb;
|
|
||||||
vec3 diffuse = irradiance * albedo;
|
|
||||||
|
|
||||||
// sample both the pre-filter map and the BRDF lut and combine them together as per the Split-Sum approximation to get the IBL specular part.
|
|
||||||
const float MAX_REFLECTION_LOD = 4.0;
|
|
||||||
vec3 R = reflect(-V, N);
|
|
||||||
vec3 prefilteredColor = textureLod(prefilterMap, R, roughness * MAX_REFLECTION_LOD).rgb;
|
|
||||||
vec2 brdf = texture(brdfLUT, vec2(clamp(dot(N, V),0.,1.), roughness)).rg;
|
|
||||||
vec3 specular = prefilteredColor * (F * brdf.x + brdf.y);
|
|
||||||
|
|
||||||
return (kD * diffuse + specular) * ao;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const int pcfRadius = 3;
|
const int pcfRadius = 3;
|
||||||
float getShadowFromLayer(vec3 fragPosWorldSpace, vec3 normal,int layer)
|
float getShadowFromLayer(vec3 fragPosWorldSpace, vec3 normal,int layer)
|
||||||
{
|
{
|
||||||
|
@ -165,28 +132,11 @@ float ShadowCalculation(vec3 fragPosWorldSpace, vec3 normal, out int layer)
|
||||||
return shadow;
|
return shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vec4 encodeRGBM(vec3 color)
|
|
||||||
{
|
|
||||||
if(dot(color,color)==0)
|
|
||||||
return vec4(0,0,0,1);
|
|
||||||
vec4 rgbm;
|
|
||||||
float range = 8;
|
|
||||||
color /= range;
|
|
||||||
rgbm.a = clamp(max(max(color.r, color.g), max(color.b, 1e-6)), 0.0, 1.0);
|
|
||||||
rgbm.a = ceil(rgbm.a * 255.0) / 255.0;
|
|
||||||
rgbm.rgb = color / rgbm.a;
|
|
||||||
return rgbm;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy);
|
ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy);
|
||||||
|
|
||||||
|
vec3 albedo = pow(texelFetch(gBaseColor, pixelLocation, 0).rgb, vec3(2.2));
|
||||||
//vec3 albedo = pow(texelFetch(gBaseColor, pixelLocation, 0).rgb, vec3(2.2));
|
|
||||||
vec3 albedo = pow(imageLoad(gBaseColor, pixelLocation).rgb, vec3(2.2));
|
|
||||||
float metallic = texelFetch(gMetallicRoughness, pixelLocation, 0).r;
|
float metallic = texelFetch(gMetallicRoughness, pixelLocation, 0).r;
|
||||||
float roughness = texelFetch(gMetallicRoughness, pixelLocation, 0).g;
|
float roughness = texelFetch(gMetallicRoughness, pixelLocation, 0).g;
|
||||||
|
|
||||||
|
@ -195,12 +145,15 @@ void main()
|
||||||
|
|
||||||
if(normal==vec3(0))
|
if(normal==vec3(0))
|
||||||
{
|
{
|
||||||
//vec3 color = mainLightRadiance;
|
vec3 color = mainLightRadiance;
|
||||||
//imageStore(gBaseColor, pixelLocation, vec4(color, 1.0));
|
|
||||||
imageStore(gBaseColor, pixelLocation, vec4(0));
|
//color = color / (color + vec3(1.0));
|
||||||
|
//color = pow(color, vec3(1.0/2.2));
|
||||||
|
|
||||||
|
imageStore(gDirectLight, pixelLocation, vec4(color, 1.0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
normal = normalize(normal);
|
|
||||||
|
|
||||||
vec3 V = normalize(camPos - worldPos);
|
vec3 V = normalize(camPos - worldPos);
|
||||||
|
|
||||||
|
@ -231,11 +184,8 @@ void main()
|
||||||
float NdotL = max(dot(normal, L), 0.0);
|
float NdotL = max(dot(normal, L), 0.0);
|
||||||
vec3 Lo = (kD * albedo / PI + specular) * radiance * NdotL;
|
vec3 Lo = (kD * albedo / PI + specular) * radiance * NdotL;
|
||||||
|
|
||||||
vec3 ambient = ambientLighting(normal, V, F0, albedo, metallic, roughness, 1);
|
|
||||||
|
|
||||||
int debugLayer;
|
int debugLayer;
|
||||||
float shadow = ShadowCalculation(worldPos, normal, debugLayer);
|
float shadow = ShadowCalculation(worldPos, normal, debugLayer);
|
||||||
|
|
||||||
vec3 color = (1-shadow)*Lo + ambient;
|
imageStore(gDirectLight, pixelLocation, vec4((1-shadow)*Lo, 1));
|
||||||
imageStore(gBaseColor, pixelLocation, encodeRGBM(color));
|
|
||||||
}
|
}
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 422 B After Width: | Height: | Size: 422 B |
Before Width: | Height: | Size: 386 B After Width: | Height: | Size: 386 B |
Before Width: | Height: | Size: 364 B After Width: | Height: | Size: 364 B |
Before Width: | Height: | Size: 404 B After Width: | Height: | Size: 404 B |
|
@ -1,311 +0,0 @@
|
||||||
#ifndef __khrplatform_h_
|
|
||||||
#define __khrplatform_h_
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright (c) 2008-2018 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
** copy of this software and/or associated documentation files (the
|
|
||||||
** "Materials"), to deal in the Materials without restriction, including
|
|
||||||
** without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
|
||||||
** permit persons to whom the Materials are furnished to do so, subject to
|
|
||||||
** the following conditions:
|
|
||||||
**
|
|
||||||
** The above copyright notice and this permission notice shall be included
|
|
||||||
** in all copies or substantial portions of the Materials.
|
|
||||||
**
|
|
||||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Khronos platform-specific types and definitions.
|
|
||||||
*
|
|
||||||
* The master copy of khrplatform.h is maintained in the Khronos EGL
|
|
||||||
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
|
|
||||||
* The last semantic modification to khrplatform.h was at commit ID:
|
|
||||||
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
|
|
||||||
*
|
|
||||||
* Adopters may modify this file to suit their platform. Adopters are
|
|
||||||
* encouraged to submit platform specific modifications to the Khronos
|
|
||||||
* group so that they can be included in future versions of this file.
|
|
||||||
* Please submit changes by filing pull requests or issues on
|
|
||||||
* the EGL Registry repository linked above.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the Implementer's Guidelines for information about where this file
|
|
||||||
* should be located on your system and for more details of its use:
|
|
||||||
* http://www.khronos.org/registry/implementers_guide.pdf
|
|
||||||
*
|
|
||||||
* This file should be included as
|
|
||||||
* #include <KHR/khrplatform.h>
|
|
||||||
* by Khronos client API header files that use its types and defines.
|
|
||||||
*
|
|
||||||
* The types in khrplatform.h should only be used to define API-specific types.
|
|
||||||
*
|
|
||||||
* Types defined in khrplatform.h:
|
|
||||||
* khronos_int8_t signed 8 bit
|
|
||||||
* khronos_uint8_t unsigned 8 bit
|
|
||||||
* khronos_int16_t signed 16 bit
|
|
||||||
* khronos_uint16_t unsigned 16 bit
|
|
||||||
* khronos_int32_t signed 32 bit
|
|
||||||
* khronos_uint32_t unsigned 32 bit
|
|
||||||
* khronos_int64_t signed 64 bit
|
|
||||||
* khronos_uint64_t unsigned 64 bit
|
|
||||||
* khronos_intptr_t signed same number of bits as a pointer
|
|
||||||
* khronos_uintptr_t unsigned same number of bits as a pointer
|
|
||||||
* khronos_ssize_t signed size
|
|
||||||
* khronos_usize_t unsigned size
|
|
||||||
* khronos_float_t signed 32 bit floating point
|
|
||||||
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
|
|
||||||
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
|
|
||||||
* nanoseconds
|
|
||||||
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
|
|
||||||
* khronos_boolean_enum_t enumerated boolean type. This should
|
|
||||||
* only be used as a base type when a client API's boolean type is
|
|
||||||
* an enum. Client APIs which use an integer or other type for
|
|
||||||
* booleans cannot use this as the base type for their boolean.
|
|
||||||
*
|
|
||||||
* Tokens defined in khrplatform.h:
|
|
||||||
*
|
|
||||||
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
|
|
||||||
*
|
|
||||||
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
|
|
||||||
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
|
|
||||||
*
|
|
||||||
* Calling convention macros defined in this file:
|
|
||||||
* KHRONOS_APICALL
|
|
||||||
* KHRONOS_APIENTRY
|
|
||||||
* KHRONOS_APIATTRIBUTES
|
|
||||||
*
|
|
||||||
* These may be used in function prototypes as:
|
|
||||||
*
|
|
||||||
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
|
|
||||||
* int arg1,
|
|
||||||
* int arg2) KHRONOS_APIATTRIBUTES;
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
|
|
||||||
# define KHRONOS_STATIC 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
|
||||||
* Definition of KHRONOS_APICALL
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
* This precedes the return type of the function in the function prototype.
|
|
||||||
*/
|
|
||||||
#if defined(KHRONOS_STATIC)
|
|
||||||
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
|
|
||||||
* header compatible with static linking. */
|
|
||||||
# define KHRONOS_APICALL
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
# define KHRONOS_APICALL __declspec(dllimport)
|
|
||||||
#elif defined (__SYMBIAN32__)
|
|
||||||
# define KHRONOS_APICALL IMPORT_C
|
|
||||||
#elif defined(__ANDROID__)
|
|
||||||
# define KHRONOS_APICALL __attribute__((visibility("default")))
|
|
||||||
#else
|
|
||||||
# define KHRONOS_APICALL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
|
||||||
* Definition of KHRONOS_APIENTRY
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
* This follows the return type of the function and precedes the function
|
|
||||||
* name in the function prototype.
|
|
||||||
*/
|
|
||||||
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
|
||||||
/* Win32 but not WinCE */
|
|
||||||
# define KHRONOS_APIENTRY __stdcall
|
|
||||||
#else
|
|
||||||
# define KHRONOS_APIENTRY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
|
||||||
* Definition of KHRONOS_APIATTRIBUTES
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
* This follows the closing parenthesis of the function prototype arguments.
|
|
||||||
*/
|
|
||||||
#if defined (__ARMCC_2__)
|
|
||||||
#define KHRONOS_APIATTRIBUTES __softfp
|
|
||||||
#else
|
|
||||||
#define KHRONOS_APIATTRIBUTES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
|
||||||
* basic type definitions
|
|
||||||
*-----------------------------------------------------------------------*/
|
|
||||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Using <stdint.h>
|
|
||||||
*/
|
|
||||||
#include <stdint.h>
|
|
||||||
typedef int32_t khronos_int32_t;
|
|
||||||
typedef uint32_t khronos_uint32_t;
|
|
||||||
typedef int64_t khronos_int64_t;
|
|
||||||
typedef uint64_t khronos_uint64_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
/*
|
|
||||||
* To support platform where unsigned long cannot be used interchangeably with
|
|
||||||
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
|
|
||||||
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
|
|
||||||
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
|
|
||||||
* unsigned long long or similar (this results in different C++ name mangling).
|
|
||||||
* To avoid changes for existing platforms, we restrict usage of intptr_t to
|
|
||||||
* platforms where the size of a pointer is larger than the size of long.
|
|
||||||
*/
|
|
||||||
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
|
|
||||||
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
|
|
||||||
#define KHRONOS_USE_INTPTR_T
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif defined(__VMS ) || defined(__sgi)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Using <inttypes.h>
|
|
||||||
*/
|
|
||||||
#include <inttypes.h>
|
|
||||||
typedef int32_t khronos_int32_t;
|
|
||||||
typedef uint32_t khronos_uint32_t;
|
|
||||||
typedef int64_t khronos_int64_t;
|
|
||||||
typedef uint64_t khronos_uint64_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
|
|
||||||
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Win32
|
|
||||||
*/
|
|
||||||
typedef __int32 khronos_int32_t;
|
|
||||||
typedef unsigned __int32 khronos_uint32_t;
|
|
||||||
typedef __int64 khronos_int64_t;
|
|
||||||
typedef unsigned __int64 khronos_uint64_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
|
|
||||||
#elif defined(__sun__) || defined(__digital__)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sun or Digital
|
|
||||||
*/
|
|
||||||
typedef int khronos_int32_t;
|
|
||||||
typedef unsigned int khronos_uint32_t;
|
|
||||||
#if defined(__arch64__) || defined(_LP64)
|
|
||||||
typedef long int khronos_int64_t;
|
|
||||||
typedef unsigned long int khronos_uint64_t;
|
|
||||||
#else
|
|
||||||
typedef long long int khronos_int64_t;
|
|
||||||
typedef unsigned long long int khronos_uint64_t;
|
|
||||||
#endif /* __arch64__ */
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
|
|
||||||
#elif 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Hypothetical platform with no float or int64 support
|
|
||||||
*/
|
|
||||||
typedef int khronos_int32_t;
|
|
||||||
typedef unsigned int khronos_uint32_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 0
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 0
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generic fallback
|
|
||||||
*/
|
|
||||||
#include <stdint.h>
|
|
||||||
typedef int32_t khronos_int32_t;
|
|
||||||
typedef uint32_t khronos_uint32_t;
|
|
||||||
typedef int64_t khronos_int64_t;
|
|
||||||
typedef uint64_t khronos_uint64_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Types that are (so far) the same on all platforms
|
|
||||||
*/
|
|
||||||
typedef signed char khronos_int8_t;
|
|
||||||
typedef unsigned char khronos_uint8_t;
|
|
||||||
typedef signed short int khronos_int16_t;
|
|
||||||
typedef unsigned short int khronos_uint16_t;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Types that differ between LLP64 and LP64 architectures - in LLP64,
|
|
||||||
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
|
|
||||||
* to be the only LLP64 architecture in current use.
|
|
||||||
*/
|
|
||||||
#ifdef KHRONOS_USE_INTPTR_T
|
|
||||||
typedef intptr_t khronos_intptr_t;
|
|
||||||
typedef uintptr_t khronos_uintptr_t;
|
|
||||||
#elif defined(_WIN64)
|
|
||||||
typedef signed long long int khronos_intptr_t;
|
|
||||||
typedef unsigned long long int khronos_uintptr_t;
|
|
||||||
#else
|
|
||||||
typedef signed long int khronos_intptr_t;
|
|
||||||
typedef unsigned long int khronos_uintptr_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN64)
|
|
||||||
typedef signed long long int khronos_ssize_t;
|
|
||||||
typedef unsigned long long int khronos_usize_t;
|
|
||||||
#else
|
|
||||||
typedef signed long int khronos_ssize_t;
|
|
||||||
typedef unsigned long int khronos_usize_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if KHRONOS_SUPPORT_FLOAT
|
|
||||||
/*
|
|
||||||
* Float type
|
|
||||||
*/
|
|
||||||
typedef float khronos_float_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if KHRONOS_SUPPORT_INT64
|
|
||||||
/* Time types
|
|
||||||
*
|
|
||||||
* These types can be used to represent a time interval in nanoseconds or
|
|
||||||
* an absolute Unadjusted System Time. Unadjusted System Time is the number
|
|
||||||
* of nanoseconds since some arbitrary system event (e.g. since the last
|
|
||||||
* time the system booted). The Unadjusted System Time is an unsigned
|
|
||||||
* 64 bit value that wraps back to 0 every 584 years. Time intervals
|
|
||||||
* may be either signed or unsigned.
|
|
||||||
*/
|
|
||||||
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
|
|
||||||
typedef khronos_int64_t khronos_stime_nanoseconds_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dummy value used to pad enum types to 32 bits.
|
|
||||||
*/
|
|
||||||
#ifndef KHRONOS_MAX_ENUM
|
|
||||||
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enumerated boolean type
|
|
||||||
*
|
|
||||||
* Values other than zero should be considered to be true. Therefore
|
|
||||||
* comparisons should not be made against KHRONOS_TRUE.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
KHRONOS_FALSE = 0,
|
|
||||||
KHRONOS_TRUE = 1,
|
|
||||||
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
|
|
||||||
} khronos_boolean_enum_t;
|
|
||||||
|
|
||||||
#endif /* __khrplatform_h_ */
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
chcp 65001
|
||||||
|
"E:\Qt\Tools\QtCreator\bin\jom\jom.exe" %*
|
|
@ -1,116 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
|
|
||||||
layout(local_size_x = 8, local_size_y = 8) in;
|
|
||||||
layout(rg16f, binding = 0) uniform image2D brdfLUT;
|
|
||||||
|
|
||||||
const float PI = 3.14159265359;
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
|
|
||||||
// efficient VanDerCorpus calculation.
|
|
||||||
float RadicalInverse_VdC(uint bits)
|
|
||||||
{
|
|
||||||
bits = (bits << 16u) | (bits >> 16u);
|
|
||||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
|
||||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
|
||||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
|
||||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
|
||||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
|
||||||
}
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
vec2 Hammersley(uint i, uint N)
|
|
||||||
{
|
|
||||||
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
|
|
||||||
}
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
|
|
||||||
{
|
|
||||||
float a = roughness*roughness;
|
|
||||||
|
|
||||||
float phi = 2.0 * PI * Xi.x;
|
|
||||||
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
|
|
||||||
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
|
|
||||||
|
|
||||||
// from spherical coordinates to cartesian coordinates - halfway vector
|
|
||||||
vec3 H;
|
|
||||||
H.x = cos(phi) * sinTheta;
|
|
||||||
H.y = sin(phi) * sinTheta;
|
|
||||||
H.z = cosTheta;
|
|
||||||
|
|
||||||
// from tangent-space H vector to world-space sample vector
|
|
||||||
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
|
||||||
vec3 tangent = normalize(cross(up, N));
|
|
||||||
vec3 bitangent = cross(N, tangent);
|
|
||||||
|
|
||||||
vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
|
||||||
return normalize(sampleVec);
|
|
||||||
}
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
float GeometrySchlickGGX(float NdotV, float roughness)
|
|
||||||
{
|
|
||||||
// note that we use a different k for IBL
|
|
||||||
float a = roughness;
|
|
||||||
float k = (a * a) / 2.0;
|
|
||||||
|
|
||||||
float nom = NdotV;
|
|
||||||
float denom = NdotV * (1.0 - k) + k;
|
|
||||||
|
|
||||||
return nom / denom;
|
|
||||||
}
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
|
||||||
{
|
|
||||||
float NdotV = max(dot(N, V), 0.0);
|
|
||||||
float NdotL = max(dot(N, L), 0.0);
|
|
||||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
|
||||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
|
||||||
|
|
||||||
return ggx1 * ggx2;
|
|
||||||
}
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
vec2 IntegrateBRDF(float NdotV, float roughness)
|
|
||||||
{
|
|
||||||
vec3 V;
|
|
||||||
V.x = sqrt(1.0 - NdotV*NdotV);
|
|
||||||
V.y = 0.0;
|
|
||||||
V.z = NdotV;
|
|
||||||
|
|
||||||
float A = 0.0;
|
|
||||||
float B = 0.0;
|
|
||||||
|
|
||||||
vec3 N = vec3(0.0, 0.0, 1.0);
|
|
||||||
|
|
||||||
const uint SAMPLE_COUNT = 1024u;
|
|
||||||
for(uint i = 0u; i < SAMPLE_COUNT; ++i)
|
|
||||||
{
|
|
||||||
// generates a sample vector that's biased towards the
|
|
||||||
// preferred alignment direction (importance sampling).
|
|
||||||
vec2 Xi = Hammersley(i, SAMPLE_COUNT);
|
|
||||||
vec3 H = ImportanceSampleGGX(Xi, N, roughness);
|
|
||||||
vec3 L = normalize(2.0 * dot(V, H) * H - V);
|
|
||||||
|
|
||||||
float NdotL = max(L.z, 0.0);
|
|
||||||
float NdotH = max(H.z, 0.0);
|
|
||||||
float VdotH = max(dot(V, H), 0.0);
|
|
||||||
|
|
||||||
if(NdotL > 0.0)
|
|
||||||
{
|
|
||||||
float G = GeometrySmith(N, V, L, roughness);
|
|
||||||
float G_Vis = (G * VdotH) / (NdotH * NdotV);
|
|
||||||
float Fc = pow(1.0 - VdotH, 5.0);
|
|
||||||
|
|
||||||
A += (1.0 - Fc) * G_Vis;
|
|
||||||
B += Fc * G_Vis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
A /= float(SAMPLE_COUNT);
|
|
||||||
B /= float(SAMPLE_COUNT);
|
|
||||||
return vec2(A, B);
|
|
||||||
}
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
uvec2 pixelLocation = gl_GlobalInvocationID.xy;
|
|
||||||
vec2 texCoords = (vec2(pixelLocation)+vec2(0.5))/vec2(imageSize(brdfLUT));
|
|
||||||
vec2 integratedBRDF = IntegrateBRDF(texCoords.x, texCoords.y);
|
|
||||||
imageStore(brdfLUT, ivec2(pixelLocation), vec4(integratedBRDF,0,0));
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
out vec4 FragColor;
|
|
||||||
in vec3 WorldPos;
|
|
||||||
|
|
||||||
uniform sampler2D equirectangularMap;
|
|
||||||
|
|
||||||
const vec2 invAtan = vec2(0.1591, 0.3183);
|
|
||||||
vec2 SampleSphericalMap(vec3 v)
|
|
||||||
{
|
|
||||||
vec2 uv = vec2(atan(v.z, v.x), asin(v.y));
|
|
||||||
uv *= invAtan;
|
|
||||||
uv += 0.5;
|
|
||||||
return uv;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
vec2 uv = SampleSphericalMap(normalize(WorldPos));
|
|
||||||
vec3 color = texture(equirectangularMap, uv).rgb;
|
|
||||||
|
|
||||||
FragColor = vec4(color, 1.0);
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
layout (location = 0) in vec3 aPos;
|
|
||||||
|
|
||||||
out vec3 WorldPos;
|
|
||||||
|
|
||||||
uniform mat4 projection;
|
|
||||||
uniform mat4 view;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
WorldPos = aPos;
|
|
||||||
gl_Position = projection * view * vec4(WorldPos, 1.0);
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
out vec4 FragColor;
|
|
||||||
in vec3 WorldPos;
|
|
||||||
|
|
||||||
uniform samplerCube environmentMap;
|
|
||||||
uniform float roughness;
|
|
||||||
|
|
||||||
const float PI = 3.14159265359;
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
float DistributionGGX(vec3 N, vec3 H, float roughness)
|
|
||||||
{
|
|
||||||
float a = roughness*roughness;
|
|
||||||
float a2 = a*a;
|
|
||||||
float NdotH = max(dot(N, H), 0.0);
|
|
||||||
float NdotH2 = NdotH*NdotH;
|
|
||||||
|
|
||||||
float nom = a2;
|
|
||||||
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
|
||||||
denom = PI * denom * denom;
|
|
||||||
|
|
||||||
return nom / denom;
|
|
||||||
}
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
|
|
||||||
// efficient VanDerCorpus calculation.
|
|
||||||
float RadicalInverse_VdC(uint bits)
|
|
||||||
{
|
|
||||||
bits = (bits << 16u) | (bits >> 16u);
|
|
||||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
|
||||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
|
||||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
|
||||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
|
||||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
|
||||||
}
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
vec2 Hammersley(uint i, uint N)
|
|
||||||
{
|
|
||||||
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
|
|
||||||
}
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
|
|
||||||
{
|
|
||||||
float a = roughness*roughness;
|
|
||||||
|
|
||||||
float phi = 2.0 * PI * Xi.x;
|
|
||||||
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
|
|
||||||
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
|
|
||||||
|
|
||||||
// from spherical coordinates to cartesian coordinates - halfway vector
|
|
||||||
vec3 H;
|
|
||||||
H.x = cos(phi) * sinTheta;
|
|
||||||
H.y = sin(phi) * sinTheta;
|
|
||||||
H.z = cosTheta;
|
|
||||||
|
|
||||||
// from tangent-space H vector to world-space sample vector
|
|
||||||
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
|
||||||
vec3 tangent = normalize(cross(up, N));
|
|
||||||
vec3 bitangent = cross(N, tangent);
|
|
||||||
|
|
||||||
vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
|
||||||
return normalize(sampleVec);
|
|
||||||
}
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
vec3 N = normalize(WorldPos);
|
|
||||||
|
|
||||||
// make the simplyfying assumption that V equals R equals the normal
|
|
||||||
vec3 R = N;
|
|
||||||
vec3 V = R;
|
|
||||||
|
|
||||||
const uint SAMPLE_COUNT = 1024u;
|
|
||||||
vec3 prefilteredColor = vec3(0.0);
|
|
||||||
float totalWeight = 0.0;
|
|
||||||
|
|
||||||
for(uint i = 0u; i < SAMPLE_COUNT; ++i)
|
|
||||||
{
|
|
||||||
// generates a sample vector that's biased towards the preferred alignment direction (importance sampling).
|
|
||||||
vec2 Xi = Hammersley(i, SAMPLE_COUNT);
|
|
||||||
vec3 H = ImportanceSampleGGX(Xi, N, roughness);
|
|
||||||
vec3 L = normalize(2.0 * dot(V, H) * H - V);
|
|
||||||
|
|
||||||
float NdotL = max(dot(N, L), 0.0);
|
|
||||||
if(NdotL > 0.0)
|
|
||||||
{
|
|
||||||
// sample from the environment's mip level based on roughness/pdf
|
|
||||||
float D = DistributionGGX(N, H, roughness);
|
|
||||||
float NdotH = max(dot(N, H), 0.0);
|
|
||||||
float HdotV = max(dot(H, V), 0.0);
|
|
||||||
float pdf = D * NdotH / (4.0 * HdotV) + 0.0001;
|
|
||||||
|
|
||||||
//float resolution = 512.0; // resolution of source cubemap (per face)
|
|
||||||
float resolution = float(textureSize(environmentMap,0).x); // resolution of source cubemap (per face)
|
|
||||||
float saTexel = 4.0 * PI / (6.0 * resolution * resolution);
|
|
||||||
float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001);
|
|
||||||
|
|
||||||
float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel);
|
|
||||||
|
|
||||||
prefilteredColor += textureLod(environmentMap, L, mipLevel).rgb * NdotL;
|
|
||||||
totalWeight += NdotL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prefilteredColor = prefilteredColor / totalWeight;
|
|
||||||
|
|
||||||
FragColor = vec4(prefilteredColor, 1.0);
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
|
|
||||||
out vec4 FragColor;
|
|
||||||
|
|
||||||
in vec2 TexCoords;
|
|
||||||
|
|
||||||
uniform sampler2D gBaseColor;
|
|
||||||
uniform float exposure = 1;
|
|
||||||
|
|
||||||
vec3 ACESToneMapping(vec3 color)
|
|
||||||
{
|
|
||||||
const float A = 2.51;
|
|
||||||
const float B = 0.03;
|
|
||||||
const float C = 2.43;
|
|
||||||
const float D = 0.59;
|
|
||||||
const float E = 0.14;
|
|
||||||
return (color * (A * color + B)) / (color * (C * color + D) + E);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
|
|
||||||
//FragColor = vec4(vec3(textureLod(gDepth, TexCoords, 1).x), 1.0);
|
|
||||||
//FragColor -= vec4(vec3(textureLod(gDepth, TexCoords, 0).x), 1.0);
|
|
||||||
//ivec2 depthCoords = ivec2(TexCoords*(textureSize(gDepth,0)-ivec2(1)) + vec2(0.5));
|
|
||||||
//float depth = texelFetch(gDepth, depthCoords/64, 6).x;
|
|
||||||
//depth -= texelFetch(gDepth, depthCoords, 0).x;
|
|
||||||
//FragColor = vec4(vec3(depth*10000),1);
|
|
||||||
//FragColor = vec4(vec3(textureSize(gShadowMap, 0)-vec3(1)),1);
|
|
||||||
//FragColor = vec4(texture(gRadiance, TexCoords).rgb, 1);
|
|
||||||
|
|
||||||
//vec3 albedo = pow(texture(gBaseColor, TexCoords).rgb, vec3(2.2));
|
|
||||||
//vec3 color = albedo * texture(gIndirectLight, TexCoords).rgb + texture(gDirectLight, TexCoords).rgb;
|
|
||||||
vec4 rgbm = texture(gBaseColor, TexCoords);
|
|
||||||
if(rgbm.a==0)
|
|
||||||
{
|
|
||||||
//FragColor = vec4(1,0,0,1);
|
|
||||||
//return;
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
vec3 color = 8 * rgbm.rgb * rgbm.a;
|
|
||||||
|
|
||||||
color *= exposure;
|
|
||||||
color = ACESToneMapping(color);
|
|
||||||
|
|
||||||
//color = color / (color + vec3(1.0));
|
|
||||||
color = pow(color, vec3(1.0/2.2));
|
|
||||||
FragColor = vec4(color, 1.0);
|
|
||||||
return;
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
out vec4 FragColor;
|
|
||||||
in vec3 WorldPos;
|
|
||||||
|
|
||||||
uniform samplerCube environmentMap;
|
|
||||||
|
|
||||||
const float PI = 3.14159265359;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
// The world vector acts as the normal of a tangent surface
|
|
||||||
// from the origin, aligned to WorldPos. Given this normal, calculate all
|
|
||||||
// incoming radiance of the environment. The result of this radiance
|
|
||||||
// is the radiance of light coming from -Normal direction, which is what
|
|
||||||
// we use in the PBR shader to sample irradiance.
|
|
||||||
vec3 N = normalize(WorldPos);
|
|
||||||
|
|
||||||
vec3 irradiance = vec3(0.0);
|
|
||||||
|
|
||||||
// tangent space calculation from origin point
|
|
||||||
vec3 up = vec3(0.0, 1.0, 0.0);
|
|
||||||
vec3 right = normalize(cross(up, N));
|
|
||||||
up = normalize(cross(N, right));
|
|
||||||
|
|
||||||
float sampleDelta = 0.025;
|
|
||||||
float nrSamples = 0.0;
|
|
||||||
for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta)
|
|
||||||
{
|
|
||||||
for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta)
|
|
||||||
{
|
|
||||||
// spherical to cartesian (in tangent space)
|
|
||||||
vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
|
|
||||||
// tangent space to world
|
|
||||||
vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N;
|
|
||||||
|
|
||||||
irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta);
|
|
||||||
nrSamples++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
irradiance = PI * irradiance * (1.0 / float(nrSamples));
|
|
||||||
|
|
||||||
FragColor = vec4(irradiance, 1.0);
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
#extension GL_ARB_sparse_texture2 : enable
|
|
||||||
|
|
||||||
uniform sampler2D texture_basecolor;
|
|
||||||
|
|
||||||
in vec2 TexCoords;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
vec4 baseColor;// = texture(texture_basecolor, TexCoords);
|
|
||||||
float lod = textureQueryLod(texture_basecolor, TexCoords).x;
|
|
||||||
while(!sparseTexelsResidentARB(sparseTextureLodARB(texture_basecolor, TexCoords, lod, baseColor))&&lod<textureQueryLevels(texture_basecolor))
|
|
||||||
lod++;
|
|
||||||
|
|
||||||
if(baseColor.a<0.4)
|
|
||||||
discard;
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
|
|
||||||
layout (local_size_x = 8, local_size_y = 8) in;
|
|
||||||
|
|
||||||
layout(rg16ui, binding = 3) uniform uimage2D gPageId;
|
|
||||||
|
|
||||||
layout(location = 0) uniform uvec2 dither = uvec2(0);
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
uvec2 targetLocation = gl_GlobalInvocationID.xy;
|
|
||||||
uvec2 sourceLocation = targetLocation * 8 + dither;
|
|
||||||
imageStore(gPageId, ivec2(targetLocation), uvec4(imageLoad(gPageId, ivec2(sourceLocation))));
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
#extension GL_ARB_sparse_texture2 : enable
|
|
||||||
|
|
||||||
uniform sampler2D texture_basecolor;
|
|
||||||
uniform sampler2D texture_metallic_roughness;
|
|
||||||
|
|
||||||
uniform uint paintingId;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 gBaseColor;
|
|
||||||
layout(location = 1) out vec3 gNormal;
|
|
||||||
layout(location = 2) out vec3 gPosition;
|
|
||||||
layout(location = 3) out vec2 gMetallicRoughness;
|
|
||||||
layout(location = 4) out uvec2 gPaintingIndex;
|
|
||||||
layout(location = 5) out vec2 gPaintingTexCoord;
|
|
||||||
|
|
||||||
in vec2 TexCoords;
|
|
||||||
in vec3 WorldPos;
|
|
||||||
in vec3 Normal;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
int lodExpect = int(textureQueryLod(texture_basecolor, TexCoords).x);
|
|
||||||
int levels = textureQueryLevels(texture_basecolor);
|
|
||||||
float lod = lodExpect;
|
|
||||||
while(!sparseTexelsResidentARB(sparseTextureLodARB(texture_basecolor, TexCoords, lod, gBaseColor))&&lod<levels)
|
|
||||||
lod++;
|
|
||||||
if(gBaseColor.a<0.4)
|
|
||||||
discard;
|
|
||||||
//gBaseColor = vec4( vec3(1),1 );
|
|
||||||
gPosition = WorldPos;
|
|
||||||
gNormal = normalize(Normal);
|
|
||||||
//gMetallicRoughness = vec2(0,1);
|
|
||||||
lod = lodExpect;
|
|
||||||
vec4 mt;
|
|
||||||
while(!sparseTexelsResidentARB(sparseTextureLodARB(texture_metallic_roughness, TexCoords, lod, mt))&&lod<levels)
|
|
||||||
lod++;
|
|
||||||
gMetallicRoughness = mt.rg;
|
|
||||||
|
|
||||||
// int pageSize = textureSize(texture_basecolor, levels-1).x;
|
|
||||||
|
|
||||||
// uint pageId = 0;
|
|
||||||
// for(uint i = 0; i < lodExpect; i++)
|
|
||||||
// pageId += 1<<(2*(levels-1-i));
|
|
||||||
uint w = 1<<(levels-1-lodExpect);
|
|
||||||
ivec2 page = ivec2(TexCoords * vec2(w));
|
|
||||||
page = clamp(page, ivec2(0), ivec2(w-1));
|
|
||||||
// pageId += page.y*w+page.x;
|
|
||||||
if(lodExpect==levels-1)
|
|
||||||
gPaintingIndex = uvec2(0);
|
|
||||||
else
|
|
||||||
gPaintingIndex = uvec2((paintingId<<4)+lodExpect, (page.y<<8)+page.x);
|
|
||||||
gPaintingTexCoord = vec2(1., 1.) - TexCoords * 2;
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
|
|
||||||
layout (location = 0) out vec4 gBaseColor;
|
|
||||||
layout (location = 1) out vec3 gNormal;
|
|
||||||
layout (location = 2) out vec3 gPosition;
|
|
||||||
layout (location = 3) out vec2 gMetallicRoughness;
|
|
||||||
layout (location = 4) out uint gPaintingIndex;
|
|
||||||
|
|
||||||
in vec2 TexCoords;
|
|
||||||
in vec3 WorldPos;
|
|
||||||
in vec3 Normal;
|
|
||||||
|
|
||||||
// material parameters
|
|
||||||
uniform vec3 albedo;
|
|
||||||
uniform float metallic;
|
|
||||||
uniform float roughness;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
gBaseColor = vec4(albedo, 1);
|
|
||||||
gPosition = WorldPos;
|
|
||||||
gNormal = normalize(Normal);
|
|
||||||
gMetallicRoughness = vec2(metallic,roughness);
|
|
||||||
gPaintingIndex = 0;
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
out vec4 FragColor;
|
|
||||||
in vec3 WorldPos;
|
|
||||||
|
|
||||||
uniform samplerCube environmentMap;
|
|
||||||
uniform float exposure = 1;
|
|
||||||
|
|
||||||
vec3 ACESToneMapping(vec3 color)
|
|
||||||
{
|
|
||||||
const float A = 2.51;
|
|
||||||
const float B = 0.03;
|
|
||||||
const float C = 2.43;
|
|
||||||
const float D = 0.59;
|
|
||||||
const float E = 0.14;
|
|
||||||
return (color * (A * color + B)) / (color * (C * color + D) + E);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
vec3 color = texture(environmentMap, WorldPos).rgb;
|
|
||||||
|
|
||||||
// HDR tonemap
|
|
||||||
//envColor = envColor / (envColor + vec3(1.0));
|
|
||||||
|
|
||||||
color *= exposure;
|
|
||||||
color = ACESToneMapping(color);
|
|
||||||
|
|
||||||
// gamma correct
|
|
||||||
color = pow(color, vec3(1.0/2.2));
|
|
||||||
|
|
||||||
FragColor = vec4(color, 1.0);
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
layout (location = 0) in vec3 aPos;
|
|
||||||
|
|
||||||
uniform mat4 projection;
|
|
||||||
uniform mat4 view;
|
|
||||||
|
|
||||||
out vec3 WorldPos;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
WorldPos = aPos;
|
|
||||||
|
|
||||||
mat4 rotView = mat4(mat3(view));
|
|
||||||
vec4 clipPos = projection * rotView * vec4(WorldPos, 1.0);
|
|
||||||
|
|
||||||
gl_Position = clipPos.xyww;
|
|
||||||
}
|
|
|
@ -1,48 +1,56 @@
|
||||||
#include "EditorWidget.h"
|
#include "EditorWidget.h"
|
||||||
#include "EditorWidgetItem.h"
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <QInputDialog>
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QFileDialog>
|
|
||||||
|
|
||||||
EditorWidget::EditorWidget(QWidget *parent) : QWidget(parent)
|
EditorWidget::EditorWidget(QWidget *parent) : QWidget(parent)
|
||||||
{
|
{
|
||||||
|
displayLayer = nullptr;
|
||||||
|
displayElement = nullptr;
|
||||||
ui.setupUi(this);
|
ui.setupUi(this);
|
||||||
this->createButton = ui.createButton;
|
previewWindow = ui.Preview;
|
||||||
this->closeButton = ui.closeButton;
|
treeWidget = ui.LayerTree;
|
||||||
this->saveButton = ui.saveButton;
|
tabWidget = ui.DisplayTab;
|
||||||
this->saveAsButton = ui.saveAsButton;
|
layerInfoDisplayWidget = dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(0));
|
||||||
this->openButton = ui.openButton;
|
elementInfoDisplayWidget = dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(1));
|
||||||
this->tabWidget = ui.tabWidget;
|
connect(treeWidget, &LayerTreeWidget::displayLayerChange, this, &EditorWidget::onLayerChange);
|
||||||
while (this->tabWidget->count() > 0)
|
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshPreview, this,
|
||||||
|
&EditorWidget::triggerRefreshPreview);
|
||||||
|
// &EditorWidget::triggerRefreshPreview);
|
||||||
|
// test
|
||||||
|
QFile settingFile;
|
||||||
|
settingFile.setFileName("../data.json");
|
||||||
|
settingFile.open(QFile::ReadOnly);
|
||||||
|
QByteArray setting = settingFile.readAll().trimmed();
|
||||||
|
QJsonParseError jError;
|
||||||
|
QJsonDocument jsonDoc(QJsonDocument::fromJson(setting, &jError));
|
||||||
|
qDebug() << jsonDoc.object().value("height").toDouble();
|
||||||
|
qDebug() << jError.errorString();
|
||||||
|
// end test
|
||||||
|
QJsonObject source = jsonDoc.object();
|
||||||
|
elementManager = new ElementManager(source);
|
||||||
|
layerManager = new LayerManager(source, elementManager);
|
||||||
|
previewWindow->initialize(layerManager);
|
||||||
|
if (layerManager->getRoot() != nullptr)
|
||||||
{
|
{
|
||||||
this->tabWidget->removeTab(0);
|
treeWidget->addTopLevelItem(layerManager->getRoot()->qTreeItem);
|
||||||
}
|
}
|
||||||
connect(this->createButton, &QPushButton::clicked, this, [this]() {
|
|
||||||
static int count = 0;
|
|
||||||
this->tabWidget->addTab(new EditorWidgetItem("../data.json",this), "untitled" + QString::number(count++));
|
|
||||||
});
|
|
||||||
connect(this->openButton, &QPushButton::clicked, this, [this]() {
|
|
||||||
QString fileName = QFileDialog::getOpenFileName(this->saveAsButton, QString::fromLocal8Bit("´ò¿ª"), "", QString::fromLocal8Bit("JSONÎļþ(*.json)"));
|
|
||||||
this->tabWidget->addTab(new EditorWidgetItem(fileName, this), fileName);
|
|
||||||
});
|
|
||||||
connect(this->closeButton, &QPushButton::clicked, this, [this]() {
|
|
||||||
this->tabWidget->removeTab(this->tabWidget->currentIndex());
|
|
||||||
});
|
|
||||||
connect(this->saveButton, &QPushButton::clicked, this, [this]() {
|
|
||||||
EditorWidgetItem* item = dynamic_cast<EditorWidgetItem*>(this->tabWidget->currentWidget());
|
|
||||||
if (item != nullptr)
|
|
||||||
{
|
|
||||||
//item->save();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(this->saveAsButton, &QPushButton::clicked, this, [this]() {
|
|
||||||
EditorWidgetItem* item = dynamic_cast<EditorWidgetItem*>(this->tabWidget->currentWidget());
|
|
||||||
if (item != nullptr)
|
|
||||||
{
|
|
||||||
QString fileName = QFileDialog::getSaveFileName(this->saveAsButton, QString::fromLocal8Bit("Áí´æΪ"), "", QString::fromLocal8Bit("JSONÎļþ(*.json)"));
|
|
||||||
item->saveAs(fileName);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EditorWidget::~EditorWidget()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorWidget::paintEvent(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorWidget::onLayerChange(LayerWrapper *layer)
|
||||||
|
{
|
||||||
|
displayLayer = layer;
|
||||||
|
// TODO : notify InfoDisplayWidget and update
|
||||||
|
dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(0))->setLayer(layer);
|
||||||
|
this->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorWidget::triggerRefreshPreview()
|
||||||
|
{
|
||||||
|
previewWindow->update();
|
||||||
|
}
|
||||||
|
|
|
@ -1,23 +1,38 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <qwidget.h>
|
|
||||||
#include "ui_EditorWidget.h"
|
|
||||||
|
|
||||||
class EditorWidget :
|
#include "ElementManager.h"
|
||||||
public QWidget
|
#include "InfoDisplayWidget.h"
|
||||||
|
#include "LayerManager.h"
|
||||||
|
#include "LayerTreeWidget.h"
|
||||||
|
#include "PreviewWindow.h"
|
||||||
|
#include "ui_EditorWidget.h"
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QTreeWidget>
|
||||||
|
#include <QWidget>
|
||||||
|
class EditorWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::EditorWidget ui;
|
// DATA PART
|
||||||
|
PreviewWindow *previewWindow;
|
||||||
|
ElementManager *elementManager;
|
||||||
|
LayerManager *layerManager;
|
||||||
|
// QT GUI PART
|
||||||
|
Ui::EditorWidgetClass ui;
|
||||||
|
LayerTreeWidget *treeWidget;
|
||||||
QTabWidget *tabWidget;
|
QTabWidget *tabWidget;
|
||||||
QPushButton* createButton;
|
InfoDisplayWidget *layerInfoDisplayWidget, *elementInfoDisplayWidget;
|
||||||
QPushButton* closeButton;
|
// QT DATA PART
|
||||||
QPushButton* saveButton;
|
LayerWrapper *displayLayer;
|
||||||
QPushButton* saveAsButton;
|
GraphicElement *displayElement;
|
||||||
QPushButton* openButton;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EditorWidget(QWidget *parent = nullptr);
|
EditorWidget(QWidget *parent = nullptr);
|
||||||
~EditorWidget()=default;
|
~EditorWidget();
|
||||||
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onLayerChange(LayerWrapper *layer);
|
||||||
|
void triggerRefreshPreview();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
#include "EditorWidgetItem.h"
|
|
||||||
|
|
||||||
EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(parent)
|
|
||||||
{
|
|
||||||
QImage x;
|
|
||||||
displayLayer = nullptr;
|
|
||||||
displayElement = nullptr;
|
|
||||||
ui.setupUi(this);
|
|
||||||
previewWindow = ui.Preview;
|
|
||||||
treeWidget = ui.LayerTree;
|
|
||||||
tabWidget = ui.DisplayTab;
|
|
||||||
this->filePath = filePath;
|
|
||||||
layerInfoDisplayWidget = dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(0));
|
|
||||||
elementInfoDisplayWidget = dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(1));
|
|
||||||
connect(treeWidget, &LayerTreeWidget::displayLayerChange, this, &EditorWidgetItem::onLayerChange);
|
|
||||||
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshPreview, this,
|
|
||||||
&EditorWidgetItem::triggerRefreshPreview);
|
|
||||||
connect(treeWidget, &LayerTreeWidget::requireRefreshPreview, this,
|
|
||||||
&EditorWidgetItem::triggerRefreshPreview);
|
|
||||||
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireSelfRefresh, layerInfoDisplayWidget, &InfoDisplayWidget::triggerSelfRefresh);
|
|
||||||
// &EditorWidget::triggerRefreshPreview);
|
|
||||||
// test
|
|
||||||
QFile settingFile;
|
|
||||||
//settingFile.setFileName("../data.json");
|
|
||||||
settingFile.setFileName(filePath);
|
|
||||||
settingFile.open(QFile::ReadOnly);
|
|
||||||
QByteArray setting = settingFile.readAll().trimmed();
|
|
||||||
QJsonParseError jError;
|
|
||||||
QJsonDocument jsonDoc(QJsonDocument::fromJson(setting, &jError));
|
|
||||||
qDebug() << jsonDoc.object().value("height").toDouble();
|
|
||||||
qDebug() << jError.errorString();
|
|
||||||
// end test
|
|
||||||
QJsonObject source = jsonDoc.object();
|
|
||||||
elementManager = new ElementManager(source,previewWindow->getRenderer());
|
|
||||||
layerManager = new LayerManager(source, elementManager);
|
|
||||||
qDebug() << layerManager->toJson();
|
|
||||||
previewWindow->initialize(layerManager,QSize(jsonDoc.object().value("width").toDouble(),jsonDoc.object().value("height").toDouble()));
|
|
||||||
if (layerManager->getRoot() != nullptr)
|
|
||||||
{
|
|
||||||
treeWidget->root = layerManager->getRoot();
|
|
||||||
treeWidget->refresh();
|
|
||||||
treeWidget->addTopLevelItem(treeWidget->root->getQTreeItem());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorWidgetItem::~EditorWidgetItem()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorWidgetItem::paintEvent(QPaintEvent *event)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorWidgetItem::onLayerChange(LayerWrapper *layer)
|
|
||||||
{
|
|
||||||
displayLayer = layer;
|
|
||||||
// TODO : notify InfoDisplayWidget and update
|
|
||||||
dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(0))->setLayer(layer);
|
|
||||||
this->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorWidgetItem::triggerRefreshPreview()
|
|
||||||
{
|
|
||||||
previewWindow->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorWidgetItem::save() const
|
|
||||||
{
|
|
||||||
saveImpl(this->filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorWidgetItem::saveAs(QString filePath) const
|
|
||||||
{
|
|
||||||
saveImpl(filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorWidgetItem::saveImpl(QString filePath) const
|
|
||||||
{
|
|
||||||
QJsonObject source1 = layerManager->toJson();
|
|
||||||
QJsonObject source2 = elementManager->toJson();
|
|
||||||
QJsonObject json;
|
|
||||||
json.insert("width", 1080);
|
|
||||||
json.insert("height", 1080);
|
|
||||||
json.insert("root-layer", source1.value("root-layer"));
|
|
||||||
json.insert("elements", source2.value("elements"));
|
|
||||||
QJsonDocument doc(json);
|
|
||||||
QFile file(filePath);
|
|
||||||
file.open(QIODevice::WriteOnly);
|
|
||||||
file.write(doc.toJson());
|
|
||||||
file.close();
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "ElementManager.h"
|
|
||||||
#include "InfoDisplayWidget.h"
|
|
||||||
#include "LayerManager.h"
|
|
||||||
#include "LayerTreeWidget.h"
|
|
||||||
#include "PreviewWindow.h"
|
|
||||||
#include "ui_EditorWidgetItem.h"
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QTreeWidget>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class EditorWidgetItem : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
private:
|
|
||||||
// DATA PART
|
|
||||||
PreviewWindow *previewWindow;
|
|
||||||
ElementManager *elementManager;
|
|
||||||
LayerManager *layerManager;
|
|
||||||
// QT GUI PART
|
|
||||||
Ui::EditorWidgetItem ui;
|
|
||||||
LayerTreeWidget *treeWidget;
|
|
||||||
QTabWidget *tabWidget;
|
|
||||||
InfoDisplayWidget *layerInfoDisplayWidget, *elementInfoDisplayWidget;
|
|
||||||
// QT DATA PART
|
|
||||||
LayerWrapper *displayLayer;
|
|
||||||
GraphicElement *displayElement;
|
|
||||||
QString filePath;
|
|
||||||
void saveImpl(QString filePath)const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
EditorWidgetItem(QString filePath, QWidget *parent = nullptr);
|
|
||||||
~EditorWidgetItem();
|
|
||||||
void paintEvent(QPaintEvent *event) override;
|
|
||||||
void save() const;
|
|
||||||
void saveAs(QString filePath)const;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onLayerChange(LayerWrapper *layer);
|
|
||||||
void triggerRefreshPreview();
|
|
||||||
};
|
|
|
@ -1,20 +1,15 @@
|
||||||
#include "ElementManager.h"
|
#include "ElementManager.h"
|
||||||
ElementManager::ElementManager(QJsonObject source,Renderer::ElementRenderer* renderer)
|
ElementManager::ElementManager(QJsonObject source)
|
||||||
{
|
{
|
||||||
auto elementsJson = source.value("elements").toArray();
|
auto elementsJson = source.value("elements").toArray();
|
||||||
qDebug() << elementsJson.size();
|
qDebug() << elementsJson.size();
|
||||||
int index = 0;
|
|
||||||
for (auto elementJson : elementsJson)
|
for (auto elementJson : elementsJson)
|
||||||
{
|
{
|
||||||
if (elementJson.toObject().value("type").toString() == "group")
|
if (elementJson.toObject().value("type").toString() == "group")
|
||||||
elements.push_back(new GroupElement());
|
elements.push_back(new GroupElement());
|
||||||
else
|
else
|
||||||
elements.push_back(new SimpleElement(elementJson.toObject()));
|
elements.push_back(new SimpleElement(elementJson.toObject()));
|
||||||
|
|
||||||
(*elements.rbegin())->renderer = renderer;
|
|
||||||
}
|
}
|
||||||
for (auto element : elements)
|
|
||||||
element->index = index++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElementManager::addElement(GraphicElement *element)
|
void ElementManager::addElement(GraphicElement *element)
|
||||||
|
@ -36,13 +31,3 @@ GraphicElement *ElementManager::getElementById(int index)
|
||||||
ElementManager::~ElementManager()
|
ElementManager::~ElementManager()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject ElementManager::toJson() const
|
|
||||||
{
|
|
||||||
QJsonArray elementsJson;
|
|
||||||
for (auto element : elements)
|
|
||||||
elementsJson.push_back(element->toJson());
|
|
||||||
QJsonObject result;
|
|
||||||
result.insert("elements", elementsJson);
|
|
||||||
return result;
|
|
||||||
}
|
|
|
@ -2,12 +2,10 @@
|
||||||
#include "GraphicElement.h"
|
#include "GraphicElement.h"
|
||||||
#include "LayerManager.h"
|
#include "LayerManager.h"
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include "../Renderer/Preview/ElementRenderer.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
using std::vector;
|
using std::vector;
|
||||||
class LayerManager;
|
class LayerManager;
|
||||||
class GraphicElement;
|
class GraphicElement;
|
||||||
class Renderer::ElementRenderer;
|
|
||||||
|
|
||||||
class ElementManager
|
class ElementManager
|
||||||
{
|
{
|
||||||
|
@ -15,11 +13,10 @@ class ElementManager
|
||||||
vector<GraphicElement *> elements;
|
vector<GraphicElement *> elements;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ElementManager(QJsonObject source,Renderer::ElementRenderer *renderer);
|
ElementManager(QJsonObject source);
|
||||||
~ElementManager();
|
~ElementManager();
|
||||||
void addElement(GraphicElement *element);
|
void addElement(GraphicElement *element);
|
||||||
void removeElement(GraphicElement *pElement);
|
void removeElement(GraphicElement *pElement);
|
||||||
QJsonObject toJson()const;
|
|
||||||
/**
|
/**
|
||||||
* only used in initialization
|
* only used in initialization
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
#include "GraphicElement.h"
|
#include "GraphicElement.h"
|
||||||
#include "util/SvgFileLoader.h"
|
#include "third-party modules/util/SvgFileLoader.h"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
QPainterPath SimpleElement::getPaintObject() const
|
||||||
PixelPath SimpleElement::getPaintObject() const
|
|
||||||
{
|
{
|
||||||
PixelPath result;
|
return painterPath;
|
||||||
result.addPath(painterPath);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleElement::loadSvgFile(const QString& filePath)
|
void SimpleElement::loadSvgFile(const QString& filePath)
|
||||||
|
@ -20,8 +17,8 @@ void SimpleElement::loadSvgFile(const QString& filePath)
|
||||||
SimpleElement::SimpleElement(QJsonObject jsonSource) : jsonSource(jsonSource)
|
SimpleElement::SimpleElement(QJsonObject jsonSource) : jsonSource(jsonSource)
|
||||||
{
|
{
|
||||||
painterPath.clear();
|
painterPath.clear();
|
||||||
//loadSvgFile("D:\\Projects\\BigC\\svg\\3.svg");
|
loadSvgFile("D:\\Projects\\BigC\\svg\\3.svg");
|
||||||
loadSvgFile("../"/*TODO: 改成json文件所在文件夹路径*/ + jsonSource.value("data").toObject().value("include").toString());
|
//loadSvgFile(jsonSource.value("data").toObject().value("include").toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupElement::GroupElement(FolderLayerWrapper *sourceLayer)
|
GroupElement::GroupElement(FolderLayerWrapper *sourceLayer)
|
||||||
|
@ -32,54 +29,12 @@ void GroupElement::setSourceLayer(FolderLayerWrapper* sourceLayer)
|
||||||
{
|
{
|
||||||
this->sourceLayer = sourceLayer;
|
this->sourceLayer = sourceLayer;
|
||||||
}
|
}
|
||||||
PixelPath GroupElement::getPaintObject() const
|
QPainterPath GroupElement::getPaintObject() const
|
||||||
{
|
{
|
||||||
if (sourceLayer != nullptr) {
|
if (sourceLayer != nullptr) {
|
||||||
sourceLayer->refresh();
|
sourceLayer->refresh();
|
||||||
return sourceLayer->getCache();
|
return sourceLayer->getCache();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return PixelPath();
|
return QPainterPath();
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: apply styles and send back
|
|
||||||
PixelPath SimpleElement::getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo> styles) const {
|
|
||||||
PixelPath result;
|
|
||||||
Renderer::ElementStyleStrokeDemo demo(2);
|
|
||||||
auto [img, mov] = renderer->drawElement(painterPath, demo, 1.0, false);
|
|
||||||
//qDebug() << img << " ------";
|
|
||||||
result.addImage(img, mov);
|
|
||||||
//result.addPath(painterPath);
|
|
||||||
// QImage img(80,80,QImage::Format_ARGB32);
|
|
||||||
// QPainter pt(&img);
|
|
||||||
//pt.setPen(QPen(Qt::red, 2));
|
|
||||||
//pt.drawLine(0, 0, 80, 80);
|
|
||||||
//pt.end();
|
|
||||||
//result.addImage(img, QPoint(0, 0));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
PixelPath GroupElement::getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo> styles) const {
|
|
||||||
return getPaintObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
//BitmapPath::BitmapPath() {
|
|
||||||
// pathCount = 0u;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//void BitmapPath::initialize(vector<QPainterPath>& paths) {
|
|
||||||
// cache.clear();
|
|
||||||
// rawPath.clear();
|
|
||||||
// pathCount = 1u;
|
|
||||||
// bound
|
|
||||||
// for (auto& path : paths) {
|
|
||||||
// rawPath.addPath(path);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//TODO : 添加细节
|
|
||||||
QJsonObject GraphicElement::toJson() const
|
|
||||||
{
|
|
||||||
QJsonObject result;
|
|
||||||
result.insert("name", name);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
|
@ -1,49 +1,31 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "LayerWrapper.h"
|
#include "LayerWrapper.h"
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QPainterPath>
|
#include <QPainterPath>
|
||||||
#include <QImage>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "../Renderer/Preview/ElementRenderer.h"
|
|
||||||
#include "../Renderer/Painting/ElementStyle.h"
|
|
||||||
#include "PixelPath.h"
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
class LayerWrapper;
|
class LayerWrapper;
|
||||||
class LeafLayerWrapper;
|
class LeafLayerWrapper;
|
||||||
class FolderLayerWrapper;
|
class FolderLayerWrapper;
|
||||||
class ComposedPainterPath;
|
|
||||||
|
|
||||||
class GraphicElement
|
class GraphicElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Renderer::ElementRenderer *renderer;
|
|
||||||
QString name="";
|
QString name="";
|
||||||
int index;
|
virtual QPainterPath getPaintObject() const = 0;
|
||||||
// TODO: ¸ÄΪBitmapPath
|
|
||||||
virtual QJsonObject toJson() const;
|
|
||||||
virtual PixelPath getPaintObject() const = 0;
|
|
||||||
virtual PixelPath getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo>) const = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SimpleElement : public GraphicElement
|
class SimpleElement : public GraphicElement
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
QJsonObject jsonSource;
|
QJsonObject jsonSource;
|
||||||
// TODO: ¸ÄΪComposedPainterPath
|
|
||||||
QPainterPath painterPath;
|
QPainterPath painterPath;
|
||||||
void loadSvgFile(const QString& filePath);
|
void loadSvgFile(const QString& filePath);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SimpleElement(QJsonObject jsonSource);
|
SimpleElement(QJsonObject jsonSource);
|
||||||
~SimpleElement() = default;
|
~SimpleElement() = default;
|
||||||
PixelPath getPaintObject() const override;
|
QPainterPath getPaintObject() const override;
|
||||||
PixelPath getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo>) const override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GroupElement : public GraphicElement
|
class GroupElement : public GraphicElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -53,31 +35,6 @@ public:
|
||||||
GroupElement() = default;
|
GroupElement() = default;
|
||||||
GroupElement(FolderLayerWrapper *mSourceLayer);
|
GroupElement(FolderLayerWrapper *mSourceLayer);
|
||||||
~GroupElement() = default;
|
~GroupElement() = default;
|
||||||
PixelPath getPaintObject() const override;
|
QPainterPath getPaintObject() const override;
|
||||||
PixelPath getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo>) const override;
|
|
||||||
void setSourceLayer(FolderLayerWrapper *sourceLayer);
|
void setSourceLayer(FolderLayerWrapper *sourceLayer);
|
||||||
};
|
};
|
||||||
|
|
||||||
//******************************** BitmapPath ********************************//
|
|
||||||
|
|
||||||
//using std::vector;
|
|
||||||
//using std::shared_ptr;
|
|
||||||
//
|
|
||||||
//class BitmapPath
|
|
||||||
//{
|
|
||||||
//private:
|
|
||||||
// QRectF *boundingRect;
|
|
||||||
// QPainterPath cache;
|
|
||||||
// QPainterPath rawPath;
|
|
||||||
// size_t pathCount;
|
|
||||||
//
|
|
||||||
//public:
|
|
||||||
// BitmapPath();
|
|
||||||
// void initialize(std::vector<QPainterPath>& paths);
|
|
||||||
// void styles(Renderer::ElementStyle* style);
|
|
||||||
// void trans(QTransform& transform);
|
|
||||||
// QPainterPath getPainterPath() const;
|
|
||||||
// void addBitmapPath(BitmapPath& path);
|
|
||||||
// QRectF boundingRect()const;
|
|
||||||
// void clear();
|
|
||||||
//};
|
|
||||||
|
|
|
@ -11,10 +11,9 @@ LayerWrapper *LayerManager::getRoot() const
|
||||||
{
|
{
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
void LayerManager::paint(QPainter *painter, QSize size) const
|
void LayerManager::paint(QPainter *painter) const
|
||||||
{
|
{
|
||||||
auto p = root->getCache().resizedPixel(size);
|
painter->drawPath(root->getCache());
|
||||||
painter->drawPixmap(0, 0, p);
|
|
||||||
}
|
}
|
||||||
bool LayerManager::singleSelectedCheck() const
|
bool LayerManager::singleSelectedCheck() const
|
||||||
{
|
{
|
||||||
|
@ -48,7 +47,7 @@ bool LayerManager::combine() const
|
||||||
if (layer->getParent() != prevCommonFather)
|
if (layer->getParent() != prevCommonFather)
|
||||||
return false;
|
return false;
|
||||||
auto newCommonFather = new FolderLayerWrapper();
|
auto newCommonFather = new FolderLayerWrapper();
|
||||||
newCommonFather->setParent(static_cast<FolderLayerWrapper*>(prevCommonFather));
|
newCommonFather->setParent(prevCommonFather);
|
||||||
for (auto &layer : selectedLayers)
|
for (auto &layer : selectedLayers)
|
||||||
layer->setParent(newCommonFather);
|
layer->setParent(newCommonFather);
|
||||||
return true;
|
return true;
|
||||||
|
@ -62,20 +61,11 @@ bool LayerManager::changeParent(FolderLayerWrapper *newParent) const
|
||||||
selectedLayers[0]->setParent(newParent);
|
selectedLayers[0]->setParent(newParent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerManager::addLayer(LayerWrapper *layer)
|
void LayerManager::addLayer(LayerWrapper *layer)
|
||||||
{
|
{
|
||||||
layerSet.insert(layer);
|
layerSet.insert(layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerManager::removeLayer(LayerWrapper *layer)
|
void LayerManager::removeLayer(LayerWrapper *layer)
|
||||||
{
|
{
|
||||||
layerSet.erase(layer);
|
layerSet.erase(layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject LayerManager::toJson() const
|
|
||||||
{
|
|
||||||
QJsonObject result;
|
|
||||||
result.insert("root-layer", root->toJson());
|
|
||||||
return result;
|
|
||||||
}
|
|
|
@ -31,8 +31,7 @@ class LayerManager
|
||||||
LayerWrapper *getRoot() const;
|
LayerWrapper *getRoot() const;
|
||||||
LayerManager() = default;
|
LayerManager() = default;
|
||||||
LayerManager(QJsonObject source, ElementManager *elementManager);
|
LayerManager(QJsonObject source, ElementManager *elementManager);
|
||||||
QJsonObject toJson() const;
|
void paint(QPainter *painter) const;
|
||||||
void paint(QPainter *painter, QSize size) const;
|
|
||||||
bool rename(QString newName) const;
|
bool rename(QString newName) const;
|
||||||
bool combine() const;
|
bool combine() const;
|
||||||
// bool seperate() const;
|
// bool seperate() const;
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
#include "LayerStyle.h"
|
|
||||||
|
|
||||||
std::vector<Renderer::BaseStyle> StrokeElementStyle::toBaseStyles() const
|
|
||||||
{
|
|
||||||
return std::vector<Renderer::BaseStyle>();
|
|
||||||
}
|
|
|
@ -1,24 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../Renderer/Painting/ElementStyle.h"
|
|
||||||
#include "../Renderer/Painting/MaterialStyleStroke.h"
|
|
||||||
|
|
||||||
class LayerStyle
|
class LayerStyle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void apply() = 0;
|
virtual void apply() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EditorStrokeMaterialStyle
|
|
||||||
{
|
|
||||||
float applyWidth;
|
|
||||||
Renderer::StrokeType strokeType;
|
|
||||||
Renderer::StrokeEndType endType;
|
|
||||||
std::shared_ptr<Renderer::MaterialStroke> materialStroke;
|
|
||||||
};
|
|
||||||
|
|
||||||
class StrokeElementStyle : Renderer::ElementStyle
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override;
|
|
||||||
std::vector<EditorStrokeMaterialStyle> materialStyles;
|
|
||||||
};
|
|
|
@ -1,11 +1,11 @@
|
||||||
#include "LayerWrapper.h"
|
#include "LayerWrapper.h"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
void FolderLayerWrapper::addChild(shared_ptr<LayerWrapper> child)
|
void FolderLayerWrapper::addChild(LayerWrapper *child)
|
||||||
{
|
{
|
||||||
for (auto &chi : children)
|
for (auto &chi : children)
|
||||||
if (chi == child)
|
if (chi.get() == child)
|
||||||
return;
|
return;
|
||||||
children.push_back(child);
|
children.push_back(shared_ptr<LayerWrapper>(child));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderLayerWrapper::removeChild(LayerWrapper *child)
|
void FolderLayerWrapper::removeChild(LayerWrapper *child)
|
||||||
|
@ -18,21 +18,20 @@ void FolderLayerWrapper::removeChild(LayerWrapper *child)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FolderLayerWrapper*LayerWrapper::getParent() const
|
LayerWrapper *LayerWrapper::getParent() const
|
||||||
{
|
{
|
||||||
return this == nullptr ? nullptr : this->parent;
|
return this == nullptr ? nullptr : this->parent.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
PixelPath LayerWrapper::getCache()
|
QPainterPath LayerWrapper::getCache()
|
||||||
{
|
{
|
||||||
this->refresh();
|
this->refresh();
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: undone
|
// TODO: undone
|
||||||
LayerWrapper::LayerWrapper(QJsonObject json, FolderLayerWrapper*parent)
|
LayerWrapper::LayerWrapper(QJsonObject json, LayerWrapper *parent)
|
||||||
{
|
{
|
||||||
this->parent = parent;
|
this->parent = shared_ptr<LayerWrapper>(parent);
|
||||||
auto transformJson = json.value("transform").toObject();
|
auto transformJson = json.value("transform").toObject();
|
||||||
property.name = json.value("name").toString();
|
property.name = json.value("name").toString();
|
||||||
property.offset = {transformJson.value("offset").toObject().value("x").toDouble(),
|
property.offset = {transformJson.value("offset").toObject().value("x").toDouble(),
|
||||||
|
@ -40,9 +39,14 @@ LayerWrapper::LayerWrapper(QJsonObject json, FolderLayerWrapper*parent)
|
||||||
property.scale = {transformJson.value("scale").toObject().value("x").toDouble(),
|
property.scale = {transformJson.value("scale").toObject().value("x").toDouble(),
|
||||||
transformJson.value("scale").toObject().value("y").toDouble()};
|
transformJson.value("scale").toObject().value("y").toDouble()};
|
||||||
property.rotation = {transformJson.value("rotation").toDouble()};
|
property.rotation = {transformJson.value("rotation").toDouble()};
|
||||||
|
qTreeItem = new QTreeWidgetItem();
|
||||||
|
qTreeItem->setText(0, property.name);
|
||||||
|
if (parent != nullptr)
|
||||||
|
parent->qTreeItem->addChild(qTreeItem);
|
||||||
|
qTreeItem->setData(0, Qt::UserRole, QVariant::fromValue(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
FolderLayerWrapper::FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent)
|
FolderLayerWrapper::FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, LayerWrapper *parent)
|
||||||
: LayerWrapper(json, parent)
|
: LayerWrapper(json, parent)
|
||||||
{
|
{
|
||||||
qDebug() << json.value("name").toString() << " " << this;
|
qDebug() << json.value("name").toString() << " " << this;
|
||||||
|
@ -53,7 +57,6 @@ FolderLayerWrapper::FolderLayerWrapper(QJsonObject json, ElementManager *element
|
||||||
auto p = reinterpret_cast<GroupElement *>(elementManager->getElementById(referencedJson.toInt()));
|
auto p = reinterpret_cast<GroupElement *>(elementManager->getElementById(referencedJson.toInt()));
|
||||||
if (p != nullptr)
|
if (p != nullptr)
|
||||||
p->setSourceLayer(this);
|
p->setSourceLayer(this);
|
||||||
this->referencedBy = referencedJson.toInt();
|
|
||||||
}
|
}
|
||||||
for (auto childJson : childrenJson)
|
for (auto childJson : childrenJson)
|
||||||
{
|
{
|
||||||
|
@ -66,26 +69,26 @@ FolderLayerWrapper::FolderLayerWrapper(QJsonObject json, ElementManager *element
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LeafLayerWrapper::LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent)
|
LeafLayerWrapper::LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, LayerWrapper *parent)
|
||||||
: LayerWrapper(json, parent)
|
: LayerWrapper(json, parent)
|
||||||
{
|
{
|
||||||
qDebug() << json.value("name").toString() << " " << this;
|
qDebug() << json.value("name").toString() << " " << this;
|
||||||
int elementIndex = json.value("element").toInt();
|
int elementIndex = json.value("element").toInt();
|
||||||
wrappedElement = elementManager->getElementById(elementIndex);
|
wrappedElement = elementManager->getElementById(elementIndex);
|
||||||
}
|
}
|
||||||
void LayerWrapper::SimpleProperty::apply(PixelPath&cache) const
|
void LayerWrapper::SimpleProperty::apply(QPainterPath &cache) const
|
||||||
{
|
{
|
||||||
QTransform trans;
|
QTransform trans;
|
||||||
double centerX = cache.getBoundingRect().center().x();
|
double centerX = cache.boundingRect().center().x();
|
||||||
double centerY = cache.getBoundingRect().center().y();
|
double centerY = cache.boundingRect().center().y();
|
||||||
//qDebug() << name << " " << cache.boundingRect().center();
|
qDebug() << name << " " << cache.boundingRect().center();
|
||||||
//qDebug() << name << " " << cache.boundingRect();
|
qDebug() << name << " " << cache.boundingRect();
|
||||||
trans.translate(centerX, centerY);
|
trans.translate(centerX, centerY);
|
||||||
trans.scale(scale.x(), scale.y());
|
trans.scale(scale.x(), scale.y());
|
||||||
trans.rotate(rotation);
|
trans.rotate(rotation);
|
||||||
trans.translate(-centerX, -centerY);
|
trans.translate(-centerX, -centerY);
|
||||||
trans.translate(offset.x(), offset.y());
|
trans.translate(offset.x(), offset.y());
|
||||||
cache = cache.trans(trans);
|
cache = trans.map(cache);
|
||||||
}
|
}
|
||||||
void LayerWrapper::refresh()
|
void LayerWrapper::refresh()
|
||||||
{
|
{
|
||||||
|
@ -95,9 +98,8 @@ void LayerWrapper::refresh()
|
||||||
void FolderLayerWrapper::refresh()
|
void FolderLayerWrapper::refresh()
|
||||||
{
|
{
|
||||||
cache.clear();
|
cache.clear();
|
||||||
for (auto& child : children) {
|
for (auto &child : children)
|
||||||
cache.addPath(child.get()->getCache());
|
cache.addPath(child.get()->getCache());
|
||||||
}
|
|
||||||
LayerWrapper::refresh();
|
LayerWrapper::refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,115 +108,26 @@ void LeafLayerWrapper::refresh()
|
||||||
cache.clear();
|
cache.clear();
|
||||||
if (wrappedElement != nullptr)
|
if (wrappedElement != nullptr)
|
||||||
{
|
{
|
||||||
cache.addPath(wrappedElement->getPaintObject(this->styles));
|
cache.addPath(wrappedElement->getPaintObject());
|
||||||
}
|
}
|
||||||
LayerWrapper::refresh();
|
LayerWrapper::refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerWrapper::setParent(FolderLayerWrapper* newParent)
|
void LayerWrapper::setParent(LayerWrapper *newParent)
|
||||||
{
|
{
|
||||||
this->parent = newParent;
|
this->parent = shared_ptr<LayerWrapper>(newParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderLayerWrapper::removeAllChild()
|
void FolderLayerWrapper::removeAllChild()
|
||||||
{
|
{
|
||||||
children.clear();
|
children.clear();
|
||||||
qTreeWidgetItem.takeChildren();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerWrapper::del() {
|
namespace LayerEvent
|
||||||
qDebug() << "LayerWrapper::del()";
|
|
||||||
if (parent != nullptr){
|
|
||||||
qTreeWidgetItem.takeChildren();
|
|
||||||
parent->qTreeWidgetItem.removeChild(&qTreeWidgetItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWrapper::delSelf() {
|
|
||||||
qDebug() << "LayerWrapper::delSelf()";
|
|
||||||
if (parent != nullptr) {
|
|
||||||
qTreeWidgetItem.takeChildren();
|
|
||||||
parent->qTreeWidgetItem.removeChild(&qTreeWidgetItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderLayerWrapper::del()
|
|
||||||
{
|
{
|
||||||
qDebug() << "FolderLayerWrapper::del()";
|
|
||||||
for (auto& child : children)
|
|
||||||
child->del();
|
|
||||||
LayerWrapper::del();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderLayerWrapper::delSelf() {
|
static void onDoubleClick(QTreeWidgetItem *qItem, LayerWrapper *layerWrapper)
|
||||||
qDebug() << "FolderLayerWrapper::delSelf() "<<this<<" "<<this->parent;
|
|
||||||
LayerWrapper::delSelf();
|
|
||||||
if (parent != nullptr) {
|
|
||||||
qDebug() << this->children.size();
|
|
||||||
qDebug() << this;
|
|
||||||
for (auto& child : this->children) {
|
|
||||||
this->parent->addChild(child);
|
|
||||||
this->parent->qTreeWidgetItem.addChild(&child.get()->qTreeWidgetItem);
|
|
||||||
child->setParent(this->parent);
|
|
||||||
}
|
|
||||||
while (!this->children.empty()) {
|
|
||||||
this->children.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
QTreeWidgetItem* LayerWrapper::getQTreeItem()
|
|
||||||
{
|
{
|
||||||
this->qTreeWidgetItem.setText(0, this->property.name);
|
|
||||||
this->qTreeWidgetItem.setData(0, Qt::UserRole, QVariant::fromValue(this));
|
|
||||||
return &this->qTreeWidgetItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QTreeWidgetItem* FolderLayerWrapper::getQTreeItem()
|
} // namespace LayerEvent
|
||||||
{
|
|
||||||
while (this->qTreeWidgetItem.childCount() > 0) {
|
|
||||||
this->qTreeWidgetItem.removeChild(this->qTreeWidgetItem.child(0));
|
|
||||||
}
|
|
||||||
for (auto& child : this->children) {
|
|
||||||
this->qTreeWidgetItem.addChild(child->getQTreeItem());
|
|
||||||
}
|
|
||||||
return LayerWrapper::getQTreeItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: add effects
|
|
||||||
|
|
||||||
QJsonObject LayerWrapper::toJson() const
|
|
||||||
{
|
|
||||||
QJsonObject json;
|
|
||||||
json.insert("name", property.name);
|
|
||||||
QJsonObject transformJson;
|
|
||||||
transformJson.insert("offset", QJsonObject({ {"x", property.offset.x()}, {"y", property.offset.y()} }));
|
|
||||||
transformJson.insert("scale", QJsonObject({ {"x", property.scale.x()}, {"y", property.scale.y()} }));
|
|
||||||
transformJson.insert("rotation", property.rotation);
|
|
||||||
json.insert("transform", transformJson);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject FolderLayerWrapper::toJson() const
|
|
||||||
{
|
|
||||||
QJsonObject json = LayerWrapper::toJson();
|
|
||||||
QJsonArray childrenJson;
|
|
||||||
for (auto& child : children)
|
|
||||||
childrenJson.push_back(child->toJson());
|
|
||||||
json.insert("children", childrenJson);
|
|
||||||
json.insert("is-folder", true);
|
|
||||||
if(this->referencedBy != -1)
|
|
||||||
json.insert("referenced-by", this->referencedBy);
|
|
||||||
else
|
|
||||||
json.insert("referenced-by", QJsonValue());
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject LeafLayerWrapper::toJson() const
|
|
||||||
{
|
|
||||||
QJsonObject json = LayerWrapper::toJson();
|
|
||||||
json.insert("element", wrappedElement->index);
|
|
||||||
json.insert("is-folder", false);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,28 +12,24 @@
|
||||||
#include <QTreeWidget>
|
#include <QTreeWidget>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "PixelPath.h"
|
|
||||||
#include "../Renderer/Painting/ElementStyle.h"
|
|
||||||
using std::shared_ptr;
|
using std::shared_ptr;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
class GraphicElement;
|
class GraphicElement;
|
||||||
class SimpleElement;
|
class SimpleElement;
|
||||||
class GroupElement;
|
class GroupElement;
|
||||||
class ElementManager;
|
class ElementManager;
|
||||||
class FolderLayerWrapper;
|
|
||||||
|
|
||||||
class LayerWrapper
|
class LayerWrapper
|
||||||
{
|
{
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FolderLayerWrapper* parent;
|
shared_ptr<LayerWrapper> parent;
|
||||||
QPointF referencePoint;
|
QPointF referencePoint;
|
||||||
// vector<LayerStyle> styles;
|
vector<LayerStyle> styles;
|
||||||
// TODO: 将cache移到子类,对Leaf用ComposedPainterPath,对Folder用FolderBitmapPath
|
QPainterPath cache;
|
||||||
PixelPath cache;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QTreeWidgetItem qTreeWidgetItem;
|
QTreeWidgetItem *qTreeItem;
|
||||||
struct SimpleProperty
|
struct SimpleProperty
|
||||||
{
|
{
|
||||||
QString name = "";
|
QString name = "";
|
||||||
|
@ -42,64 +38,44 @@ class LayerWrapper
|
||||||
double rotation = 0;
|
double rotation = 0;
|
||||||
bool flipHorizontally = 0;
|
bool flipHorizontally = 0;
|
||||||
bool flipVertically = 0;
|
bool flipVertically = 0;
|
||||||
// TODO: 将QPainterPath改为BitmapPath
|
void apply(QPainterPath &cache) const;
|
||||||
void apply(PixelPath&cache) const;
|
|
||||||
} property;
|
} property;
|
||||||
virtual void setParent(FolderLayerWrapper*newParent);
|
void setParent(LayerWrapper *newParent);
|
||||||
virtual void refresh();
|
virtual void refresh();
|
||||||
virtual QTreeWidgetItem* getQTreeItem();
|
QPainterPath getCache();
|
||||||
// TODO: 将QPainterPath改为BitmapPath/QImage,或者直接将其删除,绘制时直接使用BitmapPath的paint方法
|
LayerWrapper *getParent() const; // invoke by manager, then invoke parent's applyStyles
|
||||||
virtual PixelPath getCache();
|
LayerWrapper(QJsonObject json, LayerWrapper *parent);
|
||||||
FolderLayerWrapper*getParent() const; // invoke by manager, then invoke parent's applyStyles
|
|
||||||
LayerWrapper(QJsonObject json, FolderLayerWrapper*parent);
|
|
||||||
LayerWrapper() = default;
|
LayerWrapper() = default;
|
||||||
// TODO : export Function
|
// TODO : export Function
|
||||||
// virtual LayerWrapper *addChild() = 0; // Leaf Child Only
|
// virtual LayerWrapper *addChild() = 0; // Leaf Child Only
|
||||||
// virtual LayerWrapper *addParent() = 0; // Folder Parent Only
|
// virtual LayerWrapper *addParent() = 0; // Folder Parent Only
|
||||||
// virtual void deleteSelf() const = 0;
|
// virtual void deleteSelf() const = 0;
|
||||||
// virtual void deleteAll() const = 0;
|
// virtual void deleteAll() const = 0;
|
||||||
virtual void del();
|
|
||||||
virtual void delSelf();
|
|
||||||
virtual QJsonObject toJson() const;
|
|
||||||
~LayerWrapper() = default;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FolderLayerWrapper : public LayerWrapper
|
class FolderLayerWrapper : public LayerWrapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
vector<shared_ptr<LayerWrapper>> children;
|
vector<shared_ptr<LayerWrapper>> children;
|
||||||
int referencedBy = -1;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
~FolderLayerWrapper() = default;
|
|
||||||
void refresh() override;
|
void refresh() override;
|
||||||
FolderLayerWrapper() = default;
|
FolderLayerWrapper() = default;
|
||||||
FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
|
FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, LayerWrapper *parent);
|
||||||
void addChild(shared_ptr<LayerWrapper> child);
|
void addChild(LayerWrapper *child);
|
||||||
void removeChild(LayerWrapper *child);
|
void removeChild(LayerWrapper *child);
|
||||||
void removeAllChild();
|
void removeAllChild();
|
||||||
void del() override;
|
|
||||||
void delSelf() override;
|
|
||||||
QTreeWidgetItem* getQTreeItem() override;
|
|
||||||
QJsonObject toJson() const override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class LeafLayerWrapper : public LayerWrapper
|
class LeafLayerWrapper : public LayerWrapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GraphicElement *wrappedElement;
|
GraphicElement *wrappedElement;
|
||||||
const vector<Renderer::ElementStyleStrokeDemo> styles;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~LeafLayerWrapper() = default;
|
|
||||||
void refresh() override;
|
void refresh() override;
|
||||||
LeafLayerWrapper() = default;
|
LeafLayerWrapper() = default;
|
||||||
LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
|
LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, LayerWrapper *parent);
|
||||||
QJsonObject toJson() const override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(LayerWrapper *)
|
Q_DECLARE_METATYPE(LayerWrapper *)
|
||||||
Q_DECLARE_METATYPE(FolderLayerWrapper *)
|
|
||||||
Q_DECLARE_METATYPE(LeafLayerWrapper *)
|
|
||||||
|
|
|
@ -1,87 +0,0 @@
|
||||||
#include "PixelPath.h"
|
|
||||||
#include <QPainter>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
PixelPath::PixelPath(int w, int h) :w(w), h(h)
|
|
||||||
{
|
|
||||||
pixmap = QPixmap(w, h);
|
|
||||||
pixmap.fill(Qt::transparent);
|
|
||||||
boundingRect = QRectF(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
PixelPath::PixelPath(QPainterPath painterPath, int w, int h) :w(w), h(h)
|
|
||||||
{
|
|
||||||
pixmap = QPixmap(w, h);
|
|
||||||
pixmap.fill(Qt::transparent);
|
|
||||||
boundingRect = QRectF(0, 0, 0, 0);
|
|
||||||
addPath(painterPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
QRectF PixelPath::getBoundingRect() const
|
|
||||||
{
|
|
||||||
return boundingRect;
|
|
||||||
}
|
|
||||||
#include <QDebug>
|
|
||||||
QPixmap PixelPath::getPixmap() const
|
|
||||||
{
|
|
||||||
auto k = pixmap;
|
|
||||||
QPainter pt(&k);
|
|
||||||
//pt.fillRect(this->boundingRect, Qt::red);
|
|
||||||
//pt.fillRect(QRectF(1013.35 - 1000, 768.327 - 700,58.0887,41.5352), Qt::blue);
|
|
||||||
return k;
|
|
||||||
return pixmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PixelPath::addPath(const PixelPath& path)
|
|
||||||
{
|
|
||||||
QPainter painter(&pixmap);
|
|
||||||
painter.drawPixmap(0, 0, path.getPixmap());
|
|
||||||
boundingRect = boundingRect.united(path.getBoundingRect());
|
|
||||||
}
|
|
||||||
|
|
||||||
void PixelPath::addPath(const QPainterPath& path)
|
|
||||||
{
|
|
||||||
QPainter painter(&pixmap);
|
|
||||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
|
||||||
painter.setRenderHint(QPainter::HighQualityAntialiasing);
|
|
||||||
painter.setPen(QPen(Qt::black,1));
|
|
||||||
painter.drawPath(path);
|
|
||||||
boundingRect = boundingRect.united(path.boundingRect());
|
|
||||||
}
|
|
||||||
|
|
||||||
void PixelPath::addImage(const QImage& image,const QPointF& pos)
|
|
||||||
{
|
|
||||||
QPainter painter(&pixmap);
|
|
||||||
painter.drawImage(pos, image);
|
|
||||||
boundingRect = boundingRect.united(QRectF(pos, image.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PixelPath::clear()
|
|
||||||
{
|
|
||||||
pixmap.fill(Qt::transparent);
|
|
||||||
boundingRect = QRectF(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
PixelPath PixelPath::trans(QTransform& mat)const
|
|
||||||
{
|
|
||||||
PixelPath result(w, h);
|
|
||||||
QPainter painter(&result.pixmap);
|
|
||||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
|
||||||
painter.setRenderHint(QPainter::HighQualityAntialiasing);
|
|
||||||
painter.setTransform(mat);
|
|
||||||
painter.drawPixmap(0, 0, pixmap);
|
|
||||||
result.boundingRect = mat.mapRect(boundingRect);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPixmap PixelPath::resizedPixel(QSize size)const
|
|
||||||
{
|
|
||||||
QPixmap result(size);
|
|
||||||
result.fill(Qt::transparent);
|
|
||||||
QPainter painter(&result);
|
|
||||||
|
|
||||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
|
||||||
painter.setRenderHint(QPainter::HighQualityAntialiasing);
|
|
||||||
painter.drawPixmap(0, 0, pixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
|
||||||
return result;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QImage>
|
|
||||||
#include <QPixmap>
|
|
||||||
#include <QTransform>
|
|
||||||
#include <QPainterPath>
|
|
||||||
|
|
||||||
class PixelPath
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
QRectF boundingRect;
|
|
||||||
QPixmap pixmap;
|
|
||||||
int w,h;
|
|
||||||
public:
|
|
||||||
PixelPath(int w=1920, int h= 1080);
|
|
||||||
PixelPath(QPainterPath painterPath,int w = 1920, int h = 1080);
|
|
||||||
~PixelPath() = default;
|
|
||||||
QRectF getBoundingRect() const;
|
|
||||||
QPixmap getPixmap() const;
|
|
||||||
void addPath(const PixelPath& path);
|
|
||||||
void addPath(const QPainterPath& path);
|
|
||||||
void addImage(const QImage& image,const QPointF& pos);
|
|
||||||
void clear();
|
|
||||||
PixelPath trans(QTransform& mat)const;
|
|
||||||
QPixmap resizedPixel(QSize size)const;
|
|
||||||
};
|
|
|
@ -2,59 +2,50 @@
|
||||||
|
|
||||||
PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent)
|
PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent)
|
||||||
{
|
{
|
||||||
this->renderer = new Renderer::ElementRenderer(this);
|
|
||||||
QSurfaceFormat surfaceFormat;
|
QSurfaceFormat surfaceFormat;
|
||||||
surfaceFormat.setSamples(16);
|
surfaceFormat.setSamples(16);
|
||||||
setFormat(surfaceFormat);
|
setFormat(surfaceFormat);
|
||||||
painter = new QPainter(this);
|
painter = new QPainter(this);
|
||||||
painter->setRenderHint(QPainter::SmoothPixmapTransform);
|
|
||||||
painter->setRenderHint(QPainter::HighQualityAntialiasing);
|
|
||||||
layerManager = nullptr;
|
layerManager = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewWindow::initialize(LayerManager *layerManager,QSize windowSize)
|
void PreviewWindow::initialize(LayerManager *layerManager)
|
||||||
{
|
{
|
||||||
this->logicalSize = windowSize;
|
|
||||||
this->layerManager = layerManager;
|
this->layerManager = layerManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewWindow::show()
|
void PreviewWindow::show()
|
||||||
{
|
{
|
||||||
//QFile settingFile;
|
QFile settingFile;
|
||||||
//settingFile.setFileName("../data.json");
|
settingFile.setFileName("../data.json");
|
||||||
//settingFile.open(QFile::ReadOnly);
|
settingFile.open(QFile::ReadOnly);
|
||||||
//QByteArray setting = settingFile.readAll().trimmed();
|
QByteArray setting = settingFile.readAll().trimmed();
|
||||||
//QJsonDocument jsonDoc(QJsonDocument::fromJson(setting));
|
QJsonDocument jsonDoc(QJsonDocument::fromJson(setting));
|
||||||
//auto jElements = jsonDoc.object().value("elements").toArray();
|
auto jElements = jsonDoc.object().value("elements").toArray();
|
||||||
|
|
||||||
//for (auto &&ele : jElements)
|
for (auto &&ele : jElements)
|
||||||
//{
|
{
|
||||||
// SimpleElement element(ele.toObject());
|
SimpleElement element(ele.toObject());
|
||||||
// painter->drawPath(element.getPaintObject());
|
painter->drawPath(element.getPaintObject());
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewWindow::initializeGL()
|
void PreviewWindow::initializeGL()
|
||||||
{
|
{
|
||||||
this->renderer->initialize();
|
|
||||||
initializeOpenGLFunctions();
|
initializeOpenGLFunctions();
|
||||||
|
glClearColor(1.0, 1.0, 1.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewWindow::paintGL()
|
void PreviewWindow::paintGL()
|
||||||
{
|
{
|
||||||
glClearColor(1.0, 1.0, 1.0, 1.0);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
painter->begin(this);
|
painter->begin(this);
|
||||||
painter->setRenderHint(QPainter::Antialiasing);
|
painter->setRenderHint(QPainter::Antialiasing);
|
||||||
painter->setRenderHint(QPainter::HighQualityAntialiasing);
|
painter->setRenderHint(QPainter::HighQualityAntialiasing);
|
||||||
layerManager->paint(painter,this->size());
|
layerManager->paint(painter);
|
||||||
painter->end();
|
painter->end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewWindow::resizeGL(int w, int h)
|
void PreviewWindow::resizeGL(int w, int h)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::ElementRenderer* const PreviewWindow::getRenderer()const {
|
|
||||||
return this->renderer;
|
|
||||||
}
|
|
|
@ -8,8 +8,6 @@
|
||||||
#include <QJsonValue>
|
#include <QJsonValue>
|
||||||
#include <QOpenGLFunctions>
|
#include <QOpenGLFunctions>
|
||||||
#include <QOpenGLWidget>
|
#include <QOpenGLWidget>
|
||||||
#include "../Renderer/Preview/ElementRenderer.h"
|
|
||||||
|
|
||||||
class PreviewWindow : public QOpenGLWidget, protected QOpenGLFunctions
|
class PreviewWindow : public QOpenGLWidget, protected QOpenGLFunctions
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -17,15 +15,12 @@ class PreviewWindow : public QOpenGLWidget, protected QOpenGLFunctions
|
||||||
private:
|
private:
|
||||||
QPainter *painter;
|
QPainter *painter;
|
||||||
LayerManager *layerManager;
|
LayerManager *layerManager;
|
||||||
Renderer::ElementRenderer* renderer;
|
|
||||||
QSize logicalSize;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PreviewWindow(QWidget *parent = nullptr);
|
PreviewWindow(QWidget *parent = nullptr);
|
||||||
void initialize(LayerManager *layerManager, QSize windowSize = QSize(1920, 1080));
|
void initialize(LayerManager *layerManager);
|
||||||
void show();
|
void show();
|
||||||
void initializeGL() override;
|
void initializeGL() override;
|
||||||
void paintGL() override;
|
void paintGL() override;
|
||||||
void resizeGL(int w, int h) override;
|
void resizeGL(int w, int h) override;
|
||||||
Renderer::ElementRenderer* const getRenderer()const;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
#include "InfoDisplayWidget.h"
|
#include "InfoDisplayWidget.h"
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QTextBlock>
|
#include <QTextBlock>
|
||||||
#include <QListWidget>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QDialog>
|
|
||||||
#include <QDialogButtonBox>
|
|
||||||
|
|
||||||
void InfoDisplayWidget::setLayer(LayerWrapper *layer)
|
void InfoDisplayWidget::setLayer(LayerWrapper *layer)
|
||||||
{
|
{
|
||||||
this->displayLayer = layer;
|
this->displayLayer = layer;
|
||||||
|
@ -44,27 +39,27 @@ void InfoDisplayWidget::generateLayerForm()
|
||||||
QLineEdit *scaleX = new QLineEdit(QString::number(this->displayLayer->property.scale.x()), this);
|
QLineEdit *scaleX = new QLineEdit(QString::number(this->displayLayer->property.scale.x()), this);
|
||||||
QLineEdit *scaleY = new QLineEdit(QString::number(this->displayLayer->property.scale.y()), this);
|
QLineEdit *scaleY = new QLineEdit(QString::number(this->displayLayer->property.scale.y()), this);
|
||||||
name->setDisabled(true);
|
name->setDisabled(true);
|
||||||
rotation->setValidator(new QIntValidator(-10000, 10000, this));
|
rotation->setValidator(new QIntValidator(-1000, 1000, this));
|
||||||
connect(rotation, &QLineEdit::textChanged, [=](QString content) {
|
connect(rotation, &QLineEdit::textChanged, [=](QString content) {
|
||||||
this->displayLayer->property.rotation = content.toDouble();
|
this->displayLayer->property.rotation = content.toDouble();
|
||||||
emit requireRefreshPreview();
|
emit requireRefreshPreview();
|
||||||
});
|
});
|
||||||
offsetX->setValidator(new QIntValidator(-10000, 10000, this));
|
offsetX->setValidator(new QIntValidator(-1000, 1000, this));
|
||||||
connect(offsetX, &QLineEdit::textChanged, [=](QString content) {
|
connect(offsetX, &QLineEdit::textChanged, [=](QString content) {
|
||||||
this->displayLayer->property.offset = {content.toDouble(), this->displayLayer->property.offset.y()};
|
this->displayLayer->property.offset = {content.toDouble(), this->displayLayer->property.offset.y()};
|
||||||
emit requireRefreshPreview();
|
emit requireRefreshPreview();
|
||||||
});
|
});
|
||||||
offsetY->setValidator(new QIntValidator(-10000, 10000, this));
|
offsetY->setValidator(new QIntValidator(-1000, 1000, this));
|
||||||
connect(offsetY, &QLineEdit::textChanged, [=](QString content) {
|
connect(offsetY, &QLineEdit::textChanged, [=](QString content) {
|
||||||
this->displayLayer->property.offset = {this->displayLayer->property.offset.x(), content.toDouble()};
|
this->displayLayer->property.offset = {this->displayLayer->property.offset.x(), content.toDouble()};
|
||||||
emit requireRefreshPreview();
|
emit requireRefreshPreview();
|
||||||
});
|
});
|
||||||
scaleX->setValidator(new QDoubleValidator(0.001, 1000, 4, this));
|
scaleX->setValidator(new QDoubleValidator(0.01, 100, 4, this));
|
||||||
connect(scaleX, &QLineEdit::textChanged, [=](QString content) {
|
connect(scaleX, &QLineEdit::textChanged, [=](QString content) {
|
||||||
this->displayLayer->property.scale = {content.toDouble(), this->displayLayer->property.scale.y()};
|
this->displayLayer->property.scale = {content.toDouble(), this->displayLayer->property.scale.y()};
|
||||||
emit requireRefreshPreview();
|
emit requireRefreshPreview();
|
||||||
});
|
});
|
||||||
scaleY->setValidator(new QDoubleValidator(0.001, 1000, 4, this));
|
scaleY->setValidator(new QDoubleValidator(0.01, 100, 4, this));
|
||||||
connect(scaleY, &QLineEdit::textChanged, [=](QString content) {
|
connect(scaleY, &QLineEdit::textChanged, [=](QString content) {
|
||||||
this->displayLayer->property.scale = {this->displayLayer->property.scale.x(), content.toDouble()};
|
this->displayLayer->property.scale = {this->displayLayer->property.scale.x(), content.toDouble()};
|
||||||
emit requireRefreshPreview();
|
emit requireRefreshPreview();
|
||||||
|
@ -77,79 +72,9 @@ void InfoDisplayWidget::generateLayerForm()
|
||||||
layout->addRow("scale-X:", scaleX);
|
layout->addRow("scale-X:", scaleX);
|
||||||
layout->addRow("scale-Y:", scaleY);
|
layout->addRow("scale-Y:", scaleY);
|
||||||
layout->setRowWrapPolicy(QFormLayout::DontWrapRows);
|
layout->setRowWrapPolicy(QFormLayout::DontWrapRows);
|
||||||
|
|
||||||
bool styleEnabled = true;
|
|
||||||
if (styleEnabled) {
|
|
||||||
QListWidget* styleList = new QListWidget(this);
|
|
||||||
QListWidgetItem* item = new QListWidgetItem("样式列表");
|
|
||||||
item->setFlags(Qt::NoItemFlags);
|
|
||||||
styleList->addItem(item);
|
|
||||||
static vector<QString> styleNames = { "样例1", "样例2", "样例3" };
|
|
||||||
auto createStyleItem = [this, styleList](int index) {
|
|
||||||
QListWidgetItem* item = new QListWidgetItem;
|
|
||||||
QWidget* w = new QWidget;
|
|
||||||
item->setSizeHint(QSize(50, 40));
|
|
||||||
QHBoxLayout* layout = new QHBoxLayout;
|
|
||||||
QPushButton* deleteButton = new QPushButton(w);
|
|
||||||
QPushButton* detailButton = new QPushButton(w);
|
|
||||||
QLabel* name = new QLabel(w);
|
|
||||||
name->setText(styleNames[index]);
|
|
||||||
detailButton->setText("...");
|
|
||||||
detailButton->setFixedSize(QSize(20, 20));
|
|
||||||
deleteButton->setText("×");
|
|
||||||
deleteButton->setFixedSize(QSize(20, 20));
|
|
||||||
connect(detailButton, &QPushButton::clicked, [styleList, item, this, index]() {
|
|
||||||
QDialog dlg(this);
|
|
||||||
dlg.setWindowTitle("样式详情");
|
|
||||||
dlg.resize(400, 200);
|
|
||||||
QGridLayout *contentLayout = new QGridLayout(&dlg);
|
|
||||||
QLineEdit* name = new QLineEdit(styleNames[index], &dlg);
|
|
||||||
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
|
|
||||||
contentLayout->addWidget(buttonBox);
|
|
||||||
connect(buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept);
|
|
||||||
connect(buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject);
|
|
||||||
bool updateStyle = dlg.exec();
|
|
||||||
if (updateStyle) {
|
|
||||||
styleNames[index] = name->text();
|
|
||||||
qDebug() << name->text();
|
|
||||||
// 在此处修改新样式信息至内存
|
|
||||||
emit requireRefreshPreview();
|
|
||||||
emit requireSelfRefresh();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(deleteButton, &QPushButton::clicked, [styleList,item,this]() {
|
|
||||||
styleList->removeItemWidget(item);
|
|
||||||
delete item;
|
|
||||||
// 删除layer对应样式
|
|
||||||
emit requireRefreshPreview();
|
|
||||||
emit requireSelfRefresh();
|
|
||||||
});
|
|
||||||
layout->addWidget(name);
|
|
||||||
layout->addWidget(detailButton);
|
|
||||||
layout->addWidget(deleteButton);
|
|
||||||
w->setLayout(layout);
|
|
||||||
styleList->addItem(item);
|
|
||||||
styleList->setItemWidget(item, w);
|
|
||||||
};
|
|
||||||
for (int i = 0; i < styleNames.size(); i++)
|
|
||||||
createStyleItem(i);
|
|
||||||
|
|
||||||
|
|
||||||
layout->addRow(styleList);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this->setLayout(layout);
|
this->setLayout(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InfoDisplayWidget::generateElementForm()
|
void InfoDisplayWidget::generateElementForm()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfoDisplayWidget::triggerSelfRefresh()
|
|
||||||
{
|
|
||||||
if (this->displayLayer != nullptr)
|
|
||||||
this->generateLayerForm();
|
|
||||||
if (this->displayElement != nullptr)
|
|
||||||
this->generateElementForm();
|
|
||||||
}
|
|
|
@ -18,12 +18,6 @@ class InfoDisplayWidget : public QWidget
|
||||||
void generateLayerForm();
|
void generateLayerForm();
|
||||||
void generateElementForm();
|
void generateElementForm();
|
||||||
|
|
||||||
public slots:
|
|
||||||
void triggerSelfRefresh();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void requireRefreshPreview();
|
void requireRefreshPreview();
|
||||||
void requireSelfRefresh();
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,10 +11,7 @@ LayerTreeWidget::LayerTreeWidget(QWidget *parent)
|
||||||
connect(this, &QTreeWidget::customContextMenuRequested, this, &LayerTreeWidget::popMenu);
|
connect(this, &QTreeWidget::customContextMenuRequested, this, &LayerTreeWidget::popMenu);
|
||||||
connect(this, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *currentItem) {
|
connect(this, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *currentItem) {
|
||||||
this->selectedItem = currentItem;
|
this->selectedItem = currentItem;
|
||||||
if(this->selectedItem !=nullptr)
|
|
||||||
emit displayLayerChange(this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper *>());
|
emit displayLayerChange(this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper *>());
|
||||||
else
|
|
||||||
emit displayLayerChange(nullptr);
|
|
||||||
});
|
});
|
||||||
// connect(this, &QTreeWidget::itemDoubleClicked, this, &LayerTreeWidget::onItemDoubleClicked);
|
// connect(this, &QTreeWidget::itemDoubleClicked, this, &LayerTreeWidget::onItemDoubleClicked);
|
||||||
}
|
}
|
||||||
|
@ -29,38 +26,19 @@ LayerTreeWidget::LayerTreeWidget(QWidget *parent)
|
||||||
// this->selectedItem = item;
|
// this->selectedItem = item;
|
||||||
// // TODO
|
// // TODO
|
||||||
// }
|
// }
|
||||||
#include <QDebug>
|
|
||||||
void LayerTreeWidget::popMenu(const QPoint &pos)
|
void LayerTreeWidget::popMenu(const QPoint &pos)
|
||||||
{
|
{
|
||||||
QMenu menu;
|
QMenu menu;
|
||||||
QTreeWidgetItem *item = itemAt(pos);
|
QTreeWidgetItem *item = itemAt(pos);
|
||||||
this->selectedItem = item;
|
this->selectedItem = item;
|
||||||
// TODO
|
// TODO
|
||||||
menu.addAction(QString::fromLocal8Bit("创建子节点"), this, &LayerTreeWidget::onRenameEvent);
|
menu.addAction("Add Child", this, &LayerTreeWidget::onRenameEvent);
|
||||||
//if (item != root->getQTreeItem())
|
menu.addAction("Rename", this, &LayerTreeWidget::onRenameEvent);
|
||||||
//{
|
menu.addAction("Copy", this, &LayerTreeWidget::onRenameEvent);
|
||||||
menu.addAction(QString::fromLocal8Bit("重命名"), this, &LayerTreeWidget::onRenameEvent);
|
|
||||||
// menu.addAction("Copy", this, &LayerTreeWidget::onRenameEvent);
|
|
||||||
if (item != nullptr && item->childCount() > 0)
|
if (item != nullptr && item->childCount() > 0)
|
||||||
menu.addAction(QString::fromLocal8Bit("删除(保留子节点)"), this, [this]() {
|
menu.addAction("Delete (Self Only)", this, &LayerTreeWidget::onRenameEvent);
|
||||||
if (this->selectedItem == nullptr)
|
menu.addAction("Delete", this, &LayerTreeWidget::onRenameEvent);
|
||||||
return;
|
|
||||||
auto layer = this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>();
|
|
||||||
layer->delSelf();
|
|
||||||
layer->getParent()->removeChild(layer);
|
|
||||||
this->refresh();
|
|
||||||
emit requireRefreshPreview();
|
|
||||||
});
|
|
||||||
menu.addAction(QString::fromLocal8Bit("删除"), this, [this]() {
|
|
||||||
if (this->selectedItem == nullptr)
|
|
||||||
return;
|
|
||||||
auto layer = this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>();
|
|
||||||
layer->del();
|
|
||||||
layer->getParent()->removeChild(layer);
|
|
||||||
this->refresh();
|
|
||||||
emit requireRefreshPreview();
|
|
||||||
});
|
|
||||||
//}
|
|
||||||
menu.exec(mapToGlobal(pos));
|
menu.exec(mapToGlobal(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,11 +57,3 @@ void LayerTreeWidget::onRenameEvent()
|
||||||
}
|
}
|
||||||
emit displayLayerChange(this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper *>());
|
emit displayLayerChange(this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper *>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerTreeWidget::refresh() {
|
|
||||||
// if(this->root!=nullptr)
|
|
||||||
//{
|
|
||||||
// this->clear();
|
|
||||||
// this->addTopLevelItem(this->root->getQTreeItem());
|
|
||||||
//}
|
|
||||||
}
|
|
|
@ -10,15 +10,12 @@ class LayerTreeWidget : public QTreeWidget
|
||||||
LayerWrapper *copiedItem;
|
LayerWrapper *copiedItem;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LayerWrapper* root;
|
|
||||||
LayerTreeWidget(QWidget *parent = nullptr);
|
LayerTreeWidget(QWidget *parent = nullptr);
|
||||||
void onRenameEvent();
|
void onRenameEvent();
|
||||||
void popMenu(const QPoint &pos);
|
void popMenu(const QPoint &pos);
|
||||||
void refresh();
|
|
||||||
// void mouseDoubleClickEvent(QMouseEvent *event) override;
|
// void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||||
// void onItemDoubleClicked(QTreeWidgetItem *item, int column = 0);
|
// void onItemDoubleClicked(QTreeWidgetItem *item, int column = 0);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void displayLayerChange(LayerWrapper *);
|
void displayLayerChange(LayerWrapper *);
|
||||||
void requireRefreshPreview();
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
#include "SvgFileLoader.h"
|
#include "SvgFileLoader.h"
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include "../ThirdPartyLib/qquick/qquicksvgparser_p.h"
|
#include "../qquick/qquicksvgparser_p.h"
|
||||||
#include <QPolygonF>
|
#include <QPolygonF>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
|
||||||
using std::map;
|
using std::map;
|
||||||
using std::vector;
|
|
||||||
using std::reverse;
|
|
||||||
|
|
||||||
bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPath) {
|
bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPath) {
|
||||||
QFile file(filePath);
|
QFile file(filePath);
|
||||||
|
@ -49,12 +46,12 @@ bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qDebug() << painterPath;
|
|
||||||
file.close();
|
file.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMap<QString, QString> SvgFileLoader::handleAttrStyle(QString style) {
|
QMap<QString, QString> SvgFileLoader::transformStyle(QString style) {
|
||||||
QMap<QString, QString> resStyleMap;
|
QMap<QString, QString> resStyleMap;
|
||||||
for (auto& attr : style.split(';')) {
|
for (auto& attr : style.split(';')) {
|
||||||
if (attr.isEmpty() || attr.trimmed() == "") continue;
|
if (attr.isEmpty() || attr.trimmed() == "") continue;
|
||||||
|
@ -65,7 +62,7 @@ QMap<QString, QString> SvgFileLoader::handleAttrStyle(QString style) {
|
||||||
return resStyleMap;
|
return resStyleMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPolygonF SvgFileLoader::handleAttrPoints(QString points) {
|
QPolygonF SvgFileLoader::transformPoints(QString points) {
|
||||||
QPolygonF resPointVector;
|
QPolygonF resPointVector;
|
||||||
QPointF point(0, 0);
|
QPointF point(0, 0);
|
||||||
bool isX = true;
|
bool isX = true;
|
||||||
|
@ -83,58 +80,10 @@ QPolygonF SvgFileLoader::handleAttrPoints(QString points) {
|
||||||
return resPointVector;
|
return resPointVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SvgFileLoader::handleAttrTransform(QString transformStyle, QPainterPath& painterPath) {
|
|
||||||
QTransform trans;
|
|
||||||
QStringList ops = transformStyle.split(')');
|
|
||||||
reverse(ops.begin(), ops.end());
|
|
||||||
vector<double> numbers;
|
|
||||||
for (auto op : ops) {
|
|
||||||
op = op.simplified();
|
|
||||||
if (op.isEmpty()) continue;
|
|
||||||
QString type = (*op.split('(').begin()).trimmed();
|
|
||||||
QString numStr = (*op.split('(').rbegin()).trimmed() + ',';
|
|
||||||
QString tmpNum = "";
|
|
||||||
for (auto c : numStr) {
|
|
||||||
if (isdigit(c.toLatin1()) || c == '-' || c == '.') {
|
|
||||||
tmpNum += c;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (c == ',' && tmpNum.size() == 0) {
|
|
||||||
numbers.push_back(0);
|
|
||||||
}
|
|
||||||
else if (tmpNum.size() > 0) {
|
|
||||||
numbers.push_back(tmpNum.toDouble());
|
|
||||||
}
|
|
||||||
tmpNum.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qDebug() << type << "///:" << numbers;
|
|
||||||
if (type == "translate") {
|
|
||||||
trans.translate(numbers[0], numbers[1]);
|
|
||||||
}
|
|
||||||
if (type == "scale") {
|
|
||||||
trans.scale(numbers[0], numbers[1]);
|
|
||||||
}
|
|
||||||
if (type == "rotate") {
|
|
||||||
trans.translate(numbers[1], numbers[2]);
|
|
||||||
trans.rotate(numbers[0]);
|
|
||||||
trans.translate(-numbers[1], -numbers[2]);
|
|
||||||
}
|
|
||||||
if (type == "skewX") {
|
|
||||||
trans.shear(numbers[0], 0);
|
|
||||||
}
|
|
||||||
if (type == "skewY") {
|
|
||||||
trans.shear(0, numbers[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
painterPath = trans.map(painterPath);
|
|
||||||
qDebug() << painterPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SvgFileLoader::handleLabelG(QPainterPath& painterPath) {
|
void SvgFileLoader::handleLabelG(QPainterPath& painterPath) {
|
||||||
for (auto& attr : xmlReader->attributes()) {
|
for (auto& attr : xmlReader->attributes()) {
|
||||||
if (attr.name().toString() == QLatin1String("style")) {
|
if (attr.name().toString() == QLatin1String("style")) {
|
||||||
styleMap = handleAttrStyle(attr.value().toLatin1());
|
styleMap = transformStyle(attr.value().toLatin1());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
styleMap.insert(attr.name().toLatin1(), attr.value().toLatin1());
|
styleMap.insert(attr.name().toLatin1(), attr.value().toLatin1());
|
||||||
|
@ -145,33 +94,22 @@ void SvgFileLoader::handleLabelG(QPainterPath& painterPath) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SvgFileLoader::handleLabelPath(QPainterPath& painterPath) {
|
void SvgFileLoader::handleLabelPath(QPainterPath& painterPath) {
|
||||||
QPainterPath elementPainterPath;
|
|
||||||
QString transformStyle = "";
|
|
||||||
QMap<QString, QString> labelStyle;
|
QMap<QString, QString> labelStyle;
|
||||||
for (auto& attr : xmlReader->attributes()) {
|
for (auto& attr : xmlReader->attributes()) {
|
||||||
if (attr.name().toString() == QLatin1String("d")) {
|
if (attr.name().toString() == QLatin1String("d")) {
|
||||||
QQuickSvgParser::parsePathDataFast(attr.value().toLatin1(), elementPainterPath);
|
QQuickSvgParser::parsePathDataFast(attr.value().toLatin1(), painterPath);
|
||||||
}
|
}
|
||||||
else if (attr.name().toString() == QLatin1String("style")) {
|
else if (attr.name().toString() == QLatin1String("style")) {
|
||||||
labelStyle = handleAttrStyle(attr.value().toLatin1());
|
labelStyle = transformStyle(attr.value().toLatin1());
|
||||||
}
|
|
||||||
else if (attr.name().toString() == QLatin1String("transform")) {
|
|
||||||
transformStyle = attr.value().toLatin1();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
|
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!transformStyle.isEmpty()) {
|
|
||||||
handleAttrTransform(transformStyle, elementPainterPath);
|
|
||||||
}
|
|
||||||
painterPath.addPath(elementPainterPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) {
|
void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) {
|
||||||
QMap<QString, QString> labelStyle;
|
QMap<QString, QString> labelStyle;
|
||||||
QPainterPath elementPainterPath;
|
|
||||||
QString transformStyle = "";
|
|
||||||
double xBegin = 0, yBegin = 0, width = 0, height = 0;;
|
double xBegin = 0, yBegin = 0, width = 0, height = 0;;
|
||||||
for (auto& attr : xmlReader->attributes()) {
|
for (auto& attr : xmlReader->attributes()) {
|
||||||
if (attr.name().toString() == QLatin1String("x")) {
|
if (attr.name().toString() == QLatin1String("x")) {
|
||||||
|
@ -184,26 +122,17 @@ void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) {
|
||||||
height = attr.value().toDouble();
|
height = attr.value().toDouble();
|
||||||
}
|
}
|
||||||
else if (attr.name().toString() == QLatin1String("style")) {
|
else if (attr.name().toString() == QLatin1String("style")) {
|
||||||
labelStyle = handleAttrStyle(attr.value().toLatin1());
|
labelStyle = transformStyle(attr.value().toLatin1());
|
||||||
}
|
|
||||||
else if (attr.name().toString() == QLatin1String("transform")) {
|
|
||||||
transformStyle = attr.value().toLatin1();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
|
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qDebug() << labelStyle;
|
qDebug() << labelStyle;
|
||||||
elementPainterPath.addRect(xBegin, yBegin, xBegin + width, yBegin + height);
|
painterPath.addRect(xBegin, yBegin, xBegin + width, yBegin + height);
|
||||||
if (!transformStyle.isEmpty()) {
|
|
||||||
handleAttrTransform(transformStyle, elementPainterPath);
|
|
||||||
}
|
|
||||||
painterPath.addPath(elementPainterPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) {
|
void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) {
|
||||||
QPainterPath elementPainterPath;
|
|
||||||
QString transformStyle = "";
|
|
||||||
QMap<QString, QString> labelStyle;
|
QMap<QString, QString> labelStyle;
|
||||||
double cx = 0, cy = 0, r = 0;
|
double cx = 0, cy = 0, r = 0;
|
||||||
for (auto& attr : xmlReader->attributes()) {
|
for (auto& attr : xmlReader->attributes()) {
|
||||||
|
@ -215,28 +144,17 @@ void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) {
|
||||||
r = attr.value().toDouble();
|
r = attr.value().toDouble();
|
||||||
}
|
}
|
||||||
else if (attr.name().toString() == QLatin1String("style")) {
|
else if (attr.name().toString() == QLatin1String("style")) {
|
||||||
labelStyle = handleAttrStyle(attr.value().toLatin1());
|
labelStyle = transformStyle(attr.value().toLatin1());
|
||||||
}
|
|
||||||
else if (attr.name().toString() == QLatin1String("transform")) {
|
|
||||||
transformStyle = attr.value().toLatin1();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
|
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qDebug() << labelStyle;
|
qDebug() << labelStyle;
|
||||||
elementPainterPath.addEllipse(cx, cy, r, r);
|
painterPath.addEllipse(cx, cy, r, r);
|
||||||
if (!transformStyle.isEmpty()) {
|
|
||||||
handleAttrTransform(transformStyle, elementPainterPath);
|
|
||||||
}
|
|
||||||
painterPath.addPath(elementPainterPath);
|
|
||||||
//addEllipse(cx, cy, r, r, painterPath);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) {
|
void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) {
|
||||||
QPainterPath elementPainterPath;
|
|
||||||
QString transformStyle = "";
|
|
||||||
QMap<QString, QString> labelStyle;
|
QMap<QString, QString> labelStyle;
|
||||||
double cx = 0, cy = 0, rx = 0, ry = 0;
|
double cx = 0, cy = 0, rx = 0, ry = 0;
|
||||||
for (auto& attr : xmlReader->attributes()) {
|
for (auto& attr : xmlReader->attributes()) {
|
||||||
|
@ -249,84 +167,47 @@ void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) {
|
||||||
} else if (attr.name().toString() == QLatin1String("ry")) {
|
} else if (attr.name().toString() == QLatin1String("ry")) {
|
||||||
rx = attr.value().toDouble();
|
rx = attr.value().toDouble();
|
||||||
} else if (attr.name().toString() == QLatin1String("style")) {
|
} else if (attr.name().toString() == QLatin1String("style")) {
|
||||||
labelStyle = handleAttrStyle(attr.value().toLatin1());
|
labelStyle = transformStyle(attr.value().toLatin1());
|
||||||
}
|
|
||||||
else if (attr.name().toString() == QLatin1String("transform")) {
|
|
||||||
transformStyle = attr.value().toLatin1();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
|
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qDebug() << labelStyle;
|
qDebug() << labelStyle;
|
||||||
//addEllipse(cx, cy, rx, ry, painterPath);
|
painterPath.addEllipse(cx, cy, rx, ry);
|
||||||
elementPainterPath.addEllipse(cx, cy, rx, ry);
|
|
||||||
if (!transformStyle.isEmpty()) {
|
|
||||||
handleAttrTransform(transformStyle, elementPainterPath);
|
|
||||||
}
|
|
||||||
painterPath.addPath(elementPainterPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SvgFileLoader::handleLabelPolyline(QPainterPath& painterPath) {
|
void SvgFileLoader::handleLabelPolyline(QPainterPath& painterPath) {
|
||||||
QPainterPath elementPainterPath;
|
|
||||||
QString transformStyle = "";
|
|
||||||
QMap<QString, QString> labelStyle;
|
QMap<QString, QString> labelStyle;
|
||||||
for (auto& attr : xmlReader->attributes()) {
|
for (auto& attr : xmlReader->attributes()) {
|
||||||
if (attr.name().toString() == QLatin1String("points")) {
|
if (attr.name().toString() == QLatin1String("points")) {
|
||||||
QPolygonF points = handleAttrPoints(attr.value().toLatin1());
|
QPolygonF points = transformPoints(attr.value().toLatin1());
|
||||||
elementPainterPath.addPolygon(points);
|
painterPath.addPolygon(points);
|
||||||
}
|
}
|
||||||
else if (attr.name().toString() == QLatin1String("style")) {
|
else if (attr.name().toString() == QLatin1String("style")) {
|
||||||
labelStyle = handleAttrStyle(attr.value().toLatin1());
|
labelStyle = transformStyle(attr.value().toLatin1());
|
||||||
}
|
|
||||||
else if (attr.name().toString() == QLatin1String("transform")) {
|
|
||||||
transformStyle = attr.value().toLatin1();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
|
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qDebug() << labelStyle;
|
qDebug() << labelStyle;
|
||||||
if (!transformStyle.isEmpty()) {
|
|
||||||
handleAttrTransform(transformStyle, elementPainterPath);
|
|
||||||
}
|
|
||||||
painterPath.addPath(elementPainterPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SvgFileLoader::handleLabelPolygon(QPainterPath & painterPath) {
|
void SvgFileLoader::handleLabelPolygon(QPainterPath & painterPath) {
|
||||||
QPainterPath elementPainterPath;
|
|
||||||
QString transformStyle = "";
|
|
||||||
QMap<QString, QString> labelStyle;
|
QMap<QString, QString> labelStyle;
|
||||||
for (auto& attr : xmlReader->attributes()) {
|
for (auto& attr : xmlReader->attributes()) {
|
||||||
if (attr.name().toString() == QLatin1String("points")) {
|
if (attr.name().toString() == QLatin1String("points")) {
|
||||||
QPolygonF points = handleAttrPoints(attr.value().toLatin1());
|
QPolygonF points = transformPoints(attr.value().toLatin1());
|
||||||
//points.push_back(*points.begin());
|
points.push_back(*points.begin());
|
||||||
elementPainterPath.addPolygon(points);
|
painterPath.addPolygon(points);
|
||||||
elementPainterPath.closeSubpath();
|
|
||||||
}
|
}
|
||||||
else if (attr.name().toString() == QLatin1String("style")) {
|
else if (attr.name().toString() == QLatin1String("style")) {
|
||||||
labelStyle = handleAttrStyle(attr.value().toLatin1());
|
labelStyle = transformStyle(attr.value().toLatin1());
|
||||||
}
|
|
||||||
else if (attr.name().toString() == "transform") {
|
|
||||||
transformStyle = attr.value().toLatin1();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
|
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qDebug() << labelStyle;
|
qDebug() << labelStyle;
|
||||||
if (!transformStyle.isEmpty()) {
|
|
||||||
handleAttrTransform(transformStyle, elementPainterPath);
|
|
||||||
}
|
}
|
||||||
painterPath.addPath(elementPainterPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
void SvgFileLoader::addEllipse(double x, double y, double w, double h, QPainterPath& painterPath) {
|
|
||||||
double k = w / 0.75;
|
|
||||||
painterPath.moveTo(x, y - h);
|
|
||||||
painterPath.cubicTo(QPointF(x + k, y - h), QPointF(x + k, y + h), QPointF(x, y + h));
|
|
||||||
painterPath.cubicTo(QPointF(x - k, y + h), QPointF(x - k, y - h), QPointF(x, y - h));
|
|
||||||
painterPath.closeSubpath();
|
|
||||||
}
|
|
||||||
*/
|
|
|
@ -13,10 +13,8 @@ private:
|
||||||
bool existFatherLabelG;
|
bool existFatherLabelG;
|
||||||
QMap<QString, QString> styleMap;
|
QMap<QString, QString> styleMap;
|
||||||
std::shared_ptr<QXmlStreamReader> xmlReader;
|
std::shared_ptr<QXmlStreamReader> xmlReader;
|
||||||
QPolygonF handleAttrPoints(QString points);
|
QPolygonF transformPoints(QString points);
|
||||||
QMap<QString, QString> handleAttrStyle(QString style);
|
QMap<QString, QString> transformStyle(QString style);
|
||||||
void handleAttrTransform(QString transformStyle, QPainterPath& painterPath);
|
|
||||||
//void addEllipse(double cx, double cy, double h, double w, QPainterPath& painterPath);
|
|
||||||
void handleLabelG(QPainterPath& painterPath);
|
void handleLabelG(QPainterPath& painterPath);
|
||||||
void handleLabelPath(QPainterPath& painterPath);
|
void handleLabelPath(QPainterPath& painterPath);
|
||||||
void handleLabelRect(QPainterPath& painterPath);
|
void handleLabelRect(QPainterPath& painterPath);
|
||||||
|
@ -24,5 +22,4 @@ private:
|
||||||
void handleLabelEllipse(QPainterPath& painterPath);
|
void handleLabelEllipse(QPainterPath& painterPath);
|
||||||
void handleLabelPolyline(QPainterPath& painterPath);
|
void handleLabelPolyline(QPainterPath& painterPath);
|
||||||
void handleLabelPolygon(QPainterPath& painterPath);
|
void handleLabelPolygon(QPainterPath& painterPath);
|
||||||
|
|
||||||
};
|
};
|
|
@ -1,76 +0,0 @@
|
||||||
#include "PainterPathUtil.h"
|
|
||||||
#include <QDebug>
|
|
||||||
#include "../../Renderer/Painting/LineTree.h"
|
|
||||||
|
|
||||||
using Renderer::Point;
|
|
||||||
using Renderer::Line;
|
|
||||||
using std::vector;
|
|
||||||
using std::shared_ptr;
|
|
||||||
|
|
||||||
vector<vector<Point>> PainterPathUtil::transformToLines(const QPainterPath& painterPath) {
|
|
||||||
vector<Point> line; line.clear();
|
|
||||||
vector<vector<Point> > lines; lines.clear();
|
|
||||||
QPointF startPoint(0, 0);
|
|
||||||
Point point(0, 0);
|
|
||||||
for (int elementIndex = 0; elementIndex < painterPath.elementCount(); elementIndex++) {
|
|
||||||
auto element = painterPath.elementAt(elementIndex);
|
|
||||||
point = element;
|
|
||||||
qDebug() << element;
|
|
||||||
if (element.isMoveTo()) {
|
|
||||||
if (line.size() >= 2) {
|
|
||||||
lines.push_back(line);
|
|
||||||
}
|
|
||||||
line.clear();
|
|
||||||
line.push_back(point);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
line.push_back(point);
|
|
||||||
if (element.isLineTo()) {
|
|
||||||
lines.push_back(line);
|
|
||||||
}
|
|
||||||
if (element.isCurveTo()) {
|
|
||||||
point = painterPath.elementAt(++elementIndex);
|
|
||||||
line.push_back(point);
|
|
||||||
point = painterPath.elementAt(++elementIndex);
|
|
||||||
line.push_back(point);
|
|
||||||
lines.push_back(line);
|
|
||||||
}
|
|
||||||
line.clear();
|
|
||||||
line.push_back(point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
line.clear();
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPainterPath PainterPathUtil::monotonization(QPainterPath& painterPath) {
|
|
||||||
QPainterPath resPath;
|
|
||||||
vector<vector<Point> > lines = transformToLines(painterPath);
|
|
||||||
vector<shared_ptr<Line>> linePtrVector;
|
|
||||||
Renderer::LineTree::monotonization(lines, linePtrVector);
|
|
||||||
Point lastPoint(std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity());
|
|
||||||
for (auto& linePtr : linePtrVector) {
|
|
||||||
vector<Point> line = linePtr->toPointVector();
|
|
||||||
if (line[0] != lastPoint)
|
|
||||||
resPath.moveTo(line[0]);
|
|
||||||
if (line.size() == 2)
|
|
||||||
resPath.lineTo(line[1]);
|
|
||||||
else if (line.size() == 4)
|
|
||||||
resPath.cubicTo(line[1], line[2], line[3]);
|
|
||||||
lastPoint = line.back();
|
|
||||||
}
|
|
||||||
return resPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<QPainterPath, float> PainterPathUtil::normalized(const QPainterPath& path)
|
|
||||||
{
|
|
||||||
auto rect = path.boundingRect();
|
|
||||||
return { (QTransform::fromTranslate(-rect.center().x(), -rect.center().y()) * QTransform::fromScale(1 / (rect.width() / 1.999999), -1 / (rect.height() / 1.999999))).map(path),
|
|
||||||
rect.width() / rect.height() };
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<std::vector<std::vector<Renderer::Point>>, float> PainterPathUtil::toNormalizedLines(const QPainterPath& path)
|
|
||||||
{
|
|
||||||
auto [p, ratio] = normalized(path);
|
|
||||||
return { transformToLines(p), ratio };
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <vector>
|
|
||||||
#include <QPainterPath>
|
|
||||||
#include "../Renderer/Painting/Line.h"
|
|
||||||
|
|
||||||
class PainterPathUtil
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static std::vector<std::vector<Renderer::Point>> transformToLines(const QPainterPath& painterPath);
|
|
||||||
static QPainterPath monotonization(QPainterPath& painterPath);
|
|
||||||
static std::pair<QPainterPath, float> normalized(const QPainterPath& path);
|
|
||||||
static std::pair<std::vector<std::vector<Renderer::Point>>, float> toNormalizedLines(const QPainterPath& path);
|
|
||||||
};
|
|
||||||
|
|
|
@ -3,14 +3,8 @@
|
||||||
#include "qslider.h"
|
#include "qslider.h"
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include "NavigationBarWidget.h"
|
#include "NavigationBarWidget.h"
|
||||||
#include <FramelessHelper/Core/utils.h>
|
|
||||||
#include <FramelessHelper/Widgets/standardtitlebar.h>
|
|
||||||
#include <FramelessHelper/Widgets/standardsystembutton.h>
|
|
||||||
#include <FramelessHelper/Widgets/framelesswidgetshelper.h>
|
|
||||||
#include <qDebug>
|
#include <qDebug>
|
||||||
|
|
||||||
FRAMELESSHELPER_USE_NAMESPACE
|
|
||||||
|
|
||||||
inline void fontTheme()
|
inline void fontTheme()
|
||||||
{
|
{
|
||||||
QFont defaultFont = qApp->font();
|
QFont defaultFont = qApp->font();
|
||||||
|
@ -113,7 +107,8 @@ CentralWidget::CentralWidget(QWidget* parent) : QMainWindow(parent)
|
||||||
tabBarLayout->setMargin(0);
|
tabBarLayout->setMargin(0);
|
||||||
tabBarLayout->addWidget(navigationBarWidget, 0, Qt::AlignTop | Qt::AlignHCenter);
|
tabBarLayout->addWidget(navigationBarWidget, 0, Qt::AlignTop | Qt::AlignHCenter);
|
||||||
|
|
||||||
QObject::connect(navigationBarWidget->tabs, &QtMaterialTabs::currentChanged, ui.tabWidget, &QTabWidget::setCurrentIndex);
|
QObject::connect(navigationBarWidget->buttonGroup, &QButtonGroup::idClicked,
|
||||||
|
ui.tabWidget, &QTabWidget::setCurrentIndex);
|
||||||
QObject::connect(ui.tabWidget, &QTabWidget::currentChanged,
|
QObject::connect(ui.tabWidget, &QTabWidget::currentChanged,
|
||||||
ui.rendererWidget, &Renderer::RendererWidget::currentTabChanged);
|
ui.rendererWidget, &Renderer::RendererWidget::currentTabChanged);
|
||||||
}
|
}
|
||||||
|
@ -123,54 +118,367 @@ CentralWidget::~CentralWidget()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget* parent, const Qt::WindowFlags flags)
|
MainWindow::MainWindow(QWidget* parent)
|
||||||
|
: QGoodWindow(parent)
|
||||||
{
|
{
|
||||||
m_titleBar = new StandardTitleBar(this);
|
|
||||||
m_titleBar->setWindowIconVisible(true);
|
|
||||||
constexpr int kTitleBarHeight = 28;
|
|
||||||
m_titleBar->setFixedHeight(kTitleBarHeight);
|
|
||||||
m_titleBar->minimizeButton()->setFixedHeight(kTitleBarHeight);
|
|
||||||
m_titleBar->maximizeButton()->setFixedHeight(kTitleBarHeight);
|
|
||||||
m_titleBar->closeButton()->setFixedHeight(kTitleBarHeight);
|
|
||||||
m_titleBar->setTitleFont(QFont(QString("Segoe UI, Microsoft YaHei UI"), 10));
|
|
||||||
m_titleBar->chromePalette()->setTitleBarActiveBackgroundColor(QColor(0,0,0,0));
|
|
||||||
m_titleBar->chromePalette()->setTitleBarInactiveBackgroundColor(QColor(0, 0, 0, 0));
|
|
||||||
|
|
||||||
|
// if the system will draw borders or if this application must do that
|
||||||
|
m_draw_borders = !QGoodWindow::shouldBordersBeDrawnBySystem();
|
||||||
|
|
||||||
|
m_dark = QGoodWindow::isSystemThemeDark();
|
||||||
|
|
||||||
|
// create frameless window
|
||||||
m_window = new FramelessWindow(this);
|
m_window = new FramelessWindow(this);
|
||||||
m_central_widget = new CentralWidget(this);
|
|
||||||
|
m_central_widget = new CentralWidget(m_window);
|
||||||
|
|
||||||
|
// add the mainwindow to our custom frameless window
|
||||||
m_window->ui->windowContent->layout()->addWidget(m_central_widget);
|
m_window->ui->windowContent->layout()->addWidget(m_central_widget);
|
||||||
|
|
||||||
setMenuWidget(m_titleBar);
|
connect(this, &QGoodWindow::windowTitleChanged, this, [=](const QString& title) {
|
||||||
setCentralWidget(m_window);
|
m_window->ui->titleWidget->setText(title);
|
||||||
|
|
||||||
FramelessWidgetsHelper* helper = FramelessWidgetsHelper::get(this);
|
|
||||||
helper->setTitleBarWidget(m_titleBar);
|
|
||||||
#ifndef Q_OS_MACOS
|
|
||||||
helper->setSystemButton(m_titleBar->minimizeButton(), Global::SystemButtonType::Minimize);
|
|
||||||
helper->setSystemButton(m_titleBar->maximizeButton(), Global::SystemButtonType::Maximize);
|
|
||||||
helper->setSystemButton(m_titleBar->closeButton(), Global::SystemButtonType::Close);
|
|
||||||
#endif // Q_OS_MACOS
|
|
||||||
|
|
||||||
connect(helper, &FramelessWidgetsHelper::ready, this, [this, helper]() {
|
|
||||||
helper->moveWindowToDesktopCenter();
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(this, &QGoodWindow::windowIconChanged, this, [=](const QIcon& icon) {
|
||||||
|
m_window->ui->icon->setPixmap(icon.pixmap(16, 16));
|
||||||
|
});
|
||||||
|
int iconWidth = 30;
|
||||||
|
int captionButtonWidth = 45, captionButtonHeight = 30;
|
||||||
|
m_window->ui->icon->setFixedSize(iconWidth, 20);
|
||||||
|
m_window->ui->titleWidget->setFixedHeight(captionButtonHeight);
|
||||||
|
m_window->ui->minimizeButton->setFixedSize(captionButtonWidth, captionButtonHeight);
|
||||||
|
m_window->ui->maximizeButton->setFixedSize(captionButtonWidth, captionButtonHeight);
|
||||||
|
m_window->ui->restoreButton->setFixedSize(captionButtonWidth, captionButtonHeight);
|
||||||
|
m_window->ui->closeButton->setFixedSize(captionButtonWidth, captionButtonHeight);
|
||||||
|
|
||||||
|
m_window->ui->minimizeButton->init(CaptionButton::IconType::Minimize);
|
||||||
|
m_window->ui->maximizeButton->init(CaptionButton::IconType::Maximize);
|
||||||
|
m_window->ui->restoreButton->init(CaptionButton::IconType::Restore);
|
||||||
|
m_window->ui->closeButton->init(CaptionButton::IconType::Close);
|
||||||
|
|
||||||
|
connect(m_window->ui->minimizeButton, &CaptionButton::clicked, this, &MainWindow::showMinimized);
|
||||||
|
connect(m_window->ui->maximizeButton, &CaptionButton::clicked, this, &MainWindow::showMaximized);
|
||||||
|
connect(m_window->ui->restoreButton, &CaptionButton::clicked, this, &MainWindow::showNormal);
|
||||||
|
connect(m_window->ui->closeButton, &CaptionButton::clicked, this, &MainWindow::close);
|
||||||
|
|
||||||
|
connect(this, &QGoodWindow::captionButtonStateChanged, this, &MainWindow::captionButtonStateChanged);
|
||||||
|
|
||||||
|
|
||||||
|
setMargins(captionButtonHeight, iconWidth, 0, captionButtonWidth * 3);
|
||||||
|
|
||||||
|
setCaptionButtonsHandled(true, Qt::TopRightCorner);
|
||||||
|
|
||||||
|
// Overlap close with maximize and maximize with minimize
|
||||||
|
setCloseMask(QRect(captionButtonWidth * 2, 0, rightCaptionButtonsRect().width(), rightCaptionButtonsRect().height()));
|
||||||
|
setMaximizeMask(QRect(captionButtonWidth * 1, 0, rightCaptionButtonsRect().width(), rightCaptionButtonsRect().height()));
|
||||||
|
setMinimizeMask(QRect(0, 0, rightCaptionButtonsRect().width(), rightCaptionButtonsRect().height()));
|
||||||
|
|
||||||
|
auto theme_change_func = [=] {
|
||||||
|
if (m_dark)
|
||||||
|
darkTheme();
|
||||||
|
else
|
||||||
|
lightTheme();
|
||||||
|
|
||||||
|
//Icon color inverse of m_dark to contrast.
|
||||||
|
m_window->ui->minimizeButton->setIconMode(!m_dark);
|
||||||
|
m_window->ui->maximizeButton->setIconMode(!m_dark);
|
||||||
|
m_window->ui->restoreButton->setIconMode(!m_dark);
|
||||||
|
m_window->ui->closeButton->setIconMode(!m_dark);
|
||||||
|
};
|
||||||
|
|
||||||
|
QShortcut* shortcut1 = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_S), this);
|
||||||
|
|
||||||
|
connect(shortcut1, &QShortcut::activated, this, [=] {
|
||||||
|
m_dark = !m_dark;
|
||||||
|
theme_change_func();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(this, &QGoodWindow::systemThemeChanged, this, [=] {
|
||||||
|
m_dark = QGoodWindow::isSystemThemeDark();
|
||||||
|
theme_change_func();
|
||||||
|
});
|
||||||
|
|
||||||
|
theme_change_func();
|
||||||
|
|
||||||
|
|
||||||
setWindowIcon(QIcon(":/images/icon.png"));
|
setWindowIcon(QIcon(":/images/icon.png"));
|
||||||
setWindowTitle("ArchitectureColoredPainting");
|
setWindowTitle("ArchitectureColoredPainting");
|
||||||
|
|
||||||
|
|
||||||
resize(m_central_widget->size());
|
resize(m_central_widget->size());
|
||||||
//setCentralWidget(m_window);
|
setCentralWidget(m_window);
|
||||||
|
|
||||||
//move(QGuiApplication::primaryScreen()->availableGeometry().center() - rect().center());
|
move(QGuiApplication::primaryScreen()->availableGeometry().center() - rect().center());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
void MainWindow::styleWindow()
|
||||||
|
{
|
||||||
|
bool window_active = isActiveWindow();
|
||||||
|
bool window_no_state = windowState().testFlag(Qt::WindowNoState);
|
||||||
|
|
||||||
|
//bool draw_borders = m_draw_borders;
|
||||||
|
bool draw_borders = false;
|
||||||
|
|
||||||
|
if (window_active)
|
||||||
|
{
|
||||||
|
if (window_no_state)
|
||||||
|
{
|
||||||
|
if (draw_borders)
|
||||||
|
{
|
||||||
|
m_window->ui->windowTitlebar->setStyleSheet(
|
||||||
|
QStringLiteral("#windowTitlebar{border: 0px none palette(shadow);}"));
|
||||||
|
m_window->ui->windowFrame->setStyleSheet(
|
||||||
|
QStringLiteral("#windowFrame{border: 1px solid palette(highlight);"
|
||||||
|
"background-color: palette(Window);}"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_window->ui->windowTitlebar->setStyleSheet(
|
||||||
|
QStringLiteral("#windowTitlebar{border: 0px none palette(shadow);}"));
|
||||||
|
m_window->ui->windowFrame->setStyleSheet(
|
||||||
|
QStringLiteral("#windowFrame{border: 0px solid palette(highlight);"
|
||||||
|
"background-color: palette(Window);}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_window->ui->windowTitlebar->setStyleSheet(
|
||||||
|
QStringLiteral("#windowTitlebar{border: 0px none palette(shadow);"
|
||||||
|
"background-color :palette(shadow); height:20px;}"));
|
||||||
|
m_window->ui->windowFrame->setStyleSheet(
|
||||||
|
QStringLiteral("#windowFrame{border: 0px none palette(dark);"
|
||||||
|
"background-color: palette(Window);}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (window_no_state)
|
||||||
|
{
|
||||||
|
if (draw_borders)
|
||||||
|
{
|
||||||
|
m_window->ui->windowTitlebar->setStyleSheet(
|
||||||
|
QStringLiteral("#windowTitlebar{border: 0px none palette(shadow);"
|
||||||
|
"background-color: palette(dark); height:20px;}"));
|
||||||
|
m_window->ui->windowFrame->setStyleSheet(
|
||||||
|
QStringLiteral("#windowFrame{border: 1px solid #000000;"
|
||||||
|
"background-color: palette(Window);}"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_window->ui->windowTitlebar->setStyleSheet(
|
||||||
|
QStringLiteral("#windowTitlebar{border: 0px none palette(shadow);"
|
||||||
|
"background-color: palette(dark); height:20px;}"));
|
||||||
|
m_window->ui->windowFrame->setStyleSheet(
|
||||||
|
QStringLiteral("#windowFrame{border: 0px solid #000000;"
|
||||||
|
"background-color: palette(Window);}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_window->ui->windowTitlebar->setStyleSheet(
|
||||||
|
QStringLiteral("#titlebarWidget{border: 0px none palette(shadow);"
|
||||||
|
"background-color: palette(dark); height: 20px;}"));
|
||||||
|
m_window->ui->windowFrame->setStyleSheet(
|
||||||
|
QStringLiteral("#windowFrame{border: 0px none palette(shadow);"
|
||||||
|
"background-color: palette(Window);}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_window->ui->icon->setActive(window_active);
|
||||||
|
|
||||||
|
m_window->ui->titleWidget->setActive(window_active);
|
||||||
|
|
||||||
|
if (!isMinimized())
|
||||||
|
{
|
||||||
|
m_window->ui->maximizeButton->setVisible(window_no_state);
|
||||||
|
m_window->ui->restoreButton->setVisible(!window_no_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_window->ui->minimizeButton->setActive(window_active);
|
||||||
|
m_window->ui->maximizeButton->setActive(window_active);
|
||||||
|
m_window->ui->restoreButton->setActive(window_active);
|
||||||
|
m_window->ui->closeButton->setActive(window_active);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::captionButtonStateChanged(const QGoodWindow::CaptionButtonState& state)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
// Hover enter
|
||||||
|
case QGoodWindow::CaptionButtonState::MinimizeHoverEnter:
|
||||||
|
{
|
||||||
|
m_window->ui->minimizeButton->setState(QEvent::HoverEnter);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QGoodWindow::CaptionButtonState::MaximizeHoverEnter:
|
||||||
|
{
|
||||||
|
if (!isMaximized())
|
||||||
|
m_window->ui->maximizeButton->setState(QEvent::HoverEnter);
|
||||||
|
else
|
||||||
|
m_window->ui->restoreButton->setState(QEvent::HoverEnter);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QGoodWindow::CaptionButtonState::CloseHoverEnter:
|
||||||
|
{
|
||||||
|
m_window->ui->closeButton->setState(QEvent::HoverEnter);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Hover leave
|
||||||
|
case QGoodWindow::CaptionButtonState::MinimizeHoverLeave:
|
||||||
|
{
|
||||||
|
m_window->ui->minimizeButton->setState(QEvent::HoverLeave);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QGoodWindow::CaptionButtonState::MaximizeHoverLeave:
|
||||||
|
{
|
||||||
|
if (!isMaximized())
|
||||||
|
m_window->ui->maximizeButton->setState(QEvent::HoverLeave);
|
||||||
|
else
|
||||||
|
m_window->ui->restoreButton->setState(QEvent::HoverLeave);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QGoodWindow::CaptionButtonState::CloseHoverLeave:
|
||||||
|
{
|
||||||
|
m_window->ui->closeButton->setState(QEvent::HoverLeave);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Mouse button press
|
||||||
|
case QGoodWindow::CaptionButtonState::MinimizePress:
|
||||||
|
{
|
||||||
|
m_window->ui->minimizeButton->setState(QEvent::MouseButtonPress);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QGoodWindow::CaptionButtonState::MaximizePress:
|
||||||
|
{
|
||||||
|
if (!isMaximized())
|
||||||
|
m_window->ui->maximizeButton->setState(QEvent::MouseButtonPress);
|
||||||
|
else
|
||||||
|
m_window->ui->restoreButton->setState(QEvent::MouseButtonPress);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QGoodWindow::CaptionButtonState::ClosePress:
|
||||||
|
{
|
||||||
|
m_window->ui->closeButton->setState(QEvent::MouseButtonPress);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Mouse button release
|
||||||
|
case QGoodWindow::CaptionButtonState::MinimizeRelease:
|
||||||
|
{
|
||||||
|
m_window->ui->minimizeButton->setState(QEvent::MouseButtonRelease);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QGoodWindow::CaptionButtonState::MaximizeRelease:
|
||||||
|
{
|
||||||
|
if (!isMaximized())
|
||||||
|
m_window->ui->maximizeButton->setState(QEvent::MouseButtonRelease);
|
||||||
|
else
|
||||||
|
m_window->ui->restoreButton->setState(QEvent::MouseButtonRelease);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QGoodWindow::CaptionButtonState::CloseRelease:
|
||||||
|
{
|
||||||
|
m_window->ui->closeButton->setState(QEvent::MouseButtonRelease);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Mouse button clicked
|
||||||
|
case QGoodWindow::CaptionButtonState::MinimizeClicked:
|
||||||
|
{
|
||||||
|
emit m_window->ui->minimizeButton->clicked();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QGoodWindow::CaptionButtonState::MaximizeClicked:
|
||||||
|
{
|
||||||
|
if (!isMaximized())
|
||||||
|
emit m_window->ui->maximizeButton->clicked();
|
||||||
|
else
|
||||||
|
emit m_window->ui->restoreButton->clicked();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QGoodWindow::CaptionButtonState::CloseClicked:
|
||||||
|
{
|
||||||
|
emit m_window->ui->closeButton->clicked();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainWindow::event(QEvent* event)
|
||||||
|
{
|
||||||
|
switch (event->type())
|
||||||
|
{
|
||||||
|
case QEvent::Show:
|
||||||
|
case QEvent::WindowActivate:
|
||||||
|
case QEvent::WindowDeactivate:
|
||||||
|
case QEvent::WindowStateChange:
|
||||||
|
{
|
||||||
|
styleWindow();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QEvent::StyleChange:
|
||||||
|
{
|
||||||
|
QColor active_color = qApp->palette().color(QPalette::WindowText);
|
||||||
|
QColor inactive_color = qApp->palette().color(QPalette::Disabled, QPalette::WindowText);
|
||||||
|
|
||||||
|
m_window->ui->titleWidget->setTitleColor(active_color, inactive_color);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QGoodWindow::event(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, long* result)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
MSG* msg = static_cast<MSG*>(message);
|
||||||
|
|
||||||
|
switch (msg->message)
|
||||||
|
{
|
||||||
|
case WM_THEMECHANGED:
|
||||||
|
case WM_DWMCOMPOSITIONCHANGED:
|
||||||
|
{
|
||||||
|
//Keep window theme on Windows theme change events.
|
||||||
|
QTimer::singleShot(1000, this, [=] {
|
||||||
|
if (m_dark)
|
||||||
|
darkTheme();
|
||||||
|
else
|
||||||
|
lightTheme();
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return QGoodWindow::nativeEvent(eventType, message, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::closeEvent(QCloseEvent* event)
|
void MainWindow::closeEvent(QCloseEvent* event)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,12 +4,8 @@
|
||||||
#include "ui_MainWindow.h"
|
#include "ui_MainWindow.h"
|
||||||
#include "ui_FramelessWindow.h"
|
#include "ui_FramelessWindow.h"
|
||||||
|
|
||||||
#include <FramelessHelper/Widgets/framelessmainwindow.h>
|
#define QGOODWINDOW
|
||||||
|
#include <QGoodWindow>
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
|
||||||
class StandardTitleBar;
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
|
||||||
|
|
||||||
|
|
||||||
class FramelessWindow : public QWidget
|
class FramelessWindow : public QWidget
|
||||||
{
|
{
|
||||||
|
@ -35,21 +31,26 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class MainWindow : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessMainWindow)
|
class MainWindow : public QGoodWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY_MOVE(MainWindow)
|
|
||||||
public:
|
public:
|
||||||
explicit MainWindow(QWidget * parent = nullptr, const Qt::WindowFlags flags = {});
|
explicit MainWindow(QWidget* parent = nullptr);
|
||||||
~MainWindow() override;
|
~MainWindow();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FRAMELESSHELPER_PREPEND_NAMESPACE(StandardTitleBar)* m_titleBar = nullptr;
|
//Functions
|
||||||
Ui::MainWindowClass ui;
|
void styleWindow();
|
||||||
|
void captionButtonStateChanged(const QGoodWindow::CaptionButtonState& state);
|
||||||
|
bool event(QEvent* event);
|
||||||
|
bool nativeEvent(const QByteArray& eventType, void* message, long* result);
|
||||||
|
|
||||||
void closeEvent(QCloseEvent* event);
|
void closeEvent(QCloseEvent* event);
|
||||||
|
|
||||||
|
//Variables
|
||||||
FramelessWindow* m_window;
|
FramelessWindow* m_window;
|
||||||
|
|
||||||
CentralWidget* m_central_widget;
|
CentralWidget* m_central_widget;
|
||||||
|
bool m_draw_borders;
|
||||||
|
bool m_dark;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,24 +1,14 @@
|
||||||
#include "NavigationBarWidget.h"
|
#include "NavigationBarWidget.h"
|
||||||
#include <qtmaterialraisedbutton.h>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
NavigationBarWidget::NavigationBarWidget(QWidget *parent)
|
NavigationBarWidget::NavigationBarWidget(QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, tabs(new QtMaterialTabs)
|
|
||||||
{
|
{
|
||||||
tabs->addTab(QStringLiteral("ÎÆÀí±à¼"));
|
ui.setupUi(this);
|
||||||
tabs->addTab(QStringLiteral("³¡¾°äÖȾ"));
|
buttonGroup = new QButtonGroup(this);
|
||||||
tabs->setHaloVisible(false);
|
buttonGroup->addButton(ui.radioButton0, 0);
|
||||||
tabs->setBackgroundColor(Qt::transparent);
|
buttonGroup->addButton(ui.radioButton1, 1);
|
||||||
tabs->setTextColor(Qt::black);
|
ui.radioButton0->setChecked(true);
|
||||||
tabs->setInkColor(QColor(0, 90, 158));
|
;}
|
||||||
tabs->setFixedHeight(38);
|
|
||||||
QVBoxLayout* layout = new QVBoxLayout;
|
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
layout->addWidget(tabs);
|
|
||||||
layout->setAlignment(tabs, Qt::AlignHCenter);
|
|
||||||
setLayout(layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
NavigationBarWidget::~NavigationBarWidget()
|
NavigationBarWidget::~NavigationBarWidget()
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QButtonGroup>
|
#include <QButtonGroup>
|
||||||
#include <qtmaterialtabs.h>
|
|
||||||
#include "ui_NavigationBarWidget.h"
|
#include "ui_NavigationBarWidget.h"
|
||||||
|
|
||||||
class NavigationBarWidget : public QWidget
|
class NavigationBarWidget : public QWidget
|
||||||
|
@ -12,5 +11,8 @@ class NavigationBarWidget : public QWidget
|
||||||
public:
|
public:
|
||||||
NavigationBarWidget(QWidget *parent = nullptr);
|
NavigationBarWidget(QWidget *parent = nullptr);
|
||||||
~NavigationBarWidget();
|
~NavigationBarWidget();
|
||||||
QtMaterialTabs* tabs;
|
QButtonGroup* buttonGroup;
|
||||||
|
private:
|
||||||
|
Ui::NavigationBarWidgetClass ui;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,426 +0,0 @@
|
||||||
#include "IblUtils.h"
|
|
||||||
#include <QOpenGLShaderProgram>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <array>
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#ifndef STB_IMAGE_IMPLEMENTATION
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
|
||||||
#include <stb_image.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void Renderer::IblUtils::renderCube(QOpenGLFunctions_4_5_Core* glFunc)
|
|
||||||
{
|
|
||||||
static GLuint cubeVAO = 0, cubeVBO = 0;
|
|
||||||
// initialize (if necessary)
|
|
||||||
if (cubeVAO == 0)
|
|
||||||
{
|
|
||||||
float vertices[] = {
|
|
||||||
// back face
|
|
||||||
-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left
|
|
||||||
1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right
|
|
||||||
1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right
|
|
||||||
1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right
|
|
||||||
-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left
|
|
||||||
-1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, // top-left
|
|
||||||
// front face
|
|
||||||
-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left
|
|
||||||
1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right
|
|
||||||
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right
|
|
||||||
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right
|
|
||||||
-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left
|
|
||||||
-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left
|
|
||||||
// left face
|
|
||||||
-1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right
|
|
||||||
-1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left
|
|
||||||
-1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left
|
|
||||||
-1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left
|
|
||||||
-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right
|
|
||||||
-1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right
|
|
||||||
// right face
|
|
||||||
1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left
|
|
||||||
1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right
|
|
||||||
1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right
|
|
||||||
1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right
|
|
||||||
1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left
|
|
||||||
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left
|
|
||||||
// bottom face
|
|
||||||
-1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right
|
|
||||||
1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left
|
|
||||||
1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left
|
|
||||||
1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left
|
|
||||||
-1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right
|
|
||||||
-1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right
|
|
||||||
// top face
|
|
||||||
-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left
|
|
||||||
1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right
|
|
||||||
1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right
|
|
||||||
1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right
|
|
||||||
-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left
|
|
||||||
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left
|
|
||||||
};
|
|
||||||
glFunc->glGenVertexArrays(1, &cubeVAO);
|
|
||||||
glFunc->glGenBuffers(1, &cubeVBO);
|
|
||||||
// fill buffer
|
|
||||||
glFunc->glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
|
||||||
glFunc->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
|
||||||
// link vertex attributes
|
|
||||||
glFunc->glBindVertexArray(cubeVAO);
|
|
||||||
glFunc->glEnableVertexAttribArray(0);
|
|
||||||
glFunc->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
|
|
||||||
glFunc->glEnableVertexAttribArray(1);
|
|
||||||
glFunc->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
|
|
||||||
glFunc->glEnableVertexAttribArray(2);
|
|
||||||
glFunc->glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
|
|
||||||
glFunc->glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
glFunc->glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
// render Cube
|
|
||||||
glFunc->glBindVertexArray(cubeVAO);
|
|
||||||
glFunc->glDrawArrays(GL_TRIANGLES, 0, 36);
|
|
||||||
glFunc->glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::IblUtils::renderSphere(QOpenGLFunctions_4_5_Core* glFunc)
|
|
||||||
{
|
|
||||||
static unsigned int sphereVAO = 0;
|
|
||||||
static unsigned int indexCount;
|
|
||||||
if (sphereVAO == 0)
|
|
||||||
{
|
|
||||||
glFunc->glGenVertexArrays(1, &sphereVAO);
|
|
||||||
|
|
||||||
unsigned int vbo, ebo;
|
|
||||||
glFunc->glGenBuffers(1, &vbo);
|
|
||||||
glFunc->glGenBuffers(1, &ebo);
|
|
||||||
|
|
||||||
std::vector<glm::vec3> positions;
|
|
||||||
std::vector<glm::vec2> uv;
|
|
||||||
std::vector<glm::vec3> normals;
|
|
||||||
std::vector<unsigned int> indices;
|
|
||||||
|
|
||||||
const unsigned int X_SEGMENTS = 64;
|
|
||||||
const unsigned int Y_SEGMENTS = 64;
|
|
||||||
const float PI = 3.14159265359f;
|
|
||||||
for (unsigned int x = 0; x <= X_SEGMENTS; ++x)
|
|
||||||
{
|
|
||||||
for (unsigned int y = 0; y <= Y_SEGMENTS; ++y)
|
|
||||||
{
|
|
||||||
float xSegment = (float)x / (float)X_SEGMENTS;
|
|
||||||
float ySegment = (float)y / (float)Y_SEGMENTS;
|
|
||||||
float xPos = std::cos(xSegment * 2.0f * PI) * std::sin(ySegment * PI);
|
|
||||||
float yPos = std::cos(ySegment * PI);
|
|
||||||
float zPos = std::sin(xSegment * 2.0f * PI) * std::sin(ySegment * PI);
|
|
||||||
|
|
||||||
positions.push_back(glm::vec3(xPos, yPos, zPos));
|
|
||||||
uv.push_back(glm::vec2(xSegment, ySegment));
|
|
||||||
normals.push_back(glm::vec3(xPos, yPos, zPos));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool oddRow = false;
|
|
||||||
for (unsigned int y = 0; y < Y_SEGMENTS; ++y)
|
|
||||||
{
|
|
||||||
if (!oddRow) // even rows: y == 0, y == 2; and so on
|
|
||||||
{
|
|
||||||
for (unsigned int x = 0; x <= X_SEGMENTS; ++x)
|
|
||||||
{
|
|
||||||
indices.push_back(y * (X_SEGMENTS + 1) + x);
|
|
||||||
indices.push_back((y + 1) * (X_SEGMENTS + 1) + x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int x = X_SEGMENTS; x >= 0; --x)
|
|
||||||
{
|
|
||||||
indices.push_back((y + 1) * (X_SEGMENTS + 1) + x);
|
|
||||||
indices.push_back(y * (X_SEGMENTS + 1) + x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
oddRow = !oddRow;
|
|
||||||
}
|
|
||||||
indexCount = static_cast<unsigned int>(indices.size());
|
|
||||||
|
|
||||||
std::vector<float> data;
|
|
||||||
for (unsigned int i = 0; i < positions.size(); ++i)
|
|
||||||
{
|
|
||||||
data.push_back(positions[i].x);
|
|
||||||
data.push_back(positions[i].y);
|
|
||||||
data.push_back(positions[i].z);
|
|
||||||
if (normals.size() > 0)
|
|
||||||
{
|
|
||||||
data.push_back(normals[i].x);
|
|
||||||
data.push_back(normals[i].y);
|
|
||||||
data.push_back(normals[i].z);
|
|
||||||
}
|
|
||||||
if (uv.size() > 0)
|
|
||||||
{
|
|
||||||
data.push_back(uv[i].x);
|
|
||||||
data.push_back(uv[i].y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glFunc->glBindVertexArray(sphereVAO);
|
|
||||||
glFunc->glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
||||||
glFunc->glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(float), &data[0], GL_STATIC_DRAW);
|
|
||||||
glFunc->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
|
||||||
glFunc->glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
|
|
||||||
unsigned int stride = (3 + 2 + 3) * sizeof(float);
|
|
||||||
glFunc->glEnableVertexAttribArray(0);
|
|
||||||
glFunc->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0);
|
|
||||||
glFunc->glEnableVertexAttribArray(1);
|
|
||||||
glFunc->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)(3 * sizeof(float)));
|
|
||||||
glFunc->glEnableVertexAttribArray(2);
|
|
||||||
glFunc->glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)(6 * sizeof(float)));
|
|
||||||
}
|
|
||||||
|
|
||||||
glFunc->glBindVertexArray(sphereVAO);
|
|
||||||
glFunc->glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::tuple<GLuint, GLuint, GLuint, GLuint> Renderer::IblUtils::precomputeCubemaps(QOpenGLFunctions_4_5_Core* glFunc)
|
|
||||||
{
|
|
||||||
// pbr: setup framebuffer
|
|
||||||
// ----------------------
|
|
||||||
unsigned int captureFBO;
|
|
||||||
unsigned int captureRBO;
|
|
||||||
glFunc->glCreateFramebuffers(1, &captureFBO);
|
|
||||||
glFunc->glCreateRenderbuffers(1, &captureRBO);
|
|
||||||
|
|
||||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
|
||||||
glFunc->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, captureRBO);
|
|
||||||
|
|
||||||
// pbr: set up projection and view matrices for capturing data onto the 6 cubemap face directions
|
|
||||||
// ----------------------------------------------------------------------------------------------
|
|
||||||
QMatrix4x4 captureProjection;
|
|
||||||
captureProjection.perspective(90.0f, 1.0f, 0.1f, 10.0f);
|
|
||||||
std::array<QMatrix4x4, 6> captureViews;
|
|
||||||
captureViews[0].lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(1.0f, 0.0f, 0.0f), QVector3D(0.0f, -1.0f, 0.0f));
|
|
||||||
captureViews[1].lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(-1.0f, 0.0f, 0.0f), QVector3D(0.0f, -1.0f, 0.0f));
|
|
||||||
captureViews[2].lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, 1.0f, 0.0f), QVector3D(0.0f, 0.0f, 1.0f));
|
|
||||||
captureViews[3].lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, -1.0f, 0.0f), QVector3D(0.0f, 0.0f, -1.0f));
|
|
||||||
captureViews[4].lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, 0.0f, 1.0f), QVector3D(0.0f, -1.0f, 0.0f));
|
|
||||||
captureViews[5].lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, 0.0f, -1.0f), QVector3D(0.0f, -1.0f, 0.0f));
|
|
||||||
|
|
||||||
GLuint envCubemap = generateCubemap(glFunc, captureFBO, captureRBO, captureProjection, captureViews);
|
|
||||||
GLuint irradianceMap = generateIrradianceMap(glFunc, captureFBO, captureRBO, captureProjection, captureViews, envCubemap);
|
|
||||||
GLuint prefilterMap = generatePrefilterMap(glFunc, captureFBO, captureRBO, captureProjection, captureViews, envCubemap);
|
|
||||||
GLuint brdfLut = gererateBrdfLut(glFunc);
|
|
||||||
return { envCubemap, irradianceMap, prefilterMap, brdfLut };
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint Renderer::IblUtils::generateCubemap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& captureViews)
|
|
||||||
{
|
|
||||||
// pbr: load the HDR environment map
|
|
||||||
// ---------------------------------
|
|
||||||
stbi_set_flip_vertically_on_load(true);
|
|
||||||
int width, height, nrComponents;
|
|
||||||
float* data = stbi_loadf("HDRI/clarens_midday_4k.hdr", &width, &height, &nrComponents, 0);
|
|
||||||
unsigned int hdrTexture = 0;
|
|
||||||
if (data)
|
|
||||||
{
|
|
||||||
glFunc->glGenTextures(1, &hdrTexture);
|
|
||||||
glFunc->glBindTexture(GL_TEXTURE_2D, hdrTexture);
|
|
||||||
glFunc->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, data);
|
|
||||||
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
|
|
||||||
stbi_image_free(data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
qDebug() << "Failed to load HDR image.";
|
|
||||||
|
|
||||||
// pbr: setup cubemap to render to and attach to framebuffer
|
|
||||||
// ---------------------------------------------------------
|
|
||||||
unsigned int envCubemap;
|
|
||||||
glFunc->glGenTextures(1, &envCubemap);
|
|
||||||
glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);
|
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
|
||||||
{
|
|
||||||
glFunc->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, cubemapSize, cubemapSize, 0, GL_RGB, GL_FLOAT, nullptr);
|
|
||||||
}
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // enable pre-filter mipmap sampling (combatting visible dots artifact)
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
|
|
||||||
|
|
||||||
// pbr: convert HDR equirectangular environment map to cubemap equivalent
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
QOpenGLShaderProgram shader;
|
|
||||||
if (!shader.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/cubemap.vert"))
|
|
||||||
qDebug() << "ERROR:" << shader.log();
|
|
||||||
if (!shader.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/cubemap.frag"))
|
|
||||||
qDebug() << "ERROR:" << shader.log();
|
|
||||||
if (!shader.link())
|
|
||||||
qDebug() << "ERROR:" << shader.log();
|
|
||||||
shader.bind();
|
|
||||||
shader.setUniformValue("equirectangularMap", 0);
|
|
||||||
shader.setUniformValue("projection", captureProjection);
|
|
||||||
glFunc->glActiveTexture(GL_TEXTURE0);
|
|
||||||
glFunc->glBindTexture(GL_TEXTURE_2D, hdrTexture);
|
|
||||||
|
|
||||||
glFunc->glBindRenderbuffer(GL_RENDERBUFFER, captureRBO);
|
|
||||||
glFunc->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, cubemapSize, cubemapSize);
|
|
||||||
glFunc->glViewport(0, 0, cubemapSize, cubemapSize);
|
|
||||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
|
||||||
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
|
||||||
{
|
|
||||||
shader.setUniformValue("view", captureViews[i]);
|
|
||||||
glFunc->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, envCubemap, 0);
|
|
||||||
glFunc->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
renderCube(glFunc);
|
|
||||||
}
|
|
||||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
|
|
||||||
// then let OpenGL generate mipmaps from first mip face (combatting visible dots artifact)
|
|
||||||
glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);
|
|
||||||
glFunc->glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
|
||||||
|
|
||||||
return envCubemap;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint Renderer::IblUtils::generateIrradianceMap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& captureViews, GLuint envCubemap)
|
|
||||||
{
|
|
||||||
// pbr: create an irradiance cubemap, and re-scale capture FBO to irradiance scale.
|
|
||||||
// --------------------------------------------------------------------------------
|
|
||||||
unsigned int irradianceMap;
|
|
||||||
glFunc->glGenTextures(1, &irradianceMap);
|
|
||||||
glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, irradianceMap);
|
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
|
||||||
{
|
|
||||||
glFunc->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, irradianceMapSize, irradianceMapSize, 0, GL_RGB, GL_FLOAT, nullptr);
|
|
||||||
}
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
|
|
||||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
|
||||||
glFunc->glBindRenderbuffer(GL_RENDERBUFFER, captureRBO);
|
|
||||||
glFunc->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, irradianceMapSize, irradianceMapSize);
|
|
||||||
|
|
||||||
// pbr: solve diffuse integral by convolution to create an irradiance (cube)map.
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
QOpenGLShaderProgram irradianceShader;
|
|
||||||
if (!irradianceShader.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/cubemap.vert"))
|
|
||||||
qDebug() << "ERROR:" << irradianceShader.log();
|
|
||||||
if (!irradianceShader.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/irradiance_convolution.frag"))
|
|
||||||
qDebug() << "ERROR:" << irradianceShader.log();
|
|
||||||
if (!irradianceShader.link())
|
|
||||||
qDebug() << "ERROR:" << irradianceShader.log();
|
|
||||||
irradianceShader.bind();
|
|
||||||
irradianceShader.setUniformValue("environmentMap", 0);
|
|
||||||
irradianceShader.setUniformValue("projection", captureProjection);
|
|
||||||
glFunc->glActiveTexture(GL_TEXTURE0);
|
|
||||||
glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);
|
|
||||||
|
|
||||||
glFunc->glViewport(0, 0, irradianceMapSize, irradianceMapSize); // don't forget to configure the viewport to the capture dimensions.
|
|
||||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
|
||||||
{
|
|
||||||
irradianceShader.setUniformValue("view", captureViews[i]);
|
|
||||||
glFunc->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradianceMap, 0);
|
|
||||||
glFunc->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
renderCube(glFunc);
|
|
||||||
}
|
|
||||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
return irradianceMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint Renderer::IblUtils::generatePrefilterMap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& captureViews, GLuint envCubemap)
|
|
||||||
{
|
|
||||||
// pbr: create a pre-filter cubemap, and re-scale capture FBO to pre-filter scale.
|
|
||||||
// --------------------------------------------------------------------------------
|
|
||||||
unsigned int prefilterMap;
|
|
||||||
glFunc->glGenTextures(1, &prefilterMap);
|
|
||||||
glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, prefilterMap);
|
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
|
||||||
{
|
|
||||||
glFunc->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, prefilterMapSize, prefilterMapSize, 0, GL_RGB, GL_FLOAT, nullptr);
|
|
||||||
}
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // be sure to set minification filter to mip_linear
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
// generate mipmaps for the cubemap so OpenGL automatically allocates the required memory.
|
|
||||||
glFunc->glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
|
||||||
|
|
||||||
// pbr: run a quasi monte-carlo simulation on the environment lighting to create a prefilter (cube)map.
|
|
||||||
// ----------------------------------------------------------------------------------------------------
|
|
||||||
QOpenGLShaderProgram prefilterShader;
|
|
||||||
if (!prefilterShader.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/cubemap.vert"))
|
|
||||||
qDebug() << "ERROR:" << prefilterShader.log();
|
|
||||||
if (!prefilterShader.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/cubemap_prefilter.frag"))
|
|
||||||
qDebug() << "ERROR:" << prefilterShader.log();
|
|
||||||
if (!prefilterShader.link())
|
|
||||||
qDebug() << "ERROR:" << prefilterShader.log();
|
|
||||||
prefilterShader.bind();
|
|
||||||
prefilterShader.setUniformValue("environmentMap", 0);
|
|
||||||
prefilterShader.setUniformValue("projection", captureProjection);
|
|
||||||
glFunc->glActiveTexture(GL_TEXTURE0);
|
|
||||||
glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);
|
|
||||||
|
|
||||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
|
||||||
unsigned int maxMipLevels = 5;
|
|
||||||
for (unsigned int mip = 0; mip < maxMipLevels; ++mip)
|
|
||||||
{
|
|
||||||
// reisze framebuffer according to mip-level size.
|
|
||||||
unsigned int mipWidth = static_cast<unsigned int>(prefilterMapSize * std::pow(0.5, mip));
|
|
||||||
unsigned int mipHeight = static_cast<unsigned int>(prefilterMapSize * std::pow(0.5, mip));
|
|
||||||
glFunc->glBindRenderbuffer(GL_RENDERBUFFER, captureRBO);
|
|
||||||
glFunc->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight);
|
|
||||||
glFunc->glViewport(0, 0, mipWidth, mipHeight);
|
|
||||||
|
|
||||||
float roughness = (float)mip / (float)(maxMipLevels - 1);
|
|
||||||
prefilterShader.setUniformValue("roughness", roughness);
|
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
|
||||||
{
|
|
||||||
prefilterShader.setUniformValue("view", captureViews[i]);
|
|
||||||
glFunc->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilterMap, mip);
|
|
||||||
|
|
||||||
glFunc->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
renderCube(glFunc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
return prefilterMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint Renderer::IblUtils::gererateBrdfLut(QOpenGLFunctions_4_5_Core* glFunc)
|
|
||||||
{
|
|
||||||
constexpr int lutSize = 512;
|
|
||||||
|
|
||||||
// pbr: generate a 2D LUT from the BRDF equations used.
|
|
||||||
// ----------------------------------------------------
|
|
||||||
unsigned int brdfLUTTexture;
|
|
||||||
glFunc->glGenTextures(1, &brdfLUTTexture);
|
|
||||||
|
|
||||||
// pre-allocate enough memory for the LUT texture.
|
|
||||||
glFunc->glBindTexture(GL_TEXTURE_2D, brdfLUTTexture);
|
|
||||||
glFunc->glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, lutSize, lutSize, 0, GL_RG, GL_FLOAT, 0);
|
|
||||||
// be sure to set wrapping mode to GL_CLAMP_TO_EDGE
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
|
|
||||||
QOpenGLShaderProgram brdfShader;
|
|
||||||
if (!brdfShader.addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/brdf_lut.comp"))
|
|
||||||
qDebug() << "ERROR:" << brdfShader.log();
|
|
||||||
if (!brdfShader.link())
|
|
||||||
qDebug() << "ERROR:" << brdfShader.log();
|
|
||||||
brdfShader.bind();
|
|
||||||
glFunc->glBindImageTexture(0, brdfLUTTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG16F);
|
|
||||||
glFunc->glDispatchCompute(ceil(lutSize / 8.), ceil(lutSize / 8.), 1);
|
|
||||||
brdfShader.release();
|
|
||||||
return brdfLUTTexture;
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <QOpenGLFunctions_4_5_Core>
|
|
||||||
|
|
||||||
namespace Renderer
|
|
||||||
{
|
|
||||||
class IblUtils
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static constexpr int cubemapSize = 1024;
|
|
||||||
static constexpr int irradianceMapSize = 32;
|
|
||||||
static constexpr int prefilterMapSize = 128;
|
|
||||||
static void renderCube(QOpenGLFunctions_4_5_Core* glFunc);
|
|
||||||
static void renderSphere(QOpenGLFunctions_4_5_Core* glFunc);
|
|
||||||
/**
|
|
||||||
* @brief
|
|
||||||
* @return GLuint envCubemap
|
|
||||||
* @return GLuint irradianceMap
|
|
||||||
* @return GLuint prefilterMap
|
|
||||||
* @return GLuint brdfLut
|
|
||||||
*/
|
|
||||||
static std::tuple<GLuint, GLuint, GLuint, GLuint> precomputeCubemaps(QOpenGLFunctions_4_5_Core* glFunc);
|
|
||||||
private:
|
|
||||||
static GLuint generateCubemap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& captureViews);
|
|
||||||
static GLuint generateIrradianceMap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& captureViews, GLuint envCubemap);
|
|
||||||
static GLuint generatePrefilterMap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& captureViews, GLuint envCubemap);
|
|
||||||
static GLuint gererateBrdfLut(QOpenGLFunctions_4_5_Core* glFunc);
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -83,7 +83,6 @@ QMatrix4x4 Light::getLightSpaceMatrix(const float nearPlane, const float farPlan
|
||||||
minZ = std::min(minZ, -trf.z());
|
minZ = std::min(minZ, -trf.z());
|
||||||
maxZ = std::max(maxZ, -trf.z());
|
maxZ = std::max(maxZ, -trf.z());
|
||||||
}
|
}
|
||||||
if (model != nullptr)
|
|
||||||
for (const QVector3D& v : model->AABB)
|
for (const QVector3D& v : model->AABB)
|
||||||
{
|
{
|
||||||
const QVector4D trf = lightView * QVector4D(v, 1);
|
const QVector4D trf = lightView * QVector4D(v, 1);
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Renderer
|
||||||
std::vector<float> shadowCascadeLevels;
|
std::vector<float> shadowCascadeLevels;
|
||||||
float blendRatio = 0.3;
|
float blendRatio = 0.3;
|
||||||
std::vector<float> frustumSizes;
|
std::vector<float> frustumSizes;
|
||||||
Model* model = nullptr;
|
Model* model;
|
||||||
Light(Camera* camera);
|
Light(Camera* camera);
|
||||||
std::vector<QVector4D> getFrustumCornersWorldSpace(const QMatrix4x4& projview);
|
std::vector<QVector4D> getFrustumCornersWorldSpace(const QMatrix4x4& projview);
|
||||||
std::vector<QVector4D> getFrustumCornersWorldSpace(const QMatrix4x4& proj, const QMatrix4x4& view);
|
std::vector<QVector4D> getFrustumCornersWorldSpace(const QMatrix4x4& proj, const QMatrix4x4& view);
|
||||||
|
|
|
@ -1,59 +1,71 @@
|
||||||
#include "Mesh.h"
|
#include "Mesh.h"
|
||||||
#include <qDebug>
|
|
||||||
using namespace Renderer;
|
using namespace Renderer;
|
||||||
|
Mesh::Mesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, aiMatrix4x4 model)
|
||||||
Renderer::Vertex::Vertex(const aiVector3D& position, const aiVector3D& normal, const aiVector3D& texCoords)
|
|
||||||
: Position(position.x, position.y, position.z)
|
|
||||||
, Normal(normal.x, normal.y, normal.z)
|
|
||||||
, TexCoords(texCoords.x, texCoords.y)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Mesh::Mesh(QOpenGLFunctions_4_5_Core* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, const QMatrix4x4& model)
|
|
||||||
: glFunc(glFunc)
|
: glFunc(glFunc)
|
||||||
, shaderProgram(shaderProgram)
|
, shaderProgram(shaderProgram)
|
||||||
, shadowProgram(shadowProgram)
|
, shadowProgram(shadowProgram)
|
||||||
, VBO(QOpenGLBuffer::VertexBuffer)
|
, VBO(QOpenGLBuffer::VertexBuffer)
|
||||||
, EBO(QOpenGLBuffer::IndexBuffer)
|
, EBO(QOpenGLBuffer::IndexBuffer)
|
||||||
, model(model)
|
, model((float*)&model)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//for (int i = 0; i < 4; i++) {
|
||||||
|
// for (int j = 0; j < 4; j++) {
|
||||||
|
// this->model(i, j) = model[i][j];
|
||||||
|
// }
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
void Mesh::draw()
|
void Mesh::draw()
|
||||||
{
|
{
|
||||||
if (shaderProgram->bind())
|
shaderProgram->bind();
|
||||||
|
|
||||||
|
unsigned int diffuseNr = 1;
|
||||||
|
unsigned int specularNr = 1;
|
||||||
|
unsigned int normalNr = 1;
|
||||||
|
unsigned int heightNr = 1;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < textures.size(); i++)
|
||||||
{
|
{
|
||||||
glFunc->glBindTextureUnit(0, textureBasecolor);
|
glFunc->glActiveTexture(GL_TEXTURE0 + i); // 在绑定之前激活相应的纹理单元
|
||||||
glFunc->glBindTextureUnit(1, textureMetallicRoughness);
|
textures[i]->texture.bind();
|
||||||
glFunc->glBindTextureUnit(2, textureNormal);
|
//qDebug() << name + number;
|
||||||
shaderProgram->setUniformValue("texture_basecolor", 0);
|
shaderProgram->setUniformValue(textures[i]->type.toStdString().c_str(), i);
|
||||||
shaderProgram->setUniformValue("texture_metallic_roughness", 1);
|
}
|
||||||
shaderProgram->setUniformValue("texture_normal", 2);
|
// 绘制网格
|
||||||
|
|
||||||
QOpenGLVertexArrayObject::Binder bind(&VAO);
|
QOpenGLVertexArrayObject::Binder bind(&VAO);
|
||||||
shaderProgram->setUniformValue("model", model);
|
shaderProgram->setUniformValue("model", model);
|
||||||
EBO.bind();
|
|
||||||
glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
|
glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
shaderProgram->release();
|
shaderProgram->release();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
void Mesh::drawShadow()
|
void Mesh::drawShadow()
|
||||||
{
|
{
|
||||||
if (shadowProgram->bind())
|
shadowProgram->bind();
|
||||||
|
|
||||||
|
unsigned int diffuseNr = 1;
|
||||||
|
unsigned int specularNr = 1;
|
||||||
|
unsigned int normalNr = 1;
|
||||||
|
unsigned int heightNr = 1;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < textures.size(); i++)
|
||||||
{
|
{
|
||||||
glFunc->glBindTextureUnit(0, textureBasecolor);
|
glFunc->glActiveTexture(GL_TEXTURE0 + i); // 在绑定之前激活相应的纹理单元
|
||||||
shadowProgram->setUniformValue("texture_basecolor", 0);
|
textures[i]->texture.bind();
|
||||||
|
//qDebug() << name + number;
|
||||||
|
shadowProgram->setUniformValue(textures[i]->type.toStdString().c_str(), i);
|
||||||
|
}
|
||||||
|
// 绘制网格
|
||||||
|
|
||||||
QOpenGLVertexArrayObject::Binder bind(&VAO);
|
QOpenGLVertexArrayObject::Binder bind(&VAO);
|
||||||
shadowProgram->setUniformValue("model", model);
|
shadowProgram->setUniformValue("model", model);
|
||||||
EBO.bind();
|
|
||||||
glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
|
glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
shadowProgram->release();
|
shadowProgram->release();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
void Mesh::setupMesh()
|
void Mesh::setupMesh()
|
||||||
{
|
{
|
||||||
|
shaderProgram->bind();
|
||||||
VAO.create();
|
VAO.create();
|
||||||
VAO.bind();
|
VAO.bind();
|
||||||
|
|
||||||
|
@ -66,17 +78,23 @@ void Mesh::setupMesh()
|
||||||
EBO.bind();
|
EBO.bind();
|
||||||
EBO.allocate(indices.data(), indices.size() * sizeof(unsigned int));
|
EBO.allocate(indices.data(), indices.size() * sizeof(unsigned int));
|
||||||
|
|
||||||
if (shaderProgram->bind())
|
|
||||||
{
|
|
||||||
shaderProgram->enableAttributeArray(0);
|
shaderProgram->enableAttributeArray(0);
|
||||||
shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(Vertex));
|
shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(Vertex));
|
||||||
|
|
||||||
shaderProgram->enableAttributeArray(1);
|
shaderProgram->enableAttributeArray(1);
|
||||||
shaderProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(Vertex, Normal), 3, sizeof(Vertex));
|
shaderProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(Vertex, Normal), 3, sizeof(Vertex));
|
||||||
|
|
||||||
shaderProgram->enableAttributeArray(2);
|
shaderProgram->enableAttributeArray(2);
|
||||||
shaderProgram->setAttributeBuffer(2, GL_FLOAT, offsetof(Vertex, TexCoords), 2, sizeof(Vertex));
|
shaderProgram->setAttributeBuffer(2, GL_FLOAT, offsetof(Vertex, TexCoords), 2, sizeof(Vertex));
|
||||||
|
|
||||||
|
shaderProgram->enableAttributeArray(3);
|
||||||
|
shaderProgram->setAttributeBuffer(3, GL_FLOAT, offsetof(Vertex, Tangent), 3, sizeof(Vertex));
|
||||||
|
|
||||||
|
shaderProgram->enableAttributeArray(4);
|
||||||
|
shaderProgram->setAttributeBuffer(4, GL_FLOAT, offsetof(Vertex, Bitangent), 3, sizeof(Vertex));
|
||||||
|
|
||||||
|
VAO.release();
|
||||||
shaderProgram->release();
|
shaderProgram->release();
|
||||||
}
|
}
|
||||||
VAO.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <QOpenGLFunctions_4_5_Core>
|
#include <QOpenGLFunctions_4_5_Compatibility>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QVector2D>
|
#include <QVector2D>
|
||||||
|
@ -9,9 +9,10 @@
|
||||||
#include <QOpenGLVertexArrayObject>
|
#include <QOpenGLVertexArrayObject>
|
||||||
#include <QOpenGLTexture>
|
#include <QOpenGLTexture>
|
||||||
#include <QOpenGLWidget>
|
#include <QOpenGLWidget>
|
||||||
#include <assimp/vector3.h>
|
#include <assimp/Importer.hpp>
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
#include <assimp/postprocess.h>
|
||||||
#include "Drawable.h"
|
#include "Drawable.h"
|
||||||
|
|
||||||
namespace Renderer
|
namespace Renderer
|
||||||
{
|
{
|
||||||
struct Vertex
|
struct Vertex
|
||||||
|
@ -19,7 +20,8 @@ namespace Renderer
|
||||||
QVector3D Position;
|
QVector3D Position;
|
||||||
QVector3D Normal;
|
QVector3D Normal;
|
||||||
QVector2D TexCoords;
|
QVector2D TexCoords;
|
||||||
Vertex(const aiVector3D& position, const aiVector3D& Normal, const aiVector3D& TexCoords);
|
QVector3D Tangent;
|
||||||
|
QVector3D Bitangent;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Texture
|
struct Texture
|
||||||
|
@ -38,23 +40,22 @@ namespace Renderer
|
||||||
class Mesh : public Drawable
|
class Mesh : public Drawable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QVector<Vertex> vertices;
|
/* 网格数据 */
|
||||||
QVector<unsigned int> indices;
|
QVector<Vertex> vertices; //顶点数据
|
||||||
//QVector<Texture*> textures;
|
QVector<unsigned int> indices; //索引数组
|
||||||
GLuint textureBasecolor = 0;
|
QVector<Texture*> textures; //纹理数据
|
||||||
GLuint textureMetallicRoughness = 0;
|
QMatrix4x4 model; //模型矩阵
|
||||||
GLuint textureNormal = 0;
|
QOpenGLFunctions_4_5_Compatibility* glFunc; //opengl函数入口
|
||||||
|
QOpenGLShaderProgram* shaderProgram, * shadowProgram; //着色器程序
|
||||||
|
|
||||||
QMatrix4x4 model;
|
/* 函数 */
|
||||||
QOpenGLFunctions_4_5_Core* glFunc;
|
Mesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, aiMatrix4x4 model);
|
||||||
QOpenGLShaderProgram* shaderProgram, * shadowProgram;
|
|
||||||
|
|
||||||
Mesh(QOpenGLFunctions_4_5_Core* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, const QMatrix4x4& model);
|
|
||||||
void draw() override;
|
void draw() override;
|
||||||
void drawShadow() override;
|
void drawShadow() override;
|
||||||
void setupMesh();
|
void setupMesh();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/* 渲染数据 */
|
||||||
QOpenGLVertexArrayObject VAO;
|
QOpenGLVertexArrayObject VAO;
|
||||||
QOpenGLBuffer VBO, EBO;
|
QOpenGLBuffer VBO, EBO;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
#include <assimp/Importer.hpp>
|
|
||||||
#include <assimp/postprocess.h>
|
|
||||||
#include <QOpenGLTexture>
|
#include <QOpenGLTexture>
|
||||||
#include <QOpenGLContext>
|
#include <QOpenGLContext>
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
|
@ -11,41 +10,16 @@
|
||||||
#include "Painting/ShortCutTree.h"
|
#include "Painting/ShortCutTree.h"
|
||||||
#include "Painting/Painting.h"
|
#include "Painting/Painting.h"
|
||||||
#include "../SvgParser.h"
|
#include "../SvgParser.h"
|
||||||
#include "../Editor/util/PainterPathUtil.h"
|
|
||||||
#include "../Editor/util/SvgFileLoader.h"
|
|
||||||
#include <ThirdPartyLib/qquick/qquicksvgparser_p.h>
|
|
||||||
|
|
||||||
using namespace Renderer;
|
using namespace Renderer;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram)
|
||||||
Model::Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram,
|
|
||||||
QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager)
|
|
||||||
: context(context)
|
: context(context)
|
||||||
, glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Core>())
|
, glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Compatibility>())
|
||||||
, shaderProgram(shaderProgram)
|
, shaderProgram(shaderProgram)
|
||||||
, paintingProgram(paintingProgram)
|
, directory(path)
|
||||||
, shadowProgram(shadowProgram)
|
|
||||||
, vtManager(vtManager)
|
|
||||||
{
|
{
|
||||||
}
|
|
||||||
|
|
||||||
void Model::draw() {
|
|
||||||
//shaderProgram->bind();
|
|
||||||
for (auto& mesh : meshes) {
|
|
||||||
mesh->draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Model::drawShadow() {
|
|
||||||
//shaderProgram->bind();
|
|
||||||
for (auto& mesh : meshes) {
|
|
||||||
mesh->drawShadow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::Model::loadModel(QString path)
|
|
||||||
{
|
|
||||||
directory = path;
|
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
const aiScene* scene = importer.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs);
|
const aiScene* scene = importer.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs);
|
||||||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
|
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
|
||||||
|
@ -58,12 +32,30 @@ void Renderer::Model::loadModel(QString path)
|
||||||
qDebug() << "NumMaterials: " << scene->mNumMaterials;
|
qDebug() << "NumMaterials: " << scene->mNumMaterials;
|
||||||
qDebug() << "NumTextures: " << scene->mNumTextures;
|
qDebug() << "NumTextures: " << scene->mNumTextures;
|
||||||
directory.cdUp();
|
directory.cdUp();
|
||||||
minX = std::numeric_limits<float>::max();
|
processNode(scene->mRootNode, scene);
|
||||||
maxX = std::numeric_limits<float>::min();
|
}
|
||||||
minY = std::numeric_limits<float>::max();
|
|
||||||
maxY = std::numeric_limits<float>::min();
|
Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, PaintingHelper* paintingHelper)
|
||||||
minZ = std::numeric_limits<float>::max();
|
: context(context)
|
||||||
maxZ = std::numeric_limits<float>::min();
|
, glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Compatibility>())
|
||||||
|
, shaderProgram(shaderProgram)
|
||||||
|
, paintingProgram(paintingProgram)
|
||||||
|
, shadowProgram(shadowProgram)
|
||||||
|
, paintingHelper(paintingHelper)
|
||||||
|
, directory(path)
|
||||||
|
{
|
||||||
|
Assimp::Importer importer;
|
||||||
|
const aiScene* scene = importer.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs);
|
||||||
|
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
|
||||||
|
{
|
||||||
|
qDebug() << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qDebug() << directory.absolutePath() << "Loaded Successfully";
|
||||||
|
qDebug() << "NumMeshes: " << scene->mNumMeshes;
|
||||||
|
qDebug() << "NumMaterials: " << scene->mNumMaterials;
|
||||||
|
qDebug() << "NumTextures: " << scene->mNumTextures;
|
||||||
|
directory.cdUp();
|
||||||
processNode(scene->mRootNode, scene);
|
processNode(scene->mRootNode, scene);
|
||||||
AABB.push_back(QVector3D(minX, minY, minZ));
|
AABB.push_back(QVector3D(minX, minY, minZ));
|
||||||
AABB.push_back(QVector3D(minX, minY, maxZ));
|
AABB.push_back(QVector3D(minX, minY, maxZ));
|
||||||
|
@ -75,13 +67,50 @@ void Renderer::Model::loadModel(QString path)
|
||||||
AABB.push_back(QVector3D(maxX, maxY, maxZ));
|
AABB.push_back(QVector3D(maxX, maxY, maxZ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Model::~Model() //销毁对象
|
||||||
|
{
|
||||||
|
for (auto& it : textures_loaded) {
|
||||||
|
it->texture.destroy();
|
||||||
|
delete it;
|
||||||
|
}
|
||||||
|
for (auto& it : meshes) {
|
||||||
|
delete it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::draw() {
|
||||||
|
//shaderProgram->bind();
|
||||||
|
for (Drawable* mesh : meshes) {
|
||||||
|
mesh->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::drawShadow() {
|
||||||
|
//shaderProgram->bind();
|
||||||
|
for (Drawable* mesh : meshes) {
|
||||||
|
mesh->drawShadow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::destroy()
|
||||||
|
{
|
||||||
|
context->doneCurrent();
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Model* Model::createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram)
|
||||||
|
{
|
||||||
|
return new Model(path, context, shaderProgram);
|
||||||
|
}
|
||||||
|
|
||||||
void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4)
|
void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4)
|
||||||
{
|
{
|
||||||
|
|
||||||
// 处理节点所有的网格(如果有的话)
|
// 处理节点所有的网格(如果有的话)
|
||||||
for (unsigned int i = 0; i < node->mNumMeshes; i++)
|
for (unsigned int i = 0; i < node->mNumMeshes; i++)
|
||||||
{
|
{
|
||||||
if (auto mesh = processMesh(scene->mMeshes[node->mMeshes[i]], scene, mat4))
|
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||||
meshes.emplace_back(std::move(mesh));
|
meshes.push_back(processMesh(mesh, scene, mat4));
|
||||||
|
|
||||||
}
|
}
|
||||||
// 接下来对它的子节点重复这一过程
|
// 接下来对它的子节点重复这一过程
|
||||||
|
@ -91,34 +120,55 @@ void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model)
|
GLuint encodeChild(GLuint index)
|
||||||
|
{
|
||||||
|
return 0x80000000 + index;
|
||||||
|
}
|
||||||
|
GLuint encodeZIndexAngle(GLuint zIndex, float angle)
|
||||||
|
{
|
||||||
|
return GLuint(angle / 360 * 65536 + zIndex * 65536);
|
||||||
|
}
|
||||||
|
Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model)
|
||||||
{
|
{
|
||||||
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
|
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
|
||||||
QMatrix4x4 modelQ((float*)&model);
|
|
||||||
|
|
||||||
aiString str;
|
aiString str;
|
||||||
material->GetTexture(aiTextureType_BASE_COLOR, 0, &str);
|
material->GetTexture(aiTextureType_BASE_COLOR, 0, &str);
|
||||||
|
|
||||||
if (paintingProgram != nullptr && (std::strcmp(str.C_Str(), "17876391417123941155.jpg") == 0 || std::strcmp(str.C_Str(), "11474523244911310074.jpg") == 0))
|
if (paintingProgram != nullptr && std::strcmp(str.C_Str(), "17876391417123941155.jpg") == 0)
|
||||||
{
|
{
|
||||||
qDebug() << str.C_Str() << "Replaced";
|
qDebug() << str.C_Str() << "Replaced";
|
||||||
// 初始化网格
|
// 初始化网格
|
||||||
auto m_mesh = std::make_unique<PaintingMesh>(glFunc, paintingProgram, shadowProgram, modelQ);
|
PaintingMesh* m_mesh = new PaintingMesh(glFunc, paintingProgram, shadowProgram, model);
|
||||||
// 遍历网格的每个顶点
|
// 遍历网格的每个顶点
|
||||||
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
|
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
|
||||||
{
|
{
|
||||||
if (mesh->mNormals && mesh->mTextureCoords[0])
|
PaintingVertex vertex;
|
||||||
{
|
vertex.Position = QVector3D(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
|
||||||
Vertex vertex(mesh->mVertices[i], mesh->mNormals[i], mesh->mTextureCoords[0][i]);
|
|
||||||
minX = std::min(minX, vertex.Position.x());
|
minX = std::min(minX, vertex.Position.x());
|
||||||
maxX = std::max(maxX, vertex.Position.x());
|
maxX = std::max(maxX, vertex.Position.x());
|
||||||
minY = std::min(minY, vertex.Position.y());
|
minY = std::min(minY, vertex.Position.y());
|
||||||
maxY = std::max(maxY, vertex.Position.y());
|
maxY = std::max(maxY, vertex.Position.y());
|
||||||
minZ = std::min(minZ, vertex.Position.z());
|
minZ = std::min(minZ, vertex.Position.z());
|
||||||
maxZ = std::max(maxZ, vertex.Position.z());
|
maxZ = std::max(maxZ, vertex.Position.z());
|
||||||
|
|
||||||
|
|
||||||
|
// 法向量
|
||||||
|
if (mesh->mNormals)
|
||||||
|
vertex.Normal = QVector3D(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);
|
||||||
|
|
||||||
|
// 纹理坐标
|
||||||
|
if (mesh->mTextureCoords[0])
|
||||||
|
vertex.TexCoords = QVector2D(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y);
|
||||||
|
|
||||||
|
if (mesh->mTangents)
|
||||||
|
vertex.Tangent = QVector3D(mesh->mTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z);
|
||||||
|
|
||||||
|
if (mesh->mBitangents)
|
||||||
|
vertex.Bitangent = QVector3D(mesh->mBitangents[i].x, mesh->mBitangents[i].y, mesh->mBitangents[i].z);;
|
||||||
|
|
||||||
m_mesh->vertices.push_back(vertex);
|
m_mesh->vertices.push_back(vertex);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
|
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
|
||||||
{
|
{
|
||||||
|
@ -129,82 +179,138 @@ std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_mesh->paintingId = loadPainting(std::string(str.C_Str()));
|
m_mesh->paintingIndex = loadPainting(std::string(str.C_Str()));
|
||||||
auto& handle = vtManager->getPaintingHandle(m_mesh->paintingId);
|
|
||||||
m_mesh->textureBasecolor = handle.baseColor;
|
|
||||||
m_mesh->textureMetallicRoughness = handle.metallicRoughness;
|
|
||||||
m_mesh->setupMesh();
|
m_mesh->setupMesh();
|
||||||
return m_mesh;
|
return m_mesh;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 初始化网格
|
// 初始化网格
|
||||||
auto m_mesh = std::make_unique<Mesh>(glFunc, shaderProgram, shadowProgram, modelQ);
|
Mesh* m_mesh = new Mesh(glFunc, shaderProgram, shadowProgram, model);
|
||||||
// 遍历网格的每个顶点
|
// 遍历网格的每个顶点
|
||||||
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
|
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
|
||||||
{
|
{
|
||||||
if (mesh->mNormals && mesh->mTextureCoords[0])
|
Vertex vertex;
|
||||||
{
|
QVector3D vector; //将assimp的数据转化为QtOpenGL支持的数据
|
||||||
Vertex vertex(mesh->mVertices[i], mesh->mNormals[i], mesh->mTextureCoords[0][i]);
|
|
||||||
|
// 位置
|
||||||
|
vector.setX(mesh->mVertices[i].x);
|
||||||
|
vector.setY(mesh->mVertices[i].y);
|
||||||
|
vector.setZ(mesh->mVertices[i].z);
|
||||||
|
vertex.Position = vector;
|
||||||
minX = std::min(minX, vertex.Position.x());
|
minX = std::min(minX, vertex.Position.x());
|
||||||
maxX = std::max(maxX, vertex.Position.x());
|
maxX = std::max(maxX, vertex.Position.x());
|
||||||
minY = std::min(minY, vertex.Position.y());
|
minY = std::min(minY, vertex.Position.y());
|
||||||
maxY = std::max(maxY, vertex.Position.y());
|
maxY = std::max(maxY, vertex.Position.y());
|
||||||
minZ = std::min(minZ, vertex.Position.z());
|
minZ = std::min(minZ, vertex.Position.z());
|
||||||
maxZ = std::max(maxZ, vertex.Position.z());
|
maxZ = std::max(maxZ, vertex.Position.z());
|
||||||
|
|
||||||
|
|
||||||
|
// 法向量
|
||||||
|
if (mesh->mNormals) {
|
||||||
|
vector.setX(mesh->mNormals[i].x);
|
||||||
|
vector.setY(mesh->mNormals[i].y);
|
||||||
|
vector.setZ(mesh->mNormals[i].z);
|
||||||
|
vertex.Normal = vector;
|
||||||
|
}
|
||||||
|
// 纹理坐标
|
||||||
|
if (mesh->mTextureCoords[0]) // does the mesh contain texture coordinates?
|
||||||
|
{
|
||||||
|
QVector2D vec;
|
||||||
|
//一个顶点最多可以包含8个不同的纹理坐标。因此我们假设我们不用
|
||||||
|
//使用一个顶点可以有多个纹理坐标的模型,所以我们总是取第一个集合(0)。
|
||||||
|
vec.setX(mesh->mTextureCoords[0][i].x);
|
||||||
|
vec.setY(mesh->mTextureCoords[0][i].y);
|
||||||
|
vertex.TexCoords = vec;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vertex.TexCoords = QVector2D(0, 0);
|
||||||
|
}
|
||||||
|
if (mesh->mTangents) {
|
||||||
|
// tangent
|
||||||
|
vector.setX(mesh->mTangents[i].x);
|
||||||
|
vector.setY(mesh->mTangents[i].y);
|
||||||
|
vector.setZ(mesh->mTangents[i].z);
|
||||||
|
vertex.Tangent = vector;
|
||||||
|
}
|
||||||
|
if (mesh->mBitangents) {
|
||||||
|
vector.setX(mesh->mBitangents[i].x);
|
||||||
|
vector.setY(mesh->mBitangents[i].y);
|
||||||
|
vector.setZ(mesh->mBitangents[i].z);
|
||||||
|
vertex.Bitangent = vector;
|
||||||
|
}
|
||||||
|
// bitangent
|
||||||
m_mesh->vertices.push_back(vertex);
|
m_mesh->vertices.push_back(vertex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
|
||||||
|
{
|
||||||
|
aiFace face = mesh->mFaces[i];
|
||||||
|
// 将所有面的索引数据添加到索引数组中
|
||||||
|
for (unsigned int j = 0; j < face.mNumIndices; j++) {
|
||||||
|
m_mesh->indices.push_back(face.mIndices[j]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将所有面的索引数据添加到索引数组中
|
|
||||||
for (auto face = mesh->mFaces; face < mesh->mFaces + mesh->mNumFaces; face++)
|
|
||||||
for (auto indice = face->mIndices; indice < face->mIndices + face->mNumIndices; indice++)
|
|
||||||
m_mesh->indices.push_back(*indice);
|
|
||||||
|
|
||||||
// 处理材质
|
// 处理材质
|
||||||
if (!(m_mesh->textureBasecolor = loadMaterialTextures(material, aiTextureType_BASE_COLOR)))
|
QVector<Texture*> diffuseMaps = loadMaterialTextures(material, aiTextureType_BASE_COLOR, "texture_basecolor");
|
||||||
qWarning() << "Basecolor Texture Loading Failed!";
|
for (auto& it : diffuseMaps)
|
||||||
if (!(m_mesh->textureMetallicRoughness = loadMaterialTextures(material, aiTextureType_METALNESS)))
|
m_mesh->textures.push_back(it);
|
||||||
qWarning() << "MetallicRoughness Texture Loading Failed!";
|
|
||||||
if (!(m_mesh->textureNormal = loadMaterialTextures(material, aiTextureType_NORMALS)))
|
QVector<Texture*> metalnessMaps = loadMaterialTextures(material, aiTextureType_METALNESS, "texture_metallic_roughness");
|
||||||
qWarning() << "Normal Texture Loading Failed!";
|
for (auto& it : metalnessMaps)
|
||||||
|
m_mesh->textures.push_back(it);
|
||||||
|
|
||||||
|
QVector<Texture*> normalMaps = loadMaterialTextures(material, aiTextureType_NORMALS, "texture_normal");
|
||||||
|
for (auto& it : normalMaps)
|
||||||
|
m_mesh->textures.push_back(it);
|
||||||
|
|
||||||
if (m_mesh->textureBasecolor && m_mesh->textureMetallicRoughness && m_mesh->textureNormal)
|
|
||||||
{
|
|
||||||
m_mesh->setupMesh();
|
m_mesh->setupMesh();
|
||||||
return m_mesh;
|
return m_mesh;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type)
|
QVector<Texture*> Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, QString typeName)
|
||||||
{
|
{
|
||||||
/// Mesh只支持单纹理
|
|
||||||
if (!mat->GetTextureCount(type))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
QVector<Texture*> textures;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < mat->GetTextureCount(type); i++)
|
||||||
|
{
|
||||||
|
//qDebug() << typeName;
|
||||||
aiString str;
|
aiString str;
|
||||||
mat->GetTexture(type, 0, &str);
|
mat->GetTexture(type, i, &str);
|
||||||
const std::string path(str.C_Str());
|
|
||||||
auto iter = texturesLoaded.find(path);
|
|
||||||
if (iter != texturesLoaded.end())
|
|
||||||
return iter->second.textureId();
|
|
||||||
|
|
||||||
QImage data(directory.filePath(path.c_str()));
|
// 检查纹理是否在之前加载过,如果是,则继续到下一个迭代:跳过加载新纹理
|
||||||
if (data.isNull())
|
bool skip = false;
|
||||||
return 0;
|
for (unsigned int j = 0; j < textures_loaded.size(); j++)
|
||||||
|
{
|
||||||
//qDebug() << "Loading" << path.c_str();
|
if (std::strcmp(textures_loaded[j]->path.toStdString().c_str(), str.C_Str()) == 0)
|
||||||
auto [it, _] = texturesLoaded.emplace(path, QOpenGLTexture::Target2D);
|
{
|
||||||
auto& texture = it->second;
|
textures.push_back(textures_loaded[j]);
|
||||||
texture.create();
|
skip = true;
|
||||||
texture.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
|
break;
|
||||||
texture.setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);
|
}
|
||||||
texture.setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
|
}
|
||||||
texture.setData(data);
|
if (!skip)
|
||||||
return texture.textureId();
|
{ // 如果材质还没有加载,加载它
|
||||||
|
Texture* texture = new Texture;
|
||||||
|
QImage data(directory.filePath(str.C_Str()));
|
||||||
|
if (!data.isNull()) {
|
||||||
|
texture->texture.setData(data);
|
||||||
|
texture->type = typeName;
|
||||||
|
texture->path = str.C_Str();
|
||||||
|
textures.push_back(texture);
|
||||||
|
textures_loaded.push_back(texture); // store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qDebug() << "未能成功加载纹理:" << directory.filePath(str.C_Str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return textures;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint Renderer::Model::loadPainting(std::string path)
|
GLuint Renderer::Model::loadPainting(std::string path)
|
||||||
|
@ -213,63 +319,219 @@ GLuint Renderer::Model::loadPainting(std::string path)
|
||||||
if (iter != paintingLoaded.end())
|
if (iter != paintingLoaded.end())
|
||||||
return iter->second;
|
return iter->second;
|
||||||
|
|
||||||
//vector<std::shared_ptr<Contour>> contour = {
|
//vector < vector <Point>> lineSet = {
|
||||||
// std::make_shared<Contour>(SvgParser("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", 100, 100).parse()),
|
// {{-0.5,0.9}, {0.1,0.3}},
|
||||||
// std::make_shared<Contour>(SvgParser("M308.49,212.25l23,28.38-82,78.31c-14.28,13.64-26.34-20.6-53.44,9.32l-30.24-13.4,63.56-51.59L190.71,215.6l-32.92,26.72L149.5,232.1l32.92-26.72L173.2,194l-32.91,26.72-7.38-9.08L165.83,185l-38.69-47.66L94.22,164,85,152.65l32.91-26.72-9.21-11.35L75.79,141.3l-5.53-6.81,32.92-26.72L94,96.42,61.05,123.14l-12-14.76L37.72,117.6l12,14.75L30.41,148,0,110.55,136.2,0l30.4,37.46L147.31,53.12l-12-14.76L124,47.58l12,14.75L103.05,89.05l9.21,11.35,32.92-26.72,5.52,6.81-32.91,26.72L127,118.56l32.92-26.72,9.21,11.35-32.91,26.72,38.69,47.67,32.91-26.72,7.37,9.08-32.91,26.72L191.49,198l32.92-26.72,8.29,10.22-32.92,26.71,38.7,47.68L302,204.3l6.45,7.95Z", 331.52, 328.26).parse()),
|
// {{0.1,0.3}, {0.0204656,0.379534}, {-0.2,0.0632573}, {-0.2,0.175736}},
|
||||||
// std::make_shared<Contour>(SvgParser("M377,459.61a11.26,11.26,0,0,1,11.27-11.27H696.12a11.27,11.27,0,0,0,11-8.62A359.84,359.84,0,0,0,708,280.56a11.26,11.26,0,0,0-11-8.73H388.27A11.26,11.26,0,0,1,377,260.57h0a11.26,11.26,0,0,1,11.27-11.26H683.71A11.32,11.32,0,0,0,694.28,234C649.8,113.69,542.57,23.85,412.3,4.12a11.22,11.22,0,0,0-12.76,11.17v158.9a11.26,11.26,0,0,0,11.26,11.27H583.12a11.32,11.32,0,0,0,9.26-17.75c-31.67-46.59-78.51-75.2-109.11-90.07a11.25,11.25,0,0,0-16.13,10.17V115.2a11.24,11.24,0,0,0,6.22,10.07l7.51,3.76a11.28,11.28,0,0,1,5,15.12h0a11.27,11.27,0,0,1-15.11,5l-20-10a11.27,11.27,0,0,1-6.22-10.07V54a11.27,11.27,0,0,1,14.62-10.75c5.11,1.59,125.66,40.35,172.24,149A11.27,11.27,0,0,1,621.11,208H388.27A11.26,11.26,0,0,1,377,196.73V11.36A11.32,11.32,0,0,0,365.89.08C363.34,0,360.79,0,358.22,0s-5.11,0-7.66.08a11.32,11.32,0,0,0-11.11,11.28V196.74A11.26,11.26,0,0,1,328.18,208H95.35A11.27,11.27,0,0,1,85,192.3c46.57-108.67,167.12-147.42,172.23-149A11.26,11.26,0,0,1,271.86,54v75.11a11.25,11.25,0,0,1-6.23,10.07l-20,10a11.27,11.27,0,0,1-15.11-5h0a11.26,11.26,0,0,1,5-15.11l7.52-3.76a11.27,11.27,0,0,0,6.22-10.07V87.82a11.25,11.25,0,0,0-16.14-10.16c-30.6,14.87-77.45,43.48-109.1,90.07a11.3,11.3,0,0,0,9.25,17.74H305.66a11.26,11.26,0,0,0,11.27-11.26V15.31A11.22,11.22,0,0,0,304.17,4.14C173.88,23.86,66.66,113.71,22.17,234a11.32,11.32,0,0,0,10.56,15.29H328.18a11.26,11.26,0,0,1,11.27,11.26v0a11.26,11.26,0,0,1-11.27,11.26H19.52a11.26,11.26,0,0,0-11,8.72,359.84,359.84,0,0,0,.83,159.16,11.26,11.26,0,0,0,11,8.61H328.18a11.26,11.26,0,0,1,11.27,11.27h0a11.26,11.26,0,0,1-11.27,11.26h-294a11.32,11.32,0,0,0-10.53,15.4C69,604.65,175.3,692.78,304.16,712.3a11.21,11.21,0,0,0,12.76-11.16V542.22A11.26,11.26,0,0,0,305.66,531h-166c-9.53,0-14.89,11.22-8.69,18.47,34.09,39.77,74.45,65.66,101.77,80.18a11.25,11.25,0,0,0,16.53-10V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,271.85,591v63.85A11.27,11.27,0,0,1,256.8,665.5c-4.45-1.59-109.58-40-171-139.9a11.27,11.27,0,0,1,9.59-17.17H328.18a11.26,11.26,0,0,1,11.27,11.26V705.08a11.32,11.32,0,0,0,11.11,11.28q3.82.07,7.66.08c2.57,0,5.12,0,7.67-.08A11.32,11.32,0,0,0,377,705.08V519.69a11.25,11.25,0,0,1,11.27-11.26H621.1a11.26,11.26,0,0,1,9.59,17.16c-61.46,99.87-166.59,138.3-171,139.9a11.27,11.27,0,0,1-15-10.61V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,467.14,591v28.6a11.25,11.25,0,0,0,16.53,10c27.33-14.53,67.68-40.42,101.77-80.19,6.2-7.23.85-18.46-8.69-18.46h-166a11.26,11.26,0,0,0-11.26,11.26V701.12a11.21,11.21,0,0,0,12.76,11.17c128.86-19.51,235.14-107.66,280.48-226a11.33,11.33,0,0,0-10.53-15.41h-294A11.25,11.25,0,0,1,377,459.61ZM35.27,399.53V316.9a11.26,11.26,0,0,1,11.27-11.26H669.92a11.25,11.25,0,0,1,11.26,11.26v82.63a11.25,11.25,0,0,1-11.26,11.26H46.54a11.27,11.27,0,0,1-11.27-11.26Z", 716.45, 716.44).parse())
|
// {{-0.2,0.175736}, {-0.2,0.288215}, {-0.579534,0.220466}, {-0.5,0.3}},
|
||||||
|
// {{-0.5,0.3}, {-0.420466,0.379534}, {-0.736743,0.6}, {-0.624264,0.6}},
|
||||||
|
// {{-0.624264,0.6}, {-0.511785,0.6}, {-0.579534,0.979534}, {-0.5,0.9}}
|
||||||
//};
|
//};
|
||||||
|
|
||||||
vector<std::pair<std::shared_ptr<Contour>, float>> contours;
|
vector<std::shared_ptr<Contour>> contour = {
|
||||||
|
std::make_shared<Contour>(SvgParser("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", 100, 100).parse()),
|
||||||
QPainterPath painterPaths[3];
|
std::make_shared<Contour>(SvgParser("M308.49,212.25l23,28.38-82,78.31c-14.28,13.64-26.34-20.6-53.44,9.32l-30.24-13.4,63.56-51.59L190.71,215.6l-32.92,26.72L149.5,232.1l32.92-26.72L173.2,194l-32.91,26.72-7.38-9.08L165.83,185l-38.69-47.66L94.22,164,85,152.65l32.91-26.72-9.21-11.35L75.79,141.3l-5.53-6.81,32.92-26.72L94,96.42,61.05,123.14l-12-14.76L37.72,117.6l12,14.75L30.41,148,0,110.55,136.2,0l30.4,37.46L147.31,53.12l-12-14.76L124,47.58l12,14.75L103.05,89.05l9.21,11.35,32.92-26.72,5.52,6.81-32.91,26.72L127,118.56l32.92-26.72,9.21,11.35-32.91,26.72,38.69,47.67,32.91-26.72,7.37,9.08-32.91,26.72L191.49,198l32.92-26.72,8.29,10.22-32.92,26.71,38.7,47.68L302,204.3l6.45,7.95Z", 331.52, 328.26).parse()),
|
||||||
QQuickSvgParser::parsePathDataFast("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z",
|
std::make_shared<Contour>(SvgParser("M377,459.61a11.26,11.26,0,0,1,11.27-11.27H696.12a11.27,11.27,0,0,0,11-8.62A359.84,359.84,0,0,0,708,280.56a11.26,11.26,0,0,0-11-8.73H388.27A11.26,11.26,0,0,1,377,260.57h0a11.26,11.26,0,0,1,11.27-11.26H683.71A11.32,11.32,0,0,0,694.28,234C649.8,113.69,542.57,23.85,412.3,4.12a11.22,11.22,0,0,0-12.76,11.17v158.9a11.26,11.26,0,0,0,11.26,11.27H583.12a11.32,11.32,0,0,0,9.26-17.75c-31.67-46.59-78.51-75.2-109.11-90.07a11.25,11.25,0,0,0-16.13,10.17V115.2a11.24,11.24,0,0,0,6.22,10.07l7.51,3.76a11.28,11.28,0,0,1,5,15.12h0a11.27,11.27,0,0,1-15.11,5l-20-10a11.27,11.27,0,0,1-6.22-10.07V54a11.27,11.27,0,0,1,14.62-10.75c5.11,1.59,125.66,40.35,172.24,149A11.27,11.27,0,0,1,621.11,208H388.27A11.26,11.26,0,0,1,377,196.73V11.36A11.32,11.32,0,0,0,365.89.08C363.34,0,360.79,0,358.22,0s-5.11,0-7.66.08a11.32,11.32,0,0,0-11.11,11.28V196.74A11.26,11.26,0,0,1,328.18,208H95.35A11.27,11.27,0,0,1,85,192.3c46.57-108.67,167.12-147.42,172.23-149A11.26,11.26,0,0,1,271.86,54v75.11a11.25,11.25,0,0,1-6.23,10.07l-20,10a11.27,11.27,0,0,1-15.11-5h0a11.26,11.26,0,0,1,5-15.11l7.52-3.76a11.27,11.27,0,0,0,6.22-10.07V87.82a11.25,11.25,0,0,0-16.14-10.16c-30.6,14.87-77.45,43.48-109.1,90.07a11.3,11.3,0,0,0,9.25,17.74H305.66a11.26,11.26,0,0,0,11.27-11.26V15.31A11.22,11.22,0,0,0,304.17,4.14C173.88,23.86,66.66,113.71,22.17,234a11.32,11.32,0,0,0,10.56,15.29H328.18a11.26,11.26,0,0,1,11.27,11.26v0a11.26,11.26,0,0,1-11.27,11.26H19.52a11.26,11.26,0,0,0-11,8.72,359.84,359.84,0,0,0,.83,159.16,11.26,11.26,0,0,0,11,8.61H328.18a11.26,11.26,0,0,1,11.27,11.27h0a11.26,11.26,0,0,1-11.27,11.26h-294a11.32,11.32,0,0,0-10.53,15.4C69,604.65,175.3,692.78,304.16,712.3a11.21,11.21,0,0,0,12.76-11.16V542.22A11.26,11.26,0,0,0,305.66,531h-166c-9.53,0-14.89,11.22-8.69,18.47,34.09,39.77,74.45,65.66,101.77,80.18a11.25,11.25,0,0,0,16.53-10V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,271.85,591v63.85A11.27,11.27,0,0,1,256.8,665.5c-4.45-1.59-109.58-40-171-139.9a11.27,11.27,0,0,1,9.59-17.17H328.18a11.26,11.26,0,0,1,11.27,11.26V705.08a11.32,11.32,0,0,0,11.11,11.28q3.82.07,7.66.08c2.57,0,5.12,0,7.67-.08A11.32,11.32,0,0,0,377,705.08V519.69a11.25,11.25,0,0,1,11.27-11.26H621.1a11.26,11.26,0,0,1,9.59,17.16c-61.46,99.87-166.59,138.3-171,139.9a11.27,11.27,0,0,1-15-10.61V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,467.14,591v28.6a11.25,11.25,0,0,0,16.53,10c27.33-14.53,67.68-40.42,101.77-80.19,6.2-7.23.85-18.46-8.69-18.46h-166a11.26,11.26,0,0,0-11.26,11.26V701.12a11.21,11.21,0,0,0,12.76,11.17c128.86-19.51,235.14-107.66,280.48-226a11.33,11.33,0,0,0-10.53-15.41h-294A11.25,11.25,0,0,1,377,459.61ZM35.27,399.53V316.9a11.26,11.26,0,0,1,11.27-11.26H669.92a11.25,11.25,0,0,1,11.26,11.26v82.63a11.25,11.25,0,0,1-11.26,11.26H46.54a11.27,11.27,0,0,1-11.27-11.26Z", 716.45, 716.44).parse())
|
||||||
painterPaths[0]);
|
};
|
||||||
if (!SvgFileLoader().loadSvgFile("../svg/2.svg", painterPaths[1]))
|
vector<std::shared_ptr<ElementStyle>> style = {
|
||||||
qCritical() << "load error";
|
std::make_shared<ElementStyle>(std::vector<GLfloat>{
|
||||||
/*QQuickSvgParser::parsePathDataFast("M292.82,107.78s0,0,0,0,0,3.59,0,7.62c0,3.85,0,5.78.06,6.43a19.94,19.94,0,0,0,2.87,7.58,15.85,15.85,0,0,0,6.61,6.23A14.75,14.75,0,0,0,310,137a11.69,11.69,0,0,0,7.59-2.92,11,11,0,0,0,3.2-6.84c.15-1.27.58-4.84-1.79-7.64a8.54,8.54,0,0,0-3.56-2.44c-1.32-.52-3.32-1.31-5.06-.33a5.41,5.41,0,0,0-2.14,3,3.48,3.48,0,0,0-.16,2.71c.78,1.86,3.36,2.14,3.47,2.15",
|
//strokeStyle
|
||||||
painterPaths[1]);*/
|
//stroke
|
||||||
QQuickSvgParser::parsePathDataFast("M377,459.61a11.26,11.26,0,0,1,11.27-11.27H696.12a11.27,11.27,0,0,0,11-8.62A359.84,359.84,0,0,0,708,280.56a11.26,11.26,0,0,0-11-8.73H388.27A11.26,11.26,0,0,1,377,260.57h0a11.26,11.26,0,0,1,11.27-11.26H683.71A11.32,11.32,0,0,0,694.28,234C649.8,113.69,542.57,23.85,412.3,4.12a11.22,11.22,0,0,0-12.76,11.17v158.9a11.26,11.26,0,0,0,11.26,11.27H583.12a11.32,11.32,0,0,0,9.26-17.75c-31.67-46.59-78.51-75.2-109.11-90.07a11.25,11.25,0,0,0-16.13,10.17V115.2a11.24,11.24,0,0,0,6.22,10.07l7.51,3.76a11.28,11.28,0,0,1,5,15.12h0a11.27,11.27,0,0,1-15.11,5l-20-10a11.27,11.27,0,0,1-6.22-10.07V54a11.27,11.27,0,0,1,14.62-10.75c5.11,1.59,125.66,40.35,172.24,149A11.27,11.27,0,0,1,621.11,208H388.27A11.26,11.26,0,0,1,377,196.73V11.36A11.32,11.32,0,0,0,365.89.08C363.34,0,360.79,0,358.22,0s-5.11,0-7.66.08a11.32,11.32,0,0,0-11.11,11.28V196.74A11.26,11.26,0,0,1,328.18,208H95.35A11.27,11.27,0,0,1,85,192.3c46.57-108.67,167.12-147.42,172.23-149A11.26,11.26,0,0,1,271.86,54v75.11a11.25,11.25,0,0,1-6.23,10.07l-20,10a11.27,11.27,0,0,1-15.11-5h0a11.26,11.26,0,0,1,5-15.11l7.52-3.76a11.27,11.27,0,0,0,6.22-10.07V87.82a11.25,11.25,0,0,0-16.14-10.16c-30.6,14.87-77.45,43.48-109.1,90.07a11.3,11.3,0,0,0,9.25,17.74H305.66a11.26,11.26,0,0,0,11.27-11.26V15.31A11.22,11.22,0,0,0,304.17,4.14C173.88,23.86,66.66,113.71,22.17,234a11.32,11.32,0,0,0,10.56,15.29H328.18a11.26,11.26,0,0,1,11.27,11.26v0a11.26,11.26,0,0,1-11.27,11.26H19.52a11.26,11.26,0,0,0-11,8.72,359.84,359.84,0,0,0,.83,159.16,11.26,11.26,0,0,0,11,8.61H328.18a11.26,11.26,0,0,1,11.27,11.27h0a11.26,11.26,0,0,1-11.27,11.26h-294a11.32,11.32,0,0,0-10.53,15.4C69,604.65,175.3,692.78,304.16,712.3a11.21,11.21,0,0,0,12.76-11.16V542.22A11.26,11.26,0,0,0,305.66,531h-166c-9.53,0-14.89,11.22-8.69,18.47,34.09,39.77,74.45,65.66,101.77,80.18a11.25,11.25,0,0,0,16.53-10V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,271.85,591v63.85A11.27,11.27,0,0,1,256.8,665.5c-4.45-1.59-109.58-40-171-139.9a11.27,11.27,0,0,1,9.59-17.17H328.18a11.26,11.26,0,0,1,11.27,11.26V705.08a11.32,11.32,0,0,0,11.11,11.28q3.82.07,7.66.08c2.57,0,5.12,0,7.67-.08A11.32,11.32,0,0,0,377,705.08V519.69a11.25,11.25,0,0,1,11.27-11.26H621.1a11.26,11.26,0,0,1,9.59,17.16c-61.46,99.87-166.59,138.3-171,139.9a11.27,11.27,0,0,1-15-10.61V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,467.14,591v28.6a11.25,11.25,0,0,0,16.53,10c27.33-14.53,67.68-40.42,101.77-80.19,6.2-7.23.85-18.46-8.69-18.46h-166a11.26,11.26,0,0,0-11.26,11.26V701.12a11.21,11.21,0,0,0,12.76,11.17c128.86-19.51,235.14-107.66,280.48-226a11.33,11.33,0,0,0-10.53-15.41h-294A11.25,11.25,0,0,1,377,459.61ZM35.27,399.53V316.9a11.26,11.26,0,0,1,11.27-11.26H669.92a11.25,11.25,0,0,1,11.26,11.26v82.63a11.25,11.25,0,0,1-11.26,11.26H46.54a11.27,11.27,0,0,1-11.27-11.26Z",
|
1,
|
||||||
painterPaths[2]);
|
//strokeWidth
|
||||||
|
0.01,
|
||||||
for (auto& i : painterPaths)
|
//strokeEndType
|
||||||
{
|
0, //圆角
|
||||||
auto [contour, ratio] = PainterPathUtil::toNormalizedLines(i);
|
//strokeFillType
|
||||||
contours.emplace_back(std::make_shared<Contour>(contour), ratio);
|
0, //单色
|
||||||
}
|
//线类型
|
||||||
|
2, //双侧
|
||||||
vector<std::shared_ptr<ElementStyle>> style = {
|
//线外描边宽度
|
||||||
std::make_shared<ElementStyleFillDemo>(),
|
0,
|
||||||
std::make_shared<ElementStyleStrokeDemo>(0.02),
|
//线外描边方式
|
||||||
std::make_shared<ElementStyleStrokeRadialGradientDemo>(0.2)
|
0, //单色
|
||||||
|
//strokeFillColorMetallicRoughness
|
||||||
|
1,0,1, 0,0.8,
|
||||||
|
}),
|
||||||
|
std::make_shared<ElementStyle>(std::vector<GLfloat>{
|
||||||
|
//fillStyle
|
||||||
|
//fill
|
||||||
|
0,
|
||||||
|
//fillType
|
||||||
|
0, //单色
|
||||||
|
//fillColorMetallicRoughness
|
||||||
|
240 / 255., 220 / 255., 160 / 255., 0.996, 0.18,
|
||||||
|
}),
|
||||||
|
std::make_shared<ElementStyle>(std::vector<GLfloat>{
|
||||||
|
//fillStyle
|
||||||
|
//fill
|
||||||
|
0,
|
||||||
|
//fillType
|
||||||
|
0, //单色
|
||||||
|
//fillColorMetallicRoughness
|
||||||
|
24 / 255., 220 / 255., 16 / 255., 0., 0.18,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
vector<std::shared_ptr<Element>> element = {
|
vector<std::shared_ptr<Element>> element = {
|
||||||
std::make_shared<Element>(Element{ contours[0].first, style[0], contours[0].second}),
|
std::make_shared<Element>(Element{ contour[0], style[1]}),
|
||||||
std::make_shared<Element>(Element{ contours[1].first, style[2], contours[1].second}),
|
std::make_shared<Element>(Element{ contour[1], style[2]}),
|
||||||
std::make_shared<Element>(Element{ contours[2].first, style[0], contours[2].second}),
|
std::make_shared<Element>(Element{ contour[2], style[0]}),
|
||||||
};
|
};
|
||||||
Painting painting;
|
Painting painting;
|
||||||
|
//for (int i = 0; i < 3; i++)
|
||||||
|
//{
|
||||||
|
// float x = (float)rand() / RAND_MAX * 2 - 1;
|
||||||
|
// float y = (float)rand() / RAND_MAX * 2 - 1;
|
||||||
|
// float z = 0.05 + x;//(float)rand() / RAND_MAX * (0.1) + x;
|
||||||
|
// float w = 0.05 + y;//(float)rand() / RAND_MAX * (0.1) + y;
|
||||||
|
// //rootBvhTreeData.push_back(BvhTreeData(QVector4D(x, y, z, w), 0, encodeZIndexAngle(1, (float)rand() / RAND_MAX * 360)));
|
||||||
|
// painting.addElement(element[i%3], QVector4D(x, y, z, w), (float)rand() / RAND_MAX * 360, 1);
|
||||||
|
//}
|
||||||
|
painting.addElement(element[0], QVector4D(-0.8, -0.8, -0.2, -0.1), 0, 0);
|
||||||
|
painting.addElement(element[1], QVector4D(-0.7, 0.2, -0.2, 0.7), 0, 0);
|
||||||
|
painting.addElement(element[2], QVector4D(0.2, -0.8, 0.8, -0.1), 0, 0);
|
||||||
|
|
||||||
if (path == "17876391417123941155.jpg")
|
painting.generateBuffers();
|
||||||
{
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,-0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
|
std::vector<GLuint> bvhChildren0 = {
|
||||||
painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.45, 0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
|
//root
|
||||||
painting.addElement(*element[2], ElementTransform{ glm::vec2(0.50,-0.45), glm::vec2(0.6,0.7) / 2.f, 0, glm::bvec2(false), 0 });
|
1,2,
|
||||||
}
|
3,4, 5,6,
|
||||||
else
|
encodeChild(2),0, encodeChild(1),GLuint(30. / 360 * 65536 + 1 * 65536) /*右儿子用来表示旋转角度和zIndex*/, encodeChild(3),0, encodeChild(0),0,
|
||||||
{
|
//elememt0
|
||||||
for (int i = 0; i < 1000; i++)
|
1,2,
|
||||||
{
|
encodeChild(20)/*contour索引,由于contour不定长,这里需要给到contour在elementIndex中位置*/,0/*封闭图形*/, encodeChild(24), 0,
|
||||||
float x = (float)rand() / RAND_MAX * 2 - 1;
|
//elememt1
|
||||||
float y = (float)rand() / RAND_MAX * 2 - 1;
|
encodeChild(12)/*contour索引*/, 1/*线*/
|
||||||
painting.addElement(*element[i % 3], ElementTransform{ glm::vec2(x,y), glm::vec2(0.025), (float)rand() / RAND_MAX * 360, glm::bvec2(false), 0 });
|
|
||||||
}
|
};
|
||||||
}
|
std::vector<QVector4D> bvhBounds0 = {
|
||||||
|
//root
|
||||||
|
QVector4D(-1,-1,1,1),
|
||||||
|
QVector4D(-0.9,-0.9,-0.1,0.9), QVector4D(0.1, -0.9,0.9,0.9),
|
||||||
|
QVector4D(-0.8,-0.8,-0.2,-0.1), QVector4D(-0.7,0.2,-0.2,0.7), QVector4D(0.2,-0.8,0.8,-0.1), QVector4D(0.3,0.2,0.7,0.7),
|
||||||
|
//elememt0
|
||||||
|
QVector4D(-1,-1,1,1),
|
||||||
|
QVector4D(-1,-1,-0.2,1), QVector4D(-0.2,-1,1,1),
|
||||||
|
//elememt1
|
||||||
|
QVector4D(-1,-1,1,1)
|
||||||
|
};
|
||||||
|
std::vector<GLuint> elementOffset0 = {
|
||||||
|
//element0
|
||||||
|
7, //elementBvhRoot
|
||||||
|
14, //styleOffset
|
||||||
|
0, //pointsOffset
|
||||||
|
0, //linesOffset
|
||||||
|
//element1
|
||||||
|
10, //elementBvhRoot
|
||||||
|
39, //styleOffset
|
||||||
|
21, //pointsOffset
|
||||||
|
28, //linesOffset
|
||||||
|
//element2
|
||||||
|
10, //elementBvhRoot
|
||||||
|
51, //styleOffset
|
||||||
|
21, //pointsOffset
|
||||||
|
28, //linesOffset
|
||||||
|
//element3
|
||||||
|
10, //elementBvhRoot
|
||||||
|
63, //styleOffset
|
||||||
|
21, //pointsOffset
|
||||||
|
28, //linesOffset
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<GLuint> elementIndex0 = {
|
||||||
|
//element0
|
||||||
|
//lines, 全部当作三阶贝塞尔, 每条线四个点索引
|
||||||
|
0,1,1,2,
|
||||||
|
0,0,3,3,
|
||||||
|
3,4,4,5,
|
||||||
|
2,2,5,5,
|
||||||
|
5,5,6,6,
|
||||||
|
//contours, 第一个元素为线数,后面为轮廓线索引
|
||||||
|
3, 1,2,4,
|
||||||
|
3, 0,2,3,
|
||||||
|
//element1
|
||||||
|
//lines
|
||||||
|
0,7,8,1,
|
||||||
|
1,2,3,4,
|
||||||
|
5,5,6,6,
|
||||||
|
//contours
|
||||||
|
2, 0 ,1
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<GLfloat> elementData0 = {
|
||||||
|
//element0
|
||||||
|
//points
|
||||||
|
-0.2,1, -0.2,-0.2, 1,-0.2, -1,1, -1,-1, 1,-1, 1,1,
|
||||||
|
//fillStyle
|
||||||
|
//fill
|
||||||
|
0,
|
||||||
|
//fillType
|
||||||
|
0, //单色
|
||||||
|
//fillColorMetallicRoughness
|
||||||
|
1,1,0, 0,0.8,
|
||||||
|
|
||||||
|
//element1
|
||||||
|
//points
|
||||||
|
0.5,-0.5, 0.5,0.5, -0.2,0.5, -0.5,0.2, -0.5,-0.5, -0.8,-0.5, -0.8,0.5, 0.5,-0.4, 0.5,0.4,
|
||||||
|
//strokeStyle
|
||||||
|
//stroke
|
||||||
|
1,
|
||||||
|
//strokeWidth
|
||||||
|
0.1,
|
||||||
|
//strokeEndType
|
||||||
|
0, //圆角
|
||||||
|
//strokeFillType
|
||||||
|
0, //单色
|
||||||
|
//线类型
|
||||||
|
2, //左侧
|
||||||
|
//线外描边宽度
|
||||||
|
0,
|
||||||
|
//线外描边方式
|
||||||
|
0, //单色
|
||||||
|
//strokeFillColorMetallicRoughness
|
||||||
|
1,0,1, 0,0.8,
|
||||||
|
//strokeStyle
|
||||||
|
//stroke
|
||||||
|
1,
|
||||||
|
//strokeWidth
|
||||||
|
0.1,
|
||||||
|
//strokeEndType
|
||||||
|
0, //圆角
|
||||||
|
//strokeFillType
|
||||||
|
2, //单色
|
||||||
|
//线类型
|
||||||
|
1, //左侧
|
||||||
|
//线外描边宽度
|
||||||
|
0,
|
||||||
|
//线外描边方式
|
||||||
|
0, //单色
|
||||||
|
//strokeFillColorMetallicRoughness
|
||||||
|
1,0,1, 0,0.8,
|
||||||
|
//strokeStyle
|
||||||
|
//stroke
|
||||||
|
1,
|
||||||
|
//strokeWidth
|
||||||
|
0.1,
|
||||||
|
//strokeEndType
|
||||||
|
0, //圆角
|
||||||
|
//strokeFillType
|
||||||
|
1, //单色
|
||||||
|
//线类型
|
||||||
|
0, //左侧
|
||||||
|
//线外描边宽度
|
||||||
|
0,
|
||||||
|
//线外描边方式
|
||||||
|
0, //单色
|
||||||
|
//strokeFillColorMetallicRoughness
|
||||||
|
1,0,1, 0,0.8,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
painting.generateBuffers(glFunc);
|
//m_mesh->paintingIndex = paintingHelper->addPainting(bounds.size(), std::vector<GLuint>(children.begin()+2, children.end()), bounds,
|
||||||
|
// elementOffset, elementIndex, elementData);
|
||||||
auto index = vtManager->createVirtualTexture(painting);
|
/*m_mesh->paintingIndex = paintingHelper->addPainting(bvhChildren0, bvhBounds0,
|
||||||
paintingLoaded.emplace(path, index);
|
elementOffset0, elementIndex0, elementData0);*/
|
||||||
|
GLuint index = paintingHelper->addPainting(painting);
|
||||||
|
paintingLoaded.insert({ path, index });
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Mesh.h"
|
#include "Mesh.h"
|
||||||
#include "Drawable.h"
|
#include "Drawable.h"
|
||||||
#include "VirtualTextureManager.h"
|
#include "Painting/PaintingHelper.h"
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <assimp/scene.h>
|
|
||||||
|
|
||||||
namespace Renderer
|
namespace Renderer
|
||||||
{
|
{
|
||||||
|
@ -14,34 +14,41 @@ namespace Renderer
|
||||||
|
|
||||||
void draw();
|
void draw();
|
||||||
void drawShadow();
|
void drawShadow();
|
||||||
void loadModel(QString path);
|
void destroy();
|
||||||
Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager);
|
static Model* createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram);
|
||||||
|
Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, PaintingHelper* paintingHelper);
|
||||||
private:
|
private:
|
||||||
QOpenGLContext* context;
|
Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram);
|
||||||
QOpenGLFunctions_4_5_Core* glFunc = nullptr;
|
|
||||||
|
~Model();
|
||||||
|
QOpenGLContext* context; //opengl函数入口
|
||||||
|
QOpenGLFunctions_4_5_Compatibility* glFunc;
|
||||||
QOpenGLShaderProgram* shaderProgram = nullptr;
|
QOpenGLShaderProgram* shaderProgram = nullptr;
|
||||||
QOpenGLShaderProgram* paintingProgram = nullptr;
|
QOpenGLShaderProgram* paintingProgram = nullptr; //彩绘着色器程序
|
||||||
QOpenGLShaderProgram* shadowProgram = nullptr;
|
QOpenGLShaderProgram* shadowProgram = nullptr;
|
||||||
VirtualTextureManager* vtManager = nullptr;
|
PaintingHelper* paintingHelper = nullptr;
|
||||||
|
|
||||||
/* Ä£ÐÍÊý¾Ý */
|
/* Ä£ÐÍÊý¾Ý */
|
||||||
std::unordered_map<std::string, GLuint> paintingLoaded;
|
std::unordered_map<std::string, GLuint> paintingLoaded;
|
||||||
std::unordered_map<std::string, QOpenGLTexture> texturesLoaded;
|
QVector<Texture*> textures_loaded; //纹理
|
||||||
std::vector<std::unique_ptr<Drawable>> meshes;
|
QVector<Drawable*> meshes; //网格
|
||||||
|
QDir directory; //模型所在路径
|
||||||
|
|
||||||
/// 模型所在路径
|
float minX = std::numeric_limits<float>::max();
|
||||||
QDir directory;
|
float maxX = std::numeric_limits<float>::min();
|
||||||
|
float minY = std::numeric_limits<float>::max();
|
||||||
|
float maxY = std::numeric_limits<float>::min();
|
||||||
|
float minZ = std::numeric_limits<float>::max();
|
||||||
|
float maxZ = std::numeric_limits<float>::min();
|
||||||
|
|
||||||
float minX, maxX, minY, maxY, minZ, maxZ;
|
//递归遍历结点
|
||||||
|
|
||||||
/// 递归遍历结点
|
|
||||||
void processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4 = aiMatrix4x4());
|
void processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4 = aiMatrix4x4());
|
||||||
|
|
||||||
/// 加载网格
|
//加载网格
|
||||||
std::unique_ptr<Drawable> processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model);
|
Drawable* processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model);
|
||||||
|
|
||||||
/// 加载材质纹理
|
//加载材质纹理
|
||||||
GLuint loadMaterialTextures(aiMaterial* mat, aiTextureType type);
|
QVector<Texture*> loadMaterialTextures(aiMaterial* mat, aiTextureType type, QString typeName);
|
||||||
|
|
||||||
GLuint loadPainting(std::string path);
|
GLuint loadPainting(std::string path);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
#include "BaseStyle.h"
|
|
||||||
|
|
||||||
using namespace Renderer;
|
|
||||||
|
|
||||||
bool Renderer::Material::operator==(const Material& m) const
|
|
||||||
{
|
|
||||||
return color == m.color && metallic == m.metallic && roughness == m.roughness;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<glm::vec4, glm::vec2> Renderer::Material::toVec() const
|
|
||||||
{
|
|
||||||
return { glm::vec4(color.redF(), color.greenF(), color.blueF(), color.alphaF()), glm::vec2(metallic, roughness)};
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <qopengl.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <memory>
|
|
||||||
#include <QColor>
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
namespace Renderer
|
|
||||||
{
|
|
||||||
/// 相对变换,用于制作阴影等效果
|
|
||||||
struct TransformStyle
|
|
||||||
{
|
|
||||||
glm::vec2 translation = glm::vec2(0);
|
|
||||||
glm::vec2 scale = glm::vec2(1);
|
|
||||||
float rotation = 0;
|
|
||||||
glm::bvec2 flip = glm::bvec2(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class MaterialStyleType { kFill = 0, kStroke = 1 };
|
|
||||||
|
|
||||||
class MaterialStyle
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual MaterialStyleType type() const = 0;
|
|
||||||
virtual std::vector<GLfloat> encoded() const = 0;
|
|
||||||
virtual bool operator==(const MaterialStyle&) const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BaseStyle
|
|
||||||
{
|
|
||||||
std::shared_ptr<TransformStyle> transform;
|
|
||||||
std::shared_ptr<MaterialStyle> material;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Material
|
|
||||||
{
|
|
||||||
QColor color;
|
|
||||||
float metallic;
|
|
||||||
float roughness;
|
|
||||||
bool operator==(const Material&) const;
|
|
||||||
std::pair<glm::vec4, glm::vec2> toVec() const;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -4,8 +4,8 @@ GLuint BvhTree::getBvhNodeNum() {
|
||||||
return tot;
|
return tot;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BvhTree::buildBvhTree(BvhTreeData initBound[], int len, GLuint transformParam) {
|
void BvhTree::buildBvhTree(BvhTreeData initBound[], int len) {
|
||||||
tot = 0; transform = transformParam;
|
tot = 0;
|
||||||
root = subBvhTree(initBound, 0, len-1);
|
root = subBvhTree(initBound, 0, len-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,17 +18,6 @@ QVector4D BvhTree::Union(QVector4D a, QVector4D b) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector4D BvhTree::merge(BvhPtr lp, BvhPtr rp) {
|
|
||||||
QVector4D a = lp->bound, b = rp->bound;
|
|
||||||
if (lp->isLeaf) {
|
|
||||||
a = BvhTreeData::boundWithRotation(a, lp->getRightSon());
|
|
||||||
}
|
|
||||||
if (rp->isLeaf) {
|
|
||||||
b = BvhTreeData::boundWithRotation(b, rp->getRightSon());
|
|
||||||
}
|
|
||||||
return Union(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector4D BvhTree::calcBound(BvhTreeData initBound[], int l, int r) {
|
QVector4D BvhTree::calcBound(BvhTreeData initBound[], int l, int r) {
|
||||||
QVector4D res = initBound[l].bound;
|
QVector4D res = initBound[l].bound;
|
||||||
for (int i = l + 1; i <= r; i++) {
|
for (int i = l + 1; i <= r; i++) {
|
||||||
|
@ -41,7 +30,7 @@ BvhPtr BvhTree::subBvhTree(BvhTreeData initBound[], int l, int r) {
|
||||||
if (l > r) return NULL;
|
if (l > r) return NULL;
|
||||||
BvhPtr p(new BvhNode());
|
BvhPtr p(new BvhNode());
|
||||||
p->lab = tot++;
|
p->lab = tot++;
|
||||||
//p->bound = calcBound(initBound, l, r);
|
p->bound = calcBound(initBound, l, r);
|
||||||
if (l == r) {
|
if (l == r) {
|
||||||
p->isLeaf = true;
|
p->isLeaf = true;
|
||||||
BvhPtr lp(new BvhNode());
|
BvhPtr lp(new BvhNode());
|
||||||
|
@ -50,7 +39,6 @@ BvhPtr BvhTree::subBvhTree(BvhTreeData initBound[], int l, int r) {
|
||||||
BvhPtr rp(new BvhNode());
|
BvhPtr rp(new BvhNode());
|
||||||
rp->lab = initBound[r].rightSon;
|
rp->lab = initBound[r].rightSon;
|
||||||
p->child[1] = rp;
|
p->child[1] = rp;
|
||||||
p->bound = calcBound(initBound, l, r);
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
int dim = p->maximumBound();
|
int dim = p->maximumBound();
|
||||||
|
@ -62,13 +50,12 @@ BvhPtr BvhTree::subBvhTree(BvhTreeData initBound[], int l, int r) {
|
||||||
int mid = (l + r) >> 1;
|
int mid = (l + r) >> 1;
|
||||||
p->child[0] = subBvhTree(initBound, l, mid);
|
p->child[0] = subBvhTree(initBound, l, mid);
|
||||||
p->child[1] = subBvhTree(initBound, mid+1, r);
|
p->child[1] = subBvhTree(initBound, mid+1, r);
|
||||||
p->bound = merge(p->child[0], p->child[1]);
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BvhTree::traverseBvhTree(BvhPtr now, std::vector<GLuint>& children, std::vector<QVector4D>& bounds) {
|
void BvhTree::traverseBvhTree(BvhPtr now, std::vector<GLuint>& children, std::vector<QVector4D>& bounds) {
|
||||||
children.push_back(now->getLeftSon());
|
children.push_back(now->getLeftSon(0));
|
||||||
children.push_back(now->getRightSon());
|
children.push_back(now->getRightSon(1));
|
||||||
bounds.push_back(now->bound);
|
bounds.push_back(now->bound);
|
||||||
if (now->isLeaf) return;
|
if (now->isLeaf) return;
|
||||||
traverseBvhTree(now->child[0], children, bounds);
|
traverseBvhTree(now->child[0], children, bounds);
|
||||||
|
|
|
@ -20,24 +20,6 @@ namespace Renderer
|
||||||
bound.x(), bound.y(), bound.z(), bound.w(),
|
bound.x(), bound.y(), bound.z(), bound.w(),
|
||||||
leftSon, rightSon);
|
leftSon, rightSon);
|
||||||
}
|
}
|
||||||
static QVector4D boundWithRotation(QVector4D bound, GLuint rightSon) {
|
|
||||||
double angle = (rightSon & ((1 << 16) - 1)) / static_cast<double>((1 << 16)) * 2 * acos(-1);
|
|
||||||
double centerX = (bound.x() + bound.z()) / 2, centerY = (bound.y() + bound.w()) / 2;
|
|
||||||
double xCosMin = std::min((bound.x() - centerX) * cos(angle), (bound.z() - centerX) * cos(angle)),
|
|
||||||
xCosMax = std::max((bound.x() - centerX) * cos(angle), (bound.z() - centerX) * cos(angle));
|
|
||||||
double xSinMin = std::min((bound.x() - centerX) * sin(angle), (bound.z() - centerX) * sin(angle)),
|
|
||||||
xSinMax = std::max((bound.x() - centerX) * sin(angle), (bound.z() - centerX) * sin(angle));
|
|
||||||
double yCosMin = std::min((bound.y() - centerY) * cos(angle), (bound.w() - centerY) * cos(angle)),
|
|
||||||
yCosMax = std::max((bound.y() - centerY) * cos(angle), (bound.w() - centerY) * cos(angle));
|
|
||||||
double ySinMin = std::min((bound.y() - centerY) * sin(angle), (bound.w() - centerY) * sin(angle)),
|
|
||||||
ySinMax = std::max((bound.y() - centerY) * sin(angle), (bound.w() - centerY) * sin(angle));
|
|
||||||
return QVector4D(
|
|
||||||
xCosMin - ySinMax + centerX,
|
|
||||||
yCosMin + xSinMin + centerY,
|
|
||||||
xCosMax - ySinMin + centerX,
|
|
||||||
yCosMax + xSinMax + centerY
|
|
||||||
);
|
|
||||||
}
|
|
||||||
BvhTreeData(QVector4D bound, GLuint leftSon, GLuint rightSon)
|
BvhTreeData(QVector4D bound, GLuint leftSon, GLuint rightSon)
|
||||||
: bound(bound), leftSon(leftSon), rightSon(rightSon) {}
|
: bound(bound), leftSon(leftSon), rightSon(rightSon) {}
|
||||||
BvhTreeData()
|
BvhTreeData()
|
||||||
|
@ -56,13 +38,13 @@ namespace Renderer
|
||||||
static bool y_compare(BvhTreeData a, BvhTreeData b) {
|
static bool y_compare(BvhTreeData a, BvhTreeData b) {
|
||||||
return a.bound.y() < b.bound.y();
|
return a.bound.y() < b.bound.y();
|
||||||
}
|
}
|
||||||
GLuint getLeftSon() {
|
GLuint getLeftSon(int k) {
|
||||||
if (isLeaf) {
|
if (isLeaf) {
|
||||||
return 0x80000000 + child[0]->lab;
|
return 0x80000000 + child[0]->lab;
|
||||||
}
|
}
|
||||||
return child[0]->lab;
|
return child[0]->lab;
|
||||||
}
|
}
|
||||||
GLuint getRightSon() {
|
GLuint getRightSon(int k) {
|
||||||
if (isLeaf) {
|
if (isLeaf) {
|
||||||
return child[1]->lab;
|
return child[1]->lab;
|
||||||
}
|
}
|
||||||
|
@ -85,20 +67,19 @@ namespace Renderer
|
||||||
{
|
{
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint tot, transform;
|
GLuint tot;
|
||||||
BvhPtr root;
|
BvhPtr root;
|
||||||
static QVector4D calcBound(BvhTreeData initBound[], int l, int r);
|
static QVector4D calcBound(BvhTreeData initBound[], int l, int r);
|
||||||
static QVector4D Union(QVector4D a, QVector4D b);
|
static QVector4D Union(QVector4D a, QVector4D b);
|
||||||
BvhPtr subBvhTree(BvhTreeData initBound[], int l, int r);
|
BvhPtr subBvhTree(BvhTreeData initBound[], int l, int r);
|
||||||
void traverseBvhTree(BvhPtr now, std::vector<GLuint>& children, std::vector<QVector4D>& bounds);
|
void traverseBvhTree(BvhPtr now, std::vector<GLuint>& children, std::vector<QVector4D>& bounds);
|
||||||
QVector4D merge(BvhPtr lp, BvhPtr rp);
|
|
||||||
public:
|
public:
|
||||||
BvhTree() {
|
BvhTree() {
|
||||||
tot = 0;
|
tot = 0;
|
||||||
root = NULL;
|
root = NULL;
|
||||||
}
|
}
|
||||||
// 根据底层包围盒生成bvh树
|
// 根据底层包围盒生成bvh树
|
||||||
void buildBvhTree(BvhTreeData initBound[], int len, GLuint transformParam = 0);
|
void buildBvhTree(BvhTreeData initBound[], int len);
|
||||||
// 获得 Bvh (rootBvh部分)的 children 数组,包围盒数组 vector 传输
|
// 获得 Bvh (rootBvh部分)的 children 数组,包围盒数组 vector 传输
|
||||||
void getBvhArray(std::vector<GLuint>& children, std::vector<QVector4D>& bounds);
|
void getBvhArray(std::vector<GLuint>& children, std::vector<QVector4D>& bounds);
|
||||||
// 获得 BvhTree 中节点总数
|
// 获得 BvhTree 中节点总数
|
||||||
|
|