提交 8be813b0 编写于 作者: GamebabyRockSun_QQ's avatar GamebabyRockSun_QQ

添加25、26号示例,详情请参见Readme.md

上级 8cac7672
......@@ -22,6 +22,7 @@
#include <dxgidebug.h>
#endif
#include "../Commons/GRS_Def.h"
#include "../Commons/GRS_Assimp_Loader.h"
#include "../Commons/GRS_D3D12_Utility.h"
#include "../Commons/GRS_Texture_Loader.h"
......@@ -37,13 +38,6 @@ using namespace Microsoft::WRL;
#pragma comment(lib, "assimp-vc142-mtd.lib")
#define GRS_SLEEP(dwMilliseconds) WaitForSingleObject(GetCurrentThread(),dwMilliseconds)
#define GRS_THROW_IF_FAILED(hr) {HRESULT _hr = (hr);if (FAILED(_hr)){ ATLTRACE("Error: 0x%08x\n",_hr); AtlThrow(_hr); }}
//更简洁的向上边界对齐算法 内存管理中常用 请记住
#define GRS_UPPER(A,B) ((size_t)(((A)+((B)-1))&~((B) - 1)))
//上取整除法
#define GRS_UPPER_DIV(A,B) ((UINT)(((A)+((B)-1))/(B)))
#define GRS_WND_CLASS _T("GRS Game Window Class")
#define GRS_WND_TITLE _T("GRS DirectX12 Assimp Import Model & Animation & Render")
......@@ -1267,7 +1261,7 @@ int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR
FLOAT fStartTime = ( FLOAT )::GetTickCount64();
FLOAT fCurrentTime = fStartTime;
FLOAT fTimeInSeconds = ( fCurrentTime - fStartTime ) / 1000.0f;
CGRSARMatrix arBoneMatrixs;
CGRSMatrixArray arBoneMatrixs;
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
......
......@@ -1343,6 +1343,31 @@ void OnSize(UINT width, UINT height, bool minimized)
g_stD3DDevice.m_stScissorRect.top = static_cast<LONG>(g_stD3DDevice.m_stViewPort.TopLeftY);
g_stD3DDevice.m_stScissorRect.bottom = static_cast<LONG>(g_stD3DDevice.m_stViewPort.TopLeftY + g_stD3DDevice.m_stViewPort.Height);
//---------------------------------------------------------------------------------------------
// 更新天空盒远平面尺寸
float fHighW = -1.0f - (1.0f / (float)g_stD3DDevice.m_iWndWidth);
float fHighH = -1.0f - (1.0f / (float)g_stD3DDevice.m_iWndHeight);
float fLowW = 1.0f + (1.0f / (float)g_stD3DDevice.m_iWndWidth);
float fLowH = 1.0f + (1.0f / (float)g_stD3DDevice.m_iWndHeight);
ST_GRS_SKYBOX_VERTEX stSkyboxVertices[4] = {};
stSkyboxVertices[0].m_v4Position = XMFLOAT4(fLowW, fLowH, 1.0f, 1.0f);
stSkyboxVertices[1].m_v4Position = XMFLOAT4(fLowW, fHighH, 1.0f, 1.0f);
stSkyboxVertices[2].m_v4Position = XMFLOAT4(fHighW, fLowH, 1.0f, 1.0f);
stSkyboxVertices[3].m_v4Position = XMFLOAT4(fHighW, fHighH, 1.0f, 1.0f);
//加载天空盒子的数据
g_stBufferResSesc.Width = GRS_UPPER(sizeof(stSkyboxVertices), D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT);
//使用map-memcpy-unmap大法将数据传至顶点缓冲对象
BYTE* pData = nullptr;
GRS_THROW_IF_FAILED(g_stSkyBoxData.m_pIVertexBuffer->Map(0, nullptr, reinterpret_cast<void**>(&pData)));
memcpy(pData, stSkyboxVertices, sizeof(stSkyboxVertices));
g_stSkyBoxData.m_pIVertexBuffer->Unmap(0, nullptr);
//---------------------------------------------------------------------------------------------
// 9、设置下事件状态,从消息旁路返回主消息循环
SetEvent(g_stD3DDevice.m_hEventFence);
......
<?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>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{f23f558f-e978-4265-b862-26492f7c3906}</ProjectGuid>
<RootNamespace>My25IBLMultiInstanceSphere</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>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</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" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<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>Windows</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>Windows</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>Windows</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>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="25-IBL-MultiInstance-Sphere.cpp" />
</ItemGroup>
<ItemGroup>
<FxCompile Include="Shader\GRS_1Times_GS_HDR_2_CubeMap_VS_GS.hlsl">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="Shader\GRS_6Times_HDR_2_Cubemap_VS.hlsl">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="Shader\GRS_HDR_Spherical_Map_2_Cubemap_PS.hlsl">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="Shader\GRS_IBL_BRDF_Integration_LUT.hlsl">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="Shader\GRS_IBL_Diffuse_Irradiance_Convolution_With_Integration_PS.hlsl">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="Shader\GRS_IBL_Diffuse_Irradiance_Convolution_With_Monte_Carlo_PS.hlsl">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="Shader\GRS_IBL_Specular_Pre_Integration_PS.hlsl">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="Shader\GRS_PBR_IBL_PS_Without_Texture.hlsl">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="Shader\GRS_PBR_IBL_VS_Multi_Instance.hlsl">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="Shader\GRS_Quad_With_Dynamic_Index_Multi_Instance.hlsl">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="Shader\GRS_SkyBox_With_Spherical_Map.hlsl">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</FxCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\Shader\HDR_COLOR_CONV.hlsli">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</None>
<None Include="Shader\GRS_PBR_Function.hlsli">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</None>
<None Include="Shader\GRS_Scene_CB_Def.hlsli">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</None>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?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>
<Filter Include="Shader">
<UniqueIdentifier>{e5828034-53b6-440b-9806-c7539ed4cc88}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="25-IBL-MultiInstance-Sphere.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<FxCompile Include="Shader\GRS_1Times_GS_HDR_2_CubeMap_VS_GS.hlsl">
<Filter>Shader</Filter>
</FxCompile>
<FxCompile Include="Shader\GRS_6Times_HDR_2_Cubemap_VS.hlsl">
<Filter>Shader</Filter>
</FxCompile>
<FxCompile Include="Shader\GRS_HDR_Spherical_Map_2_Cubemap_PS.hlsl">
<Filter>Shader</Filter>
</FxCompile>
<FxCompile Include="Shader\GRS_IBL_BRDF_Integration_LUT.hlsl">
<Filter>Shader</Filter>
</FxCompile>
<FxCompile Include="Shader\GRS_IBL_Diffuse_Irradiance_Convolution_With_Integration_PS.hlsl">
<Filter>Shader</Filter>
</FxCompile>
<FxCompile Include="Shader\GRS_IBL_Diffuse_Irradiance_Convolution_With_Monte_Carlo_PS.hlsl">
<Filter>Shader</Filter>
</FxCompile>
<FxCompile Include="Shader\GRS_IBL_Specular_Pre_Integration_PS.hlsl">
<Filter>Shader</Filter>
</FxCompile>
<FxCompile Include="Shader\GRS_PBR_IBL_PS_Without_Texture.hlsl">
<Filter>Shader</Filter>
</FxCompile>
<FxCompile Include="Shader\GRS_PBR_IBL_VS_Multi_Instance.hlsl">
<Filter>Shader</Filter>
</FxCompile>
<FxCompile Include="Shader\GRS_Quad_With_Dynamic_Index_Multi_Instance.hlsl">
<Filter>Shader</Filter>
</FxCompile>
<FxCompile Include="Shader\GRS_SkyBox_With_Spherical_Map.hlsl">
<Filter>Shader</Filter>
</FxCompile>
</ItemGroup>
<ItemGroup>
<None Include="Shader\GRS_PBR_Function.hlsli">
<Filter>Shader</Filter>
</None>
<None Include="Shader\GRS_Scene_CB_Def.hlsli">
<Filter>Shader</Filter>
</None>
<None Include="..\Shader\HDR_COLOR_CONV.hlsli">
<Filter>Shader</Filter>
</None>
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
\ No newline at end of file
#include "GRS_Scene_CB_Def.hlsli"
struct ST_GRS_HLSL_VS_IN
{
float4 m_v4LPos : POSITION; // Model Local position
};
struct ST_GRS_HLSL_GS_IN
{
float4 m_v4WPos : SV_POSITION; // World position
};
struct ST_GRS_HLSL_GS_OUT
{
float4 m_v4HPos : SV_POSITION; // Projection coord
float4 m_v4WPos : POSITION; // World position
uint RTIndex : SV_RenderTargetArrayIndex;// Render Target Array Index
};
ST_GRS_HLSL_GS_IN VSMain(ST_GRS_HLSL_VS_IN stVSInput)
{
ST_GRS_HLSL_GS_IN stVSOutput;
// 从模型空间转换到世界坐标系
stVSOutput.m_v4WPos = mul(stVSInput.m_v4LPos, g_mxWorld);
return stVSOutput;
}
[maxvertexcount(18)]
void GSMain(triangle ST_GRS_HLSL_GS_IN stGSInput[3], inout TriangleStream<ST_GRS_HLSL_GS_OUT> CubeMapStream)
{
for (int f = 0; f < GRS_CUBE_MAP_FACE_CNT; ++f)
{
ST_GRS_HLSL_GS_OUT stGSOutput;
stGSOutput.RTIndex = f; //设定输出的缓冲索引
for (int v = 0; v < 3; v++)
{
stGSOutput.RTIndex = f;
// 下面的乘积是可以优化的,可以提前在 CPP 中 将6个View矩阵分别先与Projection矩阵相乘,再传入Shader
// 当然因为这里是固定的Cube
stGSOutput.m_v4WPos = stGSInput[v].m_v4WPos;
stGSOutput.m_v4HPos = mul(stGSInput[v].m_v4WPos, g_mxGSCubeView[f]);
stGSOutput.m_v4HPos = mul(stGSOutput.m_v4HPos, g_mxProj);
CubeMapStream.Append(stGSOutput);
}
CubeMapStream.RestartStrip();
}
}
\ No newline at end of file
#include "GRS_Scene_CB_Def.hlsli"
struct ST_GRS_HLSL_VS_IN
{
float4 m_v4LPos : POSITION; // Model Local position
};
struct ST_GRS_HLSL_VS_OUT
{
float4 m_v4HPos : SV_POSITION; // Projection coord
float4 m_v4WPos : POSITION; // World position
};
ST_GRS_HLSL_VS_OUT VSMain(ST_GRS_HLSL_VS_IN stVSInput)
{
ST_GRS_HLSL_VS_OUT stVSOutput;
stVSOutput.m_v4WPos = stVSInput.m_v4LPos;
// 从模型空间转换到世界坐标系
stVSOutput.m_v4HPos = mul(stVSInput.m_v4LPos, g_mxWVP);
return stVSOutput;
}
#include "HDR_COLOR_CONV.hlsli"
#include "GRS_PBR_Function.hlsli"
Texture2D g_txHDR : register(t0);
SamplerState g_smpLinear : register(s0);
struct ST_GRS_HLSL_PS_IN
{
float4 m_v4HPos : SV_POSITION; // Projection coord
float4 m_v4WPos : POSITION; // World position
};
float4 PSMain(ST_GRS_HLSL_PS_IN stPSInput) : SV_Target
{
float2 v2UV = SampleSphericalMap(normalize(stPSInput.m_v4WPos.xyz));
return float4(g_txHDR.Sample(g_smpLinear, v2UV).rgb, 1.0f);
}
#include "GRS_PBR_Function.hlsli"
struct ST_GRS_HLSL_VS_IN
{
float4 m_v4LPos : POSITION;
float2 m_v2UV : TEXCOORD;
};
struct ST_GRS_HLSL_VS_OUT
{
float4 m_v4HPos : SV_POSITION;
float2 m_v2UV : TEXCOORD;
};
ST_GRS_HLSL_VS_OUT VSMain(ST_GRS_HLSL_VS_IN stVSIn)
{
ST_GRS_HLSL_VS_OUT stVSOut = (ST_GRS_HLSL_VS_OUT)0.0f;
stVSOut.m_v2UV = stVSIn.m_v2UV;
//to clip space
stVSOut.m_v4HPos = stVSIn.m_v4LPos;
return stVSOut;
}
float2 IntegrateBRDF(float NdotV, float roughness)
{
float3 V;
V.x = sqrt(1.0f - NdotV * NdotV);
V.y = 0.0f;
V.z = NdotV;
float A = 0.0f;
float B = 0.0f;
float3 N = float3(0.0f, 0.0f, 1.0f);
uint SAMPLE_COUNT = GRS_INT_SAMPLES_CNT;
for (uint i = 0; i < SAMPLE_COUNT; ++i)
{
float2 Xi = Hammersley(i, SAMPLE_COUNT);
float3 H = ImportanceSampleGGX(Xi, N, roughness);
float3 L = normalize(2.0 * dot(V, H) * H - V);
float NdotL = max(L.z, 0.0);
float NdotH = max(H.z, 0.0);
float VdotH = max(dot(V, H), 0.0);
if (NdotL > 0.0)
{
float G = GeometrySmith_IBL(N, V, L, roughness);
float G_Vis = (G * VdotH) / (NdotH * NdotV);
float Fc = pow(1.0 - VdotH, 5.0);
A += (1.0 - Fc) * G_Vis;
B += Fc * G_Vis;
}
}
A /= float(SAMPLE_COUNT);
B /= float(SAMPLE_COUNT);
return float2(A, B);
}
float2 PSMain(ST_GRS_HLSL_VS_OUT pin) :SV_TARGET
{
return IntegrateBRDF(pin.m_v2UV.x, pin.m_v2UV.y);
}
\ No newline at end of file
#include "GRS_PBR_Function.hlsli"
TextureCube g_texHDREnvCubemap : register(t0);
SamplerState g_sapLinear : register(s0);
struct ST_GRS_HLSL_PS_INPUT
{
float4 m_v4HPos : SV_POSITION;
float3 m_v4WPos : POSITION;
};
float4 PSMain(ST_GRS_HLSL_PS_INPUT pin):SV_Target
{
float3 N = normalize(pin.m_v4WPos.xyz);
float3 irradiance = float3(0.0f, 0.0f, 0.0f);
float3 up = float3(0.0f, 1.0f, 0.0f);
//float3 right = normalize(cross(N, up));
float3 right = normalize(cross(up, N));
up = normalize(cross(N, right));
//up = normalize(cross(right,N));
N = normalize(cross(right,up));
float nrSamples = 0.0f;
float deltaPhi = (2.0f * PI) / 180.0f;
float deltaTheta = (0.5f * PI) / 90.0f;
// 卷积运算,直接翻译自公式
for (float phi = 0.0f; phi < 2.0f * PI; phi += deltaPhi)
{
for (float theta = 0.0f; theta < 0.5f * PI; theta += deltaTheta)
{
// 球坐标转换到笛卡尔坐标(切空间)
float3 tangentSample = float3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
// 切空间转换到世界坐标空间
float3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N;
//float3 sampleVec = right;
irradiance += (g_texHDREnvCubemap.Sample(g_sapLinear, sampleVec).xyz * cos(theta) * sin(theta));
nrSamples += 1.0f;
}
}
irradiance = PI * irradiance * (1.0 / float(2 * nrSamples));
return float4(irradiance, 1.0f);
}
\ No newline at end of file
#include "GRS_PBR_Function.hlsli"
TextureCube g_texHDREnvCubemap : register(t0);
SamplerState g_sapLinear : register(s0);
struct ST_GRS_HLSL_PS_INPUT
{
float4 m_v4HPos : SV_POSITION;
float3 m_v4WPos : POSITION;
};
float2 UniformOnDisk(float Xi)
{
float theta = TWO_PI * Xi;
return float2(cos(theta), sin(theta));
}
float3 CosOnHalfSphere(float2 Xi)
{
float r = sqrt(Xi.x);
float2 pInDisk = r * UniformOnDisk(Xi.y);
float z = sqrt(1 - Xi.x);
return float3(pInDisk, z);
}
float4 Quarternion_ZTo(float3 to)
{
// from = (0, 0, 1)
//float cosTheta = dot(from, to);
//float cosHalfTheta = sqrt(max(0, (cosTheta + 1) * 0.5));
float cosHalfTheta = sqrt(max(0, (to.z + 1) * 0.5));
//float3 axisSinTheta = cross(from, to);
// 0 0 1
// to.x to.y to.z
//float3 axisSinTheta = float3(-to.y, to.x, 0);
float twoCosHalfTheta = 2 * cosHalfTheta;
return float4(-to.y / twoCosHalfTheta, to.x / twoCosHalfTheta, 0, cosHalfTheta);
}
float4 Quarternion_Inverse(float4 q)
{
return float4(-q.xyz, q.w);
}
float3 Quarternion_Rotate(float4 q, float3 p)
{
// Quarternion_Mul(Quarternion_Mul(q, float4(p, 0)), Quarternion_Inverse(q)).xyz;
float4 qp = float4(q.w * p + cross(q.xyz, p), -dot(q.xyz, p));
float4 invQ = Quarternion_Inverse(q);
float3 qpInvQ = qp.w * invQ.xyz + invQ.w * qp.xyz + cross(qp.xyz, invQ.xyz);
return qpInvQ;
}
float3 CosOnHalfSphere(float2 Xi, float3 N)
{
float3 p = CosOnHalfSphere(Xi);
float4 rot = Quarternion_ZTo(N);
return Quarternion_Rotate(rot, p);
}
float4 PSMain(ST_GRS_HLSL_PS_INPUT stPSInput) :SV_Target
{
float3 N = normalize(stPSInput.m_v4WPos.xyz);
float3 irradiance = float3(0.0f,0.0f,0.0f);
const uint SAMPLE_NUM = GRS_INT_SAMPLES_CNT;
for (uint i = 0u; i < SAMPLE_NUM; i++)
{
float2 Xi = Hammersley(i, SAMPLE_NUM);
float3 L = CosOnHalfSphere(Xi, N);
irradiance += g_texHDREnvCubemap.Sample(g_sapLinear, L).xyz;
}
irradiance *= 1.0 / float(SAMPLE_NUM);
return float4(irradiance,1.0f);
}
\ No newline at end of file
#include "GRS_Scene_CB_Def.hlsli"
#include "GRS_PBR_Function.hlsli"
TextureCube g_texHDREnvCubemap : register(t0);
SamplerState g_sapLinear : register(s0);
struct ST_GRS_HLSL_PS_INPUT
{
float4 m_v4HPos : SV_POSITION;
float3 m_v4WPos : POSITION;
};
float4 PSMain(ST_GRS_HLSL_PS_INPUT pin) : SV_Target
{
float3 N = normalize(pin.m_v4WPos.xyz);
float3 R = N;
float3 V = R;
uint SAMPLE_COUNT = GRS_INT_SAMPLES_CNT;
float3 prefilteredColor = float3(0.0f, 0.0f, 0.0f);
float totalWeight = 0.0f;
for (uint i = 0; i < SAMPLE_COUNT; ++i)
{
// 生成均匀分布的无偏序列(Hammersley)
float2 Xi = Hammersley(i, SAMPLE_COUNT);
// 进行有偏的重要性采样
float3 H = ImportanceSampleGGX(Xi, N, g_fRoughness);
//float3 H = ImportanceSampleGGX(Xi, N, 0.1f);
float3 L = normalize(2.0f * dot(V, H) * H - V);
float NdotL = max(dot(N, L), 0.0f);
if ( NdotL > 0.0f )
{
//float D = DistributionGGX(N, H, roughness);
//float NdotH = max(dot(N, H), 0.0);
//float HdotV = max(dot(H, V), 0.0);
//float pdf = D * NdotH / (4.0 * HdotV) + 0.0001;
//float resolution = 512.0; // resolution of source cubemap (per face)
//float saTexel = 4.0 * PI / (6.0 * resolution * resolution);
//float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001);
//float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel);
//prefilteredColor += textureLod(g_texHDREnvCubemap, L, mipLevel).rgb * NdotL;
//totalWeight += NdotL;
prefilteredColor += g_texHDREnvCubemap.Sample(g_sapLinear, L).rgb * NdotL;
totalWeight += NdotL;
}
}
prefilteredColor = prefilteredColor / totalWeight;
return float4(prefilteredColor, 1.0f);
}
\ No newline at end of file
#define PI 3.14159265359
#define TWO_PI 6.28318530718
#define FOUR_PI 12.56637061436
#define FOUR_PI2 39.47841760436
#define INV_PI 0.31830988618
#define INV_TWO_PI 0.15915494309
#define INV_FOUR_PI 0.07957747155
#define HALF_PI 1.57079632679
#define INV_HALF_PI 0.636619772367
#define GRS_INT_SAMPLES_CNT 2048u
float RadicalInverse_VdC(uint bits)
{
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
}
float2 Hammersley(uint i, uint N)
{
return float2(float(i) / float(N), RadicalInverse_VdC(i));
}
// 等距柱状投影 转换到 Cube Map 的纹理坐标系
// 下面这段直接来自OpenGL的教程
//static const float2 invAtan = float2(0.1591, 0.3183);
//
//float2 SampleSphericalMap(float3 v)
//{
// //float2 v2UV = float2(atan(v.z/v.x), asin(v.y));
// float2 v2UV = float2(atan2(v.z, v.x), asin(v.y));
// v2UV *= invAtan;
// v2UV += 0.5;
// return v2UV;
//}
// 下面这个是修正后的版本
float2 SampleSphericalMap(float3 coord)
{
float theta = acos(coord.y);
float phi = atan2(coord.x, coord.z);
phi += (phi < 0) ? 2 * PI : 0;
float u = phi * 0.1591f;
float v = theta * 0.3183f;
return float2(u, v);
}
float DistributionGGX(float3 N, float3 H, float roughness)
{
float a = roughness * roughness;
float a2 = a * a;
float NdotH = max(dot(N, H), 0.0f);
float NdotH2 = NdotH * NdotH;
float nom = a2;
float denom = (NdotH2 * (a2 - 1.0f) + 1.0f);
denom = PI * denom / denom;
return nom / denom;
}
float GeometrySchlickGGX_DirectLight(float NdotV, float roughness)
{// Point Light Versions
float r = (roughness + 1.0);
float k = (r * r) / 8.0;
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
float GeometrySchlickGGX_IBL(float NdotV, float roughness)
{// IBL Versions
float a = roughness;
float k = (a * a) / 2.0f;
float nom = NdotV;
float denom = NdotV * (1.0f - k) + k;
return nom / denom;
}
float GeometrySmith_DirectLight(float3 N, float3 V, float3 L, float roughness)
{
float NdotV = max(dot(N, V), 0.0f);
float NdotL = max(dot(N, L), 0.0f);
float ggx2 = GeometrySchlickGGX_DirectLight(NdotV, roughness);
float ggx1 = GeometrySchlickGGX_DirectLight(NdotL, roughness);
return ggx1 * ggx2;
}
float GeometrySmith_IBL(float3 N, float3 V, float3 L, float roughness)
{
float NdotV = max(dot(N, V), 0.0f);
float NdotL = max(dot(N, L), 0.0f);
float ggx2 = GeometrySchlickGGX_IBL(NdotV, roughness);
float ggx1 = GeometrySchlickGGX_IBL(NdotL, roughness);
return ggx1 * ggx2;
}
float3 FresnelSchlick(float cosTheta, float3 F0)
{
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
}
float3 FresnelSchlickRoughness(float cosTheta, float3 F0, float roughness)
{
return F0 + (max(float3(1.0 - roughness, 1.0 - roughness, 1.0 - roughness), F0) - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
}
float3 ImportanceSampleGGX(float2 Xi, float3 N, float roughness)
{
float a = roughness * roughness;
float phi = 2.0f * PI * Xi.x;
float cosTheta = sqrt((1.0f - Xi.y) / (1.0f + (a * a - 1.0f) * Xi.y));
float sinTheta = sqrt(1.0f - cosTheta * cosTheta);
float3 H;
H.x = cos(phi) * sinTheta;
H.y = sin(phi) * sinTheta;
H.z = cosTheta;
float3 up = abs(N.z) < 0.999 ? float3(0.0f, 0.0f, 1.0f) : float3(1.0f, 0.0f, 0.0f);
float3 tangent = normalize(cross(up, N));
float3 bitangent = cross(N, tangent);
float3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
return normalize(sampleVec);
}
\ No newline at end of file
#include "GRS_Scene_CB_Def.hlsli"
#include "GRS_PBR_Function.hlsli"
#include "HDR_COLOR_CONV.hlsli"
SamplerState g_sapLinear : register(s0);
TextureCube g_texSpecularCubemap : register(t0);
TextureCube g_texDiffuseCubemap : register(t1);
Texture2D g_texLut : register(t2);
struct ST_GRS_HLSL_PBR_PS_INPUT
{
float4 m_v4HPos : SV_POSITION;
float4 m_v4WPos : POSITION;
float4 m_v4WNormal : NORMAL;
float2 m_v2UV : TEXCOORD;
float4x4 m_mxModel2World : WORLD;
float3 m_v3Albedo : COLOR0; // 反射率
float m_fMetallic : COLOR1; // 金属度
float m_fRoughness : COLOR2; // 粗糙度
float m_fAO : COLOR3; // 环境遮挡因子
};
float4 PSMain(ST_GRS_HLSL_PBR_PS_INPUT stPSInput): SV_TARGET
{
float3 N = stPSInput.m_v4WNormal.xyz;
float3 V = normalize(g_v4EyePos.xyz - stPSInput.m_v4WPos.xyz);
float3 R = reflect(-V, N);
float3 F0 = float3(0.04f, 0.04f, 0.04f);
F0 = lerp(F0, stPSInput.m_v3Albedo, stPSInput.m_fMetallic);
float3 Lo = float3(0.0f,0.0f,0.0f);
// 首先按照之前的样子计算直接光照的效果
for (int i = 0; i < GRS_LIGHT_COUNT; ++i)
{
// 计算点光源的照射
// 因为是多实例渲染,所以对每个光源做下位置变换,这样相当于每个实例有了自己的光源
// 注意这不是标准操作,一定要注意正式的代码中不要这样做
float4 v4LightWorldPos = mul(g_v4LightPos[i], stPSInput.m_mxModel2World);
v4LightWorldPos = mul(v4LightWorldPos, g_mxWorld);
float3 L = normalize(v4LightWorldPos.xyz - stPSInput.m_v4WPos.xyz);
float3 H = normalize(V + L);
float distance = length(v4LightWorldPos.xyz - stPSInput.m_v4WPos.xyz);
float attenuation = 1.0 / (distance * distance); // 距离平方衰减
float3 radiance = g_v4LightColors[i].rgb * attenuation;
// Cook-Torrance BRDF
float NDF = DistributionGGX(N, H, stPSInput.m_fRoughness);
float G = GeometrySmith_DirectLight(N, V, L, stPSInput.m_fRoughness);
float3 F = FresnelSchlick(max(dot(H, V), 0.0), F0);
float3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; // + 0.0001 to prevent divide by zero
float3 specular = numerator / denominator;
float3 kS = F;
float3 kD = float3(1.0f,1.0f,1.0f) - kS;
kD *= 1.0 - stPSInput.m_fMetallic;
float NdotL = max(dot(N, L), 0.0f);
Lo += (kD * stPSInput.m_v3Albedo / PI + specular) * radiance * NdotL; // note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again
}
// 接着开始利用前面的预积分结果计算IBL光照的效果
// IBL漫反射环境光部分
float3 F = FresnelSchlickRoughness(max(dot(N, V), 0.0), F0, stPSInput.m_fRoughness);
float3 kS = F;
float3 kD = 1.0 - kS;
kD *= 1.0 - stPSInput.m_fMetallic;
float3 irradiance = g_texDiffuseCubemap.Sample(g_sapLinear, N).rgb;
float3 diffuse = irradiance * stPSInput.m_v3Albedo;
// IBL镜面反射环境光部分
const float MAX_REFLECTION_LOD = 4.0;
float3 prefilteredColor = g_texSpecularCubemap.SampleLevel(g_sapLinear, R, stPSInput.m_fRoughness * MAX_REFLECTION_LOD).rgb;
float2 brdf = g_texLut.Sample(g_sapLinear, float2(max(dot(N, V), 0.0), stPSInput.m_fRoughness)).rg;
float3 specular = prefilteredColor * (F * brdf.x + brdf.y);
// IBL 光照合成
float3 ambient = (kD * diffuse + specular) * stPSInput.m_fAO;
// 直接光照 + IBL光照
float3 color = ambient + Lo;
// Gamma
//return float4(color, 1.0f);
return float4(LinearToSRGB(color),1.0f);
}
\ No newline at end of file
// Multi-Instance PBR IBL Vertex Shader
#include "GRS_Scene_CB_Def.hlsli"
struct ST_GRS_HLSL_PBR_VS_INPUT
{
float4 m_v4LPos : POSITION;
float4 m_v4LNormal : NORMAL;
float2 m_v2UV : TEXCOORD;
float4x4 m_mxModel2World : WORLD;
float4 m_v4Albedo : COLOR0; // 反射率
float m_fMetallic : COLOR1; // 金属度
float m_fRoughness : COLOR2; // 粗糙度
float m_fAO : COLOR3; // 环境遮挡因子
uint m_nInstanceId : SV_InstanceID;
};
struct ST_GRS_HLSL_PBR_PS_INPUT
{
float4 m_v4HPos : SV_POSITION;
float4 m_v4WPos : POSITION;
float4 m_v4WNormal : NORMAL;
float2 m_v2UV : TEXCOORD;
float4x4 m_mxModel2World : WORLD;
float3 m_v3Albedo : COLOR0; // 反射率
float m_fMetallic : COLOR1; // 金属度
float m_fRoughness : COLOR2; // 粗糙度
float m_fAO : COLOR3; // 环境遮挡因子
};
ST_GRS_HLSL_PBR_PS_INPUT VSMain(ST_GRS_HLSL_PBR_VS_INPUT stVSInput)
{
ST_GRS_HLSL_PBR_PS_INPUT stVSOutput;
// 先按每个实例将物体变换到世界坐标系中
stVSOutput.m_v4HPos = mul(stVSInput.m_v4LPos, stVSInput.m_mxModel2World);
// 再进行世界坐标系整体变换,得到最终世界坐标系中的坐标
stVSOutput.m_v4WPos = mul(stVSOutput.m_v4HPos, g_mxWorld);
// 变换到视-投影空间中
stVSOutput.m_v4HPos = mul(stVSOutput.m_v4HPos, g_mxWVP);
// 向量先变换到世界坐标系中,再进行世界坐标变换
stVSInput.m_v4LNormal.w = 0.0f;
stVSOutput.m_v4WNormal = mul(stVSInput.m_v4LNormal, stVSInput.m_mxModel2World);
stVSInput.m_v4LNormal.w = 0.0f;
stVSOutput.m_v4WNormal = mul(stVSInput.m_v4LNormal, g_mxWorld);
stVSInput.m_v4LNormal.w = 0.0f;
stVSOutput.m_v4WNormal = normalize(stVSOutput.m_v4WNormal);
stVSOutput.m_mxModel2World = stVSInput.m_mxModel2World;
stVSOutput.m_v2UV = stVSInput.m_v2UV;
stVSOutput.m_v3Albedo = stVSInput.m_v4Albedo.xyz;
stVSOutput.m_fMetallic = stVSInput.m_fMetallic;
stVSOutput.m_fRoughness = stVSInput.m_fRoughness;
stVSOutput.m_fAO = stVSInput.m_fAO;
return stVSOutput;
}
\ No newline at end of file
#include "HDR_COLOR_CONV.hlsli"
#include "GRS_Scene_CB_Def.hlsli"
Texture2D g_Texture2DArray[] : register(t0);
SamplerState g_smpLinear : register(s0);
struct ST_GRS_HLSL_VS_IN
{
float4 m_v4LPosition : POSITION;
float4 m_v4Color : COLOR0;
float2 m_v2UV : TEXCOORD;
float4x4 m_mxQuad2World : WORLD;
uint m_nTextureIndex : COLOR1;
};
struct ST_GRS_HLSL_PS_IN
{
float4 m_v4Position : SV_POSITION;
float4 m_v4Color : COLOR0;
float2 m_v2UV : TEXCOORD;
uint m_nTextureIndex : COLOR1;
};
ST_GRS_HLSL_PS_IN VSMain( ST_GRS_HLSL_VS_IN stVSInput )
{
ST_GRS_HLSL_PS_IN stVSOutput;
stVSOutput.m_v4Position = mul(stVSInput.m_v4LPosition, stVSInput.m_mxQuad2World);
// 下面两句是二选一,一般2D渲染的时候 World 和 View 矩阵都取了单位矩阵,但不排除特殊情况,所以一般还是乘以MVP综合矩阵
//stVSOutput.m_v4Position = mul(stVSOutput.m_v4Position, g_mxProj);
stVSOutput.m_v4Position = mul(stVSOutput.m_v4Position, g_mxWVP);
stVSOutput.m_v4Color = stVSInput.m_v4Color;
stVSOutput.m_v2UV = stVSInput.m_v2UV;
stVSOutput.m_nTextureIndex = stVSInput.m_nTextureIndex;
return stVSOutput;
}
float4 PSMain(ST_GRS_HLSL_PS_IN stPSInput) : SV_TARGET
{
return float4(g_Texture2DArray[stPSInput.m_nTextureIndex].Sample(g_smpLinear, stPSInput.m_v2UV).rgb,1.0f);
}
#define GRS_CUBE_MAP_FACE_CNT 6
#define GRS_LIGHT_COUNT 4
cbuffer CB_GRS_SCENE_MATRIX : register(b0)
{
matrix g_mxWorld;
matrix g_mxView;
matrix g_mxProj;
matrix g_mxWorldView;
matrix g_mxWVP;
matrix g_mxInvWVP;
matrix g_mxVP;
matrix g_mxInvVP;
};
cbuffer CB_GRS_GS_VIEW_MATRIX : register(b1)
{
matrix g_mxGSCubeView[GRS_CUBE_MAP_FACE_CNT]; // View matrices for cube map rendering
};
// Camera
cbuffer CB_GRS_SCENE_CAMERA : register(b2)
{
float4 g_v4EyePos;
float4 g_v4LookAt;
float4 g_v4UpDir ;
}
// lights
cbuffer CB_GRS_SCENE_LIGHTS : register(b3)
{
float4 g_v4LightPos[GRS_LIGHT_COUNT];
float4 g_v4LightColors[GRS_LIGHT_COUNT];
};
// Material
cbuffer CB_GRS_PBR_MATERIAL : register(b4)
{
float g_fMetallic; // 金属度
float g_fRoughness; // 粗糙度
float g_fAO; // 环境遮挡系数
float4 g_v4Albedo; // 反射率
};
#include "HDR_COLOR_CONV.hlsli"
#include "GRS_Scene_CB_Def.hlsli"
#include "GRS_PBR_Function.hlsli"
Texture2D g_txSphericalMap : register(t0);
SamplerState g_smpLinear : register(s0);
struct ST_GRS_HLSL_VS_IN
{
float4 m_v4LPos : POSITION;
};
struct ST_GRS_HLSL_PS_IN
{
float4 m_v4LPos : SV_POSITION;
float4 m_v4PPos : TEXCOORD0;
};
ST_GRS_HLSL_PS_IN SkyboxVS(ST_GRS_HLSL_VS_IN stVSInput)
{
ST_GRS_HLSL_PS_IN stVSOutput;
stVSOutput.m_v4LPos = stVSInput.m_v4LPos;
stVSOutput.m_v4PPos = normalize(mul(stVSInput.m_v4LPos, g_mxInvVP));
return stVSOutput;
}
float4 SkyboxPS(ST_GRS_HLSL_PS_IN stPSInput) : SV_TARGET
{
float2 v2UV = SampleSphericalMap(normalize(stPSInput.m_v4PPos.xyz));
return float4(g_txSphericalMap.Sample(g_smpLinear, v2UV).rgb,1.0f);
}
<?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>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{469021d1-daec-4efb-8a1e-a148a1e4ef20}</ProjectGuid>
<RootNamespace>My26NormalMapAndTangentSpace</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>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</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" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)include\;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)Lib\;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)include\;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)Lib\;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<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>Windows</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>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Commons\GRS_Assimp_Loader.cpp" />
<ClCompile Include="..\Commons\GRS_Assimp_Loader_For_DX12.cpp" />
<ClCompile Include="26-Normal-Map-And-Tangent-Space.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Commons\GRS_Assimp_Loader.h" />
<ClInclude Include="..\Commons\GRS_Assimp_Loader_For_DX12.h" />
</ItemGroup>
<ItemGroup>
<None Include="Shader\GRS_Normal_Map_CB_Def.hlsli">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</None>
</ItemGroup>
<ItemGroup>
<FxCompile Include="Shader\GRS_Normal_Map_PS_2_World_Space.hlsl">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="Shader\GRS_Normal_Map_VS_2_World_Space.hlsl">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</FxCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?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>
<Filter Include="Shader">
<UniqueIdentifier>{9a3db02e-3fa4-409e-802a-8912d8f92590}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="26-Normal-Map-And-Tangent-Space.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\Commons\GRS_Assimp_Loader_For_DX12.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\Commons\GRS_Assimp_Loader.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Commons\GRS_Assimp_Loader_For_DX12.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\Commons\GRS_Assimp_Loader.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="Shader\GRS_Normal_Map_CB_Def.hlsli">
<Filter>Shader</Filter>
</None>
</ItemGroup>
<ItemGroup>
<FxCompile Include="Shader\GRS_Normal_Map_PS_2_World_Space.hlsl">
<Filter>Shader</Filter>
</FxCompile>
<FxCompile Include="Shader\GRS_Normal_Map_VS_2_World_Space.hlsl">
<Filter>Shader</Filter>
</FxCompile>
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
\ No newline at end of file
cbuffer CB_GRS_SCENE_MATRIX : register(b0)
{
matrix g_mxModel; // Model self
matrix g_mxInvModel; // Inverse Model
matrix g_mxModel2World; // Model -> World (Sacle -> Rotate -> Displacement;
matrix g_mxInvModel2World; // Inverse Model -> World <=> World -> Model
matrix g_mxWorld; // World self
matrix g_mxView; // View self
matrix g_mxProj; // Proj self
matrix g_mxWorldView; // World * View
matrix g_mxWVP; // World * View * Proj
matrix g_mxInvWVP; // Inverse WVP
matrix g_mxVP; // View * Proj
matrix g_mxInvVP; // Inverse VP
};
// Camera
cbuffer CB_GRS_SCENE_CAMERA : register(b1)
{
float4 g_v4EyePos;
float4 g_v4LookAt;
float4 g_v4UpDir;
}
// lights
cbuffer CB_GRS_SCENE_LIGHTS : register(b2)
{
float4 g_v4LightPos;
float4 g_v4LightColors;
};
\ No newline at end of file
#include "GRS_Normal_Map_CB_Def.hlsli"
struct ST_GRS_HLSL_PS_INPUT
{
float4 m_v4HPos : SV_POSITION;
float4 m_v4WPos : POSITION;
float2 m_v2UV : TEXCOORD;
float3 m_v3WTangent : COLOR0;
float3 m_v3WBitangent : COLOR1;
float3 m_v3WNormal : COLOR2;
};
Texture2D g_texColor : register(t0); // BaseColor)
Texture2D g_texNormal : register(t1); //
SamplerState g_sapLinear : register(s0);
float4 PSMain(ST_GRS_HLSL_PS_INPUT stPSInput) : SV_TARGET
{
// ط
float3 N = g_texNormal.Sample(g_sapLinear, stPSInput.m_v2UV).xyz;
N = 2.0f * N - 1.0f;
//N.y = -N.y; // for Opengl Normal Map Texture
N = normalize(N);
float3x3 mxTBN= { stPSInput.m_v3WTangent , stPSInput.m_v3WBitangent, stPSInput.m_v3WNormal };
N = normalize(mul(N,mxTBN));
float3 v3LightDir = normalize( g_v4LightPos.xyz - stPSInput.m_v4WPos.xyz );
float3 v3ViewDir = normalize( g_v4EyePos.xyz - stPSInput.m_v4WPos.xyz );
//return float4(N, 1.0f);
// Base Color
float3 v3Color = g_texColor.Sample(g_sapLinear, stPSInput.m_v2UV).rgb;
// Ambient
float3 v3Ambient = 0.1 * v3Color;
// Diffuse
float fFiff = max(dot(v3LightDir, N), 0.0);
float3 v3Diffuse = fFiff * v3Color;
// Specular
float3 v3ReflectDir = reflect(-v3LightDir, N);
float3 v3HalfwayDir = normalize(v3LightDir + v3ViewDir);
float fSpec = pow(max(dot(N, v3HalfwayDir), 0.0), 32.0);
float3 v3Specular = float3(0.2f,0.2f,0.2f) * fSpec;
return float4(v3Ambient + v3Diffuse + v3Specular, 1.0f);
}
\ No newline at end of file
#include "GRS_Normal_Map_CB_Def.hlsli"
struct ST_GRS_HLSL_VS_INPUT
{
float4 m_v4LPos : POSITION;
float4 m_v4LNormal : NORMAL;
float2 m_v2UV : TEXCOORD;
float4 m_v4LTangent : TANGENT;
};
struct ST_GRS_HLSL_VS_OUTPUT
{
float4 m_v4HPos : SV_POSITION;
float4 m_v4WPos : POSITION;
float2 m_v2UV : TEXCOORD;
float3 m_v3WTangent : COLOR0;
float3 m_v3WBitangent : COLOR1;
float3 m_v3WNormal : COLOR2;
};
ST_GRS_HLSL_VS_OUTPUT VSMain(ST_GRS_HLSL_VS_INPUT stVSInput)
{
ST_GRS_HLSL_VS_OUTPUT stVSOutput;
stVSOutput.m_v4HPos = mul(stVSInput.m_v4LPos, g_mxModel2World);
stVSOutput.m_v4HPos = mul(stVSOutput.m_v4HPos, g_mxWVP);
stVSOutput.m_v4WPos = mul(stVSInput.m_v4LPos, g_mxModel2World);
stVSOutput.m_v4WPos = mul(stVSOutput.m_v4WPos, g_mxWorld);
stVSOutput.m_v2UV = stVSInput.m_v2UV;
// 施密特正交法计算切空间的TBN基坐标
stVSInput.m_v4LTangent.w = 0.0f;
stVSOutput.m_v3WTangent
= normalize(mul(stVSInput.m_v4LTangent, g_mxModel2World).xyz);
stVSInput.m_v4LNormal.w = 0.0f;
stVSOutput.m_v3WNormal
= normalize(mul(stVSInput.m_v4LNormal, g_mxModel2World).xyz);
stVSOutput.m_v3WTangent
= normalize(stVSOutput.m_v3WTangent - dot(stVSOutput.m_v3WTangent, stVSOutput.m_v3WNormal) * stVSOutput.m_v3WNormal);
stVSOutput.m_v3WBitangent
= normalize(cross(stVSOutput.m_v3WTangent, stVSOutput.m_v3WNormal));
return stVSOutput;
}
[Header]
ICOfile = "Mono_Lake_C_Thumb.jpg"
PREVIEWfile = "Mono_Lake_C_preview.jpg"
Name = "Mono Lake C"
Author = "Blochi"
Location = "California"
Comment = "in the shade of a tufa stone, by the water, rocks"
GEOlat = 37.9774919277906
GEOlong = -119.10999298095703
Link = "http://www.hdrlabs.com/sibl/archive.html"
Date = "2006:11:25"
Time = "14:30:00"
Height = 0.7
North = 0.62
[Background]
; beware of the 32 MegaPixels
BGfile = "Mono_Lake_C_HiRes.jpg"
BGmap = 1
BGu = 0.000000
BGv = 0.000000
BGheight = 4000
[Enviroment]
EVfile = "Mono_Lake_C_Env.hdr"
EVmap = 1
EVu = 0.000000
EVv = 0.000000
EVheight = 180
EVmulti = 1.000000
EVgamma = 1.800000
[Reflection]
REFfile = "Mono_Lake_C_Ref.hdr"
REFmap = 1
REFu = 0.000000
REFv = 0.000000
REFheight = 800
REFmulti = 1.000000
REFgamma = 1.800000
此差异已折叠。
此差异已折叠。
[Header]
ICOfile = "Tropical_Beach_thumb.jpg"
Name = "Tropical Beach"
Author = "Blochi"
Location = "Barbados"
Comment = "High noon at Bottom Bay, the most beautiful hidden beach in Barbados"
GEOlat = 13.1360692977777770
GEOlong = -59.4246902466666640
Link = "www.hdrlabs.com/sibl/archive.html"
Date = "2011:03:01"
Time = "12:30:00"
Height = 1.600000
[Background]
; boosted colors to look nicer
BGfile = "Tropical_Beach_8k.jpg"
BGmap = 1
BGu = 0.000000
BGv = 0.000000
BGheight = 4096
[Enviroment]
EVfile = "Tropical_Beach_Env.hdr"
EVmap = 1
EVu = 0.000000
EVv = 0.000000
EVheight = 180
EVmulti = 1.000000
EVgamma = 2.000000
[Reflection]
REFfile = "Tropical_Beach_3k.hdr"
REFmap = 1
REFu = 0.000000
REFv = 0.000000
REFheight = 1800
REFmulti = 1.000000
REFgamma = 2.000000
[Light1]
LIGHTname = "Sun"
LIGHTcolor = 255,252,245
LIGHTmulti = 1.200000
LIGHTu = 0.788000
LIGHTv = 0.144000
此差异已折叠。
因为 它太大了无法显示 image diff 。你可以改为 查看blob
此差异已折叠。
[Header]
ICOfile = "testgrid_icon.jpg"
Name = "UV-Testgrid"
Author = ""
Location = ""
Comment = "edit the .ibl file to test various sun positions"
[Background]
BGfile = "testgrid.jpg"
BGmap = 1
BGu = 0.000000
BGv = 0.000000
BGheight = 800
[Enviroment]
EVfile = "testgrid.jpg"
EVmap = 1
EVu = 0.000000
EVv = 0.000000
EVheight = 800
EVmulti = 1.000000
EVgamma = 1.000000
[Reflection]
REFfile = "testgrid.jpg"
REFmap = 1
REFu = 0.000000
REFv = 0.000000
REFheight = 800
REFmulti = 1.000000
REFgamma = 1.000000
[Sun]
SUNcolor = 255,255,255
SUNmulti = 1.000000
SUNu = 0.250000
SUNv = 0.500000
因为 它太大了无法显示 image diff 。你可以改为 查看blob
此差异已折叠。
[Header]
ICOfile = "WinterForest_thumb.jpg"
PREVIEWfile = "WinterForest_preview.jpg"
Name = "Winter Forest"
Author = "Blochi"
Location = "Slovakia"
Comment = "Snow on all trees, deep in the fairy tale forest, overcast skylight only"
GEOlat = 48.3323043999999980
GEOlong = 17.4495843000000010
Link = "www.hdrlabs.com/sibl/"
Date = "2007:12:31"
Time = "17:00:00"
Height = 1.600000
[Background]
BGfile = "WinterForest_8k.jpg"
BGmap = 1
BGu = 0.000000
BGv = 0.000000
BGheight = 4096
[Enviroment]
EVfile = "WinterForest_Env.hdr"
EVmap = 1
EVu = 0.000000
EVv = 0.000000
EVheight = 180
EVmulti = 1.000000
EVgamma = 1.800000
[Reflection]
REFfile = "WinterForest_Ref.hdr"
REFmap = 1
REFu = 0.000000
REFv = 0.000000
REFheight = 2048
REFmulti = 1.000000
REFgamma = 1.800000
此差异已折叠。
#pragma once
#include <SDKDDKVer.h>
#include <tchar.h>
#define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料
#include <windows.h>
#include <strsafe.h>
#include <atlconv.h>
#include <atlcoll.h>
#include <atlstr.h>
#include <d3dcompiler.h>
#include "GRS_Mem.h"
#define GRS_FILE_IS_EXIST(f) (INVALID_FILE_ATTRIBUTES != ::GetFileAttributes(f))
#ifndef GRS_SAFE_CLOSEFILE
//安全关闭一个文件句柄
#define GRS_SAFE_CLOSEFILE(h) if(INVALID_HANDLE_VALUE != (h)){::CloseHandle(h);(h)=INVALID_HANDLE_VALUE;}
#endif // !GRS_SAFE_CLOSEFILE
// 强制D3DCompiler搜索标准的Include目录,通常这也没啥用,只是保留记得有这么个设置即可
#ifndef D3D_COMPILE_STANDARD_FILE_INCLUDE
#define D3D_COMPILE_STANDARD_FILE_INCLUDE ((ID3DInclude*)(UINT_PTR)1)
#endif
typedef CAtlArray<CAtlString> CStringList;
class CGRSD3DCompilerInclude final : public ID3DInclude
{
protected:
CStringList m_DirList;
public:
CGRSD3DCompilerInclude(LPCTSTR pszDir)
{
AddDir(pszDir);
}
virtual ~CGRSD3DCompilerInclude()
{
}
public:
VOID AddDir(LPCTSTR pszDir)
{
CString strDir(pszDir);
if ( ( strDir.GetLength() > 0 ) )
{ //非空路径
if (_T('\\') == strDir[strDir.GetLength() - 1])
{
strDir.SetAt(strDir.GetLength() - 1, _T('\0'));
}
for ( size_t i = 0; i < m_DirList.GetCount(); i++ )
{
if ( m_DirList[i] == strDir )
{// 已经存在不用再添加了
return;
}
}
m_DirList.Add(strDir);
}
}
public:
STDMETHOD(Open)(THIS_ D3D_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID* ppData, UINT* pBytes) override
{
HANDLE hFile = INVALID_HANDLE_VALUE;
VOID* pFileData = nullptr;
*ppData = nullptr;
HRESULT _hrRet = S_OK;
try
{
CString strFileName(pFileName);
TCHAR pszFullFileName[MAX_PATH] = {};
for (size_t i = 0; i < m_DirList.GetCount(); i++)
{
HRESULT hr = ::StringCchPrintf(pszFullFileName
, MAX_PATH
, _T("%s\\%s")
, m_DirList[i].GetBuffer()
, strFileName.GetBuffer() );
if ( FAILED(hr) )
{
AtlThrow(hr);
}
if ( !GRS_FILE_IS_EXIST(pszFullFileName) )
{
// 记录下这个错误,直到最后真找不到那么就作为最后的错误码返回
_hrRet = HRESULT_FROM_WIN32(::GetLastError());
continue;
}
hFile = ::CreateFile(pszFullFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if ( INVALID_HANDLE_VALUE == hFile )
{
AtlThrowLastWin32();
}
DWORD dwFileSize = ::GetFileSize(hFile, NULL);//Include文件一般不会超过4G大小,所以......
if (INVALID_FILE_SIZE == dwFileSize)
{
AtlThrowLastWin32();
}
VOID* pFileData = GRS_CALLOC(dwFileSize);
if (nullptr == pFileData)
{
AtlThrowLastWin32();
}
if (!::ReadFile(hFile, pFileData, dwFileSize, (LPDWORD)pBytes, NULL))
{
AtlThrowLastWin32();
}
GRS_SAFE_CLOSEFILE(hFile);
*ppData = pFileData;
_hrRet = S_OK;
break;
}
}
catch (CAtlException& e)
{
GRS_SAFE_CLOSEFILE(hFile);
GRS_SAFE_FREE(pFileData);
_hrRet = e.m_hr;
}
GRS_SAFE_CLOSEFILE(hFile);
return _hrRet;
}
STDMETHOD(Close)(THIS_ LPCVOID pData) override
{
GRS_FREE((VOID*)pData);
return S_OK;
}
};
\ No newline at end of file
#include "GRS_Assimp_Loader.h"
#pragma comment(lib, "assimp-vc142-mtd.lib")
#define GRS_USEPRINTFA() CHAR pBuf[1024] = {};
#define GRS_TRACEA(...) \
StringCchPrintfA(pBuf,1024,__VA_ARGS__);\
......@@ -7,14 +9,17 @@
static Assimp::Importer g_aiImporter;
BOOL LoadMesh(LPCSTR pszFileName, ST_GRS_MESH_DATA& stMeshData)
BOOL LoadMesh(LPCSTR pszFileName, ST_GRS_MESH_DATA& stMeshData,UINT nFlags)
{
stMeshData.m_nCurrentAnimIndex = 0;
stMeshData.m_paiModel = g_aiImporter.ReadFile(pszFileName, ASSIMP_LOAD_FLAGS);
stMeshData.m_paiModel = g_aiImporter.ReadFile(pszFileName, nFlags);
if (nullptr == stMeshData.m_paiModel)
if ( nullptr == stMeshData.m_paiModel )
{
ATLTRACE("无法解析文件(%s):%s (%d)\n", pszFileName, g_aiImporter.GetErrorString(), ::GetLastError());
ATLTRACE("无法解析文件(%s):%s (%d)\n"
, pszFileName
, g_aiImporter.GetErrorString()
, ::GetLastError());
return FALSE;
}
......@@ -42,34 +47,74 @@ BOOL LoadMesh(LPCSTR pszFileName, ST_GRS_MESH_DATA& stMeshData)
{
paiSubMesh = stMeshData.m_paiModel->mMeshes[i];
stMeshData.m_arSubMeshInfo[i].m_nMaterialIndex = paiSubMesh->mMaterialIndex;
stMeshData.m_arSubMeshInfo[i].m_nNumIndices = paiSubMesh->mNumFaces * GRS_INDICES_PER_FACE;
stMeshData.m_arSubMeshInfo[i].m_nBaseVertex = nNumVertices;
stMeshData.m_arSubMeshInfo[i].m_nBaseIndex = nNumIndices;
stMeshData.m_arSubMeshInfo[i].m_nMaterialIndex = paiSubMesh->mMaterialIndex;
stMeshData.m_arSubMeshInfo[i].m_nNumIndices = paiSubMesh->mNumFaces * GRS_INDICES_PER_FACE;
stMeshData.m_arSubMeshInfo[i].m_nBaseVertex = nNumVertices;
stMeshData.m_arSubMeshInfo[i].m_nBaseIndex = nNumIndices;
stMeshData.m_arSubMeshInfo[i].m_bHasPosition = paiSubMesh->HasPositions();
stMeshData.m_arSubMeshInfo[i].m_bHasNormal = paiSubMesh->HasNormals();
stMeshData.m_arSubMeshInfo[i].m_bHasTexCoords = paiSubMesh->HasTextureCoords(0);
stMeshData.m_arSubMeshInfo[i].m_bHasTangent = paiSubMesh->HasTangentsAndBitangents();
// 当前Mesh的顶点数量和索引数量累加后,就是下个Mesh顶点和索引在整体缓冲中的索引开始位置
nNumVertices += stMeshData.m_paiModel->mMeshes[i]->mNumVertices;
nNumIndices += stMeshData.m_arSubMeshInfo[i].m_nNumIndices;
// 加载顶点常规数据
for (UINT j = 0; j < paiSubMesh->mNumVertices; j++)
for ( UINT j = 0; j < paiSubMesh->mNumVertices; j++ )
{
stMeshData.m_arPositions.Add(XMFLOAT4(paiSubMesh->mVertices[j].x
, paiSubMesh->mVertices[j].y
, paiSubMesh->mVertices[j].z
, 1.0f));
if ( stMeshData.m_arSubMeshInfo[i].m_bHasPosition )
{
stMeshData.m_arPositions.Add(XMFLOAT4(paiSubMesh->mVertices[j].x
, paiSubMesh->mVertices[j].y
, paiSubMesh->mVertices[j].z
, 1.0f));
}
else
{
stMeshData.m_arPositions.Add(XMFLOAT4(0.0f,0.0f,0.0f,1.0f));
}
stMeshData.m_arNormals.Add(XMFLOAT4(paiSubMesh->mNormals[j].x
, paiSubMesh->mNormals[j].y
, paiSubMesh->mNormals[j].z
, 0.0f));
if( stMeshData.m_arSubMeshInfo[i].m_bHasNormal )
{
stMeshData.m_arNormals.Add(XMFLOAT4(paiSubMesh->mNormals[j].x
, paiSubMesh->mNormals[j].y
, paiSubMesh->mNormals[j].z
, 0.0f));
}
else
{
stMeshData.m_arNormals.Add(XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f));
}
// 注意这个地方只考虑一个纹理的情况,其实最多可以有八个,可以再做个循环进行加载
const aiVector3D* pTexCoord = paiSubMesh->HasTextureCoords(0)
? &(paiSubMesh->mTextureCoords[0][j])
: &Zero3D;
if ( stMeshData.m_arSubMeshInfo[i].m_bHasTangent )
{
stMeshData.m_arTangent.Add(XMFLOAT4( paiSubMesh->mTangents[j].x
, paiSubMesh->mTangents[j].y
, paiSubMesh->mTangents[j].z
, 0.0f));
stMeshData.m_arBitangent.Add(XMFLOAT4(paiSubMesh->mBitangents[j].x
, paiSubMesh->mBitangents[j].y
, paiSubMesh->mBitangents[j].z
, 0.0f));
}
else
{
stMeshData.m_arTangent.Add(XMFLOAT4(0.0f,0.0f,0.0f, 0.0f));
stMeshData.m_arBitangent.Add(XMFLOAT4(0.0f,0.0f,0.0f, 0.0f));
}
stMeshData.m_arTexCoords.Add(XMFLOAT2(pTexCoord->x, pTexCoord->y));
// 注意这个地方只考虑一个纹理的情况,其实最多可以有八个,可以再做个循环进行加载
if ( stMeshData.m_arSubMeshInfo[i].m_bHasTexCoords )
{
stMeshData.m_arTexCoords.Add(XMFLOAT2(paiSubMesh->mTextureCoords[0][j].x
, paiSubMesh->mTextureCoords[0][j].y));
}
else
{
stMeshData.m_arTexCoords.Add(XMFLOAT2(0.0f,0.0f));
}
}
// 加载索引数据
......@@ -77,7 +122,7 @@ BOOL LoadMesh(LPCSTR pszFileName, ST_GRS_MESH_DATA& stMeshData)
{
const aiFace& Face = paiSubMesh->mFaces[j];
// 已经通过导入标志强制为三角形网格了,每个面就三个索引
ATLASSERT(Face.mNumIndices == GRS_INDICES_PER_FACE);
ATLASSERT( Face.mNumIndices == GRS_INDICES_PER_FACE );
for (UINT k = 0; k < Face.mNumIndices; k++)
{
......@@ -337,6 +382,9 @@ void ReadNodeHeirarchy(ST_GRS_MESH_DATA& stMeshData
MXEqual(mxNodeTransformation, pNode->mTransformation);
mxNodeTransformation = XMMatrixTranspose(mxNodeTransformation);
XMMATRIX mxThisTrans = XMMatrixTranspose(mxNodeTransformation);
//mxThisTrans = XMMatrixTranspose(XMMatrixInverse(nullptr,mxNodeTransformation));
CStringA strNodeName(pNode->mName.data);
const aiNodeAnim* pNodeAnim = FindNodeAnim(pAnimation, strNodeName);
......@@ -359,8 +407,7 @@ void ReadNodeHeirarchy(ST_GRS_MESH_DATA& stMeshData
XMMATRIX mxTranslationM = XMMatrixTranslationFromVector(vTranslation);
// 骨骼动画中 最经典的 SQT 组合变换
mxNodeTransformation = mxScaling * mxRotationM * mxTranslationM;
// OpenGL:TranslationM* RotationM* ScalingM;
mxNodeTransformation = mxScaling * mxRotationM * mxTranslationM; // TranslationM* RotationM* ScalingM;
}
XMMATRIX mxGlobalTransformation = mxNodeTransformation * mxParentTransform;
......@@ -370,6 +417,7 @@ void ReadNodeHeirarchy(ST_GRS_MESH_DATA& stMeshData
{
stMeshData.m_arBoneDatas[nBoneIndex].m_mxFinalTransformation
= stMeshData.m_arBoneDatas[nBoneIndex].m_mxBoneOffset
/** mxThisTrans*/
* mxGlobalTransformation
* stMeshData.m_mxModel;
}
......@@ -384,7 +432,7 @@ void ReadNodeHeirarchy(ST_GRS_MESH_DATA& stMeshData
}
}
VOID CalcAnimation(ST_GRS_MESH_DATA& stMeshData, FLOAT fTimeInSeconds, CGRSARMatrix& arTransforms)
VOID CalcAnimation(ST_GRS_MESH_DATA& stMeshData, FLOAT fTimeInSeconds, CGRSMatrixArray& arTransforms)
{
XMMATRIX mxIdentity = XMMatrixIdentity();
aiNode* pNode = stMeshData.m_paiModel->mRootNode;
......
......@@ -23,7 +23,7 @@ using namespace DirectX;
// aiProcess_ConvertToLeftHanded
//| aiProcess_MakeLeftHanded\
#define ASSIMP_LOAD_FLAGS (aiProcess_Triangulate\
#define ASSIMP_LOAD_FLAGS_DEFAULT (aiProcess_Triangulate\
| aiProcess_GenSmoothNormals\
| aiProcess_GenBoundingBoxes\
| aiProcess_JoinIdenticalVertices\
......@@ -49,7 +49,7 @@ public:
public:
VOID AddBoneData(UINT nBoneID, FLOAT fWeight)
{
for (UINT32 i = 0; i < GRS_BONE_DATACNT; i++)
for ( UINT32 i = 0; i < GRS_BONE_DATACNT; i++ )
{
if ( m_fWeights[i] == 0.0 )
{
......@@ -70,17 +70,6 @@ struct ST_GRS_BONE_DATA
XMMATRIX m_mxFinalTransformation;
};
typedef CAtlArray<XMFLOAT4> CGRSARPositions;
typedef CAtlArray<XMFLOAT4> CGRSARNormals;
typedef CAtlArray<XMFLOAT2> CGRSARTexCoords;
typedef CAtlArray<UINT> CGRSARIndices;
typedef CAtlArray<ST_GRS_VERTEX_BONE> CGRSARVertexBones;
typedef CAtlArray<ST_GRS_BONE_DATA> CGRSARBoneDatas;
typedef CAtlArray<CStringA> CGRSARTTextureName;
typedef CAtlArray<XMMATRIX> CGRSARMatrix;
typedef CAtlMap<UINT, CStringA> CGRSMapUINT2String;
typedef CAtlMap<CStringA, UINT> CGRSMapString2UINT;
typedef CAtlMap<UINT, UINT> CGRSMapUINT2UINT;
// 模型中子网格的顶点偏移等信息
struct ST_GRS_SUBMESH_DATA
{
......@@ -88,33 +77,59 @@ struct ST_GRS_SUBMESH_DATA
UINT m_nBaseVertex;
UINT m_nBaseIndex;
UINT m_nMaterialIndex;
BOOL m_bHasPosition;
BOOL m_bHasNormal;
BOOL m_bHasTexCoords;
BOOL m_bHasTangent;
};
typedef CAtlArray<ST_GRS_SUBMESH_DATA> CGRSSubMesh;
typedef CAtlArray<XMFLOAT2> CGRSFloat2Array;
typedef CAtlArray<XMFLOAT3> CGRSFloat3Array;
typedef CAtlArray<XMFLOAT4> CGRSFloat4Array;
typedef CAtlArray<XMMATRIX> CGRSMatrixArray;
typedef CAtlArray<INT> CGRSIntArray;
typedef CAtlArray<UINT> CGRSUIntArray;
typedef CAtlArray<CStringA> CGRSStringArrayA;
typedef CAtlMap<UINT, CStringA> CGRSMapUINT2String;
typedef CAtlMap<CStringA, UINT> CGRSMapString2UINT;
typedef CAtlMap<UINT, UINT> CGRSMapUINT2UINT;
typedef CAtlArray<ST_GRS_VERTEX_BONE> CGRSARVertexBones;
typedef CAtlArray<ST_GRS_BONE_DATA> CGRSARBoneDatas;
typedef CAtlArray<ST_GRS_SUBMESH_DATA> CGRSSubMesh;
const UINT g_ncSlotCnt = 4; // 用4个插槽上传顶点数据
const UINT g_ncSlotCnt = 4; // 用4个插槽上传顶点数据
struct ST_GRS_MESH_DATA
{
const aiScene* m_paiModel;
CStringA m_strFileName;
XMMATRIX m_mxModel;
CStringA m_strFileName;
const aiScene* m_paiModel;
CGRSSubMesh m_arSubMeshInfo;
CGRSARPositions m_arPositions;
CGRSARNormals m_arNormals;
CGRSARTexCoords m_arTexCoords;
CGRSFloat4Array m_arPositions; // POSITION
CGRSFloat4Array m_arNormals; // NORMAL
CGRSFloat2Array m_arTexCoords; // TEXCOORDS
CGRSFloat4Array m_arTangent; // TANGENT
CGRSFloat4Array m_arBitangent; // BITANGENT
CGRSARVertexBones m_arBoneIndices;
CGRSARIndices m_arIndices;
CGRSUIntArray m_arIndices;
CGRSStringArrayA m_arTextureName;
CGRSMapString2UINT m_mapTextrueName2Index;
CGRSMapUINT2UINT m_mapTextureIndex2HeapIndex;
CGRSARBoneDatas m_arBoneDatas;
CGRSMapString2UINT m_mapName2Bone; //名称->骨骼的索引
CGRSMapString2UINT m_mapAnimName2Index; //名称->动画的索引
UINT m_nCurrentAnimIndex; // 当前播放的动画序列索引(当前动作)
UINT m_nCurrentAnimIndex; // 当前播放的动画序列索引
};
__inline const XMMATRIX& MXEqual(XMMATRIX& mxDX, const aiMatrix4x4& mxAI)
......@@ -157,5 +172,5 @@ __inline VOID QuaternionSlerp(XMVECTOR& vOut, aiQuaternion& qStart, aiQuaternion
vOut = XMQuaternionSlerp(qdxStart, qdxEnd, t);
}
BOOL LoadMesh(LPCSTR pszFileName, ST_GRS_MESH_DATA& stMeshData);
VOID CalcAnimation(ST_GRS_MESH_DATA& stMeshData, FLOAT fTimeInSeconds, CGRSARMatrix& arTransforms);
BOOL LoadMesh(LPCSTR pszFileName, ST_GRS_MESH_DATA& stMeshData, UINT nFlags = ASSIMP_LOAD_FLAGS_DEFAULT);
VOID CalcAnimation(ST_GRS_MESH_DATA& stMeshData, FLOAT fTimeInSeconds, CGRSMatrixArray& arTransforms);
#include "GRS_Def.h"
#include "GRS_Assimp_Loader_For_DX12.h"
#include "GRS_D3D12_Utility.h"
#pragma comment(lib, "assimp-vc142-mtd.lib")
struct ST_GRS_ARRAY_DATA
{
size_t m_szESize;
size_t m_szECount;
size_t m_szBufLength; // = m_szESize * m_szECount
VOID* m_pData; // length = m_szBufLength;
};
typedef CAtlArray< ST_GRS_ARRAY_DATA > CGRSArrayData;
BOOL LoadMesh_DX12(LPCSTR pszFileName
, ID3D12Device4* pID3D12Device4
, ST_GRS_MESH_DATA_MULTI_SLOT& stMeshBufferData
, UINT nFlags)
{
try
{
if (nullptr == pID3D12Device4)
{
AtlThrow( E_INVALIDARG );
}
if (!LoadMesh(pszFileName, stMeshBufferData.m_stMeshData, nFlags))
{
AtlThrowLastWin32();
}
CGRSArrayData arArrayData;
ST_GRS_ARRAY_DATA szArData = {};
D3D12_VERTEX_BUFFER_VIEW stVBV = {};
D3D12_INPUT_ELEMENT_DESC stElementDesc = {};
UINT nSlot = 0;
//typedef struct D3D12_INPUT_ELEMENT_DESC
//{
// LPCSTR SemanticName;
// UINT SemanticIndex;
// DXGI_FORMAT Format;
// UINT InputSlot;
// UINT AlignedByteOffset;
// D3D12_INPUT_CLASSIFICATION InputSlotClass;
// UINT InstanceDataStepRate;
//} D3D12_INPUT_ELEMENT_DESC;
if ( stMeshBufferData.m_stMeshData.m_arPositions.GetCount() > 0 )
{
szArData.m_szESize = sizeof(stMeshBufferData.m_stMeshData.m_arPositions[0]);
szArData.m_szECount = stMeshBufferData.m_stMeshData.m_arPositions.GetCount();
szArData.m_szBufLength = szArData.m_szESize * szArData.m_szECount;
szArData.m_pData = stMeshBufferData.m_stMeshData.m_arPositions.GetData();
arArrayData.Add(szArData);
stVBV.SizeInBytes = (UINT)szArData.m_szBufLength;
stVBV.StrideInBytes = (UINT)szArData.m_szESize;
stMeshBufferData.m_arVBV.Add(stVBV);
size_t szIndex = stMeshBufferData.m_arSemanticName.Add("POSITION");
stElementDesc.SemanticName = stMeshBufferData.m_arSemanticName[szIndex];
stElementDesc.SemanticIndex = 0;
stElementDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
stElementDesc.InputSlot = nSlot;
stElementDesc.AlignedByteOffset = 0;
stElementDesc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
stElementDesc.InstanceDataStepRate = 0;
stMeshBufferData.m_arInputElementDesc.Add(stElementDesc);
++nSlot;
}
if (stMeshBufferData.m_stMeshData.m_arNormals.GetCount() > 0)
{
szArData.m_szESize = sizeof(stMeshBufferData.m_stMeshData.m_arNormals[0]);
szArData.m_szECount = stMeshBufferData.m_stMeshData.m_arNormals.GetCount();
szArData.m_szBufLength = szArData.m_szESize * szArData.m_szECount;
szArData.m_pData = stMeshBufferData.m_stMeshData.m_arNormals.GetData();
arArrayData.Add(szArData);
stVBV.SizeInBytes = (UINT)szArData.m_szBufLength;
stVBV.StrideInBytes = (UINT)szArData.m_szESize;
stMeshBufferData.m_arVBV.Add(stVBV);
size_t szIndex = stMeshBufferData.m_arSemanticName.Add("NORMAL");
stElementDesc.SemanticName = stMeshBufferData.m_arSemanticName[szIndex];
stElementDesc.SemanticIndex = 0;
stElementDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
stElementDesc.InputSlot = nSlot;
stElementDesc.AlignedByteOffset = 0;
stElementDesc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
stElementDesc.InstanceDataStepRate = 0;
stMeshBufferData.m_arInputElementDesc.Add(stElementDesc);
++nSlot;
}
if (stMeshBufferData.m_stMeshData.m_arTexCoords.GetCount() > 0)
{
szArData.m_szESize = sizeof(stMeshBufferData.m_stMeshData.m_arTexCoords[0]);
szArData.m_szECount = stMeshBufferData.m_stMeshData.m_arTexCoords.GetCount();
szArData.m_szBufLength = szArData.m_szESize * szArData.m_szECount;
szArData.m_pData = stMeshBufferData.m_stMeshData.m_arTexCoords.GetData();
arArrayData.Add(szArData);
stVBV.SizeInBytes = (UINT)szArData.m_szBufLength;
stVBV.StrideInBytes = (UINT)szArData.m_szESize;
stMeshBufferData.m_arVBV.Add(stVBV);
size_t szIndex = stMeshBufferData.m_arSemanticName.Add("TEXCOORD");
stElementDesc.SemanticName = stMeshBufferData.m_arSemanticName[szIndex];
stElementDesc.SemanticIndex = 0;
stElementDesc.Format = DXGI_FORMAT_R32G32_FLOAT;
stElementDesc.InputSlot = nSlot;
stElementDesc.AlignedByteOffset = 0;
stElementDesc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
stElementDesc.InstanceDataStepRate = 0;
stMeshBufferData.m_arInputElementDesc.Add(stElementDesc);
++nSlot;
}
if (stMeshBufferData.m_stMeshData.m_arTangent.GetCount() > 0)
{
szArData.m_szESize = sizeof(stMeshBufferData.m_stMeshData.m_arTangent[0]);
szArData.m_szECount = stMeshBufferData.m_stMeshData.m_arTangent.GetCount();
szArData.m_szBufLength = szArData.m_szESize * szArData.m_szECount;
szArData.m_pData = stMeshBufferData.m_stMeshData.m_arTangent.GetData();
arArrayData.Add(szArData);
stVBV.SizeInBytes = (UINT)szArData.m_szBufLength;
stVBV.StrideInBytes = (UINT)szArData.m_szESize;
stMeshBufferData.m_arVBV.Add(stVBV);
size_t szIndex = stMeshBufferData.m_arSemanticName.Add("TANGENT");
stElementDesc.SemanticName = stMeshBufferData.m_arSemanticName[szIndex];
stElementDesc.SemanticIndex = 0;
stElementDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
stElementDesc.InputSlot = nSlot;
stElementDesc.AlignedByteOffset = 0;
stElementDesc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
stElementDesc.InstanceDataStepRate = 0;
stMeshBufferData.m_arInputElementDesc.Add(stElementDesc);
++nSlot;
}
if (stMeshBufferData.m_stMeshData.m_arBitangent.GetCount() > 0)
{
szArData.m_szESize = sizeof(stMeshBufferData.m_stMeshData.m_arBitangent[0]);
szArData.m_szECount = stMeshBufferData.m_stMeshData.m_arBitangent.GetCount();
szArData.m_szBufLength = szArData.m_szESize * szArData.m_szECount;
szArData.m_pData = stMeshBufferData.m_stMeshData.m_arBitangent.GetData();
arArrayData.Add(szArData);
stVBV.SizeInBytes = (UINT)szArData.m_szBufLength;
stVBV.StrideInBytes = (UINT)szArData.m_szESize;
stMeshBufferData.m_arVBV.Add(stVBV);
size_t szIndex = stMeshBufferData.m_arSemanticName.Add("BITANGENT");
stElementDesc.SemanticName = stMeshBufferData.m_arSemanticName[szIndex];
stElementDesc.SemanticIndex = 0;
stElementDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
stElementDesc.InputSlot = nSlot;
stElementDesc.AlignedByteOffset = 0;
stElementDesc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
stElementDesc.InstanceDataStepRate = 0;
stMeshBufferData.m_arInputElementDesc.Add(stElementDesc);
++nSlot;
}
if (stMeshBufferData.m_stMeshData.m_arBoneIndices.GetCount() > 0)
{
szArData.m_szESize = sizeof(stMeshBufferData.m_stMeshData.m_arBoneIndices[0]);
szArData.m_szECount = stMeshBufferData.m_stMeshData.m_arBoneIndices.GetCount();
szArData.m_szBufLength = szArData.m_szESize * szArData.m_szECount;
szArData.m_pData = stMeshBufferData.m_stMeshData.m_arBoneIndices.GetData();
arArrayData.Add(szArData);
stVBV.SizeInBytes = (UINT)szArData.m_szBufLength;
stVBV.StrideInBytes = (UINT)szArData.m_szESize;
stMeshBufferData.m_arVBV.Add(stVBV);
size_t szIndex = stMeshBufferData.m_arSemanticName.Add("BLENDINDICES");
stElementDesc.SemanticName = stMeshBufferData.m_arSemanticName[szIndex];
stElementDesc.SemanticIndex = 0;
stElementDesc.Format = DXGI_FORMAT_R32G32B32A32_UINT;
stElementDesc.InputSlot = nSlot;
stElementDesc.AlignedByteOffset = 0;
stElementDesc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
stElementDesc.InstanceDataStepRate = 0;
stMeshBufferData.m_arInputElementDesc.Add(stElementDesc);
szIndex = stMeshBufferData.m_arSemanticName.Add("BLENDWEIGHT");
stElementDesc.SemanticName = stMeshBufferData.m_arSemanticName[szIndex];
stElementDesc.SemanticIndex = 0;
stElementDesc.Format = DXGI_FORMAT_R32G32B32A32_UINT;
stElementDesc.InputSlot = nSlot;
stElementDesc.AlignedByteOffset = 16;
stElementDesc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
stElementDesc.InstanceDataStepRate = 0;
stMeshBufferData.m_arInputElementDesc.Add(stElementDesc);
++nSlot;
}
stMeshBufferData.m_nMaxSlot = nSlot;
ATLASSERT( stMeshBufferData.m_arVBV.GetCount() == arArrayData.GetCount() );
D3D12_HEAP_PROPERTIES stUploadHeapProps = {};
stUploadHeapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
stUploadHeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
stUploadHeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
stUploadHeapProps.CreationNodeMask = 0;
stUploadHeapProps.VisibleNodeMask = 0;
D3D12_RESOURCE_DESC stBufferResSesc = {};
stBufferResSesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
stBufferResSesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
stBufferResSesc.Flags = D3D12_RESOURCE_FLAG_NONE;
stBufferResSesc.Format = DXGI_FORMAT_UNKNOWN;
stBufferResSesc.Width = 0;
stBufferResSesc.Height = 1;
stBufferResSesc.DepthOrArraySize = 1;
stBufferResSesc.MipLevels = 1;
stBufferResSesc.SampleDesc.Count = 1;
stBufferResSesc.SampleDesc.Quality = 0;
stMeshBufferData.m_arIVB.SetCount(arArrayData.GetCount());
BYTE* pData = nullptr;
// 创建 Vertex Buffer
for ( size_t i = 0; i < arArrayData.GetCount(); i++ )
{
ATLASSERT(arArrayData[i].m_szBufLength > 0);
stBufferResSesc.Width = arArrayData[i].m_szBufLength;
// 创建顶点缓冲 (共享内存中)
GRS_THROW_IF_FAILED(pID3D12Device4->CreateCommittedResource(
&stUploadHeapProps
, D3D12_HEAP_FLAG_NONE
, &stBufferResSesc
, D3D12_RESOURCE_STATE_GENERIC_READ
, nullptr
, IID_PPV_ARGS(&stMeshBufferData.m_arIVB[i])));
GRS_SET_D3D12_DEBUGNAME_INDEXED_COMPTR(stMeshBufferData.m_arIVB,(UINT)i);
GRS_THROW_IF_FAILED(stMeshBufferData.m_arIVB[i]->Map(0, nullptr, reinterpret_cast<void**>(&pData)));
// 第一次 Copy!CPU Memory -> Share Memory 实质上就是在内存中倒腾,只是物理地址不同
// 估计会有那么一天,这个Copy动作可能被简单替换为CPU物理地址映射的变更,传说Vulkan中已经大致是这样了
memcpy(pData, arArrayData[i].m_pData, arArrayData[i].m_szBufLength);
stMeshBufferData.m_arIVB[i]->Unmap(0, nullptr);
stMeshBufferData.m_arVBV[i].BufferLocation = stMeshBufferData.m_arIVB[i]->GetGPUVirtualAddress();
}
//创建 Index Buffer
size_t szIndices
= stMeshBufferData.m_stMeshData.m_arIndices.GetCount()
* sizeof(stMeshBufferData.m_stMeshData.m_arIndices[0]);
stBufferResSesc.Width = szIndices;
GRS_THROW_IF_FAILED(pID3D12Device4->CreateCommittedResource(
&stUploadHeapProps
, D3D12_HEAP_FLAG_NONE
, &stBufferResSesc
, D3D12_RESOURCE_STATE_GENERIC_READ
, nullptr
, IID_PPV_ARGS(&stMeshBufferData.m_pIIB)));
GRS_SET_D3D12_DEBUGNAME_COMPTR(stMeshBufferData.m_pIIB);
GRS_THROW_IF_FAILED(stMeshBufferData.m_pIIB->Map(0, nullptr, reinterpret_cast<void**>(&pData)));
memcpy(pData, stMeshBufferData.m_stMeshData.m_arIndices.GetData(), szIndices);
stMeshBufferData.m_pIIB->Unmap(0, nullptr);
//创建Index Buffer View
stMeshBufferData.m_stIBV.BufferLocation = stMeshBufferData.m_pIIB->GetGPUVirtualAddress();
stMeshBufferData.m_stIBV.Format = DXGI_FORMAT_R32_UINT;
stMeshBufferData.m_stIBV.SizeInBytes = (UINT)szIndices;
}
catch (CAtlException& e)
{//发生了COM异常
e;
}
catch (...)
{
}
return TRUE;
}
\ No newline at end of file
#pragma once
#include <strsafe.h>
#include <wrl.h> //WTL֧ ʹCOM
#include <atlbase.h>
#include <atlcoll.h>
#include <atlchecked.h>
#include <atlstr.h>
#include <atlconv.h>
#include <d3d12.h> //for d3d12
#include <DirectXMath.h>
using namespace DirectX;
using namespace Microsoft::WRL;
#include "GRS_Assimp_Loader.h"
struct ST_GRS_MESH_DATA_MULTI_SLOT
{
ST_GRS_MESH_DATA m_stMeshData;
UINT m_nMaxSlot;
CGRSStringArrayA m_arSemanticName;
CAtlArray< D3D12_INPUT_ELEMENT_DESC > m_arInputElementDesc;
D3D12_INDEX_BUFFER_VIEW m_stIBV;
ComPtr<ID3D12Resource> m_pIIB;
CAtlArray<D3D12_VERTEX_BUFFER_VIEW> m_arVBV;
CAtlArray<ComPtr<ID3D12Resource>> m_arIVB;
CAtlArray<ComPtr<ID3D12Resource>> m_ppITexture;
};
BOOL LoadMesh_DX12( LPCSTR pszFileName
, ID3D12Device4* pID3D12Device4
, ST_GRS_MESH_DATA_MULTI_SLOT& stMeshBufferData
, UINT nFlags = ASSIMP_LOAD_FLAGS_DEFAULT);
\ No newline at end of file
......@@ -2,6 +2,7 @@
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料
#include <windows.h>
#include <dxgi1_6.h>
#include <d3d12.h> //for d3d12
//------------------------------------------------------------------------------------------------------------
......
#pragma once
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料
#include <windows.h>
#include <fstream> //for ifstream
#include <DirectXMath.h>
#include <atlexcept.h>
#include "GRS_Mem.h"
using namespace std;
using namespace DirectX;
using namespace ATL;
struct ST_GRS_VERTEX
{
XMFLOAT4 m_v4Position; // Position
XMFLOAT4 m_v4Normal; // Normal
XMFLOAT2 m_v2UV; // Texcoord
};
__inline BOOL LoadMeshVertex(const CHAR* pszMeshFileName, UINT& nVertexCnt, ST_GRS_VERTEX*& ppVertex, UINT*& ppIndices)
{
ifstream fin;
char input;
BOOL bRet = TRUE;
try
{
fin.open(pszMeshFileName);
if (fin.fail())
{
AtlThrowLastWin32();
}
fin.get(input);
while (input != ':')
{
fin.get(input);
}
fin >> nVertexCnt;
fin.get(input);
while (input != ':')
{
fin.get(input);
}
fin.get(input);
fin.get(input);
ppVertex = (ST_GRS_VERTEX*)GRS_CALLOC(nVertexCnt * sizeof(ST_GRS_VERTEX));
ppIndices = (UINT*)GRS_CALLOC(nVertexCnt * sizeof(UINT));
for (UINT i = 0; i < nVertexCnt; i++)
{
fin >> ppVertex[i].m_v4Position.x >> ppVertex[i].m_v4Position.y >> ppVertex[i].m_v4Position.z;
ppVertex[i].m_v4Position.w = 1.0f; //点的第4维坐标设为1
fin >> ppVertex[i].m_v2UV.x >> ppVertex[i].m_v2UV.y;
fin >> ppVertex[i].m_v4Normal.x >> ppVertex[i].m_v4Normal.y >> ppVertex[i].m_v4Normal.z;
ppVertex[i].m_v4Normal.w = 0.0f; //纯向量的第4维坐标设为0
ppIndices[i] = i;
}
}
catch (CAtlException& e)
{
e;
bRet = FALSE;
}
return bRet;
}
\ No newline at end of file
......@@ -51,6 +51,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "23-Structured_Empty", "23-S
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "24-CubeMapWithoutDDS", "24-CubeMapWithoutDDS\24-CubeMapWithoutDDS.vcxproj", "{C69D3E81-FAF3-4C6B-828D-6366E1685C09}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "25-IBL-MultiInstance-Sphere", "25-IBL-MultiInstance-Sphere\25-IBL-MultiInstance-Sphere.vcxproj", "{F23F558F-E978-4265-B862-26492F7C3906}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "26-Normal-Map-And-Tangent-Space", "26-Normal-Map-And-Tangent-Space\26-Normal-Map-And-Tangent-Space.vcxproj", "{469021D1-DAEC-4EFB-8A1E-A148A1E4EF20}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
......@@ -349,6 +353,30 @@ Global
{C69D3E81-FAF3-4C6B-828D-6366E1685C09}.Release|x64.Build.0 = Release|x64
{C69D3E81-FAF3-4C6B-828D-6366E1685C09}.Release|x86.ActiveCfg = Release|Win32
{C69D3E81-FAF3-4C6B-828D-6366E1685C09}.Release|x86.Build.0 = Release|Win32
{F23F558F-E978-4265-B862-26492F7C3906}.Debug|x64.ActiveCfg = Debug|x64
{F23F558F-E978-4265-B862-26492F7C3906}.Debug|x64.Build.0 = Debug|x64
{F23F558F-E978-4265-B862-26492F7C3906}.Debug|x86.ActiveCfg = Debug|Win32
{F23F558F-E978-4265-B862-26492F7C3906}.Debug|x86.Build.0 = Debug|Win32
{F23F558F-E978-4265-B862-26492F7C3906}.Profile|x64.ActiveCfg = Debug|x64
{F23F558F-E978-4265-B862-26492F7C3906}.Profile|x64.Build.0 = Debug|x64
{F23F558F-E978-4265-B862-26492F7C3906}.Profile|x86.ActiveCfg = Debug|Win32
{F23F558F-E978-4265-B862-26492F7C3906}.Profile|x86.Build.0 = Debug|Win32
{F23F558F-E978-4265-B862-26492F7C3906}.Release|x64.ActiveCfg = Release|x64
{F23F558F-E978-4265-B862-26492F7C3906}.Release|x64.Build.0 = Release|x64
{F23F558F-E978-4265-B862-26492F7C3906}.Release|x86.ActiveCfg = Release|Win32
{F23F558F-E978-4265-B862-26492F7C3906}.Release|x86.Build.0 = Release|Win32
{469021D1-DAEC-4EFB-8A1E-A148A1E4EF20}.Debug|x64.ActiveCfg = Debug|x64
{469021D1-DAEC-4EFB-8A1E-A148A1E4EF20}.Debug|x64.Build.0 = Debug|x64
{469021D1-DAEC-4EFB-8A1E-A148A1E4EF20}.Debug|x86.ActiveCfg = Debug|Win32
{469021D1-DAEC-4EFB-8A1E-A148A1E4EF20}.Debug|x86.Build.0 = Debug|Win32
{469021D1-DAEC-4EFB-8A1E-A148A1E4EF20}.Profile|x64.ActiveCfg = Debug|x64
{469021D1-DAEC-4EFB-8A1E-A148A1E4EF20}.Profile|x64.Build.0 = Debug|x64
{469021D1-DAEC-4EFB-8A1E-A148A1E4EF20}.Profile|x86.ActiveCfg = Debug|Win32
{469021D1-DAEC-4EFB-8A1E-A148A1E4EF20}.Profile|x86.Build.0 = Debug|Win32
{469021D1-DAEC-4EFB-8A1E-A148A1E4EF20}.Release|x64.ActiveCfg = Release|x64
{469021D1-DAEC-4EFB-8A1E-A148A1E4EF20}.Release|x64.Build.0 = Release|x64
{469021D1-DAEC-4EFB-8A1E-A148A1E4EF20}.Release|x86.ActiveCfg = Release|Win32
{469021D1-DAEC-4EFB-8A1E-A148A1E4EF20}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
......@@ -6,6 +6,8 @@
&emsp;&emsp;教程中的代码跟现在这个项目中的代码有些出入,示例代码请以这里为准。
&emsp;&emsp;这套示例代码的目标就是不使用任何封装,并且使用比较原始的C-风格代码来展示D3D12编程的方方面面。不使用任何封装使大家更集中精力于D3D12本身,而不至于分散注意力。并且线性化(甚至连独立的函数都没有怎么封装)的代码风格有助于大家学习和理解D3D12,根本目的就在于让大家彻底理解和消化D3D12本身。当彻底搞明白D3D12接口之后,各位想怎么封装就怎么去封装吧。那才是真正的自由王国!
# 1、1-D3D12Triangle
......@@ -130,4 +132,42 @@
&emsp;&emsp;这个示例是个过渡示例,重点是让大家理解 Cube Map 或者说 Skybox(天空盒)纹理的构造,及单独每个面图片的创建和加载方法,也是为了让大家未来彻底丢掉DDS纹理做铺垫,因为DDS的来源较少,并且修改和使用也不直观,作为学习来说 DDS 格式本身就已经“过渡封装”了,非常不利于大家理解和掌握纹理操作的本质。另外这个示例也是为之后的 IBL 渲染做好铺垫,因为IBL渲染中有大量的Texture操作,尤其是有大量的 Cube Map 操作,如果不能很好的理解 Cube Texture 的构造及创建等相关操作方法的话,就几乎无法理解 IBL 的根本原理。
![image-20220829121837669](ScreenShot/24.png)
![image-20220829121837669](ScreenShot/24.jpg)
# 25-IBL-MultiInstance-Sphere
&emsp;&emsp;这个示例是基于IBL(Image-Based Lighting)的 PBR 无材质纹理、无法线贴图等的基本示例。因为IBL本身处理过程的复杂性,用到了很多预积分计算,同时 HDR Image 体积也较大,为了能达到演示的最佳效果,建议在**显卡配置不够时,尽量不要运行这个示例**。如果机器配置较低,并要运行,**请尽量调低几个参数**:一个是在 GRS_PBR_Function.hlsli 中的 GRS_INT_SAMPLES_CNT 调至 1024 或更低的值,以减少积分计算的量,另外运行中选择 HDR 光照图,和天空盒背景图时,请选择较低分辨率的小体积图片,从而使示例能够运行而不用耗费过多资源。若要看比较好的效果,在显卡条件够的情况下(推荐RTX2070及以上)需要反过来做,积分采样次数可以调至4096或更高,以消除摩尔纹,并达到更佳的效果。
&emsp;&emsp;HDR 图片来自:[sIBL Archive (hdrlabs.com)](http://www.hdrlabs.com/sibl/archive.html) ,非常感谢 hdrlabs 的慷慨奉献!
&emsp;&emsp;示例中还用到stb库,为了简化Git操作,直接复制了一份在项目中,stb源地址在:[https://github.com/nothings/stb.git](https://github.com/nothings/stb.git) ,在此表示感谢!
&emsp;&emsp;示例中关于解算等距柱状纹理贴图的最终修正算法,来自一位不愿公开信息的网友,在此表示感谢!
&emsp;&emsp;示例整体主要参考了:
[漫反射辐照 - LearnOpenGL CN (learnopengl-cn.github.io)](https://learnopengl-cn.github.io/07 PBR/03 IBL/01 Diffuse irradiance/)
[镜面IBL - LearnOpenGL CN (learnopengl-cn.github.io)](https://learnopengl-cn.github.io/07 PBR/03 IBL/02 Specular IBL/)
等文章,在此表示感谢!
&emsp;&emsp;示例中引用的 HDR_COLOR_CONV.hlsli 来自微软示例:[microsoft/DirectX-Graphics-Samples](https://github.com/microsoft/DirectX-Graphics-Samples) ,处理颜色空间转换,尤其是 Gamma 矫正时推荐使用这个头文件。在此也表示感谢!
![image-20220830190322210](ScreenShot/25-1.jpg)
![image-20220830190552194](ScreenShot/25-2.jpg)
![image-20220830190748845](ScreenShot/25-3.jpg)
&emsp;&emsp;**郑重声明:若因您贸然运行该示例而导致显卡损坏或设备损坏等,与本人无关!**
# 26-Normal-Map-And-Tangent-Space
&emsp;&emsp;这个示例主要演示了经典的法线贴图的基本操作,并且演示了如何利用顶点的法线和切线属性生成正确的切线空间,并在 Pixel Shader 中正确的变换逐顶点法线。这是非常常用和基础的一项操作,学习并掌握好它,是将来应对和实现更高级复杂的光照渲染模型的基础。这也是为了后续的 PBR 带材质渲染示例做准备,以方便各位平滑的阅读下一个示例。
![image-20220830190953187](ScreenShot/26-1.jpg)
![image-20220830191048067](ScreenShot/26-2.jpg)
&emsp;&emsp;再次强调一下,这套示例主要是为了演示D3D12的一些基本调用方法以及基本Shader编写的,不是介绍任何引擎框架或渲染框架及相关封装知识的。所有示例都基本保持C-Style风格的编写,并且代码集中编写,是为了方便各位阅读理解并掌握好基础技能的。因此也请各位不要过于纠结示例代码中的那些蹩脚的封装或者不严格的一些定义,这些只是为了方便组织代码而引入的东西,并没有暗示或示范说如何进行封装的内容,其本身并没有价值也没有意义,千万不要随便使用它们在你的任何正式项目中,以防发生意外,请一定关注每个示例主要向你展示的内容即可。
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
// These values must match the DisplayCurve enum in D3D12HDR.h.
#define DISPLAY_CURVE_SRGB 0
#define DISPLAY_CURVE_ST2084 1
#define DISPLAY_CURVE_LINEAR 2
float3 xyYToRec709(float2 xy, float Y = 1.0)
{
// https://github.com/ampas/aces-dev/blob/v1.0.3/transforms/ctl/README-MATRIX.md
static const float3x3 XYZtoRGB =
{
3.2409699419, -1.5373831776, -0.4986107603,
-0.9692436363, 1.8759675015, 0.0415550574,
0.0556300797, -0.2039769589, 1.0569715142
};
float3 XYZ = Y * float3(xy.x / xy.y, 1.0, (1.0 - xy.x - xy.y) / xy.y);
float3 RGB = mul(XYZtoRGB, XYZ);
float maxChannel = max(RGB.r, max(RGB.g, RGB.b));
return RGB / max(maxChannel, 1.0);
}
float3 xyYToRec2020(float2 xy, float Y = 1.0)
{
// https://github.com/ampas/aces-dev/blob/v1.0.3/transforms/ctl/README-MATRIX.md
static const float3x3 XYZtoRGB =
{
1.7166511880, -0.3556707838, -0.2533662814,
-0.6666843518, 1.6164812366, 0.0157685458,
0.0176398574, -0.0427706133, 0.9421031212
};
float3 XYZ = Y * float3(xy.x / xy.y, 1.0, (1.0 - xy.x - xy.y) / xy.y);
float3 RGB = mul(XYZtoRGB, XYZ);
float maxChannel = max(RGB.r, max(RGB.g, RGB.b));
return RGB / max(maxChannel, 1.0);
}
float3 LinearToSRGB(float3 color)
{
// Approximately pow(color, 1.0 / 2.2)
return color < 0.0031308 ? 12.92 * color : 1.055 * pow(abs(color), 1.0 / 2.4) - 0.055;
}
float3 SRGBToLinear(float3 color)
{
// Approximately pow(color, 2.2)
return color < 0.04045 ? color / 12.92 : pow(abs(color + 0.055) / 1.055, 2.4);
}
float3 Rec709ToRec2020(float3 color)
{
static const float3x3 conversion =
{
0.627402, 0.329292, 0.043306,
0.069095, 0.919544, 0.011360,
0.016394, 0.088028, 0.895578
};
return mul(conversion, color);
}
float3 Rec2020ToRec709(float3 color)
{
static const float3x3 conversion =
{
1.660496, -0.587656, -0.072840,
-0.124547, 1.132895, -0.008348,
-0.018154, -0.100597, 1.118751
};
return mul(conversion, color);
}
float3 LinearToST2084(float3 color)
{
float m1 = 2610.0 / 4096.0 / 4;
float m2 = 2523.0 / 4096.0 * 128;
float c1 = 3424.0 / 4096.0;
float c2 = 2413.0 / 4096.0 * 32;
float c3 = 2392.0 / 4096.0 * 32;
float3 cp = pow(abs(color), m1);
return pow((c1 + c2 * cp) / (1 + c3 * cp), m2);
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
// stb_divide.h - v0.93 - public domain - Sean Barrett, Feb 2010
// Three kinds of divide/modulus of signed integers.
//
// HISTORY
//
// v0.93 2020-02-02 Write useful exit() value from main()
// v0.92 2019-02-25 Fix warning
// v0.91 2010-02-27 Fix euclidean division by INT_MIN for non-truncating C
// Check result with 64-bit math to catch such cases
// v0.90 2010-02-24 First public release
//
// USAGE
//
// In *ONE* source file, put:
//
// #define STB_DIVIDE_IMPLEMENTATION
// // #define C_INTEGER_DIVISION_TRUNCATES // see Note 1
// // #define C_INTEGER_DIVISION_FLOORS // see Note 2
// #include "stb_divide.h"
//
// Other source files should just include stb_divide.h
//
// Note 1: On platforms/compilers that you know signed C division
// truncates, you can #define C_INTEGER_DIVISION_TRUNCATES.
//
// Note 2: On platforms/compilers that you know signed C division
// floors (rounds to negative infinity), you can #define
// C_INTEGER_DIVISION_FLOORS.
//
// You can #define STB_DIVIDE_TEST in which case the implementation
// will generate a main() and compiling the result will create a
// program that tests the implementation. Run it with no arguments
// and any output indicates an error; run it with any argument and
// it will also print the test results. Define STB_DIVIDE_TEST_64
// to a 64-bit integer type to avoid overflows in the result-checking
// which give false negatives.
//
// ABOUT
//
// This file provides three different consistent divide/mod pairs
// implemented on top of arbitrary C/C++ division, including correct
// handling of overflow of intermediate calculations:
//
// trunc: a/b truncates to 0, a%b has same sign as a
// floor: a/b truncates to -inf, a%b has same sign as b
// eucl: a/b truncates to sign(b)*inf, a%b is non-negative
//
// Not necessarily optimal; I tried to keep it generally efficient,
// but there may be better ways.
//
// Briefly, for those who are not familiar with the problem, we note
// the reason these divides exist and are interesting:
//
// 'trunc' is easy to implement in hardware (strip the signs,
// compute, reapply the signs), thus is commonly defined
// by many languages (including C99)
//
// 'floor' is simple to define and better behaved than trunc;
// for example it divides integers into fixed-size buckets
// without an extra-wide bucket at 0, and for a fixed
// divisor N there are only |N| possible moduli.
//
// 'eucl' guarantees fixed-sized buckets *and* a non-negative
// modulus and defines division to be whatever is needed
// to achieve that result.
//
// See "The Euclidean definition of the functions div and mod"
// by Raymond Boute (1992), or "Division and Modulus for Computer
// Scientists" by Daan Leijen (2001)
//
// We assume of the built-in C division:
// (a) modulus is the remainder for the corresponding division
// (b) a/b truncates if a and b are the same sign
//
// Property (a) requires (a/b)*b + (a%b)==a, and is required by C.
// Property (b) seems to be true of all hardware but is *not* satisfied
// by the euclidean division operator we define, so it's possibly not
// always true. If any such platform turns up, we can add more cases.
// (Possibly only stb_div_trunc currently relies on property (b).)
//
// LICENSE
//
// See end of file for license information.
#ifndef INCLUDE_STB_DIVIDE_H
#define INCLUDE_STB_DIVIDE_H
#ifdef __cplusplus
extern "C" {
#endif
extern int stb_div_trunc(int value_to_be_divided, int value_to_divide_by);
extern int stb_div_floor(int value_to_be_divided, int value_to_divide_by);
extern int stb_div_eucl (int value_to_be_divided, int value_to_divide_by);
extern int stb_mod_trunc(int value_to_be_divided, int value_to_divide_by);
extern int stb_mod_floor(int value_to_be_divided, int value_to_divide_by);
extern int stb_mod_eucl (int value_to_be_divided, int value_to_divide_by);
#ifdef __cplusplus
}
#endif
#ifdef STB_DIVIDE_IMPLEMENTATION
#if defined(__STDC_VERSION) && __STDC_VERSION__ >= 19901
#ifndef C_INTEGER_DIVISION_TRUNCATES
#define C_INTEGER_DIVISION_TRUNCATES
#endif
#endif
#ifndef INT_MIN
#include <limits.h> // if you have no limits.h, #define INT_MIN yourself
#endif
// the following macros are designed to allow testing
// other platforms by simulating them
#ifndef STB_DIVIDE_TEST_FLOOR
#define stb__div(a,b) ((a)/(b))
#define stb__mod(a,b) ((a)%(b))
#else
// implement floor-style divide on trunc platform
#ifndef C_INTEGER_DIVISION_TRUNCATES
#error "floor test requires truncating division"
#endif
#undef C_INTEGER_DIVISION_TRUNCATES
int stb__div(int v1, int v2)
{
int q = v1/v2, r = v1%v2;
if ((r > 0 && v2 < 0) || (r < 0 && v2 > 0))
return q-1;
else
return q;
}
int stb__mod(int v1, int v2)
{
int r = v1%v2;
if ((r > 0 && v2 < 0) || (r < 0 && v2 > 0))
return r+v2;
else
return r;
}
#endif
int stb_div_trunc(int v1, int v2)
{
#ifdef C_INTEGER_DIVISION_TRUNCATES
return v1/v2;
#else
if (v1 >= 0 && v2 <= 0)
return -stb__div(-v1,v2); // both negative to avoid overflow
if (v1 <= 0 && v2 >= 0)
if (v1 != INT_MIN)
return -stb__div(v1,-v2); // both negative to avoid overflow
else
return -stb__div(v1+v2,-v2)-1; // push v1 away from wrap point
else
return v1/v2; // same sign, so expect truncation
#endif
}
int stb_div_floor(int v1, int v2)
{
#ifdef C_INTEGER_DIVISION_FLOORS
return v1/v2;
#else
if (v1 >= 0 && v2 < 0) {
if ((-v1)+v2+1 < 0) // check if increasing v1's magnitude overflows
return -stb__div(-v1+v2+1,v2); // nope, so just compute it
else
return -stb__div(-v1,v2) + ((-v1)%v2 ? -1 : 0);
}
if (v1 < 0 && v2 >= 0) {
if (v1 != INT_MIN) {
if (v1-v2+1 < 0) // check if increasing v1's magnitude overflows
return -stb__div(v1-v2+1,-v2); // nope, so just compute it
else
return -stb__div(-v1,v2) + (stb__mod(v1,-v2) ? -1 : 0);
} else // it must be possible to compute -(v1+v2) without overflowing
return -stb__div(-(v1+v2),v2) + (stb__mod(-(v1+v2),v2) ? -2 : -1);
} else
return v1/v2; // same sign, so expect truncation
#endif
}
int stb_div_eucl(int v1, int v2)
{
int q,r;
#ifdef C_INTEGER_DIVISION_TRUNCATES
q = v1/v2;
r = v1%v2;
#else
// handle every quadrant separately, since we can't rely on q and r flor
if (v1 >= 0)
if (v2 >= 0)
return stb__div(v1,v2);
else if (v2 != INT_MIN)
q = -stb__div(v1,-v2), r = stb__mod(v1,-v2);
else
q = 0, r = v1;
else if (v1 != INT_MIN)
if (v2 >= 0)
q = -stb__div(-v1,v2), r = -stb__mod(-v1,v2);
else if (v2 != INT_MIN)
q = stb__div(-v1,-v2), r = -stb__mod(-v1,-v2);
else // if v2 is INT_MIN, then we can't use -v2, but we can't divide by v2
q = 1, r = v1-q*v2;
else // if v1 is INT_MIN, we have to move away from overflow place
if (v2 >= 0)
q = -stb__div(-(v1+v2),v2)-1, r = -stb__mod(-(v1+v2),v2);
else
q = stb__div(-(v1-v2),-v2)+1, r = -stb__mod(-(v1-v2),-v2);
#endif
if (r >= 0)
return q;
else
return q + (v2 > 0 ? -1 : 1);
}
int stb_mod_trunc(int v1, int v2)
{
#ifdef C_INTEGER_DIVISION_TRUNCATES
return v1%v2;
#else
if (v1 >= 0) { // modulus result should always be positive
int r = stb__mod(v1,v2);
if (r >= 0)
return r;
else
return r + (v2 > 0 ? v2 : -v2);
} else { // modulus result should always be negative
int r = stb__mod(v1,v2);
if (r <= 0)
return r;
else
return r - (v2 > 0 ? v2 : -v2);
}
#endif
}
int stb_mod_floor(int v1, int v2)
{
#ifdef C_INTEGER_DIVISION_FLOORS
return v1%v2;
#else
if (v2 >= 0) { // result should always be positive
int r = stb__mod(v1,v2);
if (r >= 0)
return r;
else
return r + v2;
} else { // result should always be negative
int r = stb__mod(v1,v2);
if (r <= 0)
return r;
else
return r + v2;
}
#endif
}
int stb_mod_eucl(int v1, int v2)
{
int r = stb__mod(v1,v2);
if (r >= 0)
return r;
else
return r + (v2 > 0 ? v2 : -v2); // abs()
}
#ifdef STB_DIVIDE_TEST
#include <stdio.h>
#include <math.h>
#include <limits.h>
int show=0;
int err=0;
void stbdiv_check(int q, int r, int a, int b, char *type, int dir)
{
if ((dir > 0 && r < 0) || (dir < 0 && r > 0)) {
fprintf(stderr, "FAILED: %s(%d,%d) remainder %d in wrong direction\n", type,a,b,r);
err++;
} else
if (b != INT_MIN) // can't compute abs(), but if b==INT_MIN all remainders are valid
if (r <= -abs(b) || r >= abs(b)) {
fprintf(stderr, "FAILED: %s(%d,%d) remainder %d out of range\n", type,a,b,r);
err++;
}
#ifdef STB_DIVIDE_TEST_64
{
STB_DIVIDE_TEST_64 q64 = q, r64=r, a64=a, b64=b;
if (q64*b64+r64 != a64) {
fprintf(stderr, "FAILED: %s(%d,%d) remainder %d doesn't match quotient %d\n", type,a,b,r,q);
err++;
}
}
#else
if (q*b+r != a) {
fprintf(stderr, "FAILED: %s(%d,%d) remainder %d doesn't match quotient %d\n", type,a,b,r,q);
err++;
}
#endif
}
void test(int a, int b)
{
int q,r;
if (show) printf("(%+11d,%+d) | ", a,b);
q = stb_div_trunc(a,b), r = stb_mod_trunc(a,b);
if (show) printf("(%+11d,%+2d) ", q,r); stbdiv_check(q,r,a,b, "trunc",a);
q = stb_div_floor(a,b), r = stb_mod_floor(a,b);
if (show) printf("(%+11d,%+2d) ", q,r); stbdiv_check(q,r,a,b, "floor",b);
q = stb_div_eucl (a,b), r = stb_mod_eucl (a,b);
if (show) printf("(%+11d,%+2d)\n", q,r); stbdiv_check(q,r,a,b, "euclidean",1);
}
void testh(int a, int b)
{
int q,r;
if (show) printf("(%08x,%08x) |\n", a,b);
q = stb_div_trunc(a,b), r = stb_mod_trunc(a,b); stbdiv_check(q,r,a,b, "trunc",a);
if (show) printf(" (%08x,%08x)", q,r);
q = stb_div_floor(a,b), r = stb_mod_floor(a,b); stbdiv_check(q,r,a,b, "floor",b);
if (show) printf(" (%08x,%08x)", q,r);
q = stb_div_eucl (a,b), r = stb_mod_eucl (a,b); stbdiv_check(q,r,a,b, "euclidean",1);
if (show) printf(" (%08x,%08x)\n ", q,r);
}
int main(int argc, char **argv)
{
if (argc > 1) show=1;
test(8,3);
test(8,-3);
test(-8,3);
test(-8,-3);
test(1,2);
test(1,-2);
test(-1,2);
test(-1,-2);
test(8,4);
test(8,-4);
test(-8,4);
test(-8,-4);
test(INT_MAX,1);
test(INT_MIN,1);
test(INT_MIN+1,1);
test(INT_MAX,-1);
//test(INT_MIN,-1); // this traps in MSVC, so we leave it untested
test(INT_MIN+1,-1);
test(INT_MIN,-2);
test(INT_MIN+1,2);
test(INT_MIN+1,-2);
test(INT_MAX,2);
test(INT_MAX,-2);
test(INT_MIN+1,2);
test(INT_MIN+1,-2);
test(INT_MIN,2);
test(INT_MIN,-2);
test(INT_MIN,7);
test(INT_MIN,-7);
test(INT_MIN+1,4);
test(INT_MIN+1,-4);
testh(-7, INT_MIN);
testh(-1, INT_MIN);
testh(1, INT_MIN);
testh(7, INT_MIN);
testh(INT_MAX-1, INT_MIN);
testh(INT_MAX, INT_MIN);
testh(INT_MIN, INT_MIN);
testh(INT_MIN+1, INT_MIN);
testh(INT_MAX-1, INT_MAX);
testh(INT_MAX , INT_MAX);
testh(INT_MIN , INT_MAX);
testh(INT_MIN+1, INT_MAX);
return err > 0 ? 1 : 0;
}
#endif // STB_DIVIDE_TEST
#endif // STB_DIVIDE_IMPLEMENTATION
#endif // INCLUDE_STB_DIVIDE_H
/*
------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------
*/
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
// stb_leakcheck.h - v0.6 - quick & dirty malloc leak-checking - public domain
// LICENSE
//
// See end of file.
#ifdef STB_LEAKCHECK_IMPLEMENTATION
#undef STB_LEAKCHECK_IMPLEMENTATION // don't implement more than once
// if we've already included leakcheck before, undefine the macros
#ifdef malloc
#undef malloc
#undef free
#undef realloc
#endif
#ifndef STB_LEAKCHECK_OUTPUT_PIPE
#define STB_LEAKCHECK_OUTPUT_PIPE stdout
#endif
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
typedef struct malloc_info stb_leakcheck_malloc_info;
struct malloc_info
{
const char *file;
int line;
size_t size;
stb_leakcheck_malloc_info *next,*prev;
};
static stb_leakcheck_malloc_info *mi_head;
void *stb_leakcheck_malloc(size_t sz, const char *file, int line)
{
stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) malloc(sz + sizeof(*mi));
if (mi == NULL) return mi;
mi->file = file;
mi->line = line;
mi->next = mi_head;
if (mi_head)
mi->next->prev = mi;
mi->prev = NULL;
mi->size = (int) sz;
mi_head = mi;
return mi+1;
}
void stb_leakcheck_free(void *ptr)
{
if (ptr != NULL) {
stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1;
mi->size = ~mi->size;
#ifndef STB_LEAKCHECK_SHOWALL
if (mi->prev == NULL) {
assert(mi_head == mi);
mi_head = mi->next;
} else
mi->prev->next = mi->next;
if (mi->next)
mi->next->prev = mi->prev;
free(mi);
#endif
}
}
void *stb_leakcheck_realloc(void *ptr, size_t sz, const char *file, int line)
{
if (ptr == NULL) {
return stb_leakcheck_malloc(sz, file, line);
} else if (sz == 0) {
stb_leakcheck_free(ptr);
return NULL;
} else {
stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1;
if (sz <= mi->size)
return ptr;
else {
#ifdef STB_LEAKCHECK_REALLOC_PRESERVE_MALLOC_FILELINE
void *q = stb_leakcheck_malloc(sz, mi->file, mi->line);
#else
void *q = stb_leakcheck_malloc(sz, file, line);
#endif
if (q) {
memcpy(q, ptr, mi->size);
stb_leakcheck_free(ptr);
}
return q;
}
}
}
static void stblkck_internal_print(const char *reason, stb_leakcheck_malloc_info *mi)
{
#if defined(_MSC_VER) && _MSC_VER < 1900 // 1900=VS 2015
// Compilers that use the old MS C runtime library don't have %zd
// and the older ones don't even have %lld either... however, the old compilers
// without "long long" don't support 64-bit targets either, so here's the
// compromise:
#if _MSC_VER < 1400 // before VS 2005
fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %8d bytes at %p\n", reason, mi->file, mi->line, (int)mi->size, (void*)(mi+1));
#else
fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %16lld bytes at %p\n", reason, mi->file, mi->line, (long long)mi->size, (void*)(mi+1));
#endif
#else
// Assume we have %zd on other targets.
#ifdef __MINGW32__
__mingw_fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %zd bytes at %p\n", reason, mi->file, mi->line, mi->size, (void*)(mi+1));
#else
fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %zd bytes at %p\n", reason, mi->file, mi->line, mi->size, (void*)(mi+1));
#endif
#endif
}
void stb_leakcheck_dumpmem(void)
{
stb_leakcheck_malloc_info *mi = mi_head;
while (mi) {
if ((ptrdiff_t) mi->size >= 0)
stblkck_internal_print("LEAKED", mi);
mi = mi->next;
}
#ifdef STB_LEAKCHECK_SHOWALL
mi = mi_head;
while (mi) {
if ((ptrdiff_t) mi->size < 0)
stblkck_internal_print("FREED ", mi);
mi = mi->next;
}
#endif
}
#endif // STB_LEAKCHECK_IMPLEMENTATION
#if !defined(INCLUDE_STB_LEAKCHECK_H) || !defined(malloc)
#define INCLUDE_STB_LEAKCHECK_H
#include <stdlib.h> // we want to define the macros *after* stdlib to avoid a slew of errors
#define malloc(sz) stb_leakcheck_malloc(sz, __FILE__, __LINE__)
#define free(p) stb_leakcheck_free(p)
#define realloc(p,sz) stb_leakcheck_realloc(p,sz, __FILE__, __LINE__)
extern void * stb_leakcheck_malloc(size_t sz, const char *file, int line);
extern void * stb_leakcheck_realloc(void *ptr, size_t sz, const char *file, int line);
extern void stb_leakcheck_free(void *ptr);
extern void stb_leakcheck_dumpmem(void);
#endif // INCLUDE_STB_LEAKCHECK_H
/*
------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------
*/
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册