添加项目文件。

This commit is contained in:
tzdwindows 7
2025-11-14 16:22:42 +08:00
parent 695f7008cf
commit 2c36bac794
31 changed files with 3045 additions and 0 deletions

37
Vivid2D/Vivid2D.cpp Normal file
View File

@@ -0,0 +1,37 @@
// Vivid2D.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
// 包含GLM主头文件
#include <glm/glm.hpp>
// 包含vec2定义
#include <iostream>
#include <glm/vec2.hpp>
int main() {
// 创建一个二维浮点向量 (Vector2f)
glm::vec2 position(100.0f, 200.0f);
// 创建另一个向量代表速度
glm::vec2 velocity(5.0f, -2.0f);
// 向量加法,更新位置
position += velocity;
// 输出新的位置
// GLM的向量可以直接用std::cout输出但需要包含<glm/gtx/string_cast.hpp>
// 这里为了简单,我们手动输出
std::cout << "New Position: (" << position.x << ", " << position.y << ")" << std::endl;
return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

134
Vivid2D/Vivid2D.vcxproj Normal file
View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{4b88f09b-523c-4678-adcc-e1421a7dc39e}</ProjectGuid>
<RootNamespace>Vivid2D</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Vivid2D.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Vivid2D.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>

44
Vivid2DRenderer.sln Normal file
View File

@@ -0,0 +1,44 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.10.35027.167
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Vivid2DRenderer", "Vivid2DRenderer\Vivid2DRenderer.vcxproj", "{CDFA4C34-767D-49C0-AFE1-EE6C49A9DA68}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Vivid2D", "Vivid2D\Vivid2D.vcxproj", "{4B88F09B-523C-4678-ADCC-E1421A7DC39E}"
ProjectSection(ProjectDependencies) = postProject
{CDFA4C34-767D-49C0-AFE1-EE6C49A9DA68} = {CDFA4C34-767D-49C0-AFE1-EE6C49A9DA68}
EndProjectSection
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
{CDFA4C34-767D-49C0-AFE1-EE6C49A9DA68}.Debug|x64.ActiveCfg = Debug|x64
{CDFA4C34-767D-49C0-AFE1-EE6C49A9DA68}.Debug|x64.Build.0 = Debug|x64
{CDFA4C34-767D-49C0-AFE1-EE6C49A9DA68}.Debug|x86.ActiveCfg = Debug|Win32
{CDFA4C34-767D-49C0-AFE1-EE6C49A9DA68}.Debug|x86.Build.0 = Debug|Win32
{CDFA4C34-767D-49C0-AFE1-EE6C49A9DA68}.Release|x64.ActiveCfg = Release|x64
{CDFA4C34-767D-49C0-AFE1-EE6C49A9DA68}.Release|x64.Build.0 = Release|x64
{CDFA4C34-767D-49C0-AFE1-EE6C49A9DA68}.Release|x86.ActiveCfg = Release|Win32
{CDFA4C34-767D-49C0-AFE1-EE6C49A9DA68}.Release|x86.Build.0 = Release|Win32
{4B88F09B-523C-4678-ADCC-E1421A7DC39E}.Debug|x64.ActiveCfg = Debug|x64
{4B88F09B-523C-4678-ADCC-E1421A7DC39E}.Debug|x64.Build.0 = Debug|x64
{4B88F09B-523C-4678-ADCC-E1421A7DC39E}.Debug|x86.ActiveCfg = Debug|Win32
{4B88F09B-523C-4678-ADCC-E1421A7DC39E}.Debug|x86.Build.0 = Debug|Win32
{4B88F09B-523C-4678-ADCC-E1421A7DC39E}.Release|x64.ActiveCfg = Release|x64
{4B88F09B-523C-4678-ADCC-E1421A7DC39E}.Release|x64.Build.0 = Release|x64
{4B88F09B-523C-4678-ADCC-E1421A7DC39E}.Release|x86.ActiveCfg = Release|Win32
{4B88F09B-523C-4678-ADCC-E1421A7DC39E}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CD348B38-5FCC-4BCC-9826-2060B6862A5C}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,179 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{cdfa4c34-767d-49c0-afe1-ee6c49a9da68}</ProjectGuid>
<RootNamespace>Vivid2DRenderer</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;VIVID2DRENDERER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;VIVID2DRENDERER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;VIVID2DRENDERER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;VIVID2DRENDERER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<LanguageStandard>stdcpp20</LanguageStandard>
<DisableSpecificWarnings>4828</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="systems\buffer\BufferUploader.h" />
<ClInclude Include="systems\buffer\BufferBuilder.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="systems\sources\def\Shader2D.h" />
<ClInclude Include="systems\sources\def\SolidColorShader.h" />
<ClInclude Include="systems\sources\CompleteShader.h" />
<ClInclude Include="systems\sources\Shader.h" />
<ClInclude Include="systems\sources\ShaderManagement.h" />
<ClInclude Include="systems\sources\ShaderProgram.h" />
<ClInclude Include="systems\RenderSystem.h" />
<ClInclude Include="systems\sources\def\TextShader.h" />
<ClInclude Include="systems\buffer\Tesselator.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="systems\buffer\BufferUploader.cpp" />
<ClCompile Include="systems\buffer\BufferBuilder.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="systems\sources\def\Shader2D.cpp" />
<ClCompile Include="systems\sources\def\SolidColorShader.cpp" />
<ClCompile Include="systems\sources\ShaderManagement.cpp" />
<ClCompile Include="systems\sources\ShaderProgram.cpp" />
<ClCompile Include="systems\RenderSystem.cpp" />
<ClCompile Include="systems\sources\def\TextShader.cpp" />
<ClCompile Include="systems\buffer\Tesselator.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>

View File

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="systems\RenderSystem.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="systems\sources\ShaderProgram.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="systems\sources\ShaderManagement.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="systems\sources\Shader.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="systems\sources\CompleteShader.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="systems\sources\def\TextShader.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="systems\sources\def\SolidColorShader.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="systems\sources\def\Shader2D.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="systems\buffer\Tesselator.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="systems\buffer\BufferBuilder.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="systems\buffer\BufferUploader.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="systems\RenderSystem.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="systems\sources\ShaderProgram.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="systems\sources\ShaderManagement.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="systems\sources\def\TextShader.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="systems\sources\def\SolidColorShader.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="systems\sources\def\Shader2D.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="systems\buffer\Tesselator.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="systems\buffer\BufferBuilder.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="systems\buffer\BufferUploader.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,19 @@
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容
// Windows 头文件
#include <windows.h>

5
Vivid2DRenderer/pch.cpp Normal file
View File

@@ -0,0 +1,5 @@
// pch.cpp: 与预编译标头对应的源文件
#include "pch.h"
// 当使用预编译的头时,需要使用此源文件,编译才能成功。

13
Vivid2DRenderer/pch.h Normal file
View File

@@ -0,0 +1,13 @@
// pch.h: 这是预编译标头文件。
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。
#ifndef PCH_H
#define PCH_H
// 添加要在此处预编译的标头
#include "framework.h"
#endif //PCH_H

View File

@@ -0,0 +1,474 @@
#include "pch.h"
#include "RenderSystem.h"
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <cassert>
#include <iostream>
#include <fstream>
#include <sstream>
#include <filesystem>
#include <stdexcept>
#include <vector>
// ================== <20><>̬<EFBFBD><CCAC>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC> ==================
std::thread::id RenderSystem::s_RenderThreadId;
std::atomic<bool> RenderSystem::s_IsInInit = false;
std::queue<std::function<void()>> RenderSystem::s_RenderQueue;
std::mutex RenderSystem::s_RenderQueueMutex;
std::atomic<bool> RenderSystem::s_IsReplayingQueue = false;
std::stack<RenderSystem::RenderState> RenderSystem::s_StateStack;
int RenderSystem::s_ViewportWidth = 800;
int RenderSystem::s_ViewportHeight = 600;
glm::vec4 RenderSystem::s_ClearColorValue = { 0.0f, 0.0f, 0.0f, 1.0f };
std::shared_ptr<spdlog::logger> RenderSystem::s_Logger;
// ================== <20><>־ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD> ==================
void RenderSystem::InitializeLogging() {
std::vector<spdlog::sink_ptr> sinks;
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
console_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [thread %t] %v");
sinks.push_back(console_sink);
try {
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/Vivid2D.log", true);
file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] [thread %t] %v");
sinks.push_back(file_sink);
}
catch (const spdlog::spdlog_ex& ex) {
std::cerr << "Log file creation failed: " << ex.what() << std::endl;
}
s_Logger = std::make_shared<spdlog::logger>("RenderSystem", begin(sinks), end(sinks));
spdlog::register_logger(s_Logger);
s_Logger->set_level(spdlog::level::trace);
s_Logger->flush_on(spdlog::level::trace);
s_Logger->info("Logging system initialized.");
}
void RenderSystem::ShutdownLogging() {
s_Logger->info("Logging system shutting down.");
s_Logger.reset();
spdlog::shutdown();
}
// ================== <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>̹߳<DFB3><CCB9><EFBFBD> ==================
void RenderSystem::initRenderThread() {
if (s_RenderThreadId == std::thread::id()) {
s_RenderThreadId = std::this_thread::get_id();
s_Logger->info("Render thread initialized on thread ID: {}", std::hash<std::thread::id>{}(s_RenderThreadId));
}
else if (s_RenderThreadId != std::this_thread::get_id()) {
s_Logger->critical("Render thread already initialized by another thread!");
throw std::runtime_error("Render thread already initialized by another thread");
}
}
void RenderSystem::beginInitialization() { s_IsInInit = true; }
void RenderSystem::finishInitialization() {
s_IsInInit = false;
if (getQueueSize() > 0) { replayQueue(); }
}
bool RenderSystem::isOnRenderThread() { return std::this_thread::get_id() == s_RenderThreadId; }
bool RenderSystem::isInInitPhase() { return s_IsInInit; }
void RenderSystem::assertOnRenderThread() { if (!isOnRenderThread()) { throw std::runtime_error("RenderSystem called from wrong thread!"); } }
void RenderSystem::assertOnRenderThreadOrInit() { if (!isInInitPhase() && !isOnRenderThread()) { throw std::runtime_error("RenderSystem called from wrong thread!"); } }
// ================== <20><>Ⱦ<EFBFBD><C8BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==================
void RenderSystem::recordRenderCall(std::function<void()>&& renderCall) {
std::lock_guard<std::mutex> lock(s_RenderQueueMutex);
s_RenderQueue.push(std::move(renderCall));
}
void RenderSystem::replayQueue() {
s_IsReplayingQueue = true;
std::queue<std::function<void()>> localQueue;
{
std::lock_guard<std::mutex> lock(s_RenderQueueMutex);
s_RenderQueue.swap(localQueue);
}
while (!localQueue.empty()) {
auto& call = localQueue.front();
if (call) { call(); }
localQueue.pop();
}
s_IsReplayingQueue = false;
}
// ================== OpenGL ״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ ==================
#define RENDER_SYSTEM_QUEUE_CALL(FunctionName, ...) \
if (!isOnRenderThread()) { \
recordRenderCall([=] { FunctionName(__VA_ARGS__); }); \
} else { \
FunctionName(__VA_ARGS__); \
}
#define RENDER_SYSTEM_QUEUE_CALL_NO_ARGS(FunctionName) \
if (!isOnRenderThread()) { \
recordRenderCall([=] { FunctionName(); }); \
} else { \
FunctionName(); \
}
void RenderSystem::enable(GLenum capability) { RENDER_SYSTEM_QUEUE_CALL(_enable, capability); }
void RenderSystem::_enable(GLenum c) { assertOnRenderThread(); glEnable(c); }
void RenderSystem::disable(GLenum capability) { RENDER_SYSTEM_QUEUE_CALL(_disable, capability); }
void RenderSystem::_disable(GLenum c) { assertOnRenderThread(); glDisable(c); }
void RenderSystem::pushState() { RENDER_SYSTEM_QUEUE_CALL_NO_ARGS(_pushState); }
void RenderSystem::_pushState() {
assertOnRenderThread();
_checkGLError("before pushState");
s_StateStack.push(RenderState());
_checkGLError("after pushState");
}
void RenderSystem::popState() { RENDER_SYSTEM_QUEUE_CALL_NO_ARGS(_popState); }
void RenderSystem::_popState() {
assertOnRenderThread();
if (!s_StateStack.empty()) {
s_StateStack.top().restore();
s_StateStack.pop();
_checkGLError("after popState");
}
else {
s_Logger->warn("popState called with empty state stack.");
}
}
int RenderSystem::getStateStackSize() { return s_StateStack.size(); }
void RenderSystem::clearColor(float r, float g, float b, float a) { RENDER_SYSTEM_QUEUE_CALL(_clearColor, r, g, b, a); }
void RenderSystem::_clearColor(float r, float g, float b, float a) {
assertOnRenderThread();
glClearColor(r, g, b, a);
s_ClearColorValue = { r, g, b, a };
}
void RenderSystem::clear(GLbitfield mask) { RENDER_SYSTEM_QUEUE_CALL(_clear, mask); }
void RenderSystem::_clear(GLbitfield m) { assertOnRenderThread(); glClear(m); }
void RenderSystem::viewport(int x, int y, int width, int height) { RENDER_SYSTEM_QUEUE_CALL(_viewport, x, y, width, height); }
void RenderSystem::_viewport(int x, int y, int w, int h) {
assertOnRenderThread();
glViewport(x, y, w, h);
s_ViewportWidth = w;
s_ViewportHeight = h;
}
// ================== VAO / VBO / EBO <20><><EFBFBD><EFBFBD> ==================
GLuint RenderSystem::GenVertexArrays() { assertOnRenderThread(); GLuint vao = 0; glGenVertexArrays(1, &vao); return vao; }
void RenderSystem::DeleteVertexArrays(GLuint vao) { RENDER_SYSTEM_QUEUE_CALL(_glDeleteVertexArrays, vao); }
void RenderSystem::_glDeleteVertexArrays(GLuint v) { assertOnRenderThread(); glDeleteVertexArrays(1, &v); }
void RenderSystem::BindVertexArray(GLuint vao) { RENDER_SYSTEM_QUEUE_CALL(_glBindVertexArray, vao); }
void RenderSystem::_glBindVertexArray(GLuint v) { assertOnRenderThread(); glBindVertexArray(v); }
GLuint RenderSystem::GenBuffers() { assertOnRenderThread(); GLuint buf; glGenBuffers(1, &buf); return buf; }
void RenderSystem::DeleteBuffers(GLuint buffer) { RENDER_SYSTEM_QUEUE_CALL(_glDeleteBuffers, buffer); }
void RenderSystem::_glDeleteBuffers(GLuint b) { assertOnRenderThread(); glDeleteBuffers(1, &b); }
void RenderSystem::BindBuffer(GLenum target, GLuint buffer) { RENDER_SYSTEM_QUEUE_CALL(_glBindBuffer, target, buffer); }
void RenderSystem::_glBindBuffer(GLenum t, GLuint b) { assertOnRenderThread(); glBindBuffer(t, b); }
void RenderSystem::BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
assertOnRenderThread();
glBufferData(target, size, data, usage);
}
// [<5B><><EFBFBD><EFBFBD>] _glBufferData <20>Ķ<EFBFBD><C4B6><EFBFBD>
void RenderSystem::_glBufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
assertOnRenderThread();
glBufferData(target, size, data, usage);
}
// ================== Uniform <20><><EFBFBD><EFBFBD> ==================
void RenderSystem::uniform1i(GLint location, int value) { RENDER_SYSTEM_QUEUE_CALL(_uniform1i, location, value); }
void RenderSystem::_uniform1i(GLint l, int v) { assertOnRenderThread(); glUniform1i(l, v); }
void RenderSystem::uniform1f(GLint location, float value) { RENDER_SYSTEM_QUEUE_CALL(_uniform1f, location, value); }
void RenderSystem::_uniform1f(GLint l, float v) { assertOnRenderThread(); glUniform1f(l, v); }
void RenderSystem::uniform2f(GLint location, float x, float y) { RENDER_SYSTEM_QUEUE_CALL(_uniform2f, location, x, y); }
void RenderSystem::_uniform2f(GLint l, float x, float y) { assertOnRenderThread(); glUniform2f(l, x, y); }
void RenderSystem::uniform3f(GLint location, float x, float y, float z) { RENDER_SYSTEM_QUEUE_CALL(_uniform3f, location, x, y, z); }
void RenderSystem::_uniform3f(GLint l, float x, float y, float z) { assertOnRenderThread(); glUniform3f(l, x, y, z); }
void RenderSystem::uniform4f(GLint location, float x, float y, float z, float w) { RENDER_SYSTEM_QUEUE_CALL(_uniform4f, location, x, y, z, w); }
void RenderSystem::_uniform4f(GLint l, float x, float y, float z, float w) { assertOnRenderThread(); glUniform4f(l, x, y, z, w); }
void RenderSystem::uniformMatrix3fv(GLint l, GLsizei c, GLboolean t, const GLfloat* v) { assertOnRenderThread(); glUniformMatrix3fv(l, c, t, v); }
void RenderSystem::uniformMatrix4fv(GLint l, GLsizei c, GLboolean t, const GLfloat* v) { assertOnRenderThread(); glUniformMatrix4fv(l, c, t, v); }
// [<5B><><EFBFBD><EFBFBD>] _uniformMatrix3fv <20>Ķ<EFBFBD><C4B6><EFBFBD>
void RenderSystem::_uniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
assertOnRenderThread();
glUniformMatrix3fv(location, count, transpose, value);
}
// [<5B><><EFBFBD><EFBFBD>] _uniformMatrix4fv <20>Ķ<EFBFBD><C4B6><EFBFBD>
void RenderSystem::_uniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
assertOnRenderThread();
glUniformMatrix4fv(location, count, transpose, value);
}
void RenderSystem::uniform2f(GLint location, const glm::vec2& vec) { uniform2f(location, vec.x, vec.y); }
void RenderSystem::uniform3f(GLint location, const glm::vec3& vec) { uniform3f(location, vec.x, vec.y, vec.z); }
void RenderSystem::uniform4f(GLint location, const glm::vec4& vec) { uniform4f(location, vec.x, vec.y, vec.z, vec.w); }
void RenderSystem::uniformMatrix3(GLint location, const glm::mat3& matrix, bool transpose) {
if (!isOnRenderThread()) { recordRenderCall([=] { _uniformMatrix3fv(location, 1, transpose, glm::value_ptr(matrix)); }); }
else { _uniformMatrix3fv(location, 1, transpose, glm::value_ptr(matrix)); }
}
void RenderSystem::uniformMatrix4(GLint location, const glm::mat4& matrix, bool transpose) {
if (!isOnRenderThread()) { recordRenderCall([=] { _uniformMatrix4fv(location, 1, transpose, glm::value_ptr(matrix)); }); }
else { _uniformMatrix4fv(location, 1, transpose, glm::value_ptr(matrix)); }
}
GLint RenderSystem::getUniformLocation(GLuint program, const std::string& name) { assertOnRenderThread(); return glGetUniformLocation(program, name.c_str()); }
// ================== <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==================
void RenderSystem::lineWidth(float width) { RENDER_SYSTEM_QUEUE_CALL(_lineWidth, width); }
void RenderSystem::_lineWidth(float w) { assertOnRenderThread(); glLineWidth(w); }
void RenderSystem::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) { RENDER_SYSTEM_QUEUE_CALL(_drawElements, mode, count, type, indices); }
void RenderSystem::_drawElements(GLenum m, GLsizei c, GLenum t, const void* i) { assertOnRenderThread(); glDrawElements(m, c, t, i); }
void RenderSystem::drawArrays(GLenum mode, GLint first, GLsizei count) { RENDER_SYSTEM_QUEUE_CALL(_drawArrays, mode, first, count); }
void RenderSystem::_drawArrays(GLenum m, GLint f, GLsizei c) { assertOnRenderThread(); glDrawArrays(m, f, c); }
// ================== <20><><EFBFBD><EFBFBD>ģʽ ==================
void RenderSystem::enableBlend() { RENDER_SYSTEM_QUEUE_CALL_NO_ARGS(_enableBlend); }
void RenderSystem::_enableBlend() { assertOnRenderThread(); glEnable(GL_BLEND); }
void RenderSystem::disableBlend() { RENDER_SYSTEM_QUEUE_CALL_NO_ARGS(_disableBlend); }
void RenderSystem::_disableBlend() { assertOnRenderThread(); glDisable(GL_BLEND); }
void RenderSystem::blendFunc(GLenum sfactor, GLenum dfactor) { RENDER_SYSTEM_QUEUE_CALL(_blendFunc, sfactor, dfactor); }
void RenderSystem::_blendFunc(GLenum s, GLenum d) { assertOnRenderThread(); glBlendFunc(s, d); }
void RenderSystem::defaultBlendFunc() { blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); }
// ================== <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==================
GLuint RenderSystem::createProgram() { assertOnRenderThread(); return glCreateProgram(); }
GLint RenderSystem::getCurrentProgram() { assertOnRenderThread(); GLint p; glGetIntegerv(GL_CURRENT_PROGRAM, &p); return p; }
void RenderSystem::attachShader(GLuint p, GLuint s) { RENDER_SYSTEM_QUEUE_CALL(_attachShader, p, s); }
void RenderSystem::_attachShader(GLuint p, GLuint s) { assertOnRenderThread(); glAttachShader(p, s); }
void RenderSystem::linkProgram(GLuint p) { RENDER_SYSTEM_QUEUE_CALL(_linkProgram, p); }
void RenderSystem::_linkProgram(GLuint p) { assertOnRenderThread(); glLinkProgram(p); }
GLint RenderSystem::getProgrami(GLuint p, GLenum n) { assertOnRenderThread(); GLint i; glGetProgramiv(p, n, &i); return i; }
std::string RenderSystem::getProgramInfoLog(GLuint program) {
assertOnRenderThread();
GLint len = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
if (len > 1) {
std::vector<char> log(len);
glGetProgramInfoLog(program, len, nullptr, log.data());
return std::string(log.begin(), log.end());
}
return "";
}
void RenderSystem::detachShader(GLuint p, GLuint s) { RENDER_SYSTEM_QUEUE_CALL(_detachShader, p, s); }
void RenderSystem::_detachShader(GLuint p, GLuint s) { assertOnRenderThread(); glDetachShader(p, s); }
void RenderSystem::deleteProgram(GLuint p) { RENDER_SYSTEM_QUEUE_CALL(_deleteProgram, p); }
void RenderSystem::_deleteProgram(GLuint p) { assertOnRenderThread(); glDeleteProgram(p); }
GLuint RenderSystem::linkProgram(GLuint vertexShader, GLuint fragmentShader) {
assertOnRenderThread();
GLuint program = createProgram();
_attachShader(program, vertexShader);
_attachShader(program, fragmentShader);
_linkProgram(program);
if (getProgrami(program, GL_LINK_STATUS) != GL_TRUE) {
std::string log = getProgramInfoLog(program);
s_Logger->error("Program link failed: {}", log);
_deleteProgram(program);
throw std::runtime_error("Program link failed: " + log);
}
_detachShader(program, vertexShader);
_detachShader(program, fragmentShader);
return program;
}
GLuint RenderSystem::linkProgram(GLuint v, GLuint g, GLuint f) {
assertOnRenderThread();
GLuint p = createProgram();
_attachShader(p, v);
if (g != 0) _attachShader(p, g);
_attachShader(p, f);
_linkProgram(p);
if (getProgrami(p, GL_LINK_STATUS) != GL_TRUE) {
std::string log = getProgramInfoLog(p);
s_Logger->error("Program link failed: {}", log);
_deleteProgram(p);
throw std::runtime_error("Program link failed: " + log);
}
_detachShader(p, v);
if (g != 0) _detachShader(p, g);
_detachShader(p, f);
return p;
}
void RenderSystem::useProgram(GLuint p) { RENDER_SYSTEM_QUEUE_CALL(_useProgram, p); }
void RenderSystem::_useProgram(GLuint p) { assertOnRenderThread(); glUseProgram(p); }
// ================== <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==================
GLuint RenderSystem::createShader(GLenum type) { assertOnRenderThread(); return glCreateShader(type); }
void RenderSystem::shaderSource(GLuint shader, const std::string& source) {
if (!isOnRenderThread()) { recordRenderCall([=] { _shaderSource(shader, source); }); }
else { _shaderSource(shader, source); }
}
void RenderSystem::_shaderSource(GLuint s, const std::string& src) {
assertOnRenderThread();
const char* c_str = src.c_str();
glShaderSource(s, 1, &c_str, nullptr);
}
void RenderSystem::compileShader(GLuint s) { RENDER_SYSTEM_QUEUE_CALL(_compileShader, s); }
void RenderSystem::_compileShader(GLuint s) { assertOnRenderThread(); glCompileShader(s); }
GLint RenderSystem::getShaderi(GLuint s, GLenum p) { assertOnRenderThread(); GLint i; glGetShaderiv(s, p, &i); return i; }
std::string RenderSystem::getShaderInfoLog(GLuint shader) {
assertOnRenderThread();
GLint len = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
if (len > 1) {
std::vector<char> log(len);
glGetShaderInfoLog(shader, len, nullptr, log.data());
return std::string(log.begin(), log.end());
}
return "";
}
void RenderSystem::deleteShader(GLuint s) { RENDER_SYSTEM_QUEUE_CALL(_deleteShader, s); }
void RenderSystem::_deleteShader(GLuint s) { assertOnRenderThread(); glDeleteShader(s); }
GLuint RenderSystem::compileShader(GLenum type, const std::string& source) {
assertOnRenderThread();
GLuint shader = createShader(type);
_shaderSource(shader, source);
_compileShader(shader);
if (getShaderi(shader, GL_COMPILE_STATUS) != GL_TRUE) {
std::string log = getShaderInfoLog(shader);
s_Logger->error("Shader compilation failed: {}", log);
_deleteShader(shader);
throw std::runtime_error("Shader compilation failed: " + log);
}
return shader;
}
// ================== <20><><EFBFBD>Ȳ<EFBFBD><C8B2><EFBFBD> ==================
void RenderSystem::depthFunc(GLenum func) { RENDER_SYSTEM_QUEUE_CALL(_depthFunc, func); }
void RenderSystem::_depthFunc(GLenum f) { assertOnRenderThread(); glDepthFunc(f); }
void RenderSystem::depthMask(bool flag) { RENDER_SYSTEM_QUEUE_CALL(_depthMask, flag); }
void RenderSystem::_depthMask(bool f) { assertOnRenderThread(); glDepthMask(f ? GL_TRUE : GL_FALSE); }
void RenderSystem::clearDepth(double depth) { RENDER_SYSTEM_QUEUE_CALL(_clearDepth, depth); }
void RenderSystem::_clearDepth(double d) { assertOnRenderThread(); glClearDepth(d); }
void RenderSystem::enableDepthTest() { RENDER_SYSTEM_QUEUE_CALL_NO_ARGS(_enableDepthTest); }
void RenderSystem::_enableDepthTest() { assertOnRenderThread(); glEnable(GL_DEPTH_TEST); }
void RenderSystem::disableDepthTest() { RENDER_SYSTEM_QUEUE_CALL_NO_ARGS(_disableDepthTest); }
void RenderSystem::_disableDepthTest() { assertOnRenderThread(); glDisable(GL_DEPTH_TEST); }
// ================== <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==================
void RenderSystem::bindTexture(GLuint texture) { RENDER_SYSTEM_QUEUE_CALL(_bindTexture, texture); }
void RenderSystem::_bindTexture(GLuint t) { assertOnRenderThread(); glBindTexture(GL_TEXTURE_2D, t); }
void RenderSystem::getTexImage(GLenum t, GLint l, GLenum f, GLenum ty, void* p) { assertOnRenderThread(); glGetTexImage(t, l, f, ty, p); }
// [<5B><><EFBFBD><EFBFBD>] _getTexImage <20>Ķ<EFBFBD><C4B6><EFBFBD>
void RenderSystem::_getTexImage(GLenum target, GLint level, GLenum format, GLenum type, void* pixels) {
assertOnRenderThread();
glGetTexImage(target, level, format, type, pixels);
}
void RenderSystem::activeTexture(GLenum texture) { RENDER_SYSTEM_QUEUE_CALL(_activeTexture, texture); }
void RenderSystem::_activeTexture(GLenum t) { assertOnRenderThread(); glActiveTexture(t); }
GLuint RenderSystem::genTextures() { assertOnRenderThread(); GLuint t; glGenTextures(1, &t); return t; }
void RenderSystem::deleteTextures(GLuint texture) { RENDER_SYSTEM_QUEUE_CALL(_deleteTextures, texture); }
void RenderSystem::_deleteTextures(GLuint t) { assertOnRenderThread(); glDeleteTextures(1, &t); }
void RenderSystem::texImage2D(GLenum t, GLint l, GLint iF, GLsizei w, GLsizei h, GLint b, GLenum f, GLenum ty, const void* p) { assertOnRenderThread(); glTexImage2D(t, l, iF, w, h, b, f, ty, p); }
// [<5B><><EFBFBD><EFBFBD>] _texImage2D <20>Ķ<EFBFBD><C4B6><EFBFBD>
void RenderSystem::_texImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) {
assertOnRenderThread();
glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels);
}
void RenderSystem::texParameteri(GLenum target, GLenum pname, GLint param) { RENDER_SYSTEM_QUEUE_CALL(_texParameteri, target, pname, param); }
void RenderSystem::_texParameteri(GLenum t, GLenum p, GLint v) { assertOnRenderThread(); glTexParameteri(t, p, v); }
void RenderSystem::setTextureMinFilter(GLenum filter) { texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); }
void RenderSystem::setTextureMagFilter(GLenum filter) { texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); }
void RenderSystem::setTextureWrapS(GLenum wrap) { texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap); }
void RenderSystem::setTextureWrapT(GLenum wrap) { texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); }
GLuint RenderSystem::createDefaultTexture() {
assertOnRenderThread();
GLuint textureId = genTextures();
_bindTexture(textureId);
unsigned char whitePixel[] = { 255, 255, 255, 255 };
texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, whitePixel);
_texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
_texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
_texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
_texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
_bindTexture(0);
return textureId;
}
// ================== <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==================
void RenderSystem::enableVertexAttribArray(GLuint i) { RENDER_SYSTEM_QUEUE_CALL(_enableVertexAttribArray, i); }
void RenderSystem::_enableVertexAttribArray(GLuint i) { assertOnRenderThread(); glEnableVertexAttribArray(i); }
void RenderSystem::disableVertexAttribArray(GLuint i) { RENDER_SYSTEM_QUEUE_CALL(_disableVertexAttribArray, i); }
void RenderSystem::_disableVertexAttribArray(GLuint i) { assertOnRenderThread(); glDisableVertexAttribArray(i); }
void RenderSystem::vertexAttribPointer(GLuint i, GLint s, GLenum t, GLboolean n, GLsizei st, const void* p) { RENDER_SYSTEM_QUEUE_CALL(_vertexAttribPointer, i, s, t, n, st, p); }
void RenderSystem::_vertexAttribPointer(GLuint i, GLint s, GLenum t, GLboolean n, GLsizei st, const void* p) { assertOnRenderThread(); glVertexAttribPointer(i, s, t, n, st, p); }
// ================== <20><><EFBFBD>߷<EFBFBD><DFB7><EFBFBD> ==================
void RenderSystem::readPixels(int x, int y, int w, int h, GLenum f, GLenum t, void* p) { assertOnRenderThread(); glReadPixels(x, y, w, h, f, t, p); }
// [<5B><><EFBFBD><EFBFBD>] _readPixels <20>Ķ<EFBFBD><C4B6><EFBFBD>
void RenderSystem::_readPixels(int x, int y, int width, int height, GLenum format, GLenum type, void* pixels) {
assertOnRenderThread();
glReadPixels(x, y, width, height, format, type, pixels);
}
bool RenderSystem::isExtensionSupported(const std::string& ext) {
assertOnRenderThread();
const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
return strstr(extensions, ext.c_str()) != nullptr;
}
void RenderSystem::pixelStore(GLenum pname, GLint param) { RENDER_SYSTEM_QUEUE_CALL(_pixelStore, pname, param); }
void RenderSystem::_pixelStore(GLenum p, GLint v) { assertOnRenderThread(); glPixelStorei(p, v); }
std::string RenderSystem::getVendor() { assertOnRenderThread(); return (const char*)glGetString(GL_VENDOR); }
std::string RenderSystem::getRenderer() { assertOnRenderThread(); return (const char*)glGetString(GL_RENDERER); }
std::string RenderSystem::getOpenGLVersion() { assertOnRenderThread(); return (const char*)glGetString(GL_VERSION); }
std::string RenderSystem::getGLSLVersion() { assertOnRenderThread(); return (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); }
void RenderSystem::logDetailedGLInfo() {
assertOnRenderThread();
s_Logger->info("=== OpenGL System Information ===");
s_Logger->info("Vendor: {}", getVendor());
s_Logger->info("Renderer: {}", getRenderer());
s_Logger->info("OpenGL Version: {}", getOpenGLVersion());
s_Logger->info("GLSL Version: {}", getGLSLVersion());
GLint val;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &val);
s_Logger->info("Max Texture Size: {}", val);
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &val);
s_Logger->info("Max Vertex Attributes: {}", val);
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &val);
s_Logger->info("Max Texture Units: {}", val);
}
void RenderSystem::setupDefaultState() {
beginInitialization();
clearColor(0.0f, 0.0f, 0.0f, 1.0f);
viewport(0, 0, s_ViewportWidth, s_ViewportHeight);
enableBlend();
defaultBlendFunc();
disableDepthTest();
finishInitialization();
}
void RenderSystem::checkGLError(const std::string& operation) { RENDER_SYSTEM_QUEUE_CALL(_checkGLError, operation); }
void RenderSystem::_checkGLError(const std::string& op) {
assertOnRenderThread();
GLenum error;
while ((error = glGetError()) != GL_NO_ERROR) {
s_Logger->error("OpenGL error during [{}]: {} ({})", op, getGLErrorString(error), error);
}
}
std::string RenderSystem::getGLErrorString(GLenum error) {
switch (error) {
case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
case GL_INVALID_FRAMEBUFFER_OPERATION: return "GL_INVALID_FRAMEBUFFER_OPERATION";
default: return "Unknown (" + std::to_string(error) + ")";
}
}
// ================== <20><>ȡ״̬ ==================
int RenderSystem::getViewportWidth() { return s_ViewportWidth; }
int RenderSystem::getViewportHeight() { return s_ViewportHeight; }
glm::vec4 RenderSystem::getClearColor() { return s_ClearColorValue; }
int RenderSystem::getQueueSize() {
std::lock_guard<std::mutex> lock(s_RenderQueueMutex);
return s_RenderQueue.size();
}

View File

@@ -0,0 +1,276 @@
#pragma once
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <functional>
#include <queue>
#include <mutex>
#include <thread>
#include <stack>
#include <string>
#include <memory>
#include <atomic>
// <20><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD> spdlog::logger <20>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD><C4BC>а<EFBFBD><D0B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
namespace spdlog {
class logger;
}
class RenderSystem {
public:
RenderSystem() = delete;
~RenderSystem() = delete;
RenderSystem(const RenderSystem&) = delete;
RenderSystem& operator=(const RenderSystem&) = delete;
// ================== <20><>־ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD> ==================
/**
* @brief <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>־ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD><CEBA><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD>֮ǰ<D6AE><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼʱ<CABC><CAB1><EFBFBD>á<EFBFBD>
*/
static void InitializeLogging();
/**
* @brief <20>ر<EFBFBD><D8B1><EFBFBD>־ϵͳ<CFB5><CDB3>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD>ˢ<EFBFBD>¡<EFBFBD>
*/
static void ShutdownLogging();
// ================== <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>̹߳<DFB3><CCB9><EFBFBD> ==================
static void initRenderThread();
static void beginInitialization();
static void finishInitialization();
static bool isOnRenderThread();
static bool isInInitPhase();
static void assertOnRenderThread();
static void assertOnRenderThreadOrInit();
// ================== <20><>Ⱦ<EFBFBD><C8BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==================
static void recordRenderCall(std::function<void()>&& renderCall);
static void replayQueue();
// ================== OpenGL ״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ ==================
static void enable(GLenum capability);
static void disable(GLenum capability);
static void pushState();
static void popState();
static int getStateStackSize();
static void clearColor(float r, float g, float b, float a);
static void clear(GLbitfield mask);
static void viewport(int x, int y, int width, int height);
// ================== VAO / VBO / EBO <20><><EFBFBD><EFBFBD> ==================
static GLuint GenVertexArrays();
static void DeleteVertexArrays(GLuint vao);
static void BindVertexArray(GLuint vao);
static GLuint GenBuffers();
static void DeleteBuffers(GLuint buffer);
static void BindBuffer(GLenum target, GLuint buffer);
static void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
// ================== Uniform <20><><EFBFBD><EFBFBD> ==================
static void uniform1i(GLint location, int value);
static void uniform1f(GLint location, float value);
static void uniform2f(GLint location, float x, float y);
static void uniform3f(GLint location, float x, float y, float z);
static void uniform4f(GLint location, float x, float y, float z, float w);
static void uniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
static void uniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
static void uniform2f(GLint location, const glm::vec2& vec);
static void uniform3f(GLint location, const glm::vec3& vec);
static void uniform4f(GLint location, const glm::vec4& vec);
static void uniformMatrix3(GLint location, const glm::mat3& matrix, bool transpose = false);
static void uniformMatrix4(GLint location, const glm::mat4& matrix, bool transpose = false);
static GLint getUniformLocation(GLuint program, const std::string& name);
// ================== <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==================
static void lineWidth(float width);
static void drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices);
static void drawArrays(GLenum mode, GLint first, GLsizei count);
// ================== <20><><EFBFBD><EFBFBD>ģʽ ==================
static void enableBlend();
static void disableBlend();
static void blendFunc(GLenum sfactor, GLenum dfactor);
static void defaultBlendFunc();
// ================== <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==================
static GLuint createProgram();
static GLint getCurrentProgram();
static void attachShader(GLuint program, GLuint shader);
static void linkProgram(GLuint program);
static GLint getProgrami(GLuint program, GLenum pname);
static std::string getProgramInfoLog(GLuint program);
static void detachShader(GLuint program, GLuint shader);
static void deleteProgram(GLuint program);
static GLuint linkProgram(GLuint vertexShader, GLuint fragmentShader);
static GLuint linkProgram(GLuint vertexShader, GLuint geometryShader, GLuint fragmentShader);
static void useProgram(GLuint program);
// ================== <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==================
static GLuint createShader(GLenum type);
static void shaderSource(GLuint shader, const std::string& source);
static void compileShader(GLuint shader);
static GLint getShaderi(GLuint shader, GLenum pname);
static std::string getShaderInfoLog(GLuint shader);
static void deleteShader(GLuint shader);
static GLuint compileShader(GLenum type, const std::string& source);
// ================== <20><><EFBFBD>Ȳ<EFBFBD><C8B2><EFBFBD> ==================
static void depthFunc(GLenum func);
static void depthMask(bool flag);
static void clearDepth(double depth);
static void enableDepthTest();
static void disableDepthTest();
// ================== <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==================
static void bindTexture(GLuint texture);
static void getTexImage(GLenum target, GLint level, GLenum format, GLenum type, void* pixels);
static void activeTexture(GLenum texture);
static GLuint genTextures();
static void deleteTextures(GLuint texture);
static void texImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
static void texParameteri(GLenum target, GLenum pname, GLint param);
static void setTextureMinFilter(GLenum filter);
static void setTextureMagFilter(GLenum filter);
static void setTextureWrapS(GLenum wrap);
static void setTextureWrapT(GLenum wrap);
static GLuint createDefaultTexture();
// ================== <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==================
static void enableVertexAttribArray(GLuint index);
static void disableVertexAttribArray(GLuint index);
static void vertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer);
// ================== <20><><EFBFBD>߷<EFBFBD><DFB7><EFBFBD> ==================
static void readPixels(int x, int y, int width, int height, GLenum format, GLenum type, void* pixels);
static bool isExtensionSupported(const std::string& extension);
static void pixelStore(GLenum pname, GLint param);
static std::string getVendor();
static std::string getRenderer();
static std::string getOpenGLVersion();
static std::string getGLSLVersion();
static void logDetailedGLInfo();
static void setupDefaultState();
static void checkGLError(const std::string& operation);
// ================== <20><>ȡ״̬ ==================
static int getViewportWidth();
static int getViewportHeight();
static glm::vec4 getClearColor();
static int getQueueSize();
private:
struct RenderState;
// ˽<>еġ<D0B5>ֱ<EFBFBD><D6B1>ִ<EFBFBD><D6B4>GL<47><4C><EFBFBD>õİ汾
static void _enable(GLenum capability);
static void _disable(GLenum capability);
static void _pushState();
static void _popState();
static void _clearColor(float r, float g, float b, float a);
static void _clear(GLbitfield mask);
static void _viewport(int x, int y, int width, int height);
static void _glDeleteVertexArrays(GLuint vao);
static void _uniform1i(GLint location, int value);
static void _uniform1f(GLint location, float value);
static void _uniform2f(GLint location, float x, float y);
static void _uniform3f(GLint location, float x, float y, float z);
static void _uniform4f(GLint location, float x, float y, float z, float w);
static void _uniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
static void _uniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
static void _lineWidth(float width);
static void _drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices);
static void _drawArrays(GLenum mode, GLint first, GLsizei count);
static void _glBindVertexArray(GLuint vao);
static void _enableBlend();
static void _disableBlend();
static void _blendFunc(GLenum sfactor, GLenum dfactor);
static void _attachShader(GLuint program, GLuint shader);
static void _linkProgram(GLuint program);
static void _detachShader(GLuint program, GLuint shader);
static void _deleteProgram(GLuint program);
static void _useProgram(GLuint program);
static void _shaderSource(GLuint shader, const std::string& source);
static void _compileShader(GLuint shader);
static void _deleteShader(GLuint shader);
static void _depthFunc(GLenum func);
static void _depthMask(bool flag);
static void _clearDepth(double depth);
static void _enableDepthTest();
static void _disableDepthTest();
static void _bindTexture(GLuint texture);
static void _getTexImage(GLenum target, GLint level, GLenum format, GLenum type, void* pixels);
static void _activeTexture(GLenum texture);
static void _deleteTextures(GLuint texture);
static void _texImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
static void _texParameteri(GLenum target, GLenum pname, GLint param);
static void _glBindBuffer(GLenum target, GLuint buffer);
static void _glBufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
static void _glDeleteBuffers(GLuint buffer);
static void _enableVertexAttribArray(GLuint index);
static void _disableVertexAttribArray(GLuint index);
static void _vertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer);
static void _readPixels(int x, int y, int width, int height, GLenum format, GLenum type, void* pixels);
static void _pixelStore(GLenum pname, GLint param);
static void _checkGLError(const std::string& operation);
static std::string getGLErrorString(GLenum error);
// <20><>̬<EFBFBD><CCAC>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD>
static std::thread::id s_RenderThreadId;
static std::atomic<bool> s_IsInInit;
static std::queue<std::function<void()>> s_RenderQueue;
static std::mutex s_RenderQueueMutex;
static std::atomic<bool> s_IsReplayingQueue;
// ================== RenderState <20><EFBFBD><E1B9B9><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5> ==================
struct RenderSystem::RenderState {
GLint currentProgram = 0;
GLboolean blendEnabled = GL_FALSE;
GLboolean depthTestEnabled = GL_FALSE;
GLint blendSrcFactor = GL_SRC_ALPHA;
GLint blendDstFactor = GL_ONE_MINUS_SRC_ALPHA;
GLint activeTexture = GL_TEXTURE0;
GLint boundTexture = 0;
glm::vec4 clearColor{ 0.0f, 0.0f, 0.0f, 1.0f };
glm::ivec4 viewport{ 0, 0, 800, 600 };
RenderState() {
glGetIntegerv(GL_CURRENT_PROGRAM, &currentProgram);
blendEnabled = glIsEnabled(GL_BLEND);
depthTestEnabled = glIsEnabled(GL_DEPTH_TEST);
glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcFactor);
glGetIntegerv(GL_BLEND_DST_RGB, &blendDstFactor);
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTexture);
glGetFloatv(GL_COLOR_CLEAR_VALUE, &clearColor[0]);
glGetIntegerv(GL_VIEWPORT, &viewport[0]);
while (glGetError() != GL_NO_ERROR) {}
}
void restore() {
glViewport(viewport.x, viewport.y, viewport.z, viewport.w);
glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
glUseProgram(currentProgram);
glActiveTexture(activeTexture);
glBindTexture(GL_TEXTURE_2D, boundTexture);
if (blendEnabled) glEnable(GL_BLEND); else glDisable(GL_BLEND);
glBlendFunc(blendSrcFactor, blendDstFactor);
if (depthTestEnabled) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
while (glGetError() != GL_NO_ERROR) {}
}
};
static std::stack<RenderState> s_StateStack;
static int s_ViewportWidth;
static int s_ViewportHeight;
static glm::vec4 s_ClearColorValue;
static std::shared_ptr<spdlog::logger> s_Logger;
};

View File

@@ -0,0 +1,182 @@
#include "pch.h"
#include "BufferUploader.h"
#include "BufferBuilder.h"
#include <glad/glad.h>
#include <spdlog/spdlog.h>
#include <glm/gtc/type_ptr.hpp>
namespace Buffer {
// ==========================================================
// RenderState ʵ<><CAB5>
// ==========================================================
void RenderState::saveCurrentState() {
GLint currentProgram = 0;
glGetIntegerv(GL_CURRENT_PROGRAM, &currentProgram);
this->shaderProgram = static_cast<unsigned int>(currentProgram);
GLint boundTexture = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTexture);
this->textureId = static_cast<unsigned int>(boundTexture);
GLint activeTextureUnit = 0;
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTextureUnit);
this->textureUnit = activeTextureUnit - GL_TEXTURE0;
this->depthTest = glIsEnabled(GL_DEPTH_TEST);
this->blending = glIsEnabled(GL_BLEND);
while (glGetError() != GL_NO_ERROR) {}
}
void RenderState::applyState() const {
// <20>ָ<EFBFBD> Program
if (shaderProgram != 0) {
glUseProgram(shaderProgram);
}
// <20>ָ<EFBFBD> Texture
if (textureId != 0) {
glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(GL_TEXTURE_2D, textureId);
}
// <20>ָ<EFBFBD> Blending/Depth
if (this->blending) {
glEnable(GL_BLEND);
}
else {
glDisable(GL_BLEND);
}
if (this->depthTest) {
glEnable(GL_DEPTH_TEST);
}
else {
glDisable(GL_DEPTH_TEST);
}
}
// ==========================================================
// BufferBuilder ʵ<><CAB5>
// ==========================================================
// Ĭ<>Ϲ<EFBFBD><CFB9><EFBFBD><ECBAAF> (256 floats -> 64 <20><><EFBFBD><EFBFBD>)
BufferBuilder::BufferBuilder() : BufferBuilder(256) {}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><ECBAAF>
BufferBuilder::BufferBuilder(int initialFloatCapacity)
: array(std::max(16, initialFloatCapacity)), size(0), vertexCount(0)
{
// Ĭ<>ϻ<EFBFBD><CFBB><EFBFBD>ģʽ
this->mode = GL_TRIANGLES;
// ȷ<><C8B7> array <20><>ʼ<EFBFBD>ǿյ<C7BF>
this->array.clear();
}
void BufferBuilder::begin(int glMode, int estimatedVertexCount) {
this->mode = glMode;
this->size = 0;
this->vertexCount = 0;
this->array.clear();
// <20><><EFBFBD>浱ǰ<E6B5B1><C7B0>Ⱦ״̬
if (!stateSaved) {
renderState.saveCurrentState();
stateSaved = true;
}
if (estimatedVertexCount > 0) {
this->array.reserve(estimatedVertexCount * COMPONENTS_PER_VERTEX);
}
}
void BufferBuilder::setTexture(unsigned int textureId, int textureUnit) {
this->renderState.textureId = textureId;
this->renderState.textureUnit = textureUnit;
}
void BufferBuilder::setShader(unsigned int programId) {
this->renderState.shaderProgram = programId;
}
void BufferBuilder::setColor(const glm::vec4& color) {
this->renderState.color = color;
}
void BufferBuilder::setOpacity(float opacity) {
this->renderState.opacity = opacity;
}
void BufferBuilder::vertex(float x, float y, float u, float v) {
this->array.push_back(x);
this->array.push_back(y);
this->array.push_back(u);
this->array.push_back(v);
this->size = this->array.size();
this->vertexCount++;
}
std::unique_ptr<BuiltBuffer> BufferBuilder::end() {
if (vertexCount == 0) return nullptr;
RenderSystem::assertOnRenderThread();
// 1. <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD><CDB0><EFBFBD> GPU <20><>Դ
unsigned int vao = RenderSystem::GenVertexArrays();
unsigned int vbo = RenderSystem::GenBuffers();
RenderSystem::BindVertexArray(vao);
RenderSystem::BindBuffer(GL_ARRAY_BUFFER, vbo);
// 2. <20>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> RenderSystem <20>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> GL_ARRAY_BUFFER <20><> GL_DYNAMIC_DRAW
RenderSystem::BufferData(GL_ARRAY_BUFFER, this->array.size() * sizeof(float),
this->array.data(), GL_DYNAMIC_DRAW);
// 3. <20><><EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (Location 0: Position, Location 1: TexCoord)
// Position (location 0): 2 floats, offset 0
RenderSystem::enableVertexAttribArray(0);
RenderSystem::vertexAttribPointer(0, 2, GL_FLOAT, false,
COMPONENTS_PER_VERTEX * sizeof(float), 0);
// Texture Coords (location 1): 2 floats, offset 2 * sizeof(float)
RenderSystem::enableVertexAttribArray(1);
RenderSystem::vertexAttribPointer(1, 2, GL_FLOAT, false,
COMPONENTS_PER_VERTEX * sizeof(float),
reinterpret_cast<const void*>(2 * sizeof(float)));
// 4. <20><><EFBFBD><EFBFBD>
RenderSystem::BindBuffer(GL_ARRAY_BUFFER, 0);
RenderSystem::BindVertexArray(0);
// 5. <20><><EFBFBD><EFBFBD> BuiltBuffer
RenderState stateCopy = renderState.copy();
stateSaved = false;
return std::make_unique<BuiltBuffer>(vao, vbo, vertexCount, mode, stateCopy);
}
void BufferBuilder::endImmediate() {
std::unique_ptr<BuiltBuffer> buffer = end();
if (buffer != nullptr) {
BufferUploader::drawWithShader(std::move(buffer));
}
}
void BufferBuilder::dispose(const BuiltBuffer* buffer) {
if (buffer != nullptr) {
RenderSystem::DeleteVertexArrays(buffer->vao);
RenderSystem::DeleteBuffers(buffer->vbo);
}
}
void BufferBuilder::clear() {
this->array.clear();
this->size = 0;
this->vertexCount = 0;
}
} // namespace Buffer

View File

@@ -0,0 +1,131 @@
#pragma once
#include <glm/glm.hpp>
#include <vector>
#include <memory>
#include <string>
#include <algorithm>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щͷ<D0A9>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>д<EFBFBD><D0B4><EFBFBD>
#include "../../systems/RenderSystem.h"
namespace Buffer {
/**
* @brief <20><>Ⱦ״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E1B9B9>
*/
struct RenderState {
// <20><>Ⱦ״̬<D7B4><CCAC><EFBFBD><EFBFBD> (<28><>Ӧ Java <20>е<EFBFBD> RenderState)
unsigned int textureId = 0;
int textureUnit = 0;
unsigned int shaderProgram = 0;
glm::vec4 color = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
float opacity = 1.0f;
int blendMode = 0;
bool depthTest = false;
bool blending = true;
/**
* @brief <20><><EFBFBD>浱ǰ OpenGL ״̬ (Program, Texture, Blending/Depth)
*/
void saveCurrentState();
/**
* @brief Ӧ<>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD> OpenGL ״̬ (<28><><EFBFBD><EFBFBD> Program <20><> Texture<72><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD> GL ״̬)
*/
void applyState() const;
/**
* @brief <20><><EFBFBD><EFBFBD>״̬
*/
RenderState copy() const {
RenderState copy;
copy.textureId = this->textureId;
copy.textureUnit = this->textureUnit;
copy.shaderProgram = this->shaderProgram;
copy.color = this->color; // glm::vec4 Ĭ<><C4AC>֧<EFBFBD><D6A7>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>
copy.opacity = this->opacity;
copy.blendMode = this->blendMode;
copy.depthTest = this->depthTest;
copy.blending = this->blending;
return copy;
}
};
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵĻ<C9B5><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݽṹ
*/
struct BuiltBuffer {
unsigned int vao;
unsigned int vbo;
int vertexCount;
int mode; // GL_TRIANGLES, GL_LINE_LOOP <20><>
RenderState renderState;
BuiltBuffer(unsigned int vao, unsigned int vbo, int vertexCount, int mode, const RenderState& state)
: vao(vao), vbo(vbo), vertexCount(vertexCount), mode(mode), renderState(state) {}
};
/**
* @brief <20>򻯰<EFBFBD> BufferBuilder<65><72><EFBFBD><EFBFBD><EFBFBD>ڰ<EFBFBD><DAB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>Ի<EFBFBD><D4BB>Ƽ<EFBFBD><C6BC><EFBFBD><EFBFBD>
* ÿ<><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD> float x, float y, float u, float v <20><><EFBFBD><EFBFBD>4<EFBFBD><34> float<61><74>
*/
class BufferBuilder {
private:
static constexpr int COMPONENTS_PER_VERTEX = 4; // x,y,u,v
std::vector<float> array;
int size; // ʵ<>ʴ洢<CAB4><E6B4A2> float <20><><EFBFBD><EFBFBD> (array.size())
int vertexCount;
int mode; // GL mode
RenderState renderState;
bool stateSaved = false;
public:
BufferBuilder();
explicit BufferBuilder(int initialFloatCapacity);
/**
* @brief <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>Ƶ<EFBFBD> GL ģʽ (<28><><EFBFBD><EFBFBD> GL_LINE_LOOP)
*/
void begin(int glMode, int estimatedVertexCount);
void setTexture(unsigned int textureId, int textureUnit);
void setShader(unsigned int programId);
void setColor(const glm::vec4& color);
void setOpacity(float opacity);
/**
* @brief <20><><EFBFBD>Ӷ<EFBFBD><D3B6>㣺x,y,u,v
*/
void vertex(float x, float y, float u, float v);
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> BuiltBuffer<65><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߸<EFBFBD><DFB8><EFBFBD> dispose<73><65>
*/
std::unique_ptr<BuiltBuffer> end();
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD><EFBFBD>ͷ<EFBFBD> GPU <20><>Դ<EFBFBD><D4B4>
*/
void endImmediate();
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> GPU <20><>Դ<EFBFBD><D4B4>
*/
static void dispose(const BuiltBuffer* buffer);
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD>
*/
void clear();
int getVertexCount() const {
return vertexCount;
}
bool isEmpty() const {
return vertexCount == 0;
}
};
} // namespace Buffer

View File

@@ -0,0 +1,107 @@
#include "pch.h"
#include "BufferUploader.h"
#include <glad/glad.h>
#include <spdlog/spdlog.h>
#include <glm/gtc/type_ptr.hpp>
namespace Buffer {
void BufferUploader::applyRenderState(const RenderState& state) {
// 1. Ӧ<><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (state.textureId != 0) {
RenderSystem::activeTexture(GL_TEXTURE0 + state.textureUnit);
RenderSystem::bindTexture(state.textureId);
}
// 2. Ӧ<><D3A6><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB>
unsigned int currentProgram = 0;
if (state.shaderProgram != 0) {
currentProgram = state.shaderProgram;
RenderSystem::useProgram(state.shaderProgram);
}
else {
// <20><><EFBFBD><EFBFBD>״̬<D7B4><CCAC>û<EFBFBD><C3BB>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ի<EFBFBD>ȡ<EFBFBD><C8A1>ǰ<EFBFBD>󶨵<EFBFBD><F3B6A8B5><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
GLint programId = 0;
glGetIntegerv(GL_CURRENT_PROGRAM, &programId);
currentProgram = static_cast<unsigned int>(programId);
}
// 3. <20><><EFBFBD><EFBFBD> uColor Uniform (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Program ʱ<><CAB1><EFBFBD><EFBFBD>)
if (currentProgram != 0) {
GLint colorLoc = RenderSystem::getUniformLocation(currentProgram, "uColor");
if (colorLoc != -1) {
// ʹ<><CAB9> RenderSystem::uniform4f <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
RenderSystem::uniform4f(colorLoc,
state.color.x, state.color.y, state.color.z, state.color.w);
}
}
else {
spdlog::debug("BufferUploader::applyRenderState: No shader program available for color setting.");
}
// 4. Ӧ<>û<EFBFBD><C3BB><EFBFBD>ģʽ
if (state.blending) {
RenderSystem::enableBlend();
// <20><><EFBFBD><EFBFBD> RenderSystem::defaultBlendFunc() <20><>װ<EFBFBD><D7B0> glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
RenderSystem::defaultBlendFunc();
}
else {
RenderSystem::disableBlend();
}
// 5. Ӧ<><D3A6><EFBFBD><EFBFBD><EFBFBD>Ȳ<EFBFBD><C8B2><EFBFBD>
if (state.depthTest) {
RenderSystem::enableDepthTest();
}
else {
RenderSystem::disableDepthTest();
}
}
void BufferUploader::restoreRenderState(const RenderState& previousState) {
// <20>ָ<EFBFBD>֮ǰ<D6AE><C7B0>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> RenderState::applyState() <20><>ʵ<EFBFBD>֡<EFBFBD>
previousState.applyState();
}
// ==========================================================
// <20><><EFBFBD><EFBFBD><EFBFBD>߼<EFBFBD>ʵ<EFBFBD><CAB5>
// ==========================================================
void BufferUploader::drawWithShader(std::unique_ptr<BuiltBuffer> buffer) {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>գ<EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>
if (!buffer) return;
RenderSystem::assertOnRenderThread();
RenderState currentState;
currentState.saveCurrentState();
try {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> -> <20><><EFBFBD><EFBFBD> unique_ptr ָ<><D6B8><EFBFBD><EFBFBD> BuiltBuffer <20><>Ա
const RenderState& bufferState = buffer->renderState;
applyRenderState(bufferState);
if (buffer->vao != 0) {
RenderSystem::BindVertexArray(buffer->vao);
}
if (buffer->vertexCount > 0) {
RenderSystem::drawArrays(buffer->mode, 0, buffer->vertexCount);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> VAO
if (buffer->vao != 0) {
RenderSystem::BindVertexArray(0);
}
}
catch (const std::exception& e) {
spdlog::error("BufferUploader drawing failed: {}", e.what());
}
restoreRenderState(currentState);
BufferBuilder::dispose(buffer.get());
}
} // namespace Buffer

View File

@@ -0,0 +1,38 @@
#pragma once
#include "BufferBuilder.h"
#include "../../systems/RenderSystem.h"
namespace Buffer {
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>Ⱦ״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> VAO <20><>ִ<EFBFBD>л<EFBFBD><D0BB>ơ<EFBFBD>
*/
class BufferUploader {
public:
/**
* @brief ʹ<><CAB9><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӹ<EFBFBD><D3B9><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8>
* @param buffer <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> BuiltBuffer <20><> unique_ptr<74><72>
*/
static void drawWithShader(std::unique_ptr<BuiltBuffer> buffer);
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> drawWithShader <20><>ͬ<EFBFBD><CDAC>
*/
static void draw(std::unique_ptr<BuiltBuffer> buffer) {
drawWithShader(std::move(buffer));
}
private:
/**
* @brief Ӧ<><D3A6>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ״̬<D7B4><CCAC>
*/
static void applyRenderState(const RenderState& state);
/**
* @brief <20>ָ<EFBFBD><D6B8><EFBFBD>֮ǰ<D6AE><C7B0><EFBFBD><EFBFBD>Ⱦ״̬<D7B4><CCAC>
*/
static void restoreRenderState(const RenderState& previousState);
};
} // namespace Buffer

View File

@@ -0,0 +1,33 @@
#include "pch.h"
#include "Tesselator.h"
#include "BufferBuilder.h"
#include "BufferUploader.h"
namespace Buffer {
Tesselator::Tesselator(int bufferSize) {
// <20><>ʼ<EFBFBD><CABC> BufferBuilder<65><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><D7B2><EFBFBD><EFBFBD><EFBFBD>
this->builder = std::make_unique<BufferBuilder>(bufferSize);
}
Tesselator::Tesselator() : Tesselator(DEFAULT_BUFFER_SIZE) {}
Tesselator& Tesselator::getInstance() {
RenderSystem::assertOnRenderThreadOrInit();
static Tesselator INSTANCE;
return INSTANCE;
}
void Tesselator::end() {
RenderSystem::assertOnRenderThread();
std::unique_ptr<BuiltBuffer> builtBuffer = this->builder->end();
if (builtBuffer) {
BufferUploader::drawWithShader(std::move(builtBuffer));
}
}
BufferBuilder& Tesselator::getBuilder() {
return *this->builder;
}
} // namespace Buffer

View File

@@ -0,0 +1,119 @@
#pragma once
#include <memory>
#include "BufferBuilder.h"
#include "../../systems/RenderSystem.h"
/**
* @file BufferSystem.h
* @brief Vivid2D <20><>Ⱦϵͳ<CFB5>ļ<EFBFBD>ʱģʽ<C4A3><CABD>Immediate Mode<64><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3>
*
* <20><><EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD>һ<E1B9A9><D2BB><EFBFBD>򵥡<EFBFBD><F2B5A5A1><EFBFBD>Ч<EFBFBD>Ľӿڣ<D3BF><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <20><>ʹ<EFBFBD><CAB9>һ<EFBFBD><D2BB> Draw Call <20><EFBFBD><E1BDBB> GPU <20><>Ⱦ<EFBFBD><C8BE>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD> GPU <20><>Դ<EFBFBD><D4B4>
*
* ==========================================================
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* ==========================================================
*
* 1. Tesselator (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
* ----------------------------
* - <20><><EFBFBD>ã<EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD>ڵ㣬<DAB5><E3A3AC><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> BufferBuilder <20><><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>
* - <20>ӿڣ<D3BF>Tesselator::getInstance() <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Tesselator::getBuilder() <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* - <20><><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD>Tesselator::end()<29><><EFBFBD><EFBFBD><EFBFBD>ô˷<C3B4><CBB7><EFBFBD><EFBFBD><EFBFBD><E1B4A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (Builder -> Uploader)<29><>
*
* 2. BufferBuilder (<28><><EFBFBD>ݹ<EFBFBD><DDB9><EFBFBD><EFBFBD><EFBFBD>)
* ----------------------------
* - <20><><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CPU <20>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>x, y, u, v<><76><EFBFBD>͵<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>Ⱦ״̬ (RenderState)<29><>
* - <20>ӿڣ<D3BF>begin() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>vertex() <20><><EFBFBD>Ӷ<EFBFBD><D3B6>㣻setTexture/setColor <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4><CCAC>
* - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>end() <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> BuiltBuffer ʵ<><CAB5><EFBFBD><EFBFBD>
*
* 3. BuiltBuffer (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
* --------------------------
* - <20><><EFBFBD>ã<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ݽṹ<DDBD><E1B9B9><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>Ҫ<EFBFBD><D2AA> GPU <20><>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD> (VAO/VBO)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>GL ģʽ<C4A3><CABD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD> RenderState <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* - <20>ص㣺<D8B5><E3A3BA><EFBFBD><EFBFBD>Ȩͨ<C8A8><CDA8> std::unique_ptr ת<>ƣ<EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD>Դֻ<D4B4><D6BB> Uploader <20><><EFBFBD>ƺ<EFBFBD><C6BA><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>Ρ<EFBFBD>
*
* 4. BufferUploader (<28><><EFBFBD>ƺ<EFBFBD><C6BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
* --------------------------------
* - <20><><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD> BuiltBuffer<65><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD>¼<EFBFBD><C2BC> RenderState Ӧ<>õ<EFBFBD> GL <20><><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD> VAO<41><4F>ִ<EFBFBD><D6B4> glDrawArrays <20><><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> GPU <20><>Դ<EFBFBD><D4B4>
* - <20><><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD>BufferUploader::drawWithShader(std::unique_ptr<BuiltBuffer> buffer)<29><>
*
* ==========================================================
* <20><><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>)
* ==========================================================
*
* 1. <20><>ʼ<EFBFBD><CABC><EFBFBD>ͻ<EFBFBD>ȡ<EFBFBD><C8A1>
* Tesselator& t = Tesselator::getInstance();
* BufferBuilder& builder = t.getBuilder();
*
* 2. <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* builder.begin(GL_QUADS, 4); // Ԥ<>ƻ<EFBFBD><C6BB><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 4 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>
*
* 3. <20><><EFBFBD><EFBFBD>״̬<D7B4><CCAC>
* builder.setShader(myProgramId);
* builder.setTexture(myTextureId, 0);
* builder.setColor(glm::vec4(1.0f, 1.0f, 1.0f, 0.5f)); // <20><>͸<EFBFBD><CDB8><EFBFBD><EFBFBD>ɫ
*
* 4. <20><><EFBFBD>Ӷ<EFBFBD><D3B6>㣨x, y, u, v<><76><EFBFBD><EFBFBD>
* builder.vertex(10.0f, 10.0f, 0.0f, 0.0f);
* builder.vertex(110.0f, 10.0f, 1.0f, 0.0f);
* builder.vertex(110.0f, 110.0f, 1.0f, 1.0f);
* builder.vertex(10.0f, 110.0f, 0.0f, 1.0f);
*
* 5. <20><EFBFBD><E1BDBB><EFBFBD>ƺ<EFBFBD><C6BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* t.end();
* // <20><>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD>GPU <20>ϵ<EFBFBD> VAO/VBO <20><>Դ<EFBFBD>ѱ<EFBFBD><D1B1>ͷš<CDB7>
*
*/
namespace Buffer {
class BufferBuilder;
/**
* @brief Tesselator <20><EFBFBD><E0A3BA>Ϊ BufferBuilder <20>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* * ְ<><D6B0><EFBFBD><EFBFBD>
* 1. <20><EFBFBD><E1B9A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʡ<EFBFBD>
* 2. <20><>װ BufferBuilder<65><72><EFBFBD>һ<E1B9A9>µļ<C2B5><C4BC><EFBFBD><EFBFBD><EFBFBD><E5B9B9><EFBFBD>ӿڡ<D3BF>
* 3. <20><> end() <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> BufferUploader <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD>
*/
class Tesselator {
private:
static constexpr int DEFAULT_BUFFER_SIZE = 2097152; // 2MB floats
std::unique_ptr<BufferBuilder> builder; // BufferBuilder ʵ<><CAB5>
/**
* @brief ˽<>й<EFBFBD><D0B9><EFBFBD><ECBAAF><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
explicit Tesselator(int bufferSize);
/**
* @brief ˽<><CBBD>Ĭ<EFBFBD>Ϲ<EFBFBD><CFB9><EFBFBD><ECBAAF><EFBFBD><EFBFBD>
*/
Tesselator();
public:
Tesselator(const Tesselator&) = delete;
Tesselator& operator=(const Tesselator&) = delete;
/**
* @brief <20><>ȡ Tesselator <20>ĵ<EFBFBD><C4B5><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD>̰߳<DFB3>ȫ<EFBFBD>ӳٳ<D3B3>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* * <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD>߳<EFBFBD><DFB3>ϵ<EFBFBD><CFB5>û<EFBFBD><C3BB>ڳ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD>׶ε<D7B6><CEB5>á<EFBFBD>
* @return Tesselator& <20><><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD>
*/
static Tesselator& getInstance();
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD> GPU<50><55><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD>
* * <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD>߳<EFBFBD><DFB3>ϵ<EFBFBD><CFB5>á<EFBFBD>
*/
void end();
/**
* @brief <20><>ȡ<EFBFBD>ײ<EFBFBD><D7B2><EFBFBD> BufferBuilder <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4><CCAC>
* @return BufferBuilder&
*/
BufferBuilder& getBuilder();
};
} // namespace Buffer

View File

@@ -0,0 +1,48 @@
#pragma once
#include "Shader.h"
#include <string>
#include <memory>
class ShaderProgram;
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><>Ӧ Java CompleteShader <20>ӿ<EFBFBD>)
* <20><>װһ<D7B0><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD>ݺͳ<DDBA>ʼ<EFBFBD><CABC><EFBFBD>߼<EFBFBD><DFBC><EFBFBD>
*/
class CompleteShader {
public:
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǻ<EFBFBD><C7BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>
virtual ~CompleteShader() = default;
/**
* @brief <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD>
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
virtual const Shader& getVertexShader() const = 0;
/**
* @brief <20><>ȡƬ<C8A1><C6AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD>
* @return Ƭ<><C6AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
virtual const Shader& getFragmentShader() const = 0;
/**
* @brief <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD>
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>
*/
virtual std::string getShaderName() const = 0;
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> true<75><65>
*/
virtual bool isDefaultShader() const = 0;
/**
* @brief <20><><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ͳһ<CDB3><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <20><>Ӧ Java <20>ӿ<EFBFBD><D3BF>е<EFBFBD> default <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param program <20><><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD> ShaderProgram <20><><EFBFBD><EFBFBD>ָ<EFBFBD>
*/
virtual void setDefaultUniforms(ShaderProgram* program) const {}
};

View File

@@ -0,0 +1,25 @@
#pragma once
#include <string>
/**
* @brief <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><>Ӧ Java Shader <20>ӿ<EFBFBD>)
* <20><>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E7B6A5><EFBFBD><EFBFBD>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD>
*/
class Shader {
public:
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǻ<EFBFBD><C7BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>
virtual ~Shader() = default;
/**
* @brief <20><>ȡ<EFBFBD><C8A1>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD> GLSL <20><><EFBFBD>
* @return <20><><EFBFBD><EFBFBD> GLSL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>
*/
virtual std::string getShaderCode() const = 0;
/**
* @brief <20><>ȡ<EFBFBD><C8A1>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD>͵<EFBFBD><CDB5>ԣ<EFBFBD><D4A3><EFBFBD>
* @return <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>
*/
virtual std::string getShaderName() const = 0;
};

View File

@@ -0,0 +1,251 @@
#include "pch.h"
#include "ShaderManagement.h"
#include <spdlog/spdlog.h>
#include <stdexcept>
#include <iostream>
#include <glm/glm.hpp>
#include "../../systems/RenderSystem.h"
#include "../../systems/sources/ShaderProgram.h"
#include "../../systems/sources/Shader.h"
#include "../../systems/sources/CompleteShader.h"
#include "def/TextShader.h"
#include "def/SolidColorShader.h"
#include "def/Shader2D.h"
std::map<std::string, std::unique_ptr<ShaderProgram>> ShaderManagement::s_shaderMap;
ShaderProgram* ShaderManagement::s_defaultProgram = nullptr;
/**
* @brief ʹ<><CAB9> helper <20><><EFBFBD><EFBFBD><EFBFBD>ƹ<EFBFBD> std::initializer_list <20>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD>
* * * @return std::vector<std::unique_ptr<CompleteShader>>
*/
static std::vector<std::unique_ptr<CompleteShader>> create_shader_list()
{
std::vector<std::unique_ptr<CompleteShader>> list;
list.push_back(std::make_unique<Shader2D>());
list.push_back(std::make_unique<SolidColorShader>());
list.push_back(std::make_unique<TextShader>());
return list;
}
std::vector<std::unique_ptr<CompleteShader>> ShaderManagement::s_shaderList = create_shader_list();
void ShaderManagement::compileAllShaders()
{
RenderSystem::assertOnRenderThread();
for (const auto& completeShader : s_shaderList) {
compileShaderProgram(completeShader.get());
}
if (s_defaultProgram == nullptr && !s_shaderMap.empty()) {
s_defaultProgram = s_shaderMap.begin()->second.get();
}
}
void ShaderManagement::compileShaderProgram(const CompleteShader* completeShader)
{
const std::string& shaderName = completeShader->getShaderName();
try {
const Shader& vertexShaderRef = completeShader->getVertexShader();
GLuint vsId = compileShader(GL_VERTEX_SHADER, vertexShaderRef.getShaderCode(),
vertexShaderRef.getShaderName());
const Shader& fragmentShaderRef = completeShader->getFragmentShader();
GLuint fsId = compileShader(GL_FRAGMENT_SHADER, fragmentShaderRef.getShaderCode(),
fragmentShaderRef.getShaderName());
GLuint programId = linkProgram(vsId, fsId, shaderName);
std::unique_ptr<ShaderProgram> shaderProgram = std::make_unique<ShaderProgram>(programId);
if (completeShader->isDefaultShader()) {
s_defaultProgram = shaderProgram.get();
setupDefaultUniforms(s_defaultProgram);
}
else {
completeShader->setDefaultUniforms(shaderProgram.get());
}
s_shaderMap[shaderName] = std::move(shaderProgram);
RenderSystem::deleteShader(vsId);
RenderSystem::deleteShader(fsId);
spdlog::info("<EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD>: {}", shaderName);
}
catch (const std::runtime_error& e) {
spdlog::error("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>: {}", shaderName);
std::cerr << "Shader compilation failed: " << shaderName << "\nError: " << e.what() << std::endl;
throw;
}
}
void ShaderManagement::setupDefaultUniforms(ShaderProgram* program)
{
if (!program) return;
program->use();
setUniformInt(program, "uTexture", 0);
setUniformFloat(program, "uOpacity", 1.0f);
setUniformVec4(program, "uColor", glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
setUniformInt(program, "uBlendMode", 0);
setUniformInt(program, "uDebugMode", 0);
setUniformInt(program, "uLightCount", 0);
program->stop();
RenderSystem::checkGLError("setupDefaultUniforms");
}
GLuint ShaderManagement::compileShader(GLenum type, const std::string& source, const std::string& shaderName)
{
GLuint shaderId = RenderSystem::createShader(type);
RenderSystem::shaderSource(shaderId, source);
RenderSystem::compileShader(shaderId);
if (RenderSystem::getShaderi(shaderId, GL_COMPILE_STATUS) != GL_TRUE) {
std::string log = RenderSystem::getShaderInfoLog(shaderId);
RenderSystem::deleteShader(shaderId);
throw std::runtime_error("<EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD> [" + shaderName + "]:\n" + log);
}
return shaderId;
}
GLuint ShaderManagement::linkProgram(GLuint vertexShaderId, GLuint fragmentShaderId, const std::string& programName)
{
GLuint programId = RenderSystem::createProgram();
RenderSystem::attachShader(programId, vertexShaderId);
RenderSystem::attachShader(programId, fragmentShaderId);
RenderSystem::linkProgram(programId);
if (RenderSystem::getProgrami(programId, GL_LINK_STATUS) != GL_TRUE) {
std::string log = RenderSystem::getProgramInfoLog(programId);
RenderSystem::deleteProgram(programId);
throw std::runtime_error("<EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD> [" + programName + "]:\n" + log);
}
validateProgram(programId, programName);
return programId;
}
void ShaderManagement::validateProgram(GLuint programId, const std::string& programName)
{
GLint validateStatus = RenderSystem::getProgrami(programId, GL_VALIDATE_STATUS);
if (validateStatus != GL_TRUE) {
std::string log = RenderSystem::getProgramInfoLog(programId);
spdlog::warn("<EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD> [{}]: {}", programName, log);
}
}
ShaderProgram* ShaderManagement::getDefaultProgram()
{
return s_defaultProgram;
}
ShaderProgram* ShaderManagement::getShaderProgram(const std::string& name)
{
auto it = s_shaderMap.find(name);
if (it != s_shaderMap.end()) {
return it->second.get();
}
return nullptr;
}
void ShaderManagement::cleanup()
{
RenderSystem::assertOnRenderThread();
s_shaderMap.clear();
s_shaderList.clear();
s_defaultProgram = nullptr;
spdlog::info("ShaderManagement cleanup completed.");
}
void ShaderManagement::setUniformInt(ShaderProgram* program, const std::string& name, GLint value)
{
if (!program) return;
program->use();
GLint location = program->getUniformLocation(name);
if (location != -1) {
RenderSystem::uniform1i(location, value);
}
}
void ShaderManagement::setUniformFloat(ShaderProgram* program, const std::string& name, GLfloat value)
{
if (!program) return;
program->use();
GLint location = program->getUniformLocation(name);
if (location != -1) {
RenderSystem::uniform1f(location, value);
}
}
void ShaderManagement::setUniformVec2(ShaderProgram* program, const std::string& name, GLfloat x, GLfloat y)
{
if (!program) return;
program->use();
GLint location = program->getUniformLocation(name);
if (location != -1) {
RenderSystem::uniform2f(location, x, y);
}
}
void ShaderManagement::setUniformVec2(ShaderProgram* program, const std::string& name, const glm::vec2& vec)
{
if (!program) return;
program->use();
GLint location = program->getUniformLocation(name);
if (location != -1) {
RenderSystem::uniform2f(location, vec);
}
}
void ShaderManagement::setUniformVec3(ShaderProgram* program, const std::string& name, GLfloat x, GLfloat y, GLfloat z)
{
if (!program) return;
program->use();
GLint location = program->getUniformLocation(name);
if (location != -1) {
RenderSystem::uniform3f(location, x, y, z);
}
}
void ShaderManagement::setUniformVec3(ShaderProgram* program, const std::string& name, const glm::vec3& vec)
{
if (!program) return;
program->use();
GLint location = program->getUniformLocation(name);
if (location != -1) {
RenderSystem::uniform3f(location, vec);
}
}
void ShaderManagement::setUniformVec4(ShaderProgram* program, const std::string& name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
if (!program) return;
program->use();
GLint location = program->getUniformLocation(name);
if (location != -1) {
RenderSystem::uniform4f(location, x, y, z, w);
}
}
void ShaderManagement::setUniformVec4(ShaderProgram* program, const std::string& name, const glm::vec4& vec)
{
if (!program) return;
program->use();
GLint location = program->getUniformLocation(name);
if (location != -1) {
RenderSystem::uniform4f(location, vec);
}
}
void ShaderManagement::setUniformMat3(ShaderProgram* program, const std::string& name, const glm::mat3& matrix)
{
if (!program) return;
program->use();
GLint location = program->getUniformLocation(name);
if (location != -1) {
RenderSystem::uniformMatrix3(location, matrix, false);
}
}

View File

@@ -0,0 +1,112 @@
#pragma once
#include <string>
#include <map>
#include <vector>
#include <memory>
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
class ShaderProgram;
class CompleteShader;
class RenderSystem;
class Shader2D;
class SolidColorShader;
class TextShader;
/**
* @brief <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EBA1A2><EFBFBD>Ӻ͹<D3BA><CDB9><EFBFBD> (C++ <20><>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>)
*/
class ShaderManagement
{
private:
// <20><>ֹʵ<D6B9><CAB5><EFBFBD><EFBFBD>
ShaderManagement() = delete;
ShaderManagement(const ShaderManagement&) = delete;
ShaderManagement& operator=(const ShaderManagement&) = delete;
public:
/**
* @brief <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD>򻺴<EFBFBD>ӳ<EFBFBD><EFBFBD><E4A3AC><EFBFBD><EFBFBD><EFBFBD>ƴ洢<C6B4>ѱ<EFBFBD><D1B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* ʹ<><CAB9> std::unique_ptr <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ShaderProgram <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static std::map<std::string, std::unique_ptr<ShaderProgram>> s_shaderMap;
/**
* @brief <20><>ɫ<EFBFBD><C9AB><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EBB6A8>
* ע<><EFBFBD><E2A3BA> C++ <20>У<EFBFBD><D0A3><EFBFBD>̬<EFBFBD><CCAC>ʼ<EFBFBD><CABC><EFBFBD>б<EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD> .cpp <20>ļ<EFBFBD><C4BC>С<EFBFBD>
* <20><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> std::vector<std::unique_ptr<CompleteShader>> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static std::vector<std::unique_ptr<CompleteShader>> s_shaderList;
/**
* @brief Ĭ<><C4AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static ShaderProgram* s_defaultProgram;
// --- <20><><EFBFBD>Ĺ<EFBFBD><C4B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB>
*/
static void compileAllShaders();
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>Դ
*/
static void cleanup();
// --- Getter <20><><EFBFBD><EFBFBD> ---
/**
* @brief <20><>ȡĬ<C8A1><C4AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static ShaderProgram* getDefaultProgram();
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD>ƻ<EFBFBD>ȡ<EFBFBD><C8A1>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static ShaderProgram* getShaderProgram(const std::string& name);
static void setUniformInt(ShaderProgram* program, const std::string& name, GLint value);
static void setUniformFloat(ShaderProgram* program, const std::string& name, GLfloat value);
// Vec2/Vec3/Vec4 (ʹ<><CAB9> GLM)
static void setUniformVec2(ShaderProgram* program, const std::string& name, GLfloat x, GLfloat y);
static void setUniformVec2(ShaderProgram* program, const std::string& name, const glm::vec2& vec);
static void setUniformVec3(ShaderProgram* program, const std::string& name, GLfloat x, GLfloat y, GLfloat z);
static void setUniformVec3(ShaderProgram* program, const std::string& name, const glm::vec3& vec);
static void setUniformVec4(ShaderProgram* program, const std::string& name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
static void setUniformVec4(ShaderProgram* program, const std::string& name, const glm::vec4& vec);
// Mat3 (ʹ<><CAB9> GLM)
static void setUniformMat3(ShaderProgram* program, const std::string& name, const glm::mat3& matrix);
private:
/**
* @brief <20><><EFBFBD><EFBFBD><EBB5A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static void compileShaderProgram(const CompleteShader* completeShader);
/**
* @brief <20><><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>uniformֵ
*/
static void setupDefaultUniforms(ShaderProgram* program);
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB>
*/
static GLuint compileShader(GLenum type, const std::string& source, const std::string& shaderName);
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static GLuint linkProgram(GLuint vertexShaderId, GLuint fragmentShaderId, const std::string& programName);
/**
* @brief <20>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><D6A4><EFBFBD><EFBFBD>
*/
static void validateProgram(GLuint programId, const std::string& programName);
};

View File

@@ -0,0 +1,120 @@
#include "pch.h"
#include "ShaderProgram.h"
#include <spdlog/spdlog.h>
ShaderProgram::ShaderProgram(GLuint programId)
: m_programId(programId)
{
spdlog::info("ShaderProgram created with ID: {}", programId);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ShaderProgram::~ShaderProgram()
{
deleteProgram();
spdlog::info("ShaderProgram {} destroyed.", m_programId);
}
void ShaderProgram::use() const
{
glUseProgram(m_programId);
}
void ShaderProgram::stop() const
{
glUseProgram(0);
}
GLint ShaderProgram::getUniformLocation(const std::string& name)
{
if (auto it = m_uniformCache.find(name); it != m_uniformCache.end()) {
return it->second;
}
GLint location = glGetUniformLocation(m_programId, name.c_str());
m_uniformCache[name] = location;
if (location == -1) {
spdlog::warn("Uniform '{}' not found in program ID: {}", name, m_programId);
}
return location;
}
// --- uniform <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD> (ʹ<><CAB9> name) ---
void ShaderProgram::setUniform1i(const std::string& name, GLint value)
{
GLint location = getUniformLocation(name);
setUniform1i(location, value);
}
void ShaderProgram::setUniform1f(const std::string& name, GLfloat value)
{
GLint location = getUniformLocation(name);
setUniform1f(location, value);
}
void ShaderProgram::setUniform2f(const std::string& name, GLfloat x, GLfloat y)
{
GLint location = getUniformLocation(name);
if (location != -1) {
glUniform2f(location, x, y);
}
}
void ShaderProgram::setUniform3f(const std::string& name, GLfloat x, GLfloat y, GLfloat z)
{
GLint location = getUniformLocation(name);
if (location != -1) {
glUniform3f(location, x, y, z);
}
}
void ShaderProgram::setUniform4f(const std::string& name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
GLint location = getUniformLocation(name);
setUniform4f(location, x, y, z, w);
}
void ShaderProgram::setUniformMatrix3(const std::string& name, const glm::mat3& matrix)
{
GLint location = getUniformLocation(name);
setUniformMatrix3(location, matrix);
}
// --- uniform <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD> (ʹ<><CAB9> location) ---
void ShaderProgram::setUniform1i(GLint location, GLint value)
{
if (location != -1) {
glUniform1i(location, value);
}
}
void ShaderProgram::setUniform1f(GLint location, GLfloat value)
{
if (location != -1) {
glUniform1f(location, value);
}
}
void ShaderProgram::setUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
if (location != -1) {
glUniform4f(location, x, y, z, w);
}
}
void ShaderProgram::setUniformMatrix3(GLint location, const glm::mat3& matrix)
{
if (location != -1) {
glUniformMatrix3fv(location, 1, GL_FALSE, glm::value_ptr(matrix));
}
}
void ShaderProgram::deleteProgram()
{
if (glIsProgram(m_programId)) {
glDeleteProgram(m_programId);
m_uniformCache.clear();
}
}

View File

@@ -0,0 +1,57 @@
#pragma once
#include <string>
#include <map>
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
/**
* @brief OpenGL<47><4C>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD>
* * <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E0A3AC><EFBFBD>ڹ<EFBFBD><DAB9><EFBFBD>OpenGL<47><4C>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD>򣬰<EFBFBD><F2A3ACB0><EFBFBD>ͳһ<CDB3><D2BB><EFBFBD><EFBFBD>(uniform)<29><><EFBFBD><EFBFBD><EFBFBD>úͻ<C3BA><CDBB>
* <20><><EFBFBD>ǵ<EFBFBD><C7B5>̳<EFBFBD><CCB3>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><E9BAAF><EFBFBD><EFBFBD>
*/
class ShaderProgram
{
public:
// <20><><EFBFBD><EFBFBD><ECBAAF>
explicit ShaderProgram(GLuint programId);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
virtual ~ShaderProgram();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void use() const;
// ֹͣʹ<D6B9><CAB9><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void stop() const;
// <20><>ȡͳһ<CDB3><D2BB><EFBFBD><EFBFBD>(uniform)λ<>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
GLint getUniformLocation(const std::string& name);
// --- uniform <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD> (ʹ<><CAB9> name) ---
void setUniform1i(const std::string& name, GLint value);
void setUniform1f(const std::string& name, GLfloat value);
void setUniform2f(const std::string& name, GLfloat x, GLfloat y);
void setUniform3f(const std::string& name, GLfloat x, GLfloat y, GLfloat z);
void setUniform4f(const std::string& name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
// ʹ<><CAB9> glm::mat3
void setUniformMatrix3(const std::string& name, const glm::mat3& matrix);
// --- uniform <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD> (ʹ<><CAB9> location) ---
void setUniform1i(GLint location, GLint value);
void setUniform1f(GLint location, GLfloat value);
void setUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void setUniformMatrix3(GLint location, const glm::mat3& matrix);
// <20><><EFBFBD><EFBFBD>OpenGL<47><4C>Դ
void deleteProgram();
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ID
GLuint getProgramId() const { return m_programId; }
protected:
const GLuint m_programId;
std::map<std::string, GLint> m_uniformCache;
};

View File

@@ -0,0 +1,163 @@
#include "pch.h"
#include "Shader2D.h"
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB> GLSL <20><><EFBFBD><EFBFBD> (<28><>Ӧ VertexShaders.java)
static const std::string VERTEX_SHADER_SRC = R"""(
#version 330 core
layout(location = 0) in vec2 aPosition;
layout(location = 1) in vec2 aTexCoord;
out vec2 vTexCoord;
out vec2 vWorldPos;
uniform mat3 uModelMatrix;
uniform mat3 uViewMatrix;
uniform mat3 uProjectionMatrix;
void main() {
// ʹ<><CAB9> 3x3 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļλ<C4BB><CEBB>
vec3 p = uProjectionMatrix * uViewMatrix * uModelMatrix * vec3(aPosition, 1.0);
gl_Position = vec4(p.xy, 0.0, 1.0);
vTexCoord = aTexCoord;
// <20><><EFBFBD><EFBFBD> world-space λ<>ù<EFBFBD> fragment shader ʹ<>ã<EFBFBD><C3A3><EFBFBD> xy<78><79>
vWorldPos = (uModelMatrix * vec3(aPosition, 1.0)).xy;
}
)""";
// Ƭ<><C6AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB> GLSL <20><><EFBFBD><EFBFBD> (<28><>Ӧ FragmentShaders.java)
static const std::string FRAGMENT_SHADER_SRC = R"""(
#version 330 core
in vec2 vTexCoord;
in vec2 vWorldPos;
out vec4 FragColor;
uniform sampler2D uTexture;
uniform vec4 uColor;
uniform float uOpacity;
uniform int uBlendMode;
uniform int uDebugMode;
#define MAX_LIGHTS 8
uniform vec2 uLightsPos[MAX_LIGHTS];
uniform vec3 uLightsColor[MAX_LIGHTS];
uniform float uLightsIntensity[MAX_LIGHTS];
uniform int uLightsIsAmbient[MAX_LIGHTS];
uniform int uLightCount;
// <20><><EFBFBD><EFBFBD>˥<EFBFBD><CBA5>ϵ<EFBFBD><CFB5>
const float ATT_CONST = 1.0;
const float ATT_LINEAR = 0.09;
const float ATT_QUAD = 0.032;
void main() {
// 1. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>͸<EFBFBD><CDB8><EFBFBD><EFBFBD>
vec4 tex = texture(uTexture, vTexCoord);
float alpha = tex.a * uOpacity;
if (alpha <= 0.001) discard;
// 2. <20>޹<EFBFBD>Դ<EFBFBD>Ż<EFBFBD>·<EFBFBD><C2B7>
if (uLightCount == 0) {
vec3 base = tex.rgb * uColor.rgb;
base = clamp(base, 0.0, 1.0);
FragColor = vec4(base, alpha);
return;
}
// 3. <20><><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>·<EFBFBD><C2B7>
vec3 baseColor = tex.rgb * uColor.rgb;
vec3 ambient = vec3(0.06); // С<><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E2B2B9>
vec3 lighting = vec3(0.0);
vec3 specularAccum = vec3(0.0);
// <20>ۻ<EFBFBD><DBBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (int i = 0; i < uLightCount; ++i) {
if (uLightsIsAmbient[i] == 1) {
lighting += uLightsColor[i] * uLightsIntensity[i];
}
}
lighting += ambient;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ/<2F>ǻ<EFBFBD><C7BB><EFBFBD><EFBFBD><EFBFBD>
for (int i = 0; i < uLightCount; ++i) {
if (uLightsIsAmbient[i] == 1) continue;
vec2 toLight = uLightsPos[i] - vWorldPos;
float dist = length(toLight);
// <20><>׼˥<D7BC><CBA5>
float attenuation = ATT_CONST / (ATT_CONST + ATT_LINEAR * dist + ATT_QUAD * dist * dist);
float radiance = uLightsIntensity[i] * attenuation;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD>ھ<EFBFBD><DABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
float diffuseFactor = clamp(1.0 - (dist * 0.0015), 0.0, 1.0);
vec3 diff = uLightsColor[i] * radiance * diffuseFactor;
lighting += diff;
// <20>򵥸߹<F2B5A5B8>
vec3 lightDir3 = normalize(vec3(toLight, 0.0));
vec3 viewDir = vec3(0.0, 0.0, 1.0);
vec3 normal = vec3(0.0, 0.0, 1.0);
vec3 reflectDir = reflect(-lightDir3, normal);
float specFactor = pow(max(dot(viewDir, reflectDir), 0.0), 16.0);
float specIntensity = 0.2;
specularAccum += uLightsColor[i] * radiance * specFactor * specIntensity;
}
// Ӧ<>ù<EFBFBD><C3B9><EFBFBD>
vec3 totalLighting = min(lighting + specularAccum, vec3(2.0));
vec3 finalColor = baseColor * totalLighting;
// 4. <20>򵥻<EFBFBD><F2B5A5BB><EFBFBD>ģʽ
if (uBlendMode == 1) finalColor = tex.rgb + uColor.rgb;
else if (uBlendMode == 2) finalColor = tex.rgb * uColor.rgb;
else if (uBlendMode == 3) finalColor = 1.0 - (1.0 - tex.rgb) * (1.0 - uColor.rgb);
// 5. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
finalColor = clamp(finalColor, 0.0, 1.0);
FragColor = vec4(finalColor, alpha);
}
)""";
class Shader2D::VertexShaders final : public Shader {
public:
virtual ~VertexShaders() = default;
std::string getShaderCode() const override {
return VERTEX_SHADER_SRC;
}
std::string getShaderName() const override {
return "Vertex Shaders";
}
};
class Shader2D::FragmentShaders final : public Shader {
public:
virtual ~FragmentShaders() = default;
std::string getShaderCode() const override {
return FRAGMENT_SHADER_SRC;
}
std::string getShaderName() const override {
return "Fragment shaders";
}
};
const Shader2D::VertexShaders Shader2D::s_vertexShader;
const Shader2D::FragmentShaders Shader2D::s_fragmentShader;
Shader2D::Shader2D()
{
}
const Shader& Shader2D::getVertexShader() const
{
return s_vertexShader;
}
const Shader& Shader2D::getFragmentShader() const
{
return s_fragmentShader;
}
void Shader2D::setDefaultUniforms(ShaderProgram* program) const
{
}

View File

@@ -0,0 +1,33 @@
#pragma once
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#include "../CompleteShader.h"
#include "../ShaderProgram.h"
#include <glm/glm.hpp>
/**
* @brief Ĭ<><C4AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB>ʵ<EFBFBD><CAB5> (Shader2D)
* <20>̳<EFBFBD><CCB3><EFBFBD> CompleteShader<65><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 2D <20><>Ⱦ<EFBFBD><C8BE>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>
*/
class Shader2D final : public CompleteShader {
public:
Shader2D();
virtual ~Shader2D() = default;
const Shader& getVertexShader() const override;
const Shader& getFragmentShader() const override;
std::string getShaderName() const override {
return "Vivid2d Shader";
}
bool isDefaultShader() const override {
return true;
}
void setDefaultUniforms(ShaderProgram* program) const override;
private:
// <20>ڲ<EFBFBD><DAB2><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> .cpp <20>ļ<EFBFBD><C4BC>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
class VertexShaders;
class FragmentShaders;
// <20><>̬<EFBFBD><CCAC>Ա<EFBFBD><EFBFBD><E6B4A2>ɫ<EFBFBD><C9AB>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ð<EFBFBD>ȫ
static const VertexShaders s_vertexShader;
static const FragmentShaders s_fragmentShader;
};

View File

@@ -0,0 +1,123 @@
#include "pch.h"
#include "SolidColorShader.h"
#include <stdexcept>
static const std::string SOLID_COLOR_VERTEX_SHADER_SRC = R"""(
#version 330 core
layout(location = 0) in vec2 aPosition;
layout(location = 1) in vec2 aTexCoord;
uniform mat3 uModelMatrix;
uniform mat3 uViewMatrix;
uniform mat3 uProjectionMatrix;
void main() {
// ʹ<><CAB9> 3x3 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļλ<C4BB><CEBB>
vec3 p = uProjectionMatrix * uViewMatrix * uModelMatrix * vec3(aPosition, 1.0);
gl_Position = vec4(p.xy, 0.0, 1.0);
}
)""";
static const std::string SOLID_COLOR_FRAGMENT_SHADER_SRC = R"""(
#version 330 core
out vec4 FragColor;
uniform vec4 uColor;
uniform float uOpacity;
void main() {
// ֱ<><D6B1>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
vec4 finalColor = uColor;
finalColor.a *= uOpacity;
// <20><><EFBFBD><EFBFBD>͸<EFBFBD><CDB8><EFBFBD><EFBFBD>̫<EFBFBD><CCAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭ<EFBFBD><C6AC>
if (finalColor.a <= 0.001) discard;
FragColor = finalColor;
}
)""";
class SolidColorShader::SolidColorVertexShader final : public Shader {
public:
virtual ~SolidColorVertexShader() = default;
std::string getShaderCode() const override {
return SOLID_COLOR_VERTEX_SHADER_SRC;
}
std::string getShaderName() const override {
return "Solid Color Vertex Shader";
}
};
class SolidColorShader::SolidColorFragmentShader final : public Shader {
public:
virtual ~SolidColorFragmentShader() = default;
std::string getShaderCode() const override {
return SOLID_COLOR_FRAGMENT_SHADER_SRC;
}
std::string getShaderName() const override {
return "Solid Color Fragment Shader";
}
};
const SolidColorShader::SolidColorVertexShader SolidColorShader::s_vertexShader;
const SolidColorShader::SolidColorFragmentShader SolidColorShader::s_fragmentShader;
SolidColorShader::SolidColorShader()
{
}
const Shader& SolidColorShader::getVertexShader() const
{
return s_vertexShader;
}
const Shader& SolidColorShader::getFragmentShader() const
{
return s_fragmentShader;
}
void SolidColorShader::setDefaultUniforms(ShaderProgram* program) const
{
if (!program) return;
program->use();
int colorLoc = program->getUniformLocation("uColor");
if (colorLoc != -1) {
program->setUniform4f(colorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
}
int opacityLoc = program->getUniformLocation("uOpacity");
if (opacityLoc != -1) {
program->setUniform1f(opacityLoc, 1.0f);
}
program->stop();
}
void SolidColorShader::setColor(ShaderProgram* program, float r, float g, float b, float a)
{
if (!program) return;
program->use();
int colorLoc = program->getUniformLocation("uColor");
if (colorLoc != -1) {
program->setUniform4f(colorLoc, r, g, b, a);
}
program->stop();
}
void SolidColorShader::setOpacity(ShaderProgram* program, float opacity)
{
if (!program) return;
program->use();
int opacityLoc = program->getUniformLocation("uOpacity");
if (opacityLoc != -1) {
program->setUniform1f(opacityLoc, opacity);
}
program->stop();
}

View File

@@ -0,0 +1,59 @@
#pragma once
#include "../CompleteShader.h"
#include "../ShaderProgram.h"
#include <glm/glm.hpp>
/**
* @brief <20><>ɫ<EFBFBD><C9AB>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (SolidColorShader)
* ר<><D7A8><EFBFBD><EFBFBD><EFBFBD>ڻ<EFBFBD><DABB>ƴ<EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E5A3AC>ѡ<EFBFBD>п򡢵<D0BF><F2A1A2B5><EFBFBD>ͼ<EFBFBD>εȡ<CEB5>
*/
class SolidColorShader final : public CompleteShader {
public:
SolidColorShader();
virtual ~SolidColorShader() = default;
// --- CompleteShader <20>ӿ<EFBFBD>ʵ<EFBFBD><CAB5> ---
// <20><><EFBFBD><EFBFBD><EBB7B5> const <20><><EFBFBD><EFBFBD>
const Shader& getVertexShader() const override;
// <20><><EFBFBD><EFBFBD><EBB7B5> const <20><><EFBFBD><EFBFBD>
const Shader& getFragmentShader() const override;
std::string getShaderName() const override {
return "Solid Color Shader";
}
bool isDefaultShader() const override {
return false;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> const <20><>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD>
void setDefaultUniforms(ShaderProgram* program) const override;
// --- <20><>ɫ/<2F><>͸<EFBFBD><CDB8><EFBFBD>ȿ<EFBFBD><C8BF>Ʒ<EFBFBD><C6B7><EFBFBD> ---
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>ɫ
* @param program <20><>ǰʹ<C7B0>õ<EFBFBD><C3B5><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param r, g, b, a <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>
*/
void setColor(ShaderProgram* program, float r, float g, float b, float a);
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>͸<EFBFBD><CDB8><EFBFBD><EFBFBD>
* @param program <20><>ǰʹ<C7B0>õ<EFBFBD><C3B5><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param opacity <20><>͸<EFBFBD><CDB8><EFBFBD><EFBFBD>ֵ
*/
void setOpacity(ShaderProgram* program, float opacity);
private:
// <20>ڲ<EFBFBD><DAB2><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> .cpp <20>ļ<EFBFBD><C4BC>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
class SolidColorVertexShader;
class SolidColorFragmentShader;
// <20><>̬<EFBFBD><CCAC>Ա<EFBFBD><EFBFBD><E6B4A2>ɫ<EFBFBD><C9AB>ʵ<EFBFBD><CAB5>
static const SolidColorVertexShader s_vertexShader;
static const SolidColorFragmentShader s_fragmentShader;
};

View File

@@ -0,0 +1,78 @@
#include "pch.h"
#include "TextShader.h"
#include "../ShaderProgram.h"
static const std::string TEXT_VERTEX_SHADER_CODE = R"""(
#version 330 core
layout(location = 0) in vec2 aPosition;
layout(location = 1) in vec2 aTexCoord;
uniform mat3 uProjectionMatrix;
out vec2 vTexCoord;
void main() {
vec3 p = uProjectionMatrix * vec3(aPosition, 1.0);
gl_Position = vec4(p.xy, 0.0, 1.0);
vTexCoord = aTexCoord;
}
)""";
static const std::string TEXT_FRAGMENT_SHADER_CODE = R"""(
#version 330 core
in vec2 vTexCoord;
out vec4 FragColor;
uniform sampler2D uTexture;
uniform vec4 uColor;
void main() {
// ʹ<><CAB9> .r ͨ<><CDA8><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λͼ)
float alpha = texture(uTexture, vTexCoord).r;
FragColor = vec4(uColor.rgb, uColor.a * alpha);
}
)""";
class TextShader::TextVertexShader : public Shader {
public:
virtual ~TextVertexShader() = default;
std::string getShaderCode() const override { return TEXT_VERTEX_SHADER_CODE; }
std::string getShaderName() const override { return "TextVertexShader"; }
};
class TextShader::TextFragmentShader : public Shader {
public:
virtual ~TextFragmentShader() = default;
std::string getShaderCode() const override { return TEXT_FRAGMENT_SHADER_CODE; }
std::string getShaderName() const override { return "TextFragmentShader"; }
};
const TextShader::TextVertexShader TextShader::s_vertexShader;
const TextShader::TextFragmentShader TextShader::s_fragmentShader;
TextShader::TextShader()
: m_color(1.0f, 1.0f, 1.0f, 1.0f)
{}
const Shader& TextShader::getVertexShader() const
{
return s_vertexShader;
}
const Shader& TextShader::getFragmentShader() const
{
return s_fragmentShader;
}
void TextShader::setColor(const glm::vec4& color)
{
this->m_color = color;
}
void TextShader::setDefaultUniforms(ShaderProgram* program)
{
if (!program) return;
program->use();
program->setUniform4f("uColor", m_color.r, m_color.g, m_color.b, m_color.a);
program->setUniform1i("uTexture", 0);
program->stop();
}

View File

@@ -0,0 +1,58 @@
#pragma once
// TextShader.h <20><> .../systems/sources/def
#include "../CompleteShader.h"
#include "../Shader.h"
#include <glm/glm.hpp>
class ShaderProgram;
/**
* @brief <20>ı<EFBFBD><C4B1><EFBFBD>ɫ<EFBFBD><C9AB> (TextShader)
* <20>̳<EFBFBD><CCB3><EFBFBD> CompleteShader<65><72><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>Ⱦ<EFBFBD><C8BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD>á<EFBFBD>
*/
class TextShader : public CompleteShader {
public:
TextShader();
virtual ~TextShader() = default;
/**
* @brief <20><>ȡ<EFBFBD><C8A1>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD>
*/
std::string getShaderName() const override { return "TextShader"; }
/**
* @brief <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD>
*/
const Shader& getVertexShader() const override;
/**
* @brief <20><>ȡƬ<C8A1><C6AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD>
*/
const Shader& getFragmentShader() const override;
/**
* @brief <20><><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ͳһ<CDB3><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void setDefaultUniforms(ShaderProgram* program);
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>ɫ<EFBFBD><C9AB>
*/
void setColor(const glm::vec4& color);
/**
* @brief <20>Ƿ<EFBFBD>ΪĬ<CEAA><C4AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>
*/
bool isDefaultShader() const override { return false; }
private:
glm::vec4 m_color;
// <20><>̬<EFBFBD><CCAC>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD><DAB7>ش<EFBFBD><D8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>
class TextVertexShader;
class TextFragmentShader;
static const TextVertexShader s_vertexShader;
static const TextFragmentShader s_fragmentShader;
};

View File

@@ -0,0 +1,7 @@
{
"name": "my-opengl-project",
"version-string": "0.1.0",
"dependencies": [
"stb"
]
}