Compare commits

..

No commits in common. "1031ba580855827a76a4fea5971aef07f27a19c9" and "53c6a4fbe530752c6d4a62dd8574be596141ffdf" have entirely different histories.

1922 changed files with 8753 additions and 85615 deletions

1
.gitignore vendored
View File

@ -361,4 +361,3 @@ MigrationBackup/
# Fody - auto-generated XML schema
FodyWeavers.xsd
/UnitTest/Qt.x64.runsettings

View File

@ -4,76 +4,26 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 17.2.32519.379
MinimumVisualStudioVersion = 10.0.40219.1
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
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709} = {3FE96A33-2BB7-4686-A710-3EB8E3BBD709}
{B982E745-C0B1-46B3-A27B-743AF105F2D0} = {B982E745-C0B1-46B3-A27B-743AF105F2D0}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "components", "qt-material-widgets\components\components.vcxproj", "{8F360763-A045-3808-87A9-3FAE38E69819}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "examples", "qt-material-widgets\examples\examples.vcxproj", "{2CF18346-77C1-3A0A-B9ED-8B38C828491B}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QGoodWindow", "QGoodWindow\QGoodWindow.vcxproj", "{B982E745-C0B1-46B3-A27B-743AF105F2D0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{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|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.Build.0 = Release|x64
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Release|x86.ActiveCfg = Release|x64
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Release|x86.Build.0 = Release|x64
{954D3D24-DF86-33A3-8867-D1735CCBDB10}.Debug|x64.ActiveCfg = Debug|x64
{954D3D24-DF86-33A3-8867-D1735CCBDB10}.Debug|x64.Build.0 = Debug|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
{B982E745-C0B1-46B3-A27B-743AF105F2D0}.Debug|x64.ActiveCfg = Debug|x64
{B982E745-C0B1-46B3-A27B-743AF105F2D0}.Debug|x64.Build.0 = Debug|x64
{B982E745-C0B1-46B3-A27B-743AF105F2D0}.Release|x64.ActiveCfg = Release|x64
{B982E745-C0B1-46B3-A27B-743AF105F2D0}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -32,7 +32,7 @@
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
<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>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
@ -55,7 +55,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<IncludePath>$(IncludePath)</IncludePath>
<IncludePath>$(SolutionDir)include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
</PropertyGroup>
@ -67,22 +67,16 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<LanguageStandard>stdcpp20</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>
<PreprocessorDefinitions>FRAMELESSHELPER_WIDGETS_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level1</WarningLevel>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)ArchitectureColoredPainting\src\Editor\RightBar;$(SolutionDir)ArchitectureColoredPainting\src\Editor\;$(SolutionDir)QGoodWindow;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration">
<ClCompile>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>MaxSpeed</Optimization>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
<Link>
@ -104,144 +98,116 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\Editor\EditorWidget.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\GraphicElement.cpp" />
<ClCompile Include="src\Editor\LayerManager.cpp" />
<ClCompile Include="src\Editor\LayerStyle.cpp" />
<ClCompile Include="src\Editor\LayerWrapper.cpp" />
<ClCompile Include="src\Editor\PixelPath.cpp" />
<ClCompile Include="src\Editor\PreviewWindow.cpp" />
<ClCompile Include="src\Editor\RightBar\InfoDisplayWidget.cpp" />
<ClCompile Include="src\Editor\RightBar\LayerTreeWidget.cpp" />
<ClCompile Include="src\Editor\ThirdPartyLib\qquick\qquicksvgparser.cpp" />
<ClCompile Include="src\Editor\ThirdPartyLib\SvgHelper.cpp" />
<ClCompile Include="src\Editor\util\PainterPathUtil.cpp" />
<ClCompile Include="src\Editor\util\SvgFileLoader.cpp" />
<ClCompile Include="src\gl.c" />
<ClCompile Include="src\Editor\third-party modules\qquick\qquicksvgparser.cpp" />
<ClCompile Include="src\Editor\third-party modules\util\SvgFileLoader.cpp" />
<ClCompile Include="src\IconWidget.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\MainWindow.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\Camera.cpp" />
<ClCompile Include="src\Renderer\Painting\CubicBezier.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\Painting\Element.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\Mesh.cpp" />
<ClCompile Include="src\Renderer\Model.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\PaintingHelper.cpp" />
<ClCompile Include="src\Renderer\PaintingMesh.cpp" />
<ClCompile Include="src\Renderer\Preview\ElementRenderer.cpp" />
<ClCompile Include="src\Renderer\RendererGLWidget.cpp" />
<ClCompile Include="src\Renderer\RendererWidget.cpp" />
<ClCompile Include="src\Renderer\Painting\ShortCutTree.cpp" />
<ClCompile Include="src\Renderer\Painting\StraightLine.cpp" />
<ClCompile Include="src\Renderer\VirtualTextureManager.cpp" />
<ClCompile Include="src\SvgParser.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="MainWindow.ui" />
<QtUic Include="NavigationBarWidget.ui" />
<QtUic Include="RendererWidget.ui" />
<QtUic Include="EditorWidget.ui" />
</ItemGroup>
<ItemGroup>
<None Include="..\data.json" />
<None Include="res\Shaders\brdf_lut.comp" />
<None Include="res\Shaders\cubemap.frag" />
<None Include="res\Shaders\cubemap.vert" />
<None Include="res\Shaders\cubemap_prefilter.frag" />
<None Include="res\Shaders\depth_init.comp" />
<None Include="res\Shaders\depth_mipmap.comp" />
<None Include="res\Shaders\element.comp" />
<None Include="res\Shaders\final.frag" />
<None Include="res\Shaders\final.vert" />
<None Include="res\Shaders\irradiance_convolution.frag" />
<None Include="res\Shaders\model.frag" />
<None Include="res\Shaders\model.vert" />
<None Include="res\Shaders\model_shadow.frag" />
<None Include="res\Shaders\model_shadow.geom" />
<None Include="res\Shaders\model_shadow.vert" />
<None Include="res\Shaders\pageId_downsample.comp" />
<None Include="res\Shaders\painting.comp" />
<None Include="res\Shaders\painting.frag" />
<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" />
<None Include="darkstyle.qss" />
<None Include="lightstyle.qss" />
<None Include="Shaders\depth_init.comp" />
<None Include="Shaders\depth_mipmap.comp" />
<None Include="Shaders\final.frag" />
<None Include="Shaders\final.vert" />
<None Include="Shaders\model.frag" />
<None Include="Shaders\model.vert" />
<None Include="Shaders\model_shadow.frag" />
<None Include="Shaders\model_shadow.geom" />
<None Include="Shaders\model_shadow.vert" />
<None Include="Shaders\painting.comp" />
<None Include="Shaders\painting.frag" />
<None Include="Shaders\painting.vert" />
<None Include="Shaders\shader.frag" />
<None Include="Shaders\shader.vert" />
<None Include="Shaders\shadow_mapping.comp" />
<None Include="Shaders\ssgi.comp" />
</ItemGroup>
<ItemGroup>
<QtMoc Include="src\Editor\RightBar\LayerTreeWidget.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\Editor\EditorWidget.h" />
<ClInclude Include="src\Editor\ElementManager.h" />
<ClInclude Include="src\Editor\GraphicElement.h" />
<ClInclude Include="src\Editor\LayerManager.h" />
<ClInclude Include="src\Editor\LayerStyle.h" />
<ClInclude Include="src\Editor\LayerWrapper.h" />
<QtMoc Include="src\Editor\PreviewWindow.h" />
<ClInclude Include="src\Editor\PixelPath.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\Editor\third-party modules\util\SvgFileLoader.h" />
<ClInclude Include="src\Renderer\Painting\CubicBezierSignedDistance.h" />
<ClInclude Include="src\Renderer\Painting\Element.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\MaterialStyleStroke.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" />
<QtMoc Include="src\TitleWidget.h" />
<QtMoc Include="src\IconWidget.h" />
<QtMoc Include="src\CaptionButton.h" />
<QtMoc Include="src\NavigationBarWidget.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\Camera.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\Light.h" />
<ClInclude Include="src\Renderer\Painting\Line.h" />
<ClInclude Include="src\Renderer\Mesh.h" />
<ClInclude Include="src\Renderer\Model.h" />
<ClInclude Include="src\Renderer\Painting\PaintingHelper.h" />
<ClInclude Include="src\Renderer\PaintingMesh.h" />
<ClInclude Include="src\Renderer\Painting\ShortCutTree.h" />
<ClInclude Include="src\Renderer\Painting\StraightLine.h" />
<QtMoc Include="src\Renderer\RendererGLWidget.h" />
</ItemGroup>
<ItemGroup>
<QtRcc Include="res\MainWindow.qrc" />
</ItemGroup>
<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 Include="..\QGoodWindow\QGoodWindow.vcxproj">
<Project>{b982e745-c0b1-46b3-a27b-743af105f2d0}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -41,29 +41,23 @@
<Filter Include="Header Files\Renderer\Painting">
<UniqueIdentifier>{22909273-2b23-49fa-84ab-444cefb09656}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Editor\ThirdPartyLib">
<UniqueIdentifier>{11f273e9-b41f-4982-b4ca-12851a03aaae}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Editor\util">
<UniqueIdentifier>{727fd876-d2b0-4928-80a7-2da7cafe1519}</UniqueIdentifier>
<UniqueIdentifier>{e3c323ec-d150-4876-8618-5800c87a4941}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Editor\ThirdPartyLib\qquick">
<UniqueIdentifier>{169687a8-6807-4571-802c-c4a95858db3a}</UniqueIdentifier>
<Filter Include="Header Files\Editor\third-party modules">
<UniqueIdentifier>{30b46cf2-d980-47be-94c4-d2ec1dcc54ed}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Editor\ThirdPartyLib">
<UniqueIdentifier>{0567e730-5508-4380-8304-86ded8ea3b2f}</UniqueIdentifier>
<Filter Include="Header Files\Editor\third-party modules\qquick">
<UniqueIdentifier>{5028c879-8b07-4033-81ac-e538a873a837}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Editor\ThirdPartyLib\qquick">
<UniqueIdentifier>{cfa316d0-97e0-49b0-9911-baebfea49236}</UniqueIdentifier>
<Filter Include="Source Files\Editor\third-party modules">
<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 Include="Source Files\Editor\util">
<UniqueIdentifier>{96f98afe-4250-44cb-a505-682a1d5932c3}</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>
<UniqueIdentifier>{d7c7ab61-0d05-4e67-9e89-852f3e56fa2f}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
@ -76,12 +70,9 @@
<QtUic Include="FramelessWindow.ui">
<Filter>Form Files</Filter>
</QtUic>
<QtUic Include="EditorWidget.ui">
<Filter>Form Files</Filter>
</QtUic>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Editor\EditorWidgetItem.cpp">
<ClCompile Include="src\Editor\EditorWidget.cpp">
<Filter>Source Files\Editor</Filter>
</ClCompile>
<ClCompile Include="src\Renderer\Camera.cpp">
@ -132,6 +123,12 @@
<ClCompile Include="src\Renderer\Painting\CubicBezier.cpp">
<Filter>Source Files\Renderer\Painting</Filter>
</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">
<Filter>Source Files\Renderer\Painting</Filter>
</ClCompile>
@ -168,6 +165,16 @@
<ClCompile Include="src\Renderer\Painting\CubicBezierSignedDistance.cpp">
<Filter>Source Files\Renderer\Painting</Filter>
</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">
<Filter>Source Files</Filter>
</ClCompile>
@ -177,54 +184,12 @@
<ClCompile Include="src\Renderer\Painting\ElementStyle.cpp">
<Filter>Source Files\Renderer\Painting</Filter>
</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>
<QtMoc Include="src\Renderer\RendererGLWidget.h">
<Filter>Header Files\Renderer</Filter>
</QtMoc>
<QtMoc Include="src\Editor\EditorWidgetItem.h">
<QtMoc Include="src\Editor\EditorWidget.h">
<Filter>Header Files\Editor</Filter>
</QtMoc>
<QtMoc Include="src\Renderer\RendererWidget.h">
@ -254,90 +219,66 @@
<QtMoc Include="src\Editor\RightBar\InfoDisplayWidget.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="src\Editor\EditorWidget.h">
<Filter>Header Files</Filter>
</QtMoc>
</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="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>
<QtUic Include="EditorWidgetItem.ui">
<QtUic Include="EditorWidget.ui">
<Filter>Form Files</Filter>
</QtUic>
<QtUic Include="RendererWidget.ui">
@ -372,9 +313,15 @@
<ClInclude Include="src\Renderer\Painting\CubicBezier.h">
<Filter>Header Files\Renderer\Painting</Filter>
</ClInclude>
<ClInclude Include="src\Renderer\Painting\CubicMonotonization.h">
<Filter>Header Files\Renderer\Painting</Filter>
</ClInclude>
<ClInclude Include="src\Renderer\Painting\Line.h">
<Filter>Header Files\Renderer\Painting</Filter>
</ClInclude>
<ClInclude Include="src\Renderer\Painting\PaintingHelper.h">
<Filter>Header Files\Renderer\Painting</Filter>
</ClInclude>
<ClInclude Include="src\Renderer\Painting\ShortCutTree.h">
<Filter>Header Files\Renderer\Painting</Filter>
</ClInclude>
@ -405,54 +352,34 @@
<ClInclude Include="src\Renderer\Painting\CubicBezierSignedDistance.h">
<Filter>Header Files\Renderer\Painting</Filter>
</ClInclude>
<ClInclude Include="src\Renderer\Painting\ElementStyle.h">
<Filter>Header Files\Renderer\Painting</Filter>
<ClInclude Include="src\Editor\third-party modules\SvgHelper.h">
<Filter>Header Files\Editor\third-party modules</Filter>
</ClInclude>
<ClInclude Include="src\Editor\ThirdPartyLib\qquick\qquicksvgparser_p.h">
<Filter>Header Files\Editor\ThirdPartyLib\qquick</Filter>
<ClInclude Include="src\Editor\third-party modules\qquick\qquicksvgparser_p.h">
<Filter>Header Files\Editor\third-party modules\qquick</Filter>
</ClInclude>
<ClInclude Include="src\Editor\ThirdPartyLib\qquick\qtquickglobal.h">
<Filter>Header Files\Editor\ThirdPartyLib\qquick</Filter>
<ClInclude Include="src\Editor\third-party modules\qquick\qtquickglobal.h">
<Filter>Header Files\Editor\third-party modules\qquick</Filter>
</ClInclude>
<ClInclude Include="src\Editor\ThirdPartyLib\qquick\qtquickglobal_p.h">
<Filter>Header Files\Editor\ThirdPartyLib\qquick</Filter>
<ClInclude Include="src\Editor\third-party modules\qquick\qtquickglobal_p.h">
<Filter>Header Files\Editor\third-party modules\qquick</Filter>
</ClInclude>
<ClInclude Include="src\Editor\ThirdPartyLib\SvgHelper.h">
<Filter>Header Files\Editor\ThirdPartyLib</Filter>
<ClInclude Include="src\Editor\third-party modules\util\SvgFileLoader.h">
<Filter>Header Files\Editor\util</Filter>
</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>
</ClInclude>
<ClInclude Include="src\Renderer\Painting\ElementStyle.h">
<Filter>Header Files\Renderer\Painting</Filter>
</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>
<QtRcc Include="res\MainWindow.qrc">
<QtRcc Include="MainWindow.qrc">
<Filter>Resource Files</Filter>
</QtRcc>
</ItemGroup>

View File

@ -1,176 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditorWidget</class>
<widget class="QWidget" name="EditorWidget">
<class>EditorWidgetClass</class>
<widget class="QWidget" name="EditorWidgetClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1139</width>
<height>685</height>
<width>1124</width>
<height>695</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<string>RendererWidget</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,1,1,20">
<property name="topMargin">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<property name="rightMargin">
<number>0</number>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
<property name="bottomMargin">
<number>0</number>
</property>
</spacer>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<widget class="QWidget" name="MainWindow" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,30">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<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>
<widget class="QLabel" name="Title">
<property name="text">
<string>新建</string>
<string>纹理编辑</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="openButton">
<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>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,18,5">
<item>
<widget class="QWidget" name="LeftBar" native="true"/>
</item>
<item>
<widget class="QPushButton" name="saveButton">
<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>
<widget class="PreviewWindow" name="Preview"/>
</item>
<item>
<widget class="QPushButton" name="saveAsButton">
<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>
<widget class="QWidget" name="RightBar" native="true">
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="1,2">
<item>
<widget class="QPushButton" name="closeButton">
<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">
<widget class="QTabWidget" name="DisplayTab">
<property name="currentIndex">
<number>1</number>
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<widget class="InfoDisplayWidget" name="LayerDisplay">
<attribute name="title">
<string>Tab 1</string>
<string>Layer</string>
</attribute>
</widget>
<widget class="QWidget" name="tab_2">
<widget class="QWidget" name="ElementDisplay">
<attribute name="title">
<string>Tab 2</string>
<string>Element</string>
</attribute>
</widget>
</widget>
</item>
<item>
<widget class="LayerTreeWidget" name="LayerTree">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
</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>

View File

@ -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>

View File

@ -38,7 +38,7 @@
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
<string notr="true">#windowFrame{ background-color:palette(Window);}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
@ -56,13 +56,108 @@
<property name="bottomMargin">
<number>1</number>
</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>
<widget class="QWidget" name="windowContent" native="true">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
<string notr="true">#windowContent{
border: 0px none palette(base);
border-radius:0px 0px 5px 5px;
}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
@ -89,6 +184,25 @@
</layout>
</widget>
<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/>
<connections/>
</ui>

View File

@ -23,15 +23,6 @@
<file>images/icon_window_restore.png</file>
<file>darkstyle.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 prefix="/qt/etc">
<file>qt.conf</file>

View File

@ -59,19 +59,18 @@
</font>
</property>
<property name="styleSheet">
<string notr="true">
QTabBar::tab.rendererWidget {
<string notr="true">QTabBar::tab {
height: 0px;
margin-top:0px;
}
QTabWidget::tab-bar.rendererWidget
QTabWidget::tab-bar
{
height: 0px;
top:0px;
}
QTabWidget::pane.rendererWidget {
QTabWidget::pane {
border: 0px;
background-color: transparent;
background-color: rgba(0, 0, 0, 0);
}
</string>
</property>

View File

@ -13,10 +13,7 @@
<property name="windowTitle">
<string>RendererWidget</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,1">
<property name="spacing">
<number>0</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
<property name="leftMargin">
<number>0</number>
</property>
@ -30,74 +27,20 @@
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<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">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</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>
<width>20</width>
<height>40</height>
</size>
</property>
<property name="title">
<string>打开</string>
</property>
</widget>
<addaction name="menu"/>
</widget>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
@ -115,20 +58,11 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>12</number>
</property>
<property name="leftMargin">
<number>12</number>
</property>
<property name="rightMargin">
<number>12</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QSlider" name="horizontalSlider">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -137,7 +71,7 @@
<number>180</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
@ -147,23 +81,7 @@
<number>360</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</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>
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>

View File

@ -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);
}

View File

@ -9,7 +9,7 @@ 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 = 4) out uint gPaintingIndex;
in vec2 TexCoords;
in vec3 WorldPos;
@ -36,22 +36,13 @@ vec3 getNormalFromMap()
void main()
{
if(textureSize(texture_basecolor,0)!=vec2(0))
//gBaseColor = vec4(1,0,0,1);
gBaseColor = texture(texture_basecolor, TexCoords);
else
gBaseColor = vec4(1);
if(gBaseColor.a<0.4)
discard;
gPosition = WorldPos;
if(textureSize(texture_normal,0)!=vec2(0))
gNormal = getNormalFromMap();
else
gNormal = Normal;
if(textureSize(texture_metallic_roughness,0)!=vec2(0))
gMetallicRoughness = texture(texture_metallic_roughness, TexCoords).bg;
else
gMetallicRoughness = vec2(0,1);
gPaintingIndex = uvec2(0);
gPaintingIndex = 0;
}

View File

@ -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;
}

View File

@ -2,35 +2,43 @@
layout (local_size_x = 8, local_size_y = 8) in;
layout(location = 0) uniform ivec2 pixelOffset;
layout(rgba8, binding = 0) uniform image2D gBaseColor;
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[];
};
layout(std430, binding = 1) buffer bvhBoundBuffer
layout(std430, binding = 3) buffer bvhBoundBuffer
{
vec4 bvhBound[];
};
layout(std430, binding = 2) buffer elementOffsetBuffer
layout(std430, binding = 4) buffer elementOffsetBuffer
{
/**
* @[0] elementBvhRoot
* @[1] styleOffset
* @[2] pointsOffset
* @[3] linesOffset
*/
uint elementOffset[][5];
/**********************
** @[0] elementBvhRoot
** @[1] styleOffset
** @[2] pointsOffset
** @[3] linesOffset
**********************/
uvec4 elementOffset[];
};
layout(std430, binding = 3) buffer elementIndexBuffer
layout(std430, binding = 5) buffer elementIndexBuffer
{
uint elementIndexs[]; //ÏߺÍÃæ
};
layout(std430, binding = 4) buffer elementDataBuffer
layout(std430, binding = 6) buffer elementDataBuffer
{
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;
}
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)
{
// 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 qu = (3. * p0.y - 6. * p1.y + 3. * p2.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);
}
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)
{
elementColor = vec4(1);
metallicRoughness = vec2(0.8);
uint headUint = floatBitsToUint(elementData[styleIndex+1]);
vec4 head = unpackUnorm4x8(headUint);
switch (int(head.a*100)%10)
//switch (2)
switch(int(elementData[styleIndex+3]))
{
/// Plain
case 0: {
metallicRoughness = head.rg;
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+2])).rgb, 1);
case 0:
{
elementColor = vec4(elementData[styleIndex+7],elementData[styleIndex+8],elementData[styleIndex+9],1);
metallicRoughness = vec2(elementData[styleIndex+10],elementData[styleIndex+11]);
break;
}
/// RadialGradient
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++)
case 1:
{
uint data = floatBitsToUint(elementData[styleIndex+2+i*2]);
float level = unpackUnorm2x16(data).y;
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;
}
elementColor = vec4(mix(vec3(0), vec3(1), d), 1);
metallicRoughness = vec2(0,0.8);
break;
}
lastMetallicRoughness = currentMetallicRoughness;
lastColor = currentColor;
lastLevel = level;
}
break;
}
case 2: {
case 2:
{
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)};
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;
vec4 elementColor = vec4(-1);
metallicRoughness = vec2(0, 0.8);
uint currentOffset[] = elementOffset[elementIndex];
uvec4 currentOffset = elementOffset[elementIndex];
uint elementBvhRoot = currentOffset[0];
//uint elementBvhLength = currentOffset[1];
uint styleIndex = currentOffset[1];
uint elementBvhLength = 0x80000000;
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 elementType = bvhChildren[elementBvhRoot + elementBvhIndex].y;
//float elementType = elementData[styleIndex];
bool isFillStyle = elementData[styleIndex]<=0;
float elementType = elementData[styleIndex];
// for(int i = 0; i<200;i++)
if (isFillStyle) //面
if (elementType == 0) //Ãæ
{
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++)
{
uint lineIndex = elementIndexs[contourIterator];
uint pLocation = linesOffset + 2 * lineIndex;
uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation]>>16, elementIndexs[pLocation]&0xFFFF, elementIndexs[pLocation+1]>>16, elementIndexs[pLocation+1]&0xFFFF);
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;
// 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]],
elementData[pxIndex[1]], elementData[pyIndex[1]],
elementData[pxIndex[2]],elementData[pyIndex[2]],
@ -1040,44 +961,38 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
{
hitElement = true;
elementColor = vec4(1,1,0,0);
vec4 head = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex]));
if(head.z==0)
if(elementData[styleIndex+1]==0)
{
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+1])).rgb,0);
metallicRoughness = head.xy;
elementColor = vec4(elementData[styleIndex+2],elementData[styleIndex+3],elementData[styleIndex+4],0);
metallicRoughness = vec2(elementData[styleIndex+5],elementData[styleIndex+6]);
}
}
}
else //线
else if (elementType == 1) //Ïß
{
float strokeWidth = elementData[styleIndex];
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;
float strokeWidth = elementData[styleIndex+1];
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];
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+1]));
float lineType = floor(styleHead.b*10);
//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 reverseFlag = 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 pLocation = linesOffset + 3 * lineIndex;
uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation]>>16, elementIndexs[pLocation]&0xFFFF, elementIndexs[pLocation+1]>>16, elementIndexs[pLocation+1]&0xFFFF);
bool reverse = false;
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;
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[3]], elementData[pyIndex[3]]);
p[0] *= ratio;
p[1] *= ratio;
p[2] *= ratio;
p[3] *= ratio;
bvec3 signTestResult = cubic_bezier_sign_test(localUV, p[0], p[1], p[2], p[3]);
if(p[0]==p[1]&&p[2]==p[3])
if(lastPIndex!=pxIndex[0])
{
p[1] = (p[0]+p[3])/2;
p[2] = p[1];
}
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))
if(lastSign)
signTmp = !signTmp;
float lineType = elementData[styleIndex+4];
/*if(d<=0.001)
{
hitElement = true;
drawLine(minDistance/strokeWidth, styleIndex, elementColor, metallicRoughness);
elementColor = vec4(0,0,0,1);
}
else if(p3Last==p[0]) hitElement = false;
// if(distance(localUV,p[0])<=strokeWidth&&p3Last==p[0]&&fill)
// {
// hitElement = true;
// elementColor = vec4(0,0,1,1);
// }
else*/ if(d<=strokeWidth && (lineType==2 || signTmp==(lineType==1-reverseFlag)))
{
d/=strokeWidth;
hitElement = true;
drawLine(d, styleIndex, elementColor, metallicRoughness);
}
if(reverse)
reverseFlag = 1;
d = 1e38;
signTmp=signTestResult[0];
lineCountTmp = 0;
}
p3Last = p[3];
p2Last = p[2];
lastPIndex = pxIndex[3];
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;
// 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;
color = elementColor.xyz;
return hitElement;
}
else
{
@ -1185,13 +1116,13 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
void main()
{
ivec2 pixelLocation = ivec2(pixelOffset + gl_GlobalInvocationID.xy);
vec2 uv = (pixelLocation + vec2(0.5)) / imageSize(gBaseColor);
//imageStore(gBaseColor, pixelLocation, vec4(uv,1,1));
//imageStore(gMetallicRoughness, pixelLocation, vec4(uv,1,1));
//return;
uv = vec2(1)-uv*2;
//vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg;
//ivec2 pixelLocation = ivec2(((gl_LocalInvocationID.xy)*imageSize(gPaintingIndex)/gl_WorkGroupSize.xy + gl_WorkGroupID.xy).xy);
ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy);
uint paintingIndex = imageLoad(gPaintingIndex, pixelLocation).r;
if(paintingIndex==0)
return;
vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg;
vec3 debugBVH = vec3(0);
//bool debugHit = false;
@ -1210,28 +1141,24 @@ void main()
uint leftChild = bvhChildren[index].x;
if (leftChild >= bvhLength)
{
uint zIndex = bvhChildren[index].y >> 18;
bvec2 flip = bvec2(bvhChildren[index].y & (1<<16), bvhChildren[index].y & (1<<17));
float angle = (float(bvhChildren[index].y&((1<<16)-1)) / 65535.0) * 2 * PI;
uint zIndex = bvhChildren[index].y / 65535;
float angle = (float(bvhChildren[index].y) / 65535.0 - zIndex) * 2 * PI;
mat2 rotation = {{cos(angle), -sin(angle)}, {sin(angle), cos(angle)}};
vec2 localUV = uv - (bound.xy + bound.zw) / 2;
localUV = rotation * localUV;
vec2 scale = (bound.zw - bound.xy) / 2;
localUV /= scale;
localUV /= (bound.zw - bound.xy) / 2;
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(vec2(-1)+vec2(0.005), localUV)) || any(greaterThan(localUV, vec2(1)-vec2(0.005))))
if (any(greaterThan(bound.xy+vec2(0.005), uv)) || any(greaterThan(uv, bound.zw-vec2(0.005))))
debugBVH.g += 0.3;
//uint elementIndex = leftChild - bvhLength;
//debugBVH.bg += 0.5 * (localUV + vec2(1));
//debugBVH = vec3(0);
if(flip.x) localUV.x = -localUV.x;
if(flip.y) localUV.y = -localUV.y;
vec3 elementColor;
vec2 elementMetallicRoughness;
if(drawElement(leftChild - 0x80000000, localUV, scale, elementColor, elementMetallicRoughness, debugBVH))
if(drawElement(leftChild - 0x80000000, localUV, elementColor, elementMetallicRoughness, debugBVH))
{
color = vec4(elementColor, zIndex);
metallicRoughness = elementMetallicRoughness;

View File

@ -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;
}

View File

@ -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);
}

View File

@ -2,16 +2,11 @@
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 gPosition;
uniform sampler2D gMetallicRoughness;
uniform sampler2DArray gShadowMap;
uniform samplerCube irradianceMap;
uniform samplerCube prefilterMap;
uniform sampler2D brdfLUT;
layout(rgba16f, binding = 1) uniform image2D gDirectLight;
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);
}
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;
float getShadowFromLayer(vec3 fragPosWorldSpace, vec3 normal,int layer)
{
@ -165,28 +132,11 @@ float ShadowCalculation(vec3 fragPosWorldSpace, vec3 normal, out int layer)
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()
{
ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy);
//vec3 albedo = pow(texelFetch(gBaseColor, pixelLocation, 0).rgb, vec3(2.2));
vec3 albedo = pow(imageLoad(gBaseColor, pixelLocation).rgb, vec3(2.2));
vec3 albedo = pow(texelFetch(gBaseColor, pixelLocation, 0).rgb, vec3(2.2));
float metallic = texelFetch(gMetallicRoughness, pixelLocation, 0).r;
float roughness = texelFetch(gMetallicRoughness, pixelLocation, 0).g;
@ -195,12 +145,15 @@ void main()
if(normal==vec3(0))
{
//vec3 color = mainLightRadiance;
//imageStore(gBaseColor, pixelLocation, vec4(color, 1.0));
imageStore(gBaseColor, pixelLocation, vec4(0));
vec3 color = mainLightRadiance;
//color = color / (color + vec3(1.0));
//color = pow(color, vec3(1.0/2.2));
imageStore(gDirectLight, pixelLocation, vec4(color, 1.0));
return;
}
normal = normalize(normal);
vec3 V = normalize(camPos - worldPos);
@ -231,11 +184,8 @@ void main()
float NdotL = max(dot(normal, L), 0.0);
vec3 Lo = (kD * albedo / PI + specular) * radiance * NdotL;
vec3 ambient = ambientLighting(normal, V, F0, albedo, metallic, roughness, 1);
int debugLayer;
float shadow = ShadowCalculation(worldPos, normal, debugLayer);
vec3 color = (1-shadow)*Lo + ambient;
imageStore(gBaseColor, pixelLocation, encodeRGBM(color));
imageStore(gDirectLight, pixelLocation, vec4((1-shadow)*Lo, 1));
}

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 422 B

After

Width:  |  Height:  |  Size: 422 B

View File

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 386 B

View File

Before

Width:  |  Height:  |  Size: 364 B

After

Width:  |  Height:  |  Size: 364 B

View File

Before

Width:  |  Height:  |  Size: 404 B

After

Width:  |  Height:  |  Size: 404 B

View File

@ -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_ */

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
chcp 65001
"E:\Qt\Tools\QtCreator\bin\jom\jom.exe" %*

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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))));
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -1,48 +1,56 @@
#include "EditorWidget.h"
#include "EditorWidgetItem.h"
#include <QMouseEvent>
#include <QInputDialog>
#include <QMenu>
#include <QFileDialog>
EditorWidget::EditorWidget(QWidget *parent) : QWidget(parent)
{
displayLayer = nullptr;
displayElement = nullptr;
ui.setupUi(this);
this->createButton = ui.createButton;
this->closeButton = ui.closeButton;
this->saveButton = ui.saveButton;
this->saveAsButton = ui.saveAsButton;
this->openButton = ui.openButton;
this->tabWidget = ui.tabWidget;
while (this->tabWidget->count() > 0)
previewWindow = ui.Preview;
treeWidget = ui.LayerTree;
tabWidget = ui.DisplayTab;
layerInfoDisplayWidget = dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(0));
elementInfoDisplayWidget = dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(1));
connect(treeWidget, &LayerTreeWidget::displayLayerChange, this, &EditorWidget::onLayerChange);
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();
}

View File

@ -1,23 +1,38 @@
#pragma once
#include <qwidget.h>
#include "ui_EditorWidget.h"
class EditorWidget :
public QWidget
#include "ElementManager.h"
#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
private:
Ui::EditorWidget ui;
// DATA PART
PreviewWindow *previewWindow;
ElementManager *elementManager;
LayerManager *layerManager;
// QT GUI PART
Ui::EditorWidgetClass ui;
LayerTreeWidget *treeWidget;
QTabWidget *tabWidget;
QPushButton* createButton;
QPushButton* closeButton;
QPushButton* saveButton;
QPushButton* saveAsButton;
QPushButton* openButton;
InfoDisplayWidget *layerInfoDisplayWidget, *elementInfoDisplayWidget;
// QT DATA PART
LayerWrapper *displayLayer;
GraphicElement *displayElement;
public:
EditorWidget(QWidget *parent = nullptr);
~EditorWidget()=default;
~EditorWidget();
void paintEvent(QPaintEvent *event) override;
private slots:
void onLayerChange(LayerWrapper *layer);
void triggerRefreshPreview();
};

View File

@ -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();
}

View File

@ -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();
};

View File

@ -1,20 +1,15 @@
#include "ElementManager.h"
ElementManager::ElementManager(QJsonObject source,Renderer::ElementRenderer* renderer)
ElementManager::ElementManager(QJsonObject source)
{
auto elementsJson = source.value("elements").toArray();
qDebug() << elementsJson.size();
int index = 0;
for (auto elementJson : elementsJson)
{
if (elementJson.toObject().value("type").toString() == "group")
elements.push_back(new GroupElement());
else
elements.push_back(new SimpleElement(elementJson.toObject()));
(*elements.rbegin())->renderer = renderer;
}
for (auto element : elements)
element->index = index++;
}
void ElementManager::addElement(GraphicElement *element)
@ -36,13 +31,3 @@ GraphicElement *ElementManager::getElementById(int index)
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;
}

View File

@ -2,12 +2,10 @@
#include "GraphicElement.h"
#include "LayerManager.h"
#include <QJsonArray>
#include "../Renderer/Preview/ElementRenderer.h"
#include <vector>
using std::vector;
class LayerManager;
class GraphicElement;
class Renderer::ElementRenderer;
class ElementManager
{
@ -15,11 +13,10 @@ class ElementManager
vector<GraphicElement *> elements;
public:
ElementManager(QJsonObject source,Renderer::ElementRenderer *renderer);
ElementManager(QJsonObject source);
~ElementManager();
void addElement(GraphicElement *element);
void removeElement(GraphicElement *pElement);
QJsonObject toJson()const;
/**
* only used in initialization
*/

View File

@ -1,12 +1,9 @@
#include "GraphicElement.h"
#include "util/SvgFileLoader.h"
#include "third-party modules/util/SvgFileLoader.h"
using namespace std;
PixelPath SimpleElement::getPaintObject() const
QPainterPath SimpleElement::getPaintObject() const
{
PixelPath result;
result.addPath(painterPath);
return result;
return painterPath;
}
void SimpleElement::loadSvgFile(const QString& filePath)
@ -20,8 +17,8 @@ void SimpleElement::loadSvgFile(const QString& filePath)
SimpleElement::SimpleElement(QJsonObject jsonSource) : jsonSource(jsonSource)
{
painterPath.clear();
//loadSvgFile("D:\\Projects\\BigC\\svg\\3.svg");
loadSvgFile("../"/*TODO: 改成json文件所在文件夹路径*/ + jsonSource.value("data").toObject().value("include").toString());
loadSvgFile("D:\\Projects\\BigC\\svg\\3.svg");
//loadSvgFile(jsonSource.value("data").toObject().value("include").toString());
}
GroupElement::GroupElement(FolderLayerWrapper *sourceLayer)
@ -32,54 +29,12 @@ void GroupElement::setSourceLayer(FolderLayerWrapper* sourceLayer)
{
this->sourceLayer = sourceLayer;
}
PixelPath GroupElement::getPaintObject() const
QPainterPath GroupElement::getPaintObject() const
{
if (sourceLayer != nullptr) {
sourceLayer->refresh();
return sourceLayer->getCache();
}
else
return PixelPath();
}
//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;
return QPainterPath();
}

View File

@ -1,49 +1,31 @@
#pragma once
#include "LayerWrapper.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QPainterPath>
#include <QImage>
#include <vector>
#include <string>
#include "../Renderer/Preview/ElementRenderer.h"
#include "../Renderer/Painting/ElementStyle.h"
#include "PixelPath.h"
#include <functional>
class LayerWrapper;
class LeafLayerWrapper;
class FolderLayerWrapper;
class ComposedPainterPath;
class GraphicElement
{
public:
Renderer::ElementRenderer *renderer;
QString name="";
int index;
// TODO: ¸ÄΪBitmapPath
virtual QJsonObject toJson() const;
virtual PixelPath getPaintObject() const = 0;
virtual PixelPath getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo>) const = 0;
virtual QPainterPath getPaintObject() const = 0;
};
class SimpleElement : public GraphicElement
{
private:
QJsonObject jsonSource;
// TODO: ¸ÄΪComposedPainterPath
QPainterPath painterPath;
void loadSvgFile(const QString& filePath);
public:
SimpleElement(QJsonObject jsonSource);
~SimpleElement() = default;
PixelPath getPaintObject() const override;
PixelPath getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo>) const override;
QPainterPath getPaintObject() const override;
};
class GroupElement : public GraphicElement
{
public:
@ -53,31 +35,6 @@ public:
GroupElement() = default;
GroupElement(FolderLayerWrapper *mSourceLayer);
~GroupElement() = default;
PixelPath getPaintObject() const override;
PixelPath getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo>) const override;
QPainterPath getPaintObject() const override;
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();
//};

View File

@ -11,10 +11,9 @@ LayerWrapper *LayerManager::getRoot() const
{
return root;
}
void LayerManager::paint(QPainter *painter, QSize size) const
void LayerManager::paint(QPainter *painter) const
{
auto p = root->getCache().resizedPixel(size);
painter->drawPixmap(0, 0, p);
painter->drawPath(root->getCache());
}
bool LayerManager::singleSelectedCheck() const
{
@ -48,7 +47,7 @@ bool LayerManager::combine() const
if (layer->getParent() != prevCommonFather)
return false;
auto newCommonFather = new FolderLayerWrapper();
newCommonFather->setParent(static_cast<FolderLayerWrapper*>(prevCommonFather));
newCommonFather->setParent(prevCommonFather);
for (auto &layer : selectedLayers)
layer->setParent(newCommonFather);
return true;
@ -62,20 +61,11 @@ bool LayerManager::changeParent(FolderLayerWrapper *newParent) const
selectedLayers[0]->setParent(newParent);
return true;
}
void LayerManager::addLayer(LayerWrapper *layer)
{
layerSet.insert(layer);
}
void LayerManager::removeLayer(LayerWrapper *layer)
{
layerSet.erase(layer);
}
QJsonObject LayerManager::toJson() const
{
QJsonObject result;
result.insert("root-layer", root->toJson());
return result;
}

View File

@ -31,8 +31,7 @@ class LayerManager
LayerWrapper *getRoot() const;
LayerManager() = default;
LayerManager(QJsonObject source, ElementManager *elementManager);
QJsonObject toJson() const;
void paint(QPainter *painter, QSize size) const;
void paint(QPainter *painter) const;
bool rename(QString newName) const;
bool combine() const;
// bool seperate() const;

View File

@ -1,6 +0,0 @@
#include "LayerStyle.h"
std::vector<Renderer::BaseStyle> StrokeElementStyle::toBaseStyles() const
{
return std::vector<Renderer::BaseStyle>();
}

View File

@ -1,24 +1,6 @@
#pragma once
#include "../Renderer/Painting/ElementStyle.h"
#include "../Renderer/Painting/MaterialStyleStroke.h"
class LayerStyle
{
public:
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;
};

View File

@ -1,11 +1,11 @@
#include "LayerWrapper.h"
using namespace std;
void FolderLayerWrapper::addChild(shared_ptr<LayerWrapper> child)
void FolderLayerWrapper::addChild(LayerWrapper *child)
{
for (auto &chi : children)
if (chi == child)
if (chi.get() == child)
return;
children.push_back(child);
children.push_back(shared_ptr<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();
return cache;
}
// 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();
property.name = json.value("name").toString();
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(),
transformJson.value("scale").toObject().value("y").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)
{
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()));
if (p != nullptr)
p->setSourceLayer(this);
this->referencedBy = referencedJson.toInt();
}
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)
{
qDebug() << json.value("name").toString() << " " << this;
int elementIndex = json.value("element").toInt();
wrappedElement = elementManager->getElementById(elementIndex);
}
void LayerWrapper::SimpleProperty::apply(PixelPath&cache) const
void LayerWrapper::SimpleProperty::apply(QPainterPath &cache) const
{
QTransform trans;
double centerX = cache.getBoundingRect().center().x();
double centerY = cache.getBoundingRect().center().y();
//qDebug() << name << " " << cache.boundingRect().center();
//qDebug() << name << " " << cache.boundingRect();
double centerX = cache.boundingRect().center().x();
double centerY = cache.boundingRect().center().y();
qDebug() << name << " " << cache.boundingRect().center();
qDebug() << name << " " << cache.boundingRect();
trans.translate(centerX, centerY);
trans.scale(scale.x(), scale.y());
trans.rotate(rotation);
trans.translate(-centerX, -centerY);
trans.translate(offset.x(), offset.y());
cache = cache.trans(trans);
cache = trans.map(cache);
}
void LayerWrapper::refresh()
{
@ -95,9 +98,8 @@ void LayerWrapper::refresh()
void FolderLayerWrapper::refresh()
{
cache.clear();
for (auto& child : children) {
for (auto &child : children)
cache.addPath(child.get()->getCache());
}
LayerWrapper::refresh();
}
@ -106,115 +108,26 @@ void LeafLayerWrapper::refresh()
cache.clear();
if (wrappedElement != nullptr)
{
cache.addPath(wrappedElement->getPaintObject(this->styles));
cache.addPath(wrappedElement->getPaintObject());
}
LayerWrapper::refresh();
}
void LayerWrapper::setParent(FolderLayerWrapper* newParent)
void LayerWrapper::setParent(LayerWrapper *newParent)
{
this->parent = newParent;
this->parent = shared_ptr<LayerWrapper>(newParent);
}
void FolderLayerWrapper::removeAllChild()
{
children.clear();
qTreeWidgetItem.takeChildren();
}
void LayerWrapper::del() {
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()
namespace LayerEvent
{
qDebug() << "FolderLayerWrapper::del()";
for (auto& child : children)
child->del();
LayerWrapper::del();
}
void FolderLayerWrapper::delSelf() {
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()
static void onDoubleClick(QTreeWidgetItem *qItem, LayerWrapper *layerWrapper)
{
this->qTreeWidgetItem.setText(0, this->property.name);
this->qTreeWidgetItem.setData(0, Qt::UserRole, QVariant::fromValue(this));
return &this->qTreeWidgetItem;
}
QTreeWidgetItem* FolderLayerWrapper::getQTreeItem()
{
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;
}
} // namespace LayerEvent

View File

@ -12,28 +12,24 @@
#include <QTreeWidget>
#include <memory>
#include <vector>
#include "PixelPath.h"
#include "../Renderer/Painting/ElementStyle.h"
using std::shared_ptr;
using std::vector;
class GraphicElement;
class SimpleElement;
class GroupElement;
class ElementManager;
class FolderLayerWrapper;
class LayerWrapper
{
protected:
FolderLayerWrapper* parent;
shared_ptr<LayerWrapper> parent;
QPointF referencePoint;
// vector<LayerStyle> styles;
// TODO: 将cache移到子类对Leaf用ComposedPainterPath对Folder用FolderBitmapPath
PixelPath cache;
vector<LayerStyle> styles;
QPainterPath cache;
public:
QTreeWidgetItem qTreeWidgetItem;
QTreeWidgetItem *qTreeItem;
struct SimpleProperty
{
QString name = "";
@ -42,64 +38,44 @@ class LayerWrapper
double rotation = 0;
bool flipHorizontally = 0;
bool flipVertically = 0;
// TODO: 将QPainterPath改为BitmapPath
void apply(PixelPath&cache) const;
void apply(QPainterPath &cache) const;
} property;
virtual void setParent(FolderLayerWrapper*newParent);
void setParent(LayerWrapper *newParent);
virtual void refresh();
virtual QTreeWidgetItem* getQTreeItem();
// TODO: 将QPainterPath改为BitmapPath/QImage或者直接将其删除绘制时直接使用BitmapPath的paint方法
virtual PixelPath getCache();
FolderLayerWrapper*getParent() const; // invoke by manager, then invoke parent's applyStyles
LayerWrapper(QJsonObject json, FolderLayerWrapper*parent);
QPainterPath getCache();
LayerWrapper *getParent() const; // invoke by manager, then invoke parent's applyStyles
LayerWrapper(QJsonObject json, LayerWrapper *parent);
LayerWrapper() = default;
// TODO : export Function
// virtual LayerWrapper *addChild() = 0; // Leaf Child Only
// virtual LayerWrapper *addParent() = 0; // Folder Parent Only
// virtual void deleteSelf() const = 0;
// virtual void deleteAll() const = 0;
virtual void del();
virtual void delSelf();
virtual QJsonObject toJson() const;
~LayerWrapper() = default;
};
class FolderLayerWrapper : public LayerWrapper
{
public:
vector<shared_ptr<LayerWrapper>> children;
int referencedBy = -1;
public:
~FolderLayerWrapper() = default;
void refresh() override;
FolderLayerWrapper() = default;
FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
void addChild(shared_ptr<LayerWrapper> child);
FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, LayerWrapper *parent);
void addChild(LayerWrapper *child);
void removeChild(LayerWrapper *child);
void removeAllChild();
void del() override;
void delSelf() override;
QTreeWidgetItem* getQTreeItem() override;
QJsonObject toJson() const override;
};
class LeafLayerWrapper : public LayerWrapper
{
public:
GraphicElement *wrappedElement;
const vector<Renderer::ElementStyleStrokeDemo> styles;
public:
~LeafLayerWrapper() = default;
void refresh() override;
LeafLayerWrapper() = default;
LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
QJsonObject toJson() const override;
LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, LayerWrapper *parent);
};
Q_DECLARE_METATYPE(LayerWrapper *)
Q_DECLARE_METATYPE(FolderLayerWrapper *)
Q_DECLARE_METATYPE(LeafLayerWrapper *)

View File

@ -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;
}

View File

@ -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;
};

View File

@ -2,59 +2,50 @@
PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent)
{
this->renderer = new Renderer::ElementRenderer(this);
QSurfaceFormat surfaceFormat;
surfaceFormat.setSamples(16);
setFormat(surfaceFormat);
painter = new QPainter(this);
painter->setRenderHint(QPainter::SmoothPixmapTransform);
painter->setRenderHint(QPainter::HighQualityAntialiasing);
layerManager = nullptr;
}
void PreviewWindow::initialize(LayerManager *layerManager,QSize windowSize)
void PreviewWindow::initialize(LayerManager *layerManager)
{
this->logicalSize = windowSize;
this->layerManager = layerManager;
}
void PreviewWindow::show()
{
//QFile settingFile;
//settingFile.setFileName("../data.json");
//settingFile.open(QFile::ReadOnly);
//QByteArray setting = settingFile.readAll().trimmed();
//QJsonDocument jsonDoc(QJsonDocument::fromJson(setting));
//auto jElements = jsonDoc.object().value("elements").toArray();
QFile settingFile;
settingFile.setFileName("../data.json");
settingFile.open(QFile::ReadOnly);
QByteArray setting = settingFile.readAll().trimmed();
QJsonDocument jsonDoc(QJsonDocument::fromJson(setting));
auto jElements = jsonDoc.object().value("elements").toArray();
//for (auto &&ele : jElements)
//{
// SimpleElement element(ele.toObject());
// painter->drawPath(element.getPaintObject());
//}
for (auto &&ele : jElements)
{
SimpleElement element(ele.toObject());
painter->drawPath(element.getPaintObject());
}
}
void PreviewWindow::initializeGL()
{
this->renderer->initialize();
initializeOpenGLFunctions();
glClearColor(1.0, 1.0, 1.0, 1.0);
}
void PreviewWindow::paintGL()
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
painter->begin(this);
painter->setRenderHint(QPainter::Antialiasing);
painter->setRenderHint(QPainter::HighQualityAntialiasing);
layerManager->paint(painter,this->size());
layerManager->paint(painter);
painter->end();
}
void PreviewWindow::resizeGL(int w, int h)
{
}
Renderer::ElementRenderer* const PreviewWindow::getRenderer()const {
return this->renderer;
}

View File

@ -8,8 +8,6 @@
#include <QJsonValue>
#include <QOpenGLFunctions>
#include <QOpenGLWidget>
#include "../Renderer/Preview/ElementRenderer.h"
class PreviewWindow : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
@ -17,15 +15,12 @@ class PreviewWindow : public QOpenGLWidget, protected QOpenGLFunctions
private:
QPainter *painter;
LayerManager *layerManager;
Renderer::ElementRenderer* renderer;
QSize logicalSize;
public:
PreviewWindow(QWidget *parent = nullptr);
void initialize(LayerManager *layerManager, QSize windowSize = QSize(1920, 1080));
void initialize(LayerManager *layerManager);
void show();
void initializeGL() override;
void paintGL() override;
void resizeGL(int w, int h) override;
Renderer::ElementRenderer* const getRenderer()const;
};

View File

@ -1,11 +1,6 @@
#include "InfoDisplayWidget.h"
#include <QLineEdit>
#include <QTextBlock>
#include <QListWidget>
#include <QPushButton>
#include <QDialog>
#include <QDialogButtonBox>
void InfoDisplayWidget::setLayer(LayerWrapper *layer)
{
this->displayLayer = layer;
@ -44,27 +39,27 @@ void InfoDisplayWidget::generateLayerForm()
QLineEdit *scaleX = new QLineEdit(QString::number(this->displayLayer->property.scale.x()), this);
QLineEdit *scaleY = new QLineEdit(QString::number(this->displayLayer->property.scale.y()), this);
name->setDisabled(true);
rotation->setValidator(new QIntValidator(-10000, 10000, this));
rotation->setValidator(new QIntValidator(-1000, 1000, this));
connect(rotation, &QLineEdit::textChanged, [=](QString content) {
this->displayLayer->property.rotation = content.toDouble();
emit requireRefreshPreview();
});
offsetX->setValidator(new QIntValidator(-10000, 10000, this));
offsetX->setValidator(new QIntValidator(-1000, 1000, this));
connect(offsetX, &QLineEdit::textChanged, [=](QString content) {
this->displayLayer->property.offset = {content.toDouble(), this->displayLayer->property.offset.y()};
emit requireRefreshPreview();
});
offsetY->setValidator(new QIntValidator(-10000, 10000, this));
offsetY->setValidator(new QIntValidator(-1000, 1000, this));
connect(offsetY, &QLineEdit::textChanged, [=](QString content) {
this->displayLayer->property.offset = {this->displayLayer->property.offset.x(), content.toDouble()};
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) {
this->displayLayer->property.scale = {content.toDouble(), this->displayLayer->property.scale.y()};
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) {
this->displayLayer->property.scale = {this->displayLayer->property.scale.x(), content.toDouble()};
emit requireRefreshPreview();
@ -77,79 +72,9 @@ void InfoDisplayWidget::generateLayerForm()
layout->addRow("scale-X:", scaleX);
layout->addRow("scale-Y:", scaleY);
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);
}
void InfoDisplayWidget::generateElementForm()
{
}
void InfoDisplayWidget::triggerSelfRefresh()
{
if (this->displayLayer != nullptr)
this->generateLayerForm();
if (this->displayElement != nullptr)
this->generateElementForm();
}

View File

@ -18,12 +18,6 @@ class InfoDisplayWidget : public QWidget
void generateLayerForm();
void generateElementForm();
public slots:
void triggerSelfRefresh();
signals:
void requireRefreshPreview();
void requireSelfRefresh();
};

View File

@ -11,10 +11,7 @@ LayerTreeWidget::LayerTreeWidget(QWidget *parent)
connect(this, &QTreeWidget::customContextMenuRequested, this, &LayerTreeWidget::popMenu);
connect(this, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *currentItem) {
this->selectedItem = currentItem;
if(this->selectedItem !=nullptr)
emit displayLayerChange(this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper *>());
else
emit displayLayerChange(nullptr);
});
// connect(this, &QTreeWidget::itemDoubleClicked, this, &LayerTreeWidget::onItemDoubleClicked);
}
@ -29,38 +26,19 @@ LayerTreeWidget::LayerTreeWidget(QWidget *parent)
// this->selectedItem = item;
// // TODO
// }
#include <QDebug>
void LayerTreeWidget::popMenu(const QPoint &pos)
{
QMenu menu;
QTreeWidgetItem *item = itemAt(pos);
this->selectedItem = item;
// TODO
menu.addAction(QString::fromLocal8Bit("创建子节点"), this, &LayerTreeWidget::onRenameEvent);
//if (item != root->getQTreeItem())
//{
menu.addAction(QString::fromLocal8Bit("重命名"), this, &LayerTreeWidget::onRenameEvent);
// menu.addAction("Copy", this, &LayerTreeWidget::onRenameEvent);
menu.addAction("Add Child", this, &LayerTreeWidget::onRenameEvent);
menu.addAction("Rename", this, &LayerTreeWidget::onRenameEvent);
menu.addAction("Copy", this, &LayerTreeWidget::onRenameEvent);
if (item != nullptr && item->childCount() > 0)
menu.addAction(QString::fromLocal8Bit("删除(保留子节点)"), this, [this]() {
if (this->selectedItem == nullptr)
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.addAction("Delete (Self Only)", this, &LayerTreeWidget::onRenameEvent);
menu.addAction("Delete", this, &LayerTreeWidget::onRenameEvent);
menu.exec(mapToGlobal(pos));
}
@ -79,11 +57,3 @@ void LayerTreeWidget::onRenameEvent()
}
emit displayLayerChange(this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper *>());
}
void LayerTreeWidget::refresh() {
// if(this->root!=nullptr)
//{
// this->clear();
// this->addTopLevelItem(this->root->getQTreeItem());
//}
}

View File

@ -10,15 +10,12 @@ class LayerTreeWidget : public QTreeWidget
LayerWrapper *copiedItem;
public:
LayerWrapper* root;
LayerTreeWidget(QWidget *parent = nullptr);
void onRenameEvent();
void popMenu(const QPoint &pos);
void refresh();
// void mouseDoubleClickEvent(QMouseEvent *event) override;
// void onItemDoubleClicked(QTreeWidgetItem *item, int column = 0);
signals:
void displayLayerChange(LayerWrapper *);
void requireRefreshPreview();
};

View File

@ -1,13 +1,10 @@
#include "SvgFileLoader.h"
#include <QFile>
#include "../ThirdPartyLib/qquick/qquicksvgparser_p.h"
#include "../qquick/qquicksvgparser_p.h"
#include <QPolygonF>
#include <iostream>
using std::map;
using std::vector;
using std::reverse;
bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPath) {
QFile file(filePath);
@ -49,12 +46,12 @@ bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPa
}
}
}
qDebug() << painterPath;
file.close();
return true;
}
QMap<QString, QString> SvgFileLoader::handleAttrStyle(QString style) {
QMap<QString, QString> SvgFileLoader::transformStyle(QString style) {
QMap<QString, QString> resStyleMap;
for (auto& attr : style.split(';')) {
if (attr.isEmpty() || attr.trimmed() == "") continue;
@ -65,7 +62,7 @@ QMap<QString, QString> SvgFileLoader::handleAttrStyle(QString style) {
return resStyleMap;
}
QPolygonF SvgFileLoader::handleAttrPoints(QString points) {
QPolygonF SvgFileLoader::transformPoints(QString points) {
QPolygonF resPointVector;
QPointF point(0, 0);
bool isX = true;
@ -83,58 +80,10 @@ QPolygonF SvgFileLoader::handleAttrPoints(QString points) {
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) {
for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("style")) {
styleMap = handleAttrStyle(attr.value().toLatin1());
styleMap = transformStyle(attr.value().toLatin1());
}
else {
styleMap.insert(attr.name().toLatin1(), attr.value().toLatin1());
@ -145,33 +94,22 @@ void SvgFileLoader::handleLabelG(QPainterPath& painterPath) {
}
void SvgFileLoader::handleLabelPath(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle;
for (auto& attr : xmlReader->attributes()) {
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")) {
labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
labelStyle = transformStyle(attr.value().toLatin1());
}
else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
}
}
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
}
void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) {
QMap<QString, QString> labelStyle;
QPainterPath elementPainterPath;
QString transformStyle = "";
double xBegin = 0, yBegin = 0, width = 0, height = 0;;
for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("x")) {
@ -184,26 +122,17 @@ void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) {
height = attr.value().toDouble();
}
else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
labelStyle = transformStyle(attr.value().toLatin1());
}
else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
}
}
qDebug() << labelStyle;
elementPainterPath.addRect(xBegin, yBegin, xBegin + width, yBegin + height);
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
painterPath.addRect(xBegin, yBegin, xBegin + width, yBegin + height);
}
void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle;
double cx = 0, cy = 0, r = 0;
for (auto& attr : xmlReader->attributes()) {
@ -215,28 +144,17 @@ void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) {
r = attr.value().toDouble();
}
else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
labelStyle = transformStyle(attr.value().toLatin1());
}
else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
}
}
qDebug() << labelStyle;
elementPainterPath.addEllipse(cx, cy, r, r);
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
//addEllipse(cx, cy, r, r, painterPath);
painterPath.addEllipse(cx, cy, r, r);
}
void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle;
double cx = 0, cy = 0, rx = 0, ry = 0;
for (auto& attr : xmlReader->attributes()) {
@ -249,84 +167,47 @@ void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) {
} else if (attr.name().toString() == QLatin1String("ry")) {
rx = attr.value().toDouble();
} else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
labelStyle = transformStyle(attr.value().toLatin1());
}
else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
}
}
qDebug() << labelStyle;
//addEllipse(cx, cy, rx, ry, painterPath);
elementPainterPath.addEllipse(cx, cy, rx, ry);
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
painterPath.addEllipse(cx, cy, rx, ry);
}
void SvgFileLoader::handleLabelPolyline(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle;
for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("points")) {
QPolygonF points = handleAttrPoints(attr.value().toLatin1());
elementPainterPath.addPolygon(points);
QPolygonF points = transformPoints(attr.value().toLatin1());
painterPath.addPolygon(points);
}
else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == QLatin1String("transform")) {
transformStyle = attr.value().toLatin1();
labelStyle = transformStyle(attr.value().toLatin1());
}
else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
}
}
qDebug() << labelStyle;
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
}
void SvgFileLoader::handleLabelPolygon(QPainterPath & painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle;
for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("points")) {
QPolygonF points = handleAttrPoints(attr.value().toLatin1());
//points.push_back(*points.begin());
elementPainterPath.addPolygon(points);
elementPainterPath.closeSubpath();
QPolygonF points = transformPoints(attr.value().toLatin1());
points.push_back(*points.begin());
painterPath.addPolygon(points);
}
else if (attr.name().toString() == QLatin1String("style")) {
labelStyle = handleAttrStyle(attr.value().toLatin1());
}
else if (attr.name().toString() == "transform") {
transformStyle = attr.value().toLatin1();
labelStyle = transformStyle(attr.value().toLatin1());
}
else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
}
}
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();
}
*/

View File

@ -13,10 +13,8 @@ private:
bool existFatherLabelG;
QMap<QString, QString> styleMap;
std::shared_ptr<QXmlStreamReader> xmlReader;
QPolygonF handleAttrPoints(QString points);
QMap<QString, QString> handleAttrStyle(QString style);
void handleAttrTransform(QString transformStyle, QPainterPath& painterPath);
//void addEllipse(double cx, double cy, double h, double w, QPainterPath& painterPath);
QPolygonF transformPoints(QString points);
QMap<QString, QString> transformStyle(QString style);
void handleLabelG(QPainterPath& painterPath);
void handleLabelPath(QPainterPath& painterPath);
void handleLabelRect(QPainterPath& painterPath);
@ -24,5 +22,4 @@ private:
void handleLabelEllipse(QPainterPath& painterPath);
void handleLabelPolyline(QPainterPath& painterPath);
void handleLabelPolygon(QPainterPath& painterPath);
};

View File

@ -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 };
}

View File

@ -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);
};

View File

@ -3,14 +3,8 @@
#include "qslider.h"
#include <QPushButton>
#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>
FRAMELESSHELPER_USE_NAMESPACE
inline void fontTheme()
{
QFont defaultFont = qApp->font();
@ -113,7 +107,8 @@ CentralWidget::CentralWidget(QWidget* parent) : QMainWindow(parent)
tabBarLayout->setMargin(0);
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,
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_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);
setMenuWidget(m_titleBar);
setCentralWidget(m_window);
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::windowTitleChanged, this, [=](const QString& title) {
m_window->ui->titleWidget->setText(title);
});
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"));
setWindowTitle("ArchitectureColoredPainting");
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()
{}
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)
{

View File

@ -4,12 +4,8 @@
#include "ui_MainWindow.h"
#include "ui_FramelessWindow.h"
#include <FramelessHelper/Widgets/framelessmainwindow.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
class StandardTitleBar;
FRAMELESSHELPER_END_NAMESPACE
#define QGOODWINDOW
#include <QGoodWindow>
class FramelessWindow : public QWidget
{
@ -35,21 +31,26 @@ public:
};
class MainWindow : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessMainWindow)
class MainWindow : public QGoodWindow
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(MainWindow)
public:
explicit MainWindow(QWidget * parent = nullptr, const Qt::WindowFlags flags = {});
~MainWindow() override;
explicit MainWindow(QWidget* parent = nullptr);
~MainWindow();
private:
FRAMELESSHELPER_PREPEND_NAMESPACE(StandardTitleBar)* m_titleBar = nullptr;
Ui::MainWindowClass ui;
//Functions
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);
//Variables
FramelessWindow* m_window;
CentralWidget* m_central_widget;
bool m_draw_borders;
bool m_dark;
};

View File

@ -1,24 +1,14 @@
#include "NavigationBarWidget.h"
#include <qtmaterialraisedbutton.h>
#include <QDebug>
NavigationBarWidget::NavigationBarWidget(QWidget *parent)
: QWidget(parent)
, tabs(new QtMaterialTabs)
{
tabs->addTab(QStringLiteral("ÎÆÀí±à¼­"));
tabs->addTab(QStringLiteral("³¡¾°äÖȾ"));
tabs->setHaloVisible(false);
tabs->setBackgroundColor(Qt::transparent);
tabs->setTextColor(Qt::black);
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);
}
ui.setupUi(this);
buttonGroup = new QButtonGroup(this);
buttonGroup->addButton(ui.radioButton0, 0);
buttonGroup->addButton(ui.radioButton1, 1);
ui.radioButton0->setChecked(true);
;}
NavigationBarWidget::~NavigationBarWidget()
{}

View File

@ -2,7 +2,6 @@
#include <QWidget>
#include <QButtonGroup>
#include <qtmaterialtabs.h>
#include "ui_NavigationBarWidget.h"
class NavigationBarWidget : public QWidget
@ -12,5 +11,8 @@ class NavigationBarWidget : public QWidget
public:
NavigationBarWidget(QWidget *parent = nullptr);
~NavigationBarWidget();
QtMaterialTabs* tabs;
QButtonGroup* buttonGroup;
private:
Ui::NavigationBarWidgetClass ui;
};

View File

@ -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;
}

View File

@ -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);
};
}

View File

@ -83,7 +83,6 @@ QMatrix4x4 Light::getLightSpaceMatrix(const float nearPlane, const float farPlan
minZ = std::min(minZ, -trf.z());
maxZ = std::max(maxZ, -trf.z());
}
if (model != nullptr)
for (const QVector3D& v : model->AABB)
{
const QVector4D trf = lightView * QVector4D(v, 1);

View File

@ -18,7 +18,7 @@ namespace Renderer
std::vector<float> shadowCascadeLevels;
float blendRatio = 0.3;
std::vector<float> frustumSizes;
Model* model = nullptr;
Model* model;
Light(Camera* camera);
std::vector<QVector4D> getFrustumCornersWorldSpace(const QMatrix4x4& projview);
std::vector<QVector4D> getFrustumCornersWorldSpace(const QMatrix4x4& proj, const QMatrix4x4& view);

View File

@ -1,59 +1,71 @@
#include "Mesh.h"
#include <qDebug>
using namespace Renderer;
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)
Mesh::Mesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, aiMatrix4x4 model)
: glFunc(glFunc)
, shaderProgram(shaderProgram)
, shadowProgram(shadowProgram)
, VBO(QOpenGLBuffer::VertexBuffer)
, 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()
{
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->glBindTextureUnit(1, textureMetallicRoughness);
glFunc->glBindTextureUnit(2, textureNormal);
shaderProgram->setUniformValue("texture_basecolor", 0);
shaderProgram->setUniformValue("texture_metallic_roughness", 1);
shaderProgram->setUniformValue("texture_normal", 2);
glFunc->glActiveTexture(GL_TEXTURE0 + i); // 在绑定之前激活相应的纹理单元
textures[i]->texture.bind();
//qDebug() << name + number;
shaderProgram->setUniformValue(textures[i]->type.toStdString().c_str(), i);
}
// 绘制网格
QOpenGLVertexArrayObject::Binder bind(&VAO);
shaderProgram->setUniformValue("model", model);
EBO.bind();
glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
shaderProgram->release();
}
}
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);
shadowProgram->setUniformValue("texture_basecolor", 0);
glFunc->glActiveTexture(GL_TEXTURE0 + i); // 在绑定之前激活相应的纹理单元
textures[i]->texture.bind();
//qDebug() << name + number;
shadowProgram->setUniformValue(textures[i]->type.toStdString().c_str(), i);
}
// 绘制网格
QOpenGLVertexArrayObject::Binder bind(&VAO);
shadowProgram->setUniformValue("model", model);
EBO.bind();
glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
shadowProgram->release();
}
}
void Mesh::setupMesh()
{
shaderProgram->bind();
VAO.create();
VAO.bind();
@ -66,17 +78,23 @@ void Mesh::setupMesh()
EBO.bind();
EBO.allocate(indices.data(), indices.size() * sizeof(unsigned int));
if (shaderProgram->bind())
{
shaderProgram->enableAttributeArray(0);
shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(Vertex));
shaderProgram->enableAttributeArray(1);
shaderProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(Vertex, Normal), 3, sizeof(Vertex));
shaderProgram->enableAttributeArray(2);
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();
}
VAO.release();
}

View File

@ -1,5 +1,5 @@
#pragma once
#include <QOpenGLFunctions_4_5_Core>
#include <QOpenGLFunctions_4_5_Compatibility>
#include <QString>
#include <QVector>
#include <QVector2D>
@ -9,9 +9,10 @@
#include <QOpenGLVertexArrayObject>
#include <QOpenGLTexture>
#include <QOpenGLWidget>
#include <assimp/vector3.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include "Drawable.h"
namespace Renderer
{
struct Vertex
@ -19,7 +20,8 @@ namespace Renderer
QVector3D Position;
QVector3D Normal;
QVector2D TexCoords;
Vertex(const aiVector3D& position, const aiVector3D& Normal, const aiVector3D& TexCoords);
QVector3D Tangent;
QVector3D Bitangent;
};
struct Texture
@ -38,23 +40,22 @@ namespace Renderer
class Mesh : public Drawable
{
public:
QVector<Vertex> vertices;
QVector<unsigned int> indices;
//QVector<Texture*> textures;
GLuint textureBasecolor = 0;
GLuint textureMetallicRoughness = 0;
GLuint textureNormal = 0;
/* 网格数据 */
QVector<Vertex> vertices; //顶点数据
QVector<unsigned int> indices; //索引数组
QVector<Texture*> textures; //纹理数据
QMatrix4x4 model; //模型矩阵
QOpenGLFunctions_4_5_Compatibility* glFunc; //opengl函数入口
QOpenGLShaderProgram* shaderProgram, * shadowProgram; //着色器程序
QMatrix4x4 model;
QOpenGLFunctions_4_5_Core* glFunc;
QOpenGLShaderProgram* shaderProgram, * shadowProgram;
Mesh(QOpenGLFunctions_4_5_Core* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, const QMatrix4x4& model);
/* 函数 */
Mesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, aiMatrix4x4 model);
void draw() override;
void drawShadow() override;
void setupMesh();
private:
/* 渲染数据 */
QOpenGLVertexArrayObject VAO;
QOpenGLBuffer VBO, EBO;

View File

@ -1,6 +1,5 @@
#include "Model.h"
#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
#include <QOpenGLTexture>
#include <QOpenGLContext>
#include <QTextCodec>
@ -11,41 +10,16 @@
#include "Painting/ShortCutTree.h"
#include "Painting/Painting.h"
#include "../SvgParser.h"
#include "../Editor/util/PainterPathUtil.h"
#include "../Editor/util/SvgFileLoader.h"
#include <ThirdPartyLib/qquick/qquicksvgparser_p.h>
using namespace Renderer;
using std::vector;
Model::Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram,
QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager)
Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram)
: context(context)
, glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Core>())
, glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Compatibility>())
, shaderProgram(shaderProgram)
, paintingProgram(paintingProgram)
, shadowProgram(shadowProgram)
, vtManager(vtManager)
, directory(path)
{
}
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;
const aiScene* scene = importer.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs);
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() << "NumTextures: " << scene->mNumTextures;
directory.cdUp();
minX = std::numeric_limits<float>::max();
maxX = std::numeric_limits<float>::min();
minY = std::numeric_limits<float>::max();
maxY = std::numeric_limits<float>::min();
minZ = std::numeric_limits<float>::max();
maxZ = std::numeric_limits<float>::min();
processNode(scene->mRootNode, scene);
}
Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, PaintingHelper* paintingHelper)
: context(context)
, 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);
AABB.push_back(QVector3D(minX, minY, minZ));
AABB.push_back(QVector3D(minX, minY, maxZ));
@ -75,13 +67,50 @@ void Renderer::Model::loadModel(QString path)
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)
{
// 处理节点所有的网格(如果有的话)
for (unsigned int i = 0; i < node->mNumMeshes; i++)
{
if (auto mesh = processMesh(scene->mMeshes[node->mMeshes[i]], scene, mat4))
meshes.emplace_back(std::move(mesh));
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
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];
QMatrix4x4 modelQ((float*)&model);
aiString 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";
// 初始化网格
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++)
{
if (mesh->mNormals && mesh->mTextureCoords[0])
{
Vertex vertex(mesh->mVertices[i], mesh->mNormals[i], mesh->mTextureCoords[0][i]);
PaintingVertex vertex;
vertex.Position = QVector3D(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
minX = std::min(minX, vertex.Position.x());
maxX = std::max(maxX, vertex.Position.x());
minY = std::min(minY, vertex.Position.y());
maxY = std::max(maxY, vertex.Position.y());
minZ = std::min(minZ, 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);
}
}
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()));
auto& handle = vtManager->getPaintingHandle(m_mesh->paintingId);
m_mesh->textureBasecolor = handle.baseColor;
m_mesh->textureMetallicRoughness = handle.metallicRoughness;
m_mesh->paintingIndex = loadPainting(std::string(str.C_Str()));
m_mesh->setupMesh();
return m_mesh;
}
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++)
{
if (mesh->mNormals && mesh->mTextureCoords[0])
{
Vertex vertex(mesh->mVertices[i], mesh->mNormals[i], mesh->mTextureCoords[0][i]);
Vertex vertex;
QVector3D vector; //将assimp的数据转化为QtOpenGL支持的数据
// 位置
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());
maxX = std::max(maxX, vertex.Position.x());
minY = std::min(minY, vertex.Position.y());
maxY = std::max(maxY, vertex.Position.y());
minZ = std::min(minZ, 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);
}
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)))
qWarning() << "Basecolor Texture Loading Failed!";
if (!(m_mesh->textureMetallicRoughness = loadMaterialTextures(material, aiTextureType_METALNESS)))
qWarning() << "MetallicRoughness Texture Loading Failed!";
if (!(m_mesh->textureNormal = loadMaterialTextures(material, aiTextureType_NORMALS)))
qWarning() << "Normal Texture Loading Failed!";
QVector<Texture*> diffuseMaps = loadMaterialTextures(material, aiTextureType_BASE_COLOR, "texture_basecolor");
for (auto& it : diffuseMaps)
m_mesh->textures.push_back(it);
QVector<Texture*> metalnessMaps = loadMaterialTextures(material, aiTextureType_METALNESS, "texture_metallic_roughness");
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();
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;
mat->GetTexture(type, 0, &str);
const std::string path(str.C_Str());
auto iter = texturesLoaded.find(path);
if (iter != texturesLoaded.end())
return iter->second.textureId();
mat->GetTexture(type, i, &str);
QImage data(directory.filePath(path.c_str()));
if (data.isNull())
return 0;
//qDebug() << "Loading" << path.c_str();
auto [it, _] = texturesLoaded.emplace(path, QOpenGLTexture::Target2D);
auto& texture = it->second;
texture.create();
texture.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
texture.setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);
texture.setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
texture.setData(data);
return texture.textureId();
// 检查纹理是否在之前加载过,如果是,则继续到下一个迭代:跳过加载新纹理
bool skip = false;
for (unsigned int j = 0; j < textures_loaded.size(); j++)
{
if (std::strcmp(textures_loaded[j]->path.toStdString().c_str(), str.C_Str()) == 0)
{
textures.push_back(textures_loaded[j]);
skip = true;
break;
}
}
if (!skip)
{ // 如果材质还没有加载,加载它
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)
@ -213,63 +319,219 @@ GLuint Renderer::Model::loadPainting(std::string path)
if (iter != paintingLoaded.end())
return iter->second;
//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()),
// 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()),
// 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())
//vector < vector <Point>> lineSet = {
// {{-0.5,0.9}, {0.1,0.3}},
// {{0.1,0.3}, {0.0204656,0.379534}, {-0.2,0.0632573}, {-0.2,0.175736}},
// {{-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;
QPainterPath painterPaths[3];
QQuickSvgParser::parsePathDataFast("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z",
painterPaths[0]);
if (!SvgFileLoader().loadSvgFile("../svg/2.svg", painterPaths[1]))
qCritical() << "load error";
/*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",
painterPaths[1]);*/
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",
painterPaths[2]);
for (auto& i : painterPaths)
{
auto [contour, ratio] = PainterPathUtil::toNormalizedLines(i);
contours.emplace_back(std::make_shared<Contour>(contour), ratio);
}
vector<std::shared_ptr<ElementStyle>> style = {
std::make_shared<ElementStyleFillDemo>(),
std::make_shared<ElementStyleStrokeDemo>(0.02),
std::make_shared<ElementStyleStrokeRadialGradientDemo>(0.2)
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()),
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()),
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())
};
vector<std::shared_ptr<ElementStyle>> style = {
std::make_shared<ElementStyle>(std::vector<GLfloat>{
//strokeStyle
//stroke
1,
//strokeWidth
0.01,
//strokeEndType
0, //圆角
//strokeFillType
0, //单色
//线类型
2, //双侧
//线外描边宽度
0,
//线外描边方式
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 = {
std::make_shared<Element>(Element{ contours[0].first, style[0], contours[0].second}),
std::make_shared<Element>(Element{ contours[1].first, style[2], contours[1].second}),
std::make_shared<Element>(Element{ contours[2].first, style[0], contours[2].second}),
std::make_shared<Element>(Element{ contour[0], style[1]}),
std::make_shared<Element>(Element{ contour[1], style[2]}),
std::make_shared<Element>(Element{ contour[2], style[0]}),
};
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.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,-0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.45, 0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
painting.addElement(*element[2], ElementTransform{ glm::vec2(0.50,-0.45), glm::vec2(0.6,0.7) / 2.f, 0, glm::bvec2(false), 0 });
}
else
{
for (int i = 0; i < 1000; i++)
{
float x = (float)rand() / RAND_MAX * 2 - 1;
float y = (float)rand() / RAND_MAX * 2 - 1;
painting.addElement(*element[i % 3], ElementTransform{ glm::vec2(x,y), glm::vec2(0.025), (float)rand() / RAND_MAX * 360, glm::bvec2(false), 0 });
}
}
painting.generateBuffers();
/////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<GLuint> bvhChildren0 = {
//root
1,2,
3,4, 5,6,
encodeChild(2),0, encodeChild(1),GLuint(30. / 360 * 65536 + 1 * 65536) /*右儿子用来表示旋转角度和zIndex*/, encodeChild(3),0, encodeChild(0),0,
//elememt0
1,2,
encodeChild(20)/*contour索引由于contour不定长这里需要给到contour在elementIndex中位置*/,0/*封闭图形*/, encodeChild(24), 0,
//elememt1
encodeChild(12)/*contour索引*/, 1/*线*/
};
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);
auto index = vtManager->createVirtualTexture(painting);
paintingLoaded.emplace(path, index);
//m_mesh->paintingIndex = paintingHelper->addPainting(bounds.size(), std::vector<GLuint>(children.begin()+2, children.end()), bounds,
// elementOffset, elementIndex, elementData);
/*m_mesh->paintingIndex = paintingHelper->addPainting(bvhChildren0, bvhBounds0,
elementOffset0, elementIndex0, elementData0);*/
GLuint index = paintingHelper->addPainting(painting);
paintingLoaded.insert({ path, index });
return index;
}

View File

@ -1,9 +1,9 @@
#pragma once
#include "Mesh.h"
#include "Drawable.h"
#include "VirtualTextureManager.h"
#include "Painting/PaintingHelper.h"
#include <QDir>
#include <assimp/scene.h>
namespace Renderer
{
@ -14,34 +14,41 @@ namespace Renderer
void draw();
void drawShadow();
void loadModel(QString path);
Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager);
void destroy();
static Model* createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram);
Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, PaintingHelper* paintingHelper);
private:
QOpenGLContext* context;
QOpenGLFunctions_4_5_Core* glFunc = nullptr;
Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram);
~Model();
QOpenGLContext* context; //opengl函数入口
QOpenGLFunctions_4_5_Compatibility* glFunc;
QOpenGLShaderProgram* shaderProgram = nullptr;
QOpenGLShaderProgram* paintingProgram = nullptr;
QOpenGLShaderProgram* paintingProgram = nullptr; //彩绘着色器程序
QOpenGLShaderProgram* shadowProgram = nullptr;
VirtualTextureManager* vtManager = nullptr;
PaintingHelper* paintingHelper = nullptr;
/* Ä£ÐÍÊý¾Ý */
std::unordered_map<std::string, GLuint> paintingLoaded;
std::unordered_map<std::string, QOpenGLTexture> texturesLoaded;
std::vector<std::unique_ptr<Drawable>> meshes;
QVector<Texture*> textures_loaded; //纹理
QVector<Drawable*> meshes; //网格
QDir directory; //模型所在路径
/// 模型所在路径
QDir directory;
float minX = std::numeric_limits<float>::max();
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());
/// 加载网格
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);
};

View File

@ -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)};
}

View File

@ -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;
};
}

View File

@ -4,8 +4,8 @@ GLuint BvhTree::getBvhNodeNum() {
return tot;
}
void BvhTree::buildBvhTree(BvhTreeData initBound[], int len, GLuint transformParam) {
tot = 0; transform = transformParam;
void BvhTree::buildBvhTree(BvhTreeData initBound[], int len) {
tot = 0;
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 res = initBound[l].bound;
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;
BvhPtr p(new BvhNode());
p->lab = tot++;
//p->bound = calcBound(initBound, l, r);
p->bound = calcBound(initBound, l, r);
if (l == r) {
p->isLeaf = true;
BvhPtr lp(new BvhNode());
@ -50,7 +39,6 @@ BvhPtr BvhTree::subBvhTree(BvhTreeData initBound[], int l, int r) {
BvhPtr rp(new BvhNode());
rp->lab = initBound[r].rightSon;
p->child[1] = rp;
p->bound = calcBound(initBound, l, r);
return p;
}
int dim = p->maximumBound();
@ -62,13 +50,12 @@ BvhPtr BvhTree::subBvhTree(BvhTreeData initBound[], int l, int r) {
int mid = (l + r) >> 1;
p->child[0] = subBvhTree(initBound, l, mid);
p->child[1] = subBvhTree(initBound, mid+1, r);
p->bound = merge(p->child[0], p->child[1]);
return p;
}
void BvhTree::traverseBvhTree(BvhPtr now, std::vector<GLuint>& children, std::vector<QVector4D>& bounds) {
children.push_back(now->getLeftSon());
children.push_back(now->getRightSon());
children.push_back(now->getLeftSon(0));
children.push_back(now->getRightSon(1));
bounds.push_back(now->bound);
if (now->isLeaf) return;
traverseBvhTree(now->child[0], children, bounds);

View File

@ -20,24 +20,6 @@ namespace Renderer
bound.x(), bound.y(), bound.z(), bound.w(),
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)
: bound(bound), leftSon(leftSon), rightSon(rightSon) {}
BvhTreeData()
@ -56,13 +38,13 @@ namespace Renderer
static bool y_compare(BvhTreeData a, BvhTreeData b) {
return a.bound.y() < b.bound.y();
}
GLuint getLeftSon() {
GLuint getLeftSon(int k) {
if (isLeaf) {
return 0x80000000 + child[0]->lab;
}
return child[0]->lab;
}
GLuint getRightSon() {
GLuint getRightSon(int k) {
if (isLeaf) {
return child[1]->lab;
}
@ -85,20 +67,19 @@ namespace Renderer
{
private:
GLuint tot, transform;
GLuint tot;
BvhPtr root;
static QVector4D calcBound(BvhTreeData initBound[], int l, int r);
static QVector4D Union(QVector4D a, QVector4D b);
BvhPtr subBvhTree(BvhTreeData initBound[], int l, int r);
void traverseBvhTree(BvhPtr now, std::vector<GLuint>& children, std::vector<QVector4D>& bounds);
QVector4D merge(BvhPtr lp, BvhPtr rp);
public:
BvhTree() {
tot = 0;
root = NULL;
}
// 根据底层包围盒生成bvh树
void buildBvhTree(BvhTreeData initBound[], int len, GLuint transformParam = 0);
void buildBvhTree(BvhTreeData initBound[], int len);
// 获得 Bvh rootBvh部分的 children 数组,包围盒数组 vector 传输
void getBvhArray(std::vector<GLuint>& children, std::vector<QVector4D>& bounds);
// 获得 BvhTree 中节点总数

Some files were not shown because too many files have changed in this diff Show More