├── .clang-format ├── .clang-tidy ├── .gitattributes ├── .gitignore ├── Assets ├── Model │ ├── ground.mtl │ └── ground_35.mbo └── Texture │ ├── floor.png │ ├── lake │ ├── back.jpg │ ├── bottom.jpg │ ├── front.jpg │ ├── left.jpg │ ├── right.jpg │ └── top.jpg │ └── wall.png ├── Include ├── Component │ ├── Camera.h │ ├── LightHelper.h │ └── Transform.h ├── Effect │ ├── EffectHelper.h │ ├── Effects.h │ ├── FluidRender.h │ ├── NeighborSearch.h │ ├── PBFSolver.h │ └── SkyRender.h ├── Graphics │ ├── Buffer.h │ ├── DDSTextureLoader.h │ ├── RenderStates.h │ ├── Texture2D.h │ ├── Vertex.h │ ├── WICTextureLoader.h │ └── d3dApp.h ├── Hierarchy │ ├── CameraController.h │ ├── FluidSystem.h │ └── GameObject.h └── Utils │ ├── Collision.h │ ├── DXTrace.h │ ├── GameTimer.h │ ├── Geometry.h │ ├── GpuTimer.h │ ├── Keyboard.h │ ├── Model.h │ ├── Mouse.h │ ├── ObjReader.h │ ├── ScreenGrab.h │ └── d3dUtil.h ├── LICENSE.md ├── README.md ├── Src ├── Component │ ├── Camera.cpp │ └── Transform.cpp ├── Effect │ ├── BasicEffect.cpp │ ├── EffectHelper.cpp │ ├── FluidEffect.cpp │ ├── FluidRender.cpp │ ├── NeighborSearch.cpp │ ├── NeighborSearchEffect.cpp │ ├── PBFSolver.cpp │ ├── PBFSolverEffect.cpp │ ├── SkyEffect.cpp │ └── SkyRender.cpp ├── GameApp.cpp ├── Graphics │ ├── Buffer.cpp │ ├── DDSTextureLoader.cpp │ ├── RenderStates.cpp │ ├── Texture2D.cpp │ ├── Vertex.cpp │ ├── WICTextureLoader.cpp │ └── d3dApp.cpp ├── Hierarchy │ ├── CameraController.cpp │ ├── FluidSystem.cpp │ └── GameObject.cpp ├── Main.cpp └── Utils │ ├── Collision.cpp │ ├── DXTrace.cpp │ ├── GameTimer.cpp │ ├── GpuTimer.cpp │ ├── Keyboard.cpp │ ├── Model.cpp │ ├── Mouse.cpp │ ├── ObjReader.cpp │ ├── ScreenGrab.cpp │ └── d3dUtil.cpp ├── cmakelists.txt ├── include ├── GameApp.h └── Utils │ ├── Property.h │ ├── WinMin.h │ └── XUtil.h ├── shaders ├── Basic.hlsli ├── BasicInstance_VS.hlsl ├── BasicObject_VS.hlsl ├── Basic_PS.hlsl ├── DisplacementMapInstance_VS.hlsl ├── DisplacementMapObject_VS.hlsl ├── DisplacementMap_DS.hlsl ├── DisplacementMap_HS.hlsl ├── Fluid │ ├── AddDeltaPosition_CS.hlsl │ ├── BlurDepth_PS.hlsl │ ├── CalcAnisotropy_CS.hlsl │ ├── CalcBoundsFinalize_CS.hlsl │ ├── CalcBoundsGroup_CS.hlsl │ ├── CalcBounds_CS.hlsl │ ├── CalcDisplacement_CS.hlsl │ ├── CalcHash_CS.hlsl │ ├── CalcLagrangeMultiplier_CS.hlsl │ ├── CalcVorticity_CS.hlsl │ ├── CollisionParticle_CS.hlsl │ ├── CollisionPlane_CS.hlsl │ ├── Composite_PS.hlsl │ ├── EllipsoidDepth_GS.hlsl │ ├── EllipsoidDepth_PS.hlsl │ ├── EllipsoidDepth_VS.hlsl │ ├── FindCellStart_CS.hlsl │ ├── FliudCommon.hlsli │ ├── NerghborSearchCommon.hlsli │ ├── PBFFinalize_CS.hlsl │ ├── PBFSolverCommon.hlsli │ ├── PassThrough_VS.hlsl │ ├── PointSpriteDepth_PS.hlsl │ ├── PointSpriteThickness_PS.hlsl │ ├── PointSprite_GS.hlsl │ ├── PointSprite_PS.hlsl │ ├── PointSprite_VS.hlsl │ ├── PredictPosition_CS.hlsl │ ├── RadixSortCount_CS.hlsl │ ├── RadixSortCountersPrefix_CS.hlsl │ ├── RadixSortDispatch_CS.hlsl │ ├── ReorderParticle_CS.hlsl │ ├── SmoothPosition_CS.hlsl │ ├── SolveContact_CS.hlsl │ ├── SolverVelocities_CS.hlsl │ └── UpdateVelocity_CS.hlsl ├── LightHelper.hlsli ├── NormalMapInstance_VS.hlsl ├── NormalMapObject_VS.hlsl ├── NormalMap_PS.hlsl ├── Sky.hlsli ├── Sky_PS.hlsl └── Sky_VS.hlsl ├── thirdParty ├── cmakelists.txt ├── imgui.cmake ├── imgui │ ├── imconfig.h │ ├── imgui.cpp │ ├── imgui.h │ ├── imgui_demo.cpp │ ├── imgui_draw.cpp │ ├── imgui_impl_dx11.cpp │ ├── imgui_impl_dx11.h │ ├── imgui_impl_win32.cpp │ ├── imgui_impl_win32.h │ ├── imgui_internal.h │ ├── imgui_tables.cpp │ ├── imgui_widgets.cpp │ ├── imstb_rectpack.h │ ├── imstb_textedit.h │ └── imstb_truetype.h └── xmake.lua ├── xmake.lua └── xmake_func.lua /.clang-format: -------------------------------------------------------------------------------- 1 | # Commented out parameters are those with the same value as base LLVM style. 2 | # We can uncomment them if we want to change their value, or enforce the 3 | # chosen value in case the base style changes (last sync: Clang 14.0). 4 | --- 5 | ### General config, applies to all languages ### 6 | ### C++ specific config ### 7 | Language: Cpp 8 | Standard: c++17 9 | BasedOnStyle: LLVM 10 | ColumnLimit: 120 11 | AlignAfterOpenBracket: Align 12 | BreakBeforeBinaryOperators: All 13 | AlignOperands: AlignAfterOperator 14 | AlignConsecutiveAssignments: 15 | Enabled: true 16 | AcrossEmptyLines: true 17 | AcrossComments: true 18 | AlignConsecutiveBitFields: 19 | Enabled: true 20 | AcrossEmptyLines: true 21 | AcrossComments: false 22 | AlignConsecutiveDeclarations: 23 | Enabled: true 24 | AcrossEmptyLines: true 25 | AcrossComments: false 26 | AlignTrailingComments: 27 | Kind: Always 28 | OverEmptyLines: 2 29 | BinPackParameters: false 30 | BinPackArguments: false 31 | AllowAllArgumentsOnNextLine: false 32 | AllowAllParametersOfDeclarationOnNextLine: false 33 | AllowShortCaseLabelsOnASingleLine: true 34 | BreakBeforeBraces: Custom 35 | BraceWrapping: 36 | AfterCaseLabel: True 37 | AfterClass: True 38 | AfterControlStatement: Always 39 | AfterEnum: True 40 | AfterFunction: True 41 | AfterNamespace: True 42 | AfterStruct: True 43 | AfterUnion: True 44 | AfterExternBlock: True 45 | BeforeCatch: True 46 | BeforeElse: True 47 | BeforeLambdaBody: false 48 | BeforeWhile: false 49 | SplitEmptyFunction: false 50 | SplitEmptyRecord: false 51 | SplitEmptyNamespace: false 52 | BreakBeforeConceptDeclarations: Always 53 | BreakInheritanceList: BeforeColon 54 | BreakBeforeTernaryOperators: true 55 | BreakConstructorInitializers: AfterColon 56 | QualifierAlignment: Leave 57 | CompactNamespaces: false 58 | Cpp11BracedListStyle: false 59 | DerivePointerAlignment: false 60 | EmptyLineAfterAccessModifier: Never 61 | EmptyLineBeforeAccessModifier: LogicalBlock 62 | ForEachMacros: 63 | - foreach 64 | - Q_FOREACH 65 | - BOOST_FOREACH 66 | IncludeBlocks: Preserve 67 | IncludeCategories: 68 | - Regex: '".*"' 69 | Priority: 1 70 | - Regex: '^<.*\.h>' 71 | Priority: 2 72 | - Regex: '^<.*' 73 | Priority: 3 74 | IncludeIsMainRegex: '(Test)?$' 75 | IncludeIsMainSourceRegex: '' 76 | # TabWidth: 4 77 | IndentCaseLabels: true 78 | IndentCaseBlocks: true 79 | NamespaceIndentation: All 80 | IndentAccessModifiers: true 81 | # AccessModifierOffsets: -4 82 | IndentPPDirectives: None 83 | IndentExternBlock: Indent 84 | IndentRequiresClause: false 85 | IndentWidth: 4 86 | IndentWrappedFunctionNames: True 87 | InsertTrailingCommas: None 88 | KeepEmptyLinesAtTheStartOfBlocks: false 89 | LambdaBodyIndentation: Signature 90 | MacroBlockBegin: '' 91 | MacroBlockEnd: '' 92 | MaxEmptyLinesToKeep: 1 93 | PointerAlignment: Right 94 | PPIndentWidth: -1 95 | ReferenceAlignment: Pointer 96 | ReflowComments: true 97 | RemoveBracesLLVM: false 98 | SeparateDefinitionBlocks: Leave 99 | ShortNamespaceLines: 1 100 | SortIncludes: CaseSensitive 101 | SortJavaStaticImport: Before 102 | SortUsingDeclarations: true 103 | SpaceAfterCStyleCast: false 104 | SpaceAfterLogicalNot: false 105 | SpaceAfterTemplateKeyword: true 106 | SpaceBeforeAssignmentOperators: true 107 | SpaceBeforeCaseColon: false 108 | SpaceBeforeCpp11BracedList: false 109 | SpaceBeforeCtorInitializerColon: true 110 | SpaceBeforeInheritanceColon: false 111 | # The following options make the DSL macros behave 112 | # more like the C++ keywords they correspond to. 113 | SpaceBeforeParens: Custom 114 | SpaceBeforeParensOptions: 115 | AfterControlStatements: true 116 | AfterForeachMacros: false 117 | AfterFunctionDeclarationName: false 118 | AfterFunctionDefinitionName: false 119 | AfterIfMacros: true 120 | AfterOverloadedOperator: false 121 | BeforeNonEmptyParentheses: false 122 | SpaceAroundPointerQualifiers: Default 123 | SpaceBeforeRangeBasedForLoopColon: true 124 | SpaceInEmptyBlock: false 125 | SpacesBeforeTrailingComments: 1 126 | SpacesInAngles: Never 127 | 128 | SpacesInContainerLiterals: true 129 | ## Godot TODO: We'll want to use a min of 1, but we need to see how to fix 130 | ## our comment capitalization at the same time. 131 | SpacesInLineCommentPrefix: 132 | Minimum: 0 133 | Maximum: -1 134 | SpacesInSquareBrackets: false 135 | SpaceBeforeSquareBrackets: false 136 | BitFieldColonSpacing: Both 137 | AlignArrayOfStructures: Right -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | # Generated from CLion Inspection settings --- Checks: '-*, 2 | bugprone-argument-comment, 3 | bugprone-assert-side-effect, 4 | bugprone-bad-signal-to-kill-thread, 5 | bugprone-branch-clone, 6 | bugprone-copy-constructor-init, 7 | bugprone-dangling-handle, 8 | bugprone-dynamic-static-initializers, 9 | bugprone-fold-init-type, 10 | bugprone-forward-declaration-namespace, 11 | bugprone-forwarding-reference-overload, 12 | bugprone-inaccurate-erase, 13 | bugprone-incorrect-roundings, 14 | bugprone-integer-division, 15 | bugprone-lambda-function-name, 16 | bugprone-macro-repeated-side-effects, 17 | bugprone-misplaced-operator-in-strlen-in-alloc, 18 | bugprone-misplaced-pointer-arithmetic-in-alloc, 19 | bugprone-misplaced-widening-cast, 20 | bugprone-move-forwarding-reference, 21 | bugprone-multiple-statement-macro, 22 | bugprone-no-escape, 23 | bugprone-not-null-terminated-result, 24 | bugprone-parent-virtual-call, 25 | bugprone-posix-return, 26 | bugprone-reserved-identifier, 27 | bugprone-sizeof-container, 28 | bugprone-sizeof-expression, 29 | bugprone-spuriously-wake-up-functions, 30 | bugprone-string-constructor, 31 | bugprone-string-integer-assignment, 32 | bugprone-string-literal-with-embedded-nul, 33 | bugprone-suspicious-enum-usage, 34 | bugprone-suspicious-include, 35 | bugprone-suspicious-memset-usage, 36 | bugprone-suspicious-missing-comma, 37 | bugprone-suspicious-semicolon, 38 | bugprone-suspicious-string-compare, 39 | bugprone-suspicious-memory-comparison, 40 | bugprone-suspicious-realloc-usage, 41 | bugprone-swapped-arguments, 42 | bugprone-terminating-continue, 43 | bugprone-throw-keyword-missing, 44 | bugprone-too-small-loop-variable, 45 | bugprone-undefined-memory-manipulation, 46 | bugprone-undelegated-constructor, 47 | bugprone-unhandled-self-assignment, 48 | bugprone-unused-raii, 49 | bugprone-unused-return-value, 50 | bugprone-use-after-move, 51 | bugprone-virtual-near-miss, 52 | cert-dcl21-cpp, 53 | cert-dcl58-cpp, 54 | cert-err34-c, 55 | cert-err52-cpp, 56 | cert-err60-cpp, 57 | cert-flp30-c, 58 | cert-msc50-cpp, 59 | cert-msc51-cpp, 60 | cert-str34-c, 61 | cppcoreguidelines-interfaces-global-init, 62 | cppcoreguidelines-narrowing-conversions, 63 | cppcoreguidelines-pro-type-member-init, 64 | cppcoreguidelines-slicing, 65 | google-default-arguments, 66 | google-explicit-constructor, 67 | google-runtime-operator, 68 | hicpp-exception-baseclass, 69 | hicpp-multiway-paths-covered, 70 | misc-misplaced-const, 71 | misc-new-delete-overloads, 72 | misc-non-copyable-objects, 73 | misc-throw-by-value-catch-by-reference, 74 | misc-unconventional-assign-operator, 75 | misc-uniqueptr-reset-release, 76 | modernize-avoid-bind, 77 | modernize-concat-nested-namespaces, 78 | modernize-deprecated-headers, 79 | modernize-deprecated-ios-base-aliases, 80 | modernize-loop-convert, 81 | modernize-make-shared, 82 | modernize-make-unique, 83 | modernize-pass-by-value, 84 | modernize-raw-string-literal, 85 | modernize-redundant-void-arg, 86 | modernize-replace-auto-ptr, 87 | modernize-replace-disallow-copy-and-assign-macro, 88 | modernize-replace-random-shuffle, 89 | modernize-return-braced-init-list, 90 | modernize-shrink-to-fit, 91 | modernize-unary-static-assert, 92 | modernize-use-auto, 93 | modernize-use-bool-literals, 94 | modernize-use-emplace, 95 | modernize-use-equals-default, 96 | modernize-use-equals-delete, 97 | modernize-use-nodiscard, 98 | modernize-use-noexcept, 99 | modernize-use-nullptr, 100 | modernize-use-override, 101 | modernize-use-transparent-functors, 102 | modernize-use-uncaught-exceptions, 103 | mpi-buffer-deref, 104 | mpi-type-mismatch, 105 | openmp-use-default-none, 106 | performance-faster-string-find, 107 | performance-for-range-copy, 108 | performance-implicit-conversion-in-loop, 109 | performance-inefficient-algorithm, 110 | performance-inefficient-string-concatenation, 111 | performance-inefficient-vector-operation, 112 | performance-move-const-arg, 113 | performance-move-constructor-init, 114 | performance-no-automatic-move, 115 | performance-noexcept-move-constructor, 116 | performance-trivially-destructible, 117 | performance-type-promotion-in-math-fn, 118 | performance-unnecessary-copy-initialization, 119 | performance-unnecessary-value-param, 120 | portability-simd-intrinsics, 121 | readability-avoid-const-params-in-decls, 122 | readability-const-return-type, 123 | readability-container-size-empty, 124 | readability-delete-null-pointer, 125 | readability-deleted-default, 126 | readability-inconsistent-declaration-parameter-name, 127 | readability-make-member-function-const, 128 | readability-misleading-indentation, 129 | readability-misplaced-array-index, 130 | readability-non-const-parameter, 131 | readability-redundant-control-flow, 132 | readability-redundant-declaration, 133 | readability-redundant-function-ptr-dereference, 134 | readability-redundant-smartptr-get, 135 | readability-redundant-string-cstr, 136 | readability-redundant-string-init, 137 | readability-simplify-subscript-expr, 138 | readability-static-accessed-through-instance, 139 | readability-static-definition-in-anonymous-namespace, 140 | readability-string-compare, 141 | readability-uniqueptr-delete-release, 142 | readability-use-anyofallof' -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Assets/Model/ground.mtl: -------------------------------------------------------------------------------- 1 | newmtl TestMat 2 | d 1.0000 3 | Ns 10.0000 4 | Ka 0.8000 0.8000 0.8000 5 | Kd 0.3000 0.3000 0.3000 6 | Ks 0.0000 0.0000 0.0000 7 | map_Kd ..\Texture\floor.png 8 | -------------------------------------------------------------------------------- /Assets/Model/ground_35.mbo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Assets/Model/ground_35.mbo -------------------------------------------------------------------------------- /Assets/Texture/floor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Assets/Texture/floor.png -------------------------------------------------------------------------------- /Assets/Texture/lake/back.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Assets/Texture/lake/back.jpg -------------------------------------------------------------------------------- /Assets/Texture/lake/bottom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Assets/Texture/lake/bottom.jpg -------------------------------------------------------------------------------- /Assets/Texture/lake/front.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Assets/Texture/lake/front.jpg -------------------------------------------------------------------------------- /Assets/Texture/lake/left.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Assets/Texture/lake/left.jpg -------------------------------------------------------------------------------- /Assets/Texture/lake/right.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Assets/Texture/lake/right.jpg -------------------------------------------------------------------------------- /Assets/Texture/lake/top.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Assets/Texture/lake/top.jpg -------------------------------------------------------------------------------- /Assets/Texture/wall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Assets/Texture/wall.png -------------------------------------------------------------------------------- /Include/Component/Camera.h: -------------------------------------------------------------------------------- 1 | //*************************************************************************************** 2 | // Camera.h by X_Jun(MKXJun) (C) 2018-2020 All Rights Reserved. 3 | // Licensed under the MIT License. 4 | // 5 | // 提供第一人称(自由视角)和第三人称摄像机 6 | // Provide 1st person(free view) and 3rd person cameras. 7 | //*************************************************************************************** 8 | 9 | #ifndef CAMERA_H 10 | #define CAMERA_H 11 | 12 | #include "Transform.h" 13 | #include 14 | #include 15 | 16 | class Camera 17 | { 18 | public: 19 | Camera() = default; 20 | virtual ~Camera() = 0; 21 | 22 | // 23 | // 获取摄像机位置 24 | // 25 | 26 | DirectX::XMVECTOR GetPositionXM() const; 27 | DirectX::XMFLOAT3 GetPosition() const; 28 | 29 | // 30 | // 获取摄像机旋转 31 | // 32 | 33 | // 获取绕X轴旋转的欧拉角弧度 34 | float GetRotationX() const; 35 | // 获取绕Y轴旋转的欧拉角弧度 36 | float GetRotationY() const; 37 | 38 | // 获取fovy(垂直视场角) 39 | float GetFovy() const; 40 | // 获取宽高比 41 | float GetAspect() const; 42 | 43 | // 44 | // 获取摄像机的坐标轴向量 45 | // 46 | 47 | DirectX::XMVECTOR GetRightAxisXM() const; 48 | DirectX::XMFLOAT3 GetRightAxis() const; 49 | DirectX::XMVECTOR GetUpAxisXM() const; 50 | DirectX::XMFLOAT3 GetUpAxis() const; 51 | DirectX::XMVECTOR GetLookAxisXM() const; 52 | DirectX::XMFLOAT3 GetLookAxis() const; 53 | 54 | // 55 | // 获取矩阵 56 | // 57 | 58 | DirectX::XMMATRIX GetViewXM() const; 59 | DirectX::XMMATRIX GetProjXM() const; 60 | DirectX::XMMATRIX GetViewProjXM() const; 61 | 62 | // 获取视口 63 | D3D11_VIEWPORT GetViewPort() const; 64 | 65 | // 设置视锥体 66 | void SetFrustum(float fovY, float aspect, float nearZ, float farZ); 67 | 68 | // 设置视口 69 | void SetViewPort(const D3D11_VIEWPORT &viewPort); 70 | void SetViewPort(float topLeftX, 71 | float topLeftY, 72 | float width, 73 | float height, 74 | float minDepth = 0.0f, 75 | float maxDepth = 1.0f); 76 | 77 | protected: 78 | // 摄像机的变换 79 | Transform m_Transform = {}; 80 | 81 | // 视锥体属性 82 | float m_NearZ = 0.0f; 83 | float m_FarZ = 0.0f; 84 | float m_Aspect = 0.0f; 85 | float m_FovY = 0.0f; 86 | 87 | // 当前视口 88 | D3D11_VIEWPORT m_ViewPort = {}; 89 | }; 90 | 91 | class FirstPersonCamera: public Camera 92 | { 93 | public: 94 | FirstPersonCamera() = default; 95 | ~FirstPersonCamera() override; 96 | 97 | // 设置摄像机位置 98 | void SetPosition(float x, float y, float z); 99 | void SetPosition(const DirectX::XMFLOAT3 &pos); 100 | // 设置摄像机的朝向 101 | void LookAt(const DirectX::XMFLOAT3 &pos, const DirectX::XMFLOAT3 &target, const DirectX::XMFLOAT3 &up); 102 | void LookTo(const DirectX::XMFLOAT3 &pos, const DirectX::XMFLOAT3 &to, const DirectX::XMFLOAT3 &up); 103 | // 平移 104 | void Strafe(float d); 105 | // 直行(平面移动) 106 | void Walk(float d); 107 | // 前进(朝前向移动) 108 | void MoveForward(float d); 109 | // 上下观察 110 | // 正rad值向上观察 111 | // 负rad值向下观察 112 | void Pitch(float rad); 113 | // 左右观察 114 | // 正rad值向右观察 115 | // 负rad值向左观察 116 | void RotateY(float rad); 117 | }; 118 | 119 | class ThirdPersonCamera: public Camera 120 | { 121 | public: 122 | ThirdPersonCamera() = default; 123 | ~ThirdPersonCamera() override; 124 | 125 | // 获取当前跟踪物体的位置 126 | DirectX::XMFLOAT3 GetTargetPosition() const; 127 | // 获取与物体的距离 128 | float GetDistance() const; 129 | // 绕物体垂直旋转(注意绕x轴旋转欧拉角弧度限制在[0, pi/3]) 130 | void RotateX(float rad); 131 | // 绕物体水平旋转 132 | void RotateY(float rad); 133 | // 拉近物体 134 | void Approach(float dist); 135 | // 设置初始绕X轴的弧度(注意绕x轴旋转欧拉角弧度限制在[0, pi/3]) 136 | void SetRotationX(float rad); 137 | // 设置初始绕Y轴的弧度 138 | void SetRotationY(float rad); 139 | // 设置并绑定待跟踪物体的位置 140 | void SetTarget(const DirectX::XMFLOAT3 &target); 141 | // 设置初始距离 142 | void SetDistance(float dist); 143 | // 设置最小最大允许距离 144 | void SetDistanceMinMax(float minDist, float maxDist); 145 | 146 | private: 147 | DirectX::XMFLOAT3 m_Target = {}; 148 | float m_Distance = 0.0f; 149 | // 最小允许距离,最大允许距离 150 | float m_MinDist = 0.0f, m_MaxDist = 0.0f; 151 | }; 152 | 153 | #endif 154 | -------------------------------------------------------------------------------- /Include/Component/LightHelper.h: -------------------------------------------------------------------------------- 1 | #ifndef LIGHTHELPER_H 2 | #define LIGHTHELPER_H 3 | 4 | #include 5 | #include 6 | 7 | // 方向光 8 | struct DirectionalLight 9 | { 10 | DirectionalLight() = default; 11 | 12 | DirectionalLight(const DirectionalLight&) = default; 13 | DirectionalLight& operator=(const DirectionalLight&) = default; 14 | 15 | DirectionalLight(DirectionalLight&&) = default; 16 | DirectionalLight& operator=(DirectionalLight&&) = default; 17 | 18 | DirectionalLight(const DirectX::XMFLOAT4& _ambient, const DirectX::XMFLOAT4& _diffuse, const DirectX::XMFLOAT4& _specular, 19 | const DirectX::XMFLOAT3& _direction) : 20 | ambient(_ambient), diffuse(_diffuse), specular(_specular), direction(_direction), pad() {} 21 | 22 | DirectX::XMFLOAT4 ambient; 23 | DirectX::XMFLOAT4 diffuse; 24 | DirectX::XMFLOAT4 specular; 25 | DirectX::XMFLOAT3 direction; 26 | float pad; // 最后用一个浮点数填充使得该结构体大小满足16的倍数,便于我们以后在HLSL设置数组 27 | }; 28 | 29 | //// 方向光 30 | //struct DirectionalLight 31 | //{ 32 | // DirectionalLight() = default; 33 | // 34 | // DirectionalLight(const DirectionalLight&) = default; 35 | // DirectionalLight& operator=(const DirectionalLight&) = default; 36 | // 37 | // DirectionalLight(DirectionalLight&&) = default; 38 | // DirectionalLight& operator=(DirectionalLight&&) = default; 39 | // 40 | // DirectionalLight(const DirectX::XMFLOAT4& _Color, const DirectX::XMFLOAT3& _direction,float _idensity): 41 | // Color(_Color), Direction(_direction),Idensity(_idensity) {} 42 | // 43 | // 44 | // DirectX::XMFLOAT4 Color; 45 | // DirectX::XMFLOAT3 Direction; 46 | // float Idensity; 47 | //}; 48 | 49 | // 点光 50 | struct PointLight 51 | { 52 | PointLight() = default; 53 | 54 | PointLight(const PointLight&) = default; 55 | PointLight& operator=(const PointLight&) = default; 56 | 57 | PointLight(PointLight&&) = default; 58 | PointLight& operator=(PointLight&&) = default; 59 | 60 | PointLight(const DirectX::XMFLOAT4& _ambient, const DirectX::XMFLOAT4& _diffuse, const DirectX::XMFLOAT4& _specular, 61 | const DirectX::XMFLOAT3& _position, float _range, const DirectX::XMFLOAT3& _att) : 62 | ambient(_ambient), diffuse(_diffuse), specular(_specular), position(_position), range(_range), att(_att), pad() {} 63 | 64 | DirectX::XMFLOAT4 ambient; 65 | DirectX::XMFLOAT4 diffuse; 66 | DirectX::XMFLOAT4 specular; 67 | 68 | // 打包成4D向量: (position, range) 69 | DirectX::XMFLOAT3 position; 70 | float range; 71 | 72 | // 打包成4D向量: (A0, A1, A2, pad) 73 | DirectX::XMFLOAT3 att; 74 | float pad; // 最后用一个浮点数填充使得该结构体大小满足16的倍数,便于我们以后在HLSL设置数组 75 | }; 76 | 77 | // 聚光灯 78 | struct SpotLight 79 | { 80 | SpotLight() = default; 81 | 82 | SpotLight(const SpotLight&) = default; 83 | SpotLight& operator=(const SpotLight&) = default; 84 | 85 | SpotLight(SpotLight&&) = default; 86 | SpotLight& operator=(SpotLight&&) = default; 87 | 88 | SpotLight(const DirectX::XMFLOAT4& _ambient, const DirectX::XMFLOAT4& _diffuse, const DirectX::XMFLOAT4& _specular, 89 | const DirectX::XMFLOAT3& _position, float _range, const DirectX::XMFLOAT3& _direction, 90 | float _spot, const DirectX::XMFLOAT3& _att) : 91 | ambient(_ambient), diffuse(_diffuse), specular(_specular), 92 | position(_position), range(_range), direction(_direction), spot(_spot), att(_att), pad() {} 93 | 94 | DirectX::XMFLOAT4 ambient; 95 | DirectX::XMFLOAT4 diffuse; 96 | DirectX::XMFLOAT4 specular; 97 | 98 | // 打包成4D向量: (position, range) 99 | DirectX::XMFLOAT3 position; 100 | float range; 101 | 102 | // 打包成4D向量: (direction, spot) 103 | DirectX::XMFLOAT3 direction; 104 | float spot; 105 | 106 | // 打包成4D向量: (att, pad) 107 | DirectX::XMFLOAT3 att; 108 | float pad; // 最后用一个浮点数填充使得该结构体大小满足16的倍数,便于我们以后在HLSL设置数组 109 | }; 110 | 111 | 112 | // 物体表面材质 113 | struct Material 114 | { 115 | Material() = default; 116 | 117 | Material(const Material&) = default; 118 | Material& operator=(const Material&) = default; 119 | 120 | Material(Material&&) = default; 121 | Material& operator=(Material&&) = default; 122 | 123 | Material(const DirectX::XMFLOAT4& _ambient, const DirectX::XMFLOAT4& _diffuse, const DirectX::XMFLOAT4& _specular, 124 | const DirectX::XMFLOAT4& _reflect) : 125 | ambient(_ambient), diffuse(_diffuse), specular(_specular), reflect(_reflect) {} 126 | 127 | DirectX::XMFLOAT4 ambient; 128 | DirectX::XMFLOAT4 diffuse; 129 | DirectX::XMFLOAT4 specular; // w = 镜面反射强度 130 | DirectX::XMFLOAT4 reflect; 131 | }; 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /Include/Component/Transform.h: -------------------------------------------------------------------------------- 1 | //*************************************************************************************** 2 | // Transform.h by X_Jun(MKXJun) (C) 2018-2020 All Rights Reserved. 3 | // Licensed under the MIT License. 4 | // 5 | // 描述对象缩放、旋转(欧拉角为基础)、平移 6 | // Provide 1st person(free view) and 3rd person cameras. 7 | //*************************************************************************************** 8 | 9 | #ifndef TRANSFORM_H 10 | #define TRANSFORM_H 11 | 12 | #include 13 | 14 | class Transform 15 | { 16 | public: 17 | Transform() = default; 18 | Transform(const DirectX::XMFLOAT3 &scale, const DirectX::XMFLOAT3 &rotation, const DirectX::XMFLOAT3 &position); 19 | ~Transform() = default; 20 | 21 | Transform(const Transform &) = default; 22 | Transform &operator=(const Transform &) = default; 23 | 24 | Transform(Transform &&) = default; 25 | Transform &operator=(Transform &&) = default; 26 | 27 | // 获取对象缩放比例 28 | DirectX::XMFLOAT3 GetScale() const; 29 | // 获取对象缩放比例 30 | DirectX::XMVECTOR GetScaleXM() const; 31 | 32 | // 获取对象欧拉角(弧度制) 33 | // 对象以Z-X-Y轴顺序旋转 34 | DirectX::XMFLOAT3 GetRotation() const; 35 | // 获取对象欧拉角(弧度制) 36 | // 对象以Z-X-Y轴顺序旋转 37 | DirectX::XMVECTOR GetRotationXM() const; 38 | 39 | // 获取对象位置 40 | DirectX::XMFLOAT3 GetPosition() const; 41 | // 获取对象位置 42 | DirectX::XMVECTOR GetPositionXM() const; 43 | 44 | // 获取右方向轴 45 | DirectX::XMFLOAT3 GetRightAxis() const; 46 | // 获取右方向轴 47 | DirectX::XMVECTOR GetRightAxisXM() const; 48 | 49 | // 获取上方向轴 50 | DirectX::XMFLOAT3 GetUpAxis() const; 51 | // 获取上方向轴 52 | DirectX::XMVECTOR GetUpAxisXM() const; 53 | 54 | // 获取前方向轴 55 | DirectX::XMFLOAT3 GetForwardAxis() const; 56 | // 获取前方向轴 57 | DirectX::XMVECTOR GetForwardAxisXM() const; 58 | 59 | // 获取世界变换矩阵 60 | DirectX::XMFLOAT4X4 GetLocalToWorldMatrix() const; 61 | // 获取世界变换矩阵 62 | DirectX::XMMATRIX GetLocalToWorldMatrixXM() const; 63 | 64 | // 获取逆世界变换矩阵 65 | DirectX::XMFLOAT4X4 GetWorldToLocalMatrix() const; 66 | // 获取逆世界变换矩阵 67 | DirectX::XMMATRIX GetWorldToLocalMatrixXM() const; 68 | 69 | // 设置对象缩放比例 70 | void SetScale(const DirectX::XMFLOAT3 &scale); 71 | // 设置对象缩放比例 72 | void SetScale(float x, float y, float z); 73 | 74 | // 设置对象欧拉角(弧度制) 75 | // 对象将以Z-X-Y轴顺序旋转 76 | void SetRotation(const DirectX::XMFLOAT3 &eulerAnglesInRadian); 77 | // 设置对象欧拉角(弧度制) 78 | // 对象将以Z-X-Y轴顺序旋转 79 | void SetRotation(float x, float y, float z); 80 | 81 | // 设置对象位置 82 | void SetPosition(const DirectX::XMFLOAT3 &position); 83 | // 设置对象位置 84 | void SetPosition(float x, float y, float z); 85 | 86 | // 指定欧拉角旋转对象 87 | void Rotate(const DirectX::XMFLOAT3 &eulerAnglesInRadian); 88 | // 指定以原点为中心绕轴旋转 89 | void RotateAxis(const DirectX::XMFLOAT3 &axis, float radian); 90 | // 指定以point为旋转中心绕轴旋转 91 | void RotateAround(const DirectX::XMFLOAT3 &point, const DirectX::XMFLOAT3 &axis, float radian); 92 | 93 | // 沿着某一方向平移 94 | void Translate(const DirectX::XMFLOAT3 &direction, float magnitude); 95 | 96 | // 观察某一点 97 | void LookAt(const DirectX::XMFLOAT3 &target, const DirectX::XMFLOAT3 &up = { 0.0f, 1.0f, 0.0f }); 98 | // 沿着某一方向观察 99 | void LookTo(const DirectX::XMFLOAT3 &direction, const DirectX::XMFLOAT3 &up = { 0.0f, 1.0f, 0.0f }); 100 | 101 | private: 102 | // 从旋转矩阵获取旋转欧拉角 103 | DirectX::XMFLOAT3 GetEulerAnglesFromRotationMatrix(const DirectX::XMFLOAT4X4 &rotationMatrix); 104 | 105 | private: 106 | DirectX::XMFLOAT3 m_Scale = { 1.0f, 1.0f, 1.0f }; // 缩放 107 | DirectX::XMFLOAT3 m_Rotation = {}; // 旋转欧拉角(弧度制) 108 | DirectX::XMFLOAT3 m_Position = {}; // 位置 109 | }; 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /Include/Effect/FluidRender.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Effects.h" 4 | #include 5 | #include 6 | #include 7 | 8 | class FluidRender 9 | { 10 | public: 11 | template using ComPtr = Microsoft::WRL::ComPtr; 12 | 13 | struct ParticleParams 14 | { 15 | UINT particleNums; 16 | DirectX::XMFLOAT4 color; 17 | float radius; 18 | float RestDistance; 19 | float scale; 20 | float blurRadiusWorld; 21 | float blurScale; 22 | float blurFalloff; 23 | float ior; 24 | DirectX::XMFLOAT4 invTexScale; 25 | DirectX::XMFLOAT4 clipToEye; 26 | DirectX::XMFLOAT4 invViewPort; 27 | DirectionalLight dirLight[1]; 28 | }; 29 | 30 | public: 31 | FluidRender() = default; 32 | ~FluidRender() = default; 33 | // 不允许拷贝,允许移动 34 | FluidRender(const FluidRender &) = delete; 35 | FluidRender &operator=(const FluidRender &) = delete; 36 | FluidRender(FluidRender &&) = default; 37 | FluidRender &operator=(FluidRender &&) = default; 38 | 39 | HRESULT Init(ID3D11Device *device, UINT particleNums, int clientWidth, int clientHeight); 40 | 41 | //窗口大小变化 42 | HRESULT OnResize(ID3D11Device *device, int clientWidth, int clientHeight); 43 | //粒子数量改变 44 | HRESULT ParticlesNumsResize(ID3D11Device *device, UINT particleNums); 45 | 46 | void UpdateVertexInputBuffer(ID3D11DeviceContext *deviceContext, 47 | ID3D11Buffer *updatePos, 48 | ID3D11Buffer *updateDensity); 49 | 50 | //绘制流体点精灵的深度图 51 | void CreateParticleDepth(ID3D11DeviceContext *deviceContext, 52 | FluidEffect &effect, 53 | ParticleParams params, 54 | int offset); 55 | 56 | void CreateEllipsoidDepth(ID3D11DeviceContext *deviceContext, 57 | FluidEffect &effect, 58 | ID3D11Buffer *anisotropy, 59 | ParticleParams params, 60 | int offset); 61 | 62 | void CreateParticleThickness(ID3D11DeviceContext *deviceContext, 63 | FluidEffect &effect, 64 | ParticleParams params, 65 | int offset); 66 | 67 | void DrawParticle(ID3D11DeviceContext *deviceContext, FluidEffect &effect, ParticleParams params, int offset); 68 | 69 | void DrawFluid(ID3D11DeviceContext *deviceContext, 70 | FluidEffect &effect, 71 | ID3D11RenderTargetView *sceneRTV, 72 | ID3D11DepthStencilView *sceneDSV, 73 | ID3D11Buffer *anisotropy, 74 | ParticleParams params, 75 | int offset); 76 | 77 | void BlurDepth(ID3D11DeviceContext *deviceContext, FluidEffect &effect, ParticleParams params, int offset); 78 | 79 | void Composite(ID3D11DeviceContext *deviceContext, 80 | FluidEffect &effect, 81 | ID3D11RenderTargetView *sceneRTV, 82 | ID3D11DepthStencilView *sceneDSV, 83 | ParticleParams params, 84 | int offset); 85 | 86 | ID3D11ShaderResourceView *GetDepthTexture2DSRV() { return m_pDepthTextrue->GetShaderResource(); }; 87 | ID3D11ShaderResourceView *GetBlurDepthTexture2DSRV() { return m_pBlurDepthTexture->GetShaderResource(); }; 88 | ID3D11ShaderResourceView *GetThicknessTexture2DSRV() { return m_pThicknessTextrue->GetShaderResource(); }; 89 | ID3D11ShaderResourceView *GetNormalTexture2DSRV() { return m_pReCalcNormalTextrue->GetShaderResource(); }; 90 | 91 | void SetDebugObjectName(const std::string &name); 92 | 93 | private: 94 | UINT m_ParticleNums = 0; 95 | 96 | int m_ClientWidth = 0; 97 | int m_ClientHeigh = 0; 98 | 99 | std::unique_ptr m_pDepthTextrue; //粒子深度图 100 | std::unique_ptr m_pBlurDepthTexture; //模糊后的深度图 101 | std::unique_ptr m_pThicknessTextrue; //粒子厚度图 102 | std::unique_ptr m_pCurrSeceneTextrue; //当前场景的场景信息 103 | std::unique_ptr m_pReCalcNormalTextrue; //根据深度重建的法线信息 104 | 105 | std::unique_ptr m_pEllipsoidDepthTexture; 106 | 107 | ComPtr m_pParticlePostionVB; //粒子的顶点数据 108 | ComPtr m_pParticleDensityVB; //粒子的顶点数据 109 | ComPtr m_pParticleAnsotropyVB; //粒子的各向异性 110 | ComPtr m_pParticleIB; //粒子的顶点索引数据 111 | ComPtr m_pQuadVB; 112 | ComPtr m_pQuadIB; 113 | }; 114 | -------------------------------------------------------------------------------- /Include/Effect/NeighborSearch.h: -------------------------------------------------------------------------------- 1 | #ifndef _NEIGHBORSEARCH_H 2 | #define _NEIGHBORSEARCH_H 3 | 4 | #include "Effects.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class NeighborSearch 11 | { 12 | public: 13 | template using ComPtr = Microsoft::WRL::ComPtr; 14 | 15 | public: 16 | NeighborSearch() = default; 17 | ~NeighborSearch() = default; 18 | // 不允许拷贝,允许移动 19 | NeighborSearch(const NeighborSearch &) = delete; 20 | NeighborSearch &operator=(const NeighborSearch &) = delete; 21 | NeighborSearch(NeighborSearch &&) = default; 22 | NeighborSearch &operator=(NeighborSearch &&) = default; 23 | 24 | HRESULT Init(ID3D11Device *device, UINT particleNums); 25 | //粒子数量改变 26 | HRESULT ParticlesNumsResize(ID3D11Device *device, UINT particleNums); 27 | 28 | void BeginNeighborSearch(ID3D11DeviceContext *deviceContext, 29 | ID3D11Buffer *pos, 30 | ID3D11Buffer *index, 31 | float cellSize); 32 | void CalcBounds(ID3D11DeviceContext *deviceContext, 33 | NeighborSearchEffect &effect, 34 | ID3D11Buffer *pos, 35 | ID3D11Buffer *index, 36 | float cellSize); 37 | //call after calcBounds 38 | void RadixSort(ID3D11DeviceContext *deviceContext, NeighborSearchEffect &effect); 39 | void FindCellStartAndEnd(ID3D11DeviceContext *deviceContext, NeighborSearchEffect &effect); 40 | void EndNeighborSearch(); 41 | 42 | void SetDebugName(std::string name); 43 | 44 | /*得到数据*/ 45 | ID3D11Buffer *GetSortedCellid() { return m_pDstKeyBuffer->GetBuffer(); } 46 | ID3D11Buffer *GetSortedParticleIndex() { return m_pDstValBuffer->GetBuffer(); } 47 | ID3D11Buffer *GetSortedCellStart() { return m_pCellStartBuffer->GetBuffer(); } 48 | ID3D11Buffer *GetSortedCellEnd() { return m_pCellEndBuffer->GetBuffer(); } 49 | ID3D11Buffer *GetBounds() { return m_pBoundsBuffer->GetBuffer(); } 50 | 51 | private: 52 | float m_Cellsize = 0.0f; 53 | 54 | UINT m_ParticleNums = 0; // the numbers of particle 55 | UINT m_HashTableSize = 0; // hash table size 56 | 57 | //bound group nums 58 | UINT m_BoundsGroup = 0; 59 | UINT m_BoundFinalizeNum = 0; 60 | 61 | //块的数量 62 | UINT m_BlockNums = 0; 63 | //处理总数 64 | UINT m_TotalNums = 0; 65 | UINT m_ConuterNums = 0; 66 | 67 | std::unique_ptr> m_pParticlePosBuffer; 68 | std::unique_ptr> m_pActiveIndexsBuffer; 69 | #pragma region Bounds 70 | std::unique_ptr> m_pReadBoundsLowerBuffer; 71 | std::unique_ptr> m_pReadBoundsUpperBuffer; 72 | std::unique_ptr> m_pWriteBoundsLowerBuffer; 73 | std::unique_ptr> m_pWriteBoundsUpperBuffer; 74 | std::unique_ptr> m_pBoundsBuffer; 75 | 76 | #pragma endregion 77 | 78 | #pragma region calchashBuffer 79 | 80 | std::unique_ptr> m_pCellHashBuffer; 81 | std::unique_ptr> m_pCellIndexsBuffer; 82 | #pragma endregion 83 | 84 | #pragma region RadixSortBuffer 85 | std::unique_ptr> m_pPrefixSumBuffer; 86 | std::unique_ptr> m_pSrcCountersBuffers; 87 | std::unique_ptr> m_pDstCountersBuffers; 88 | 89 | std::unique_ptr> m_pDstKeyBuffer; 90 | std::unique_ptr> m_pDstValBuffer; 91 | #pragma endregion 92 | 93 | #pragma region FindCellStart 94 | std::unique_ptr> m_pCellStartBuffer; 95 | std::unique_ptr> m_pCellEndBuffer; 96 | #pragma endregion 97 | }; 98 | 99 | #endif // !_NEIGHBORSEARCH_H 100 | -------------------------------------------------------------------------------- /Include/Effect/SkyRender.h: -------------------------------------------------------------------------------- 1 | //*************************************************************************************** 2 | // SkyRender.h by X_Jun(MKXJun) (C) 2018-2020 All Rights Reserved. 3 | // Licensed under the MIT License. 4 | // 5 | // 天空盒加载与渲染类 6 | // Skybox loader and render classes. 7 | //*************************************************************************************** 8 | 9 | #ifndef SKYRENDER_H 10 | #define SKYRENDER_H 11 | 12 | #include 13 | #include 14 | #include "Effects.h" 15 | #include 16 | 17 | class SkyRender 18 | { 19 | public: 20 | template 21 | using ComPtr = Microsoft::WRL::ComPtr; 22 | 23 | SkyRender() = default; 24 | ~SkyRender() = default; 25 | // 不允许拷贝,允许移动 26 | SkyRender(const SkyRender&) = delete; 27 | SkyRender& operator=(const SkyRender&) = delete; 28 | SkyRender(SkyRender&&) = default; 29 | SkyRender& operator=(SkyRender&&) = default; 30 | 31 | 32 | // 需要提供完整的天空盒贴图 或者 已经创建好的天空盒纹理.dds文件 33 | HRESULT InitResource(ID3D11Device* device, 34 | ID3D11DeviceContext* deviceContext, 35 | const std::wstring& cubemapFilename, 36 | float skySphereRadius, // 天空球半径 37 | bool generateMips = false); // 默认不为静态天空盒生成mipmaps 38 | 39 | // 需要提供天空盒的六张正方形贴图 40 | HRESULT InitResource(ID3D11Device* device, 41 | ID3D11DeviceContext* deviceContext, 42 | const std::vector& cubemapFilenames, 43 | float skySphereRadius, // 天空球半径 44 | bool generateMips = false); // 默认不为静态天空盒生成mipmaps 45 | 46 | ID3D11ShaderResourceView* GetTextureCube(); 47 | 48 | void Draw(ID3D11DeviceContext* deviceContext, SkyEffect& skyEffect, const Camera& camera); 49 | 50 | // 设置调试对象名 51 | void SetDebugObjectName(const std::string& name); 52 | 53 | private: 54 | HRESULT InitResource(ID3D11Device* device, float skySphereRadius); 55 | 56 | 57 | private: 58 | ComPtr m_pVertexBuffer; 59 | ComPtr m_pIndexBuffer; 60 | 61 | UINT m_IndexCount = 0; 62 | 63 | ComPtr m_pTextureCubeSRV; 64 | }; 65 | 66 | class DynamicSkyRender : public SkyRender 67 | { 68 | public: 69 | DynamicSkyRender() = default; 70 | ~DynamicSkyRender() = default; 71 | // 不允许拷贝,允许移动 72 | DynamicSkyRender(const DynamicSkyRender&) = delete; 73 | DynamicSkyRender& operator=(const DynamicSkyRender&) = delete; 74 | DynamicSkyRender(DynamicSkyRender&&) = default; 75 | DynamicSkyRender& operator=(DynamicSkyRender&&) = default; 76 | 77 | HRESULT InitResource(ID3D11Device* device, 78 | ID3D11DeviceContext* deviceContext, 79 | const std::wstring& cubemapFilename, 80 | float skySphereRadius, // 天空球半径 81 | int dynamicCubeSize, // 立方体棱长 82 | bool generateMips = false); // 默认不为静态天空盒生成mipmaps 83 | // 动态天空盒必然生成mipmaps 84 | 85 | HRESULT InitResource(ID3D11Device* device, 86 | ID3D11DeviceContext* deviceContext, 87 | const std::vector& cubemapFilenames, 88 | float skySphereRadius, // 天空球半径 89 | int dynamicCubeSize, // 立方体棱长 90 | bool generateMips = false); // 默认不为静态天空盒生成mipmaps 91 | // 动态天空盒必然生成mipmaps 92 | 93 | 94 | // 缓存当前渲染目标视图 95 | void Cache(ID3D11DeviceContext* deviceContext, BasicEffect& effect); 96 | 97 | // 指定天空盒某一面开始绘制,需要先调用Cache方法 98 | void BeginCapture(ID3D11DeviceContext* deviceContext, BasicEffect& effect, const DirectX::XMFLOAT3& pos, 99 | D3D11_TEXTURECUBE_FACE face, float nearZ = 1e-3f, float farZ = 1e3f); 100 | 101 | // 恢复渲染目标视图及摄像机,并绑定当前动态天空盒 102 | void Restore(ID3D11DeviceContext* deviceContext, BasicEffect& effect, const Camera& camera); 103 | 104 | // 获取动态天空盒 105 | // 注意:该方法只能在Restore后再调用 106 | ID3D11ShaderResourceView* GetDynamicTextureCube(); 107 | 108 | // 获取当前用于捕获的天空盒 109 | const Camera& GetCamera() const; 110 | 111 | // 设置调试对象名 112 | void SetDebugObjectName(const std::string& name); 113 | 114 | private: 115 | HRESULT InitResource(ID3D11Device* device, int dynamicCubeSize); 116 | 117 | private: 118 | ComPtr m_pCacheRTV; // 临时缓存的后备缓冲区 119 | ComPtr m_pCacheDSV; // 临时缓存的深度/模板缓冲区 120 | 121 | FirstPersonCamera m_pCamera; // 捕获当前天空盒其中一面的摄像机 122 | ComPtr m_pDynamicCubeMapDSV; // 动态天空盒渲染对应的深度/模板视图 123 | ComPtr m_pDynamicCubeMapSRV; // 动态天空盒对应的着色器资源视图 124 | ComPtr m_pDynamicCubeMapRTVs[6]; // 动态天空盒每个面对应的渲染目标视图 125 | 126 | }; 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /Include/Graphics/DDSTextureLoader.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------- 2 | // File: DDSTextureLoader.h 3 | // 4 | // Functions for loading a DDS texture and creating a Direct3D runtime resource for it 5 | // 6 | // Note these functions are useful as a light-weight runtime loader for DDS files. For 7 | // a full-featured DDS file reader, writer, and texture processing pipeline see 8 | // the 'Texconv' sample and the 'DirectXTex' library. 9 | // 10 | // Copyright (c) Microsoft Corporation. All rights reserved. 11 | // Licensed under the MIT License. 12 | // 13 | // http://go.microsoft.com/fwlink/?LinkId=248926 14 | // http://go.microsoft.com/fwlink/?LinkId=248929 15 | //-------------------------------------------------------------------------------------- 16 | 17 | #pragma once 18 | 19 | #include 20 | #include 21 | 22 | 23 | namespace DirectX 24 | { 25 | enum DDS_ALPHA_MODE 26 | { 27 | DDS_ALPHA_MODE_UNKNOWN = 0, 28 | DDS_ALPHA_MODE_STRAIGHT = 1, 29 | DDS_ALPHA_MODE_PREMULTIPLIED = 2, 30 | DDS_ALPHA_MODE_OPAQUE = 3, 31 | DDS_ALPHA_MODE_CUSTOM = 4, 32 | }; 33 | 34 | // Standard version 35 | HRESULT CreateDDSTextureFromMemory( 36 | _In_ ID3D11Device* d3dDevice, 37 | _In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, 38 | _In_ size_t ddsDataSize, 39 | _Outptr_opt_ ID3D11Resource** texture, 40 | _Outptr_opt_ ID3D11ShaderResourceView** textureView, 41 | _In_ size_t maxsize = 0, 42 | _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr); 43 | 44 | HRESULT CreateDDSTextureFromFile( 45 | _In_ ID3D11Device* d3dDevice, 46 | _In_z_ const wchar_t* szFileName, 47 | _Outptr_opt_ ID3D11Resource** texture, 48 | _Outptr_opt_ ID3D11ShaderResourceView** textureView, 49 | _In_ size_t maxsize = 0, 50 | _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr); 51 | 52 | // Standard version with optional auto-gen mipmap support 53 | HRESULT CreateDDSTextureFromMemory( 54 | _In_ ID3D11Device* d3dDevice, 55 | _In_opt_ ID3D11DeviceContext* d3dContext, 56 | _In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, 57 | _In_ size_t ddsDataSize, 58 | _Outptr_opt_ ID3D11Resource** texture, 59 | _Outptr_opt_ ID3D11ShaderResourceView** textureView, 60 | _In_ size_t maxsize = 0, 61 | _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr); 62 | 63 | HRESULT CreateDDSTextureFromFile( 64 | _In_ ID3D11Device* d3dDevice, 65 | _In_opt_ ID3D11DeviceContext* d3dContext, 66 | _In_z_ const wchar_t* szFileName, 67 | _Outptr_opt_ ID3D11Resource** texture, 68 | _Outptr_opt_ ID3D11ShaderResourceView** textureView, 69 | _In_ size_t maxsize = 0, 70 | _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr); 71 | 72 | // Extended version 73 | HRESULT CreateDDSTextureFromMemoryEx( 74 | _In_ ID3D11Device* d3dDevice, 75 | _In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, 76 | _In_ size_t ddsDataSize, 77 | _In_ size_t maxsize, 78 | _In_ D3D11_USAGE usage, 79 | _In_ unsigned int bindFlags, 80 | _In_ unsigned int cpuAccessFlags, 81 | _In_ unsigned int miscFlags, 82 | _In_ bool forceSRGB, 83 | _Outptr_opt_ ID3D11Resource** texture, 84 | _Outptr_opt_ ID3D11ShaderResourceView** textureView, 85 | _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr); 86 | 87 | HRESULT CreateDDSTextureFromFileEx( 88 | _In_ ID3D11Device* d3dDevice, 89 | _In_z_ const wchar_t* szFileName, 90 | _In_ size_t maxsize, 91 | _In_ D3D11_USAGE usage, 92 | _In_ unsigned int bindFlags, 93 | _In_ unsigned int cpuAccessFlags, 94 | _In_ unsigned int miscFlags, 95 | _In_ bool forceSRGB, 96 | _Outptr_opt_ ID3D11Resource** texture, 97 | _Outptr_opt_ ID3D11ShaderResourceView** textureView, 98 | _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr); 99 | 100 | // Extended version with optional auto-gen mipmap support 101 | HRESULT CreateDDSTextureFromMemoryEx( 102 | _In_ ID3D11Device* d3dDevice, 103 | _In_opt_ ID3D11DeviceContext* d3dContext, 104 | _In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, 105 | _In_ size_t ddsDataSize, 106 | _In_ size_t maxsize, 107 | _In_ D3D11_USAGE usage, 108 | _In_ unsigned int bindFlags, 109 | _In_ unsigned int cpuAccessFlags, 110 | _In_ unsigned int miscFlags, 111 | _In_ bool forceSRGB, 112 | _Outptr_opt_ ID3D11Resource** texture, 113 | _Outptr_opt_ ID3D11ShaderResourceView** textureView, 114 | _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr); 115 | 116 | HRESULT CreateDDSTextureFromFileEx( 117 | _In_ ID3D11Device* d3dDevice, 118 | _In_opt_ ID3D11DeviceContext* d3dContext, 119 | _In_z_ const wchar_t* szFileName, 120 | _In_ size_t maxsize, 121 | _In_ D3D11_USAGE usage, 122 | _In_ unsigned int bindFlags, 123 | _In_ unsigned int cpuAccessFlags, 124 | _In_ unsigned int miscFlags, 125 | _In_ bool forceSRGB, 126 | _Outptr_opt_ ID3D11Resource** texture, 127 | _Outptr_opt_ ID3D11ShaderResourceView** textureView, 128 | _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr); 129 | } -------------------------------------------------------------------------------- /Include/Graphics/RenderStates.h: -------------------------------------------------------------------------------- 1 | //*************************************************************************************** 2 | // RenderStates.h by X_Jun(MKXJun) (C) 2018-2020 All Rights Reserved. 3 | // Licensed under the MIT License. 4 | // 5 | // 提供一些渲染状态 6 | // Provide some render states. 7 | //*************************************************************************************** 8 | 9 | #ifndef RENDERSTATES_H 10 | #define RENDERSTATES_H 11 | 12 | #include 13 | #include 14 | 15 | 16 | class RenderStates 17 | { 18 | public: 19 | template 20 | using ComPtr = Microsoft::WRL::ComPtr; 21 | 22 | static bool IsInit(); 23 | 24 | static void InitAll(ID3D11Device * device); 25 | // 使用ComPtr无需手工释放 26 | 27 | public: 28 | static ComPtr RSWireframe; // 光栅化器状态:线框模式 29 | static ComPtr RSNoCull; // 光栅化器状态:无背面裁剪模式 30 | static ComPtr RSCullClockWise; // 光栅化器状态:顺时针裁剪模式 31 | static ComPtr RSDepth; // 光栅化器状态:深度偏移模式 32 | static ComPtr RSNoCullWithFrontCCW; // 光栅化器状态:无背面+CCW 33 | 34 | static ComPtr SSPointClamp; // 采样器状态:点过滤与Clamp模式 35 | static ComPtr SSLinearWrap; // 采样器状态:线性过滤与Wrap模式 36 | static ComPtr SSAnistropicWrap; // 采样器状态:各向异性过滤与Wrap模式 37 | static ComPtr SSShadow; // 采样器状态:深度比较与Border模式 38 | static ComPtr SSClampWrap; 39 | 40 | static ComPtr BSNoColorWrite; // 混合状态:不写入颜色 41 | static ComPtr BSTransparent; // 混合状态:透明混合 42 | static ComPtr BSAlphaToCoverage; // 混合状态:Alpha-To-Coverage 43 | static ComPtr BSAdditive; // 混合状态:加法混合 44 | static ComPtr BSAlphaWeightedAdditive; // 混合状态:以Alpha为权重的加法混合 45 | 46 | static ComPtr DSSEqual; // 深度/模板状态:仅允许绘制深度值相等的像素 47 | static ComPtr DSSLessEqual; // 深度/模板状态:在默认深度测试的基础上额外允许绘制深度值相等的像素 48 | static ComPtr DSSWriteStencil; // 深度/模板状态:写入模板值 49 | static ComPtr DSSDrawWithStencil; // 深度/模板状态:对指定模板值的区域进行绘制 50 | static ComPtr DSSNoDoubleBlend; // 深度/模板状态:无二次混合区域 51 | static ComPtr DSSNoDepthTest; // 深度/模板状态:关闭深度测试 52 | static ComPtr DSSNoDepthWrite; // 深度/模板状态:仅深度测试,不写入深度值 53 | static ComPtr DSSNoDepthTestWithStencil; // 深度/模板状态:关闭深度测试,对指定模板值的区域进行绘制 54 | static ComPtr DSSNoDepthWriteWithStencil; // 深度/模板状态:仅深度测试,不写入深度值,对指定模板值的区域进行绘制 55 | }; 56 | 57 | 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /Include/Graphics/WICTextureLoader.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------- 2 | // File: WICTextureLoader.h 3 | // 4 | // Function for loading a WIC image and creating a Direct3D runtime texture for it 5 | // (auto-generating mipmaps if possible) 6 | // 7 | // Note: Assumes application has already called CoInitializeEx 8 | // 9 | // Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for 10 | // auto-gen mipmap support. 11 | // 12 | // Note these functions are useful for images created as simple 2D textures. For 13 | // more complex resources, DDSTextureLoader is an excellent light-weight runtime loader. 14 | // For a full-featured DDS file reader, writer, and texture processing pipeline see 15 | // the 'Texconv' sample and the 'DirectXTex' library. 16 | // 17 | // Copyright (c) Microsoft Corporation. All rights reserved. 18 | // Licensed under the MIT License. 19 | // 20 | // http://go.microsoft.com/fwlink/?LinkId=248926 21 | // http://go.microsoft.com/fwlink/?LinkId=248929 22 | //-------------------------------------------------------------------------------------- 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | 29 | 30 | namespace DirectX 31 | { 32 | enum WIC_LOADER_FLAGS 33 | { 34 | WIC_LOADER_DEFAULT = 0, 35 | WIC_LOADER_FORCE_SRGB = 0x1, 36 | WIC_LOADER_IGNORE_SRGB = 0x2, 37 | }; 38 | 39 | // Standard version 40 | HRESULT CreateWICTextureFromMemory( 41 | _In_ ID3D11Device* d3dDevice, 42 | _In_reads_bytes_(wicDataSize) const uint8_t* wicData, 43 | _In_ size_t wicDataSize, 44 | _Outptr_opt_ ID3D11Resource** texture, 45 | _Outptr_opt_ ID3D11ShaderResourceView** textureView, 46 | _In_ size_t maxsize = 0); 47 | 48 | HRESULT CreateWICTextureFromFile( 49 | _In_ ID3D11Device* d3dDevice, 50 | _In_z_ const wchar_t* szFileName, 51 | _Outptr_opt_ ID3D11Resource** texture, 52 | _Outptr_opt_ ID3D11ShaderResourceView** textureView, 53 | _In_ size_t maxsize = 0); 54 | 55 | // Standard version with optional auto-gen mipmap support 56 | HRESULT CreateWICTextureFromMemory( 57 | _In_ ID3D11Device* d3dDevice, 58 | _In_opt_ ID3D11DeviceContext* d3dContext, 59 | _In_reads_bytes_(wicDataSize) const uint8_t* wicData, 60 | _In_ size_t wicDataSize, 61 | _Outptr_opt_ ID3D11Resource** texture, 62 | _Outptr_opt_ ID3D11ShaderResourceView** textureView, 63 | _In_ size_t maxsize = 0); 64 | 65 | HRESULT CreateWICTextureFromFile( 66 | _In_ ID3D11Device* d3dDevice, 67 | _In_opt_ ID3D11DeviceContext* d3dContext, 68 | _In_z_ const wchar_t* szFileName, 69 | _Outptr_opt_ ID3D11Resource** texture, 70 | _Outptr_opt_ ID3D11ShaderResourceView** textureView, 71 | _In_ size_t maxsize = 0); 72 | 73 | // Extended version 74 | HRESULT CreateWICTextureFromMemoryEx( 75 | _In_ ID3D11Device* d3dDevice, 76 | _In_reads_bytes_(wicDataSize) const uint8_t* wicData, 77 | _In_ size_t wicDataSize, 78 | _In_ size_t maxsize, 79 | _In_ D3D11_USAGE usage, 80 | _In_ unsigned int bindFlags, 81 | _In_ unsigned int cpuAccessFlags, 82 | _In_ unsigned int miscFlags, 83 | _In_ unsigned int loadFlags, 84 | _Outptr_opt_ ID3D11Resource** texture, 85 | _Outptr_opt_ ID3D11ShaderResourceView** textureView); 86 | 87 | HRESULT CreateWICTextureFromFileEx( 88 | _In_ ID3D11Device* d3dDevice, 89 | _In_z_ const wchar_t* szFileName, 90 | _In_ size_t maxsize, 91 | _In_ D3D11_USAGE usage, 92 | _In_ unsigned int bindFlags, 93 | _In_ unsigned int cpuAccessFlags, 94 | _In_ unsigned int miscFlags, 95 | _In_ unsigned int loadFlags, 96 | _Outptr_opt_ ID3D11Resource** texture, 97 | _Outptr_opt_ ID3D11ShaderResourceView** textureView); 98 | 99 | // Extended version with optional auto-gen mipmap support 100 | HRESULT CreateWICTextureFromMemoryEx( 101 | _In_ ID3D11Device* d3dDevice, 102 | _In_opt_ ID3D11DeviceContext* d3dContext, 103 | _In_reads_bytes_(wicDataSize) const uint8_t* wicData, 104 | _In_ size_t wicDataSize, 105 | _In_ size_t maxsize, 106 | _In_ D3D11_USAGE usage, 107 | _In_ unsigned int bindFlags, 108 | _In_ unsigned int cpuAccessFlags, 109 | _In_ unsigned int miscFlags, 110 | _In_ unsigned int loadFlags, 111 | _Outptr_opt_ ID3D11Resource** texture, 112 | _Outptr_opt_ ID3D11ShaderResourceView** textureView); 113 | 114 | HRESULT CreateWICTextureFromFileEx( 115 | _In_ ID3D11Device* d3dDevice, 116 | _In_opt_ ID3D11DeviceContext* d3dContext, 117 | _In_z_ const wchar_t* szFileName, 118 | _In_ size_t maxsize, 119 | _In_ D3D11_USAGE usage, 120 | _In_ unsigned int bindFlags, 121 | _In_ unsigned int cpuAccessFlags, 122 | _In_ unsigned int miscFlags, 123 | _In_ unsigned int loadFlags, 124 | _Outptr_opt_ ID3D11Resource** texture, 125 | _Outptr_opt_ ID3D11ShaderResourceView** textureView); 126 | } -------------------------------------------------------------------------------- /Include/Graphics/d3dApp.h: -------------------------------------------------------------------------------- 1 | #ifndef D3DAPP_H 2 | #define D3DAPP_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | class D3DApp 16 | { 17 | public: 18 | D3DApp(HINSTANCE hInstance, const std::wstring &windowName, int initWidth, int initHeight); 19 | virtual ~D3DApp(); 20 | 21 | HINSTANCE AppInst() const; // 获取应用实例的句柄 22 | HWND MainWnd() const; // 获取主窗口句柄 23 | float AspectRatio() const; // 获取屏幕宽高比 24 | 25 | int Run(); // 运行程序,执行消息事件的循环 26 | 27 | // 框架方法。客户派生类需要重载这些方法以实现特定的应用需求 28 | virtual bool Init(); // 该父类方法需要初始化窗口、Direct2D和Direct3D部分 29 | virtual void OnResize(); // 该父类方法需要在窗口大小变动的时候调用 30 | virtual void UpdateScene(float dt) = 0; // 子类需要实现该方法,完成每一帧的更新 31 | virtual void DrawScene() = 0; // 子类需要实现该方法,完成每一帧的绘制 32 | virtual LRESULT MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); 33 | // 窗口的消息回调函数 34 | 35 | protected: 36 | bool InitMainWindow(); // 窗口初始化 37 | bool InitDirect3D(); // Direct3D初始化 38 | bool InitImGui(); // ImGui初始化 39 | 40 | void CalculateFrameStats(); // 计算每秒帧数并在窗口显示 41 | 42 | protected: 43 | HINSTANCE m_hAppInst; // 应用实例句柄 44 | HWND m_hMainWnd; // 主窗口句柄 45 | bool m_AppPaused; // 应用是否暂停 46 | bool m_Minimized; // 应用是否最小化 47 | bool m_Maximized; // 应用是否最大化 48 | bool m_Resizing; // 窗口大小是否变化 49 | 50 | GameTimer m_Timer; // 计时器 51 | 52 | // 使用模板别名(C++11)简化类型名 53 | template using ComPtr = Microsoft::WRL::ComPtr; 54 | // Direct3D 11 55 | ComPtr m_pd3dDevice; // D3D11设备 56 | ComPtr m_pd3dImmediateContext; // D3D11设备上下文 57 | ComPtr m_pSwapChain; // D3D11交换链 58 | // Direct3D 11.1 59 | ComPtr m_pd3dDevice1; // D3D11.1设备 60 | ComPtr m_pd3dImmediateContext1; // D3D11.1设备上下文 61 | ComPtr m_pSwapChain1; // D3D11.1交换链 62 | // 常用资源 63 | ComPtr m_pDepthStencilBuffer; // 深度模板缓冲区 64 | ComPtr m_pRenderTargetView; // 渲染目标视图 65 | ComPtr m_pDepthStencilView; // 深度模板视图 66 | D3D11_VIEWPORT m_ScreenViewport; // 视口 67 | // 派生类应该在构造函数设置好这些自定义的初始参数 68 | std::wstring m_MainWndCaption; // 主窗口标题 69 | int m_ClientWidth; // 视口宽度 70 | int m_ClientHeight; // 视口高度 71 | }; 72 | 73 | #endif // D3DAPP_H -------------------------------------------------------------------------------- /Include/Hierarchy/CameraController.h: -------------------------------------------------------------------------------- 1 | //*************************************************************************************** 2 | // Camera.h by X_Jun(MKXJun) (C) 2018-2022 All Rights Reserved. 3 | // Licensed under the MIT License. 4 | // 5 | // 提供第一人称(自由视角)的简易控制器,需要ImGui 6 | // Provide 1st person(free view) camera controller. ImGui is required. 7 | //*************************************************************************************** 8 | 9 | #ifndef CAMERACONTROLLER_H 10 | #define CAMERACONTROLLER_H 11 | 12 | #include 13 | 14 | class CameraController 15 | { 16 | public: 17 | CameraController() = default; 18 | CameraController &operator=(const CameraController &) = delete; 19 | virtual ~CameraController() {} 20 | virtual void Update(float deltaTime) = 0; 21 | 22 | // Helper function 23 | 24 | static void ApplyMomentum(float &oldValue, float &newValue, float deltaTime); 25 | }; 26 | 27 | class FirstPersonCameraController: public CameraController 28 | { 29 | public: 30 | ~FirstPersonCameraController() override{}; 31 | void Update(float deltaTime) override; 32 | 33 | void InitCamera(FirstPersonCamera *pCamera); 34 | 35 | void SlowMovement(bool enable); 36 | void SlowRotation(bool enable); 37 | void EnableMomentum(bool enable); 38 | 39 | void SetMouseSensitivity(float x, float y); 40 | void SetMoveSpeed(float speed); 41 | void SetStrafeSpeed(float speed); 42 | 43 | private: 44 | FirstPersonCamera *m_pCamera = nullptr; 45 | 46 | float m_MoveSpeed = 5.0f; 47 | float m_StrafeSpeed = 5.0f; 48 | float m_MouseSensitivityX = 0.005f; 49 | float m_MouseSensitivityY = 0.005f; 50 | 51 | float m_CurrentYaw = 0.0f; 52 | float m_CurrentPitch = 0.0f; 53 | 54 | bool m_FineMovement = false; 55 | bool m_FineRotation = false; 56 | bool m_Momentum = true; 57 | 58 | float m_LastForward = 0.0f; 59 | float m_LastStrafe = 0.0f; 60 | }; 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /Include/Hierarchy/FluidSystem.h: -------------------------------------------------------------------------------- 1 | #ifndef _FLUIDSYSTEM_H 2 | #define _FLUIDSYSTEM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | //**************** 16 | //流体系统类 17 | class FluidSystem 18 | { 19 | public: 20 | template using ComPtr = Microsoft::WRL::ComPtr; 21 | 22 | public: 23 | FluidSystem(); 24 | ~FluidSystem(); 25 | 26 | bool InitEffect(ID3D11Device *device); 27 | 28 | //窗口大小变化 29 | HRESULT OnResize(ID3D11Device *device, int clientWidth, int clientHeight); 30 | 31 | bool InitResource(ID3D11Device *device, 32 | int clientWidth, 33 | int clientHeight, 34 | UINT particleNums, 35 | std::vector pos, 36 | std::vector vec, 37 | std::vector index); 38 | 39 | void TickRender(ID3D11DeviceContext *deviceContext, 40 | FluidRender::ParticleParams params, 41 | const Camera &camera, 42 | ID3D11RenderTargetView *sceneRTV, 43 | ID3D11DepthStencilView *sceneDSV, 44 | bool isFluid); 45 | void TickLogic(ID3D11DeviceContext *deviceContext, PBFSolver::PBFParams params); 46 | void TickDebugTextrue(ID3D11DeviceContext *deviceContext, 47 | FluidRender::ParticleParams params, 48 | float aspectRatio, 49 | bool isFluid); 50 | void TickGpuTimes(); 51 | 52 | void SetBoundary(std::vector pos, std::vector nor); 53 | void Reset(ID3D11Device *device, 54 | UINT particleNums, 55 | std::vector pos, 56 | std::vector vec, 57 | std::vector index); 58 | 59 | void SetDebugObjectName(std::string name); 60 | 61 | private: 62 | GpuTimer m_GpuTimer_RadixSort; 63 | GpuTimer m_GpuTimer_NeighBorSearch; 64 | GpuTimer m_GpuTimer_PBF; 65 | GpuTimer m_GpuTimer_Anisotropy; 66 | GpuTimer m_GpuTimer_FluidRender; 67 | 68 | std::unique_ptr> m_pParticlePosBuffer; 69 | std::unique_ptr> m_pParticleVecBuffer; 70 | std::unique_ptr> m_pParticleIndexBuffer; 71 | std::unique_ptr> m_pParticleDensityBuffer; 72 | 73 | std::unique_ptr m_pFluidEffect; //点精灵特效 74 | std::unique_ptr m_pFluidRender; //点精灵渲染类 75 | 76 | std::unique_ptr m_pNeighborSearchEffect; 77 | std::unique_ptr m_pNeighborSearch; 78 | 79 | std::unique_ptr m_pPBFSolverEffect; 80 | std::unique_ptr m_pPBFSolver; 81 | }; 82 | #endif // !_FLUIDSYSTEM_H 83 | -------------------------------------------------------------------------------- /Include/Hierarchy/GameObject.h: -------------------------------------------------------------------------------- 1 | //*************************************************************************************** 2 | // GameObject.h by X_Jun(MKXJun) (C) 2018-2020 All Rights Reserved. 3 | // Licensed under the MIT License. 4 | // 5 | // 简易游戏对象 6 | // Simple game object. 7 | //*************************************************************************************** 8 | 9 | #ifndef GAMEOBJECT_H 10 | #define GAMEOBJECT_H 11 | 12 | #include 13 | #include 14 | 15 | class GameObject 16 | { 17 | public: 18 | template 19 | using ComPtr = Microsoft::WRL::ComPtr; 20 | 21 | 22 | GameObject() = default; 23 | ~GameObject() = default; 24 | 25 | GameObject(const GameObject&) = default; 26 | GameObject& operator=(const GameObject&) = default; 27 | 28 | GameObject(GameObject&&) = default; 29 | GameObject& operator=(GameObject&&) = default; 30 | 31 | // 获取物体变换 32 | Transform& GetTransform(); 33 | // 获取物体变换 34 | const Transform& GetTransform() const; 35 | 36 | // 37 | // 获取包围盒 38 | // 39 | 40 | DirectX::BoundingBox GetLocalBoundingBox() const; 41 | DirectX::BoundingBox GetBoundingBox() const; 42 | DirectX::BoundingOrientedBox GetBoundingOrientedBox() const; 43 | 44 | // 45 | // 设置实例缓冲区 46 | // 47 | 48 | // 获取缓冲区可容纳实例的数目 49 | size_t GetCapacity() const; 50 | // 重新设置实例缓冲区可容纳实例的数目 51 | void ResizeBuffer(ID3D11Device * device, size_t count); 52 | // 获取实例缓冲区 53 | 54 | // 55 | // 设置模型 56 | // 57 | 58 | void SetModel(Model&& model); 59 | void SetModel(const Model& model); 60 | 61 | // 62 | // 绘制 63 | // 64 | 65 | // 绘制对象 66 | void Draw(ID3D11DeviceContext* deviceContext, IEffect* effect); 67 | // 绘制实例 68 | void DrawInstanced(ID3D11DeviceContext* deviceContext, IEffect* effect, const std::vector& data); 69 | 70 | // 71 | // 调试 72 | // 73 | 74 | // 设置调试对象名 75 | // 若模型被重新设置,调试对象名也需要被重新设置 76 | void SetDebugObjectName(const std::string& name); 77 | 78 | private: 79 | Model m_Model = {}; // 模型 80 | Transform m_Transform = {}; // 物体变换 81 | 82 | ComPtr m_pInstancedBuffer = nullptr; // 实例缓冲区 83 | size_t m_Capacity = 0; // 缓冲区容量 84 | }; 85 | 86 | 87 | 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /Include/Utils/Collision.h: -------------------------------------------------------------------------------- 1 | //*************************************************************************************** 2 | // Collision.h by X_Jun(MKXJun) (C) 2018-2020 All Rights Reserved. 3 | // Licensed under the MIT License. 4 | // 5 | // 提供一些封装好的对象和碰撞检测方法 6 | // 注意:WireFrameData目前仍未经过稳定测试,未来有可能会移植到Geometry.h中 7 | // Provide encapsulated collision classes and detection method. 8 | //*************************************************************************************** 9 | 10 | #ifndef COLLISION_H 11 | #define COLLISION_H 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | struct Ray 20 | { 21 | Ray(); 22 | Ray(const DirectX::XMFLOAT3& origin, const DirectX::XMFLOAT3& direction); 23 | 24 | static Ray ScreenToRay(const Camera& camera, float screenX, float screenY); 25 | 26 | bool Hit(const DirectX::BoundingBox& box, float* pOutDist = nullptr, float maxDist = FLT_MAX); 27 | bool Hit(const DirectX::BoundingOrientedBox& box, float* pOutDist = nullptr, float maxDist = FLT_MAX); 28 | bool Hit(const DirectX::BoundingSphere& sphere, float* pOutDist = nullptr, float maxDist = FLT_MAX); 29 | bool XM_CALLCONV Hit(DirectX::FXMVECTOR V0, DirectX::FXMVECTOR V1, DirectX::FXMVECTOR V2, float* pOutDist = nullptr, float maxDist = FLT_MAX); 30 | 31 | DirectX::XMFLOAT3 origin; // 射线原点 32 | DirectX::XMFLOAT3 direction; // 单位方向向量 33 | }; 34 | 35 | 36 | class Collision 37 | { 38 | public: 39 | 40 | // 线框顶点/索引数组 41 | struct WireFrameData 42 | { 43 | std::vector vertexVec; // 顶点数组 44 | std::vector indexVec; // 索引数组 45 | }; 46 | 47 | // 48 | // 包围盒线框的创建 49 | // 50 | 51 | // 创建AABB盒线框 52 | static WireFrameData CreateBoundingBox(const DirectX::BoundingBox& box, const DirectX::XMFLOAT4& color); 53 | // 创建OBB盒线框 54 | static WireFrameData CreateBoundingOrientedBox(const DirectX::BoundingOrientedBox& box, const DirectX::XMFLOAT4& color); 55 | // 创建包围球线框 56 | static WireFrameData CreateBoundingSphere(const DirectX::BoundingSphere& sphere, const DirectX::XMFLOAT4& color, int slices = 20); 57 | // 创建视锥体线框 58 | static WireFrameData CreateBoundingFrustum(const DirectX::BoundingFrustum& frustum, const DirectX::XMFLOAT4& color); 59 | 60 | // 61 | // 三种等价的测试视锥体裁剪的方法,获取所有与视锥体碰撞的碰撞体对应的世界矩阵数组 62 | // 63 | 64 | // 视锥体裁剪 65 | static std::vector XM_CALLCONV FrustumCulling( 66 | const std::vector& Matrices, const DirectX::BoundingBox& localBox, DirectX::FXMMATRIX View, DirectX::CXMMATRIX Proj); 67 | // 视锥体裁剪2 68 | static std::vector XM_CALLCONV FrustumCulling2( 69 | const std::vector& Matrices, const DirectX::BoundingBox& localBox, DirectX::FXMMATRIX View, DirectX::CXMMATRIX Proj); 70 | // 视锥体裁剪3 71 | static std::vector XM_CALLCONV FrustumCulling3( 72 | const std::vector& Matrices, const DirectX::BoundingBox& localBox, DirectX::FXMMATRIX View, DirectX::CXMMATRIX Proj); 73 | 74 | // 视锥体裁剪 75 | static std::vector XM_CALLCONV FrustumCulling( 76 | const std::vector& transforms, const DirectX::BoundingBox& localBox, DirectX::FXMMATRIX View, DirectX::CXMMATRIX Proj); 77 | // 视锥体裁剪2 78 | static std::vector XM_CALLCONV FrustumCulling2( 79 | const std::vector& transforms, const DirectX::BoundingBox& localBox, DirectX::FXMMATRIX View, DirectX::CXMMATRIX Proj); 80 | // 视锥体裁剪3 81 | static std::vector XM_CALLCONV FrustumCulling3( 82 | const std::vector& transforms, const DirectX::BoundingBox& localBox, DirectX::FXMMATRIX View, DirectX::CXMMATRIX Proj); 83 | 84 | 85 | private: 86 | static WireFrameData CreateFromCorners(const DirectX::XMFLOAT3(&corners)[8], const DirectX::XMFLOAT4& color); 87 | }; 88 | 89 | 90 | 91 | 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /Include/Utils/DXTrace.h: -------------------------------------------------------------------------------- 1 | //*************************************************************************************** 2 | // DXTrace.h by X_Jun(MKXJun) (C) 2018-2020 All Rights Reserved. 3 | // Licensed under the MIT License. 4 | // 5 | // DirectX错误追踪 6 | // DirectX Error Tracing. 7 | //*************************************************************************************** 8 | 9 | #ifndef DXTRACE_H 10 | #define DXTRACE_H 11 | 12 | #include 13 | 14 | // ------------------------------ 15 | // DXTraceW函数 16 | // ------------------------------ 17 | // 在调试输出窗口中输出格式化错误信息,可选的错误窗口弹出(已汉化) 18 | // [In]strFile 当前文件名,通常传递宏__FILEW__ 19 | // [In]hlslFileName 当前行号,通常传递宏__LINE__ 20 | // [In]hr 函数执行出现问题时返回的HRESULT值 21 | // [In]strMsg 用于帮助调试定位的字符串,通常传递L#x(可能为NULL) 22 | // [In]bPopMsgBox 如果为TRUE,则弹出一个消息弹窗告知错误信息 23 | // 返回值: 形参hr 24 | HRESULT WINAPI DXTraceW(_In_z_ const WCHAR* strFile, _In_ DWORD dwLine, _In_ HRESULT hr, _In_opt_ const WCHAR* strMsg, _In_ bool bPopMsgBox); 25 | 26 | 27 | // ------------------------------ 28 | // HR宏 29 | // ------------------------------ 30 | // Debug模式下的错误提醒与追踪 31 | #if defined(DEBUG) | defined(_DEBUG) 32 | #ifndef HR 33 | #define HR(x) \ 34 | { \ 35 | HRESULT hr = (x); \ 36 | if(FAILED(hr)) \ 37 | { \ 38 | DXTraceW(__FILEW__, (DWORD)__LINE__, hr, L#x, true);\ 39 | } \ 40 | } 41 | #endif 42 | #else 43 | #ifndef HR 44 | #define HR(x) (x) 45 | #endif 46 | #endif 47 | 48 | 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /Include/Utils/GameTimer.h: -------------------------------------------------------------------------------- 1 | //*************************************************************************************** 2 | // GameTimer.h by Frank Luna (C) 2011 All Rights Reserved. 3 | //*************************************************************************************** 4 | 5 | #ifndef GAMETIMER_H 6 | #define GAMETIMER_H 7 | 8 | class GameTimer 9 | { 10 | public: 11 | GameTimer(); 12 | 13 | float TotalTime() const; // 总游戏时间 14 | float DeltaTime() const; // 帧间隔时间 15 | 16 | void Reset(); // 在消息循环之前调用 17 | void Start(); // 在取消暂停的时候调用 18 | void Stop(); // 在暂停的时候调用 19 | void Tick(); // 在每一帧的时候调用 20 | 21 | private: 22 | double m_SecondsPerCount; 23 | double m_DeltaTime; 24 | 25 | __int64 m_BaseTime; 26 | __int64 m_PausedTime; 27 | __int64 m_StopTime; 28 | __int64 m_PrevTime; 29 | __int64 m_CurrTime; 30 | 31 | bool m_Stopped; 32 | }; 33 | 34 | #endif // GAMETIMER_H -------------------------------------------------------------------------------- /Include/Utils/GpuTimer.h: -------------------------------------------------------------------------------- 1 | //*************************************************************************************** 2 | // GameObject.h by X_Jun(MKXJun) (C) 2018-2022 All Rights Reserved. 3 | // Licensed under the MIT License. 4 | // 5 | // 获取GPU两个时间戳的间隔 6 | // Retrieve the interval between two timestamps of the GPU. 7 | //*************************************************************************************** 8 | 9 | #pragma once 10 | 11 | #ifndef GPUTIMER_H 12 | #define GPUTIMER_H 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | struct GpuTimerInfo 20 | { 21 | D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData{}; 22 | uint64_t startData = 0; 23 | uint64_t stopData = 0; 24 | Microsoft::WRL::ComPtr disjointQuery; 25 | Microsoft::WRL::ComPtr startQuery; 26 | Microsoft::WRL::ComPtr stopQuery; 27 | bool isStopped = false; 28 | }; 29 | 30 | class GpuTimer 31 | { 32 | public: 33 | GpuTimer() = default; 34 | 35 | // recentCount为0时统计所有间隔的平均值 36 | // 否则统计最近N帧间隔的平均值 37 | void Init(ID3D11Device *device, size_t recentCount = 0); 38 | 39 | // 重置平均用时 40 | // recentCount为0时统计所有间隔的平均值 41 | // 否则统计最近N帧间隔的平均值 42 | void Reset(size_t recentCount = 0); 43 | // 给命令队列插入起始时间戳 44 | HRESULT Start(); 45 | // 给命令队列插入结束时间戳 46 | void Stop(); 47 | // 尝试获取间隔 48 | bool TryGetTime(double *pOut); 49 | // 强制获取间隔 50 | double GetTime(); 51 | // 计算平均用时 52 | double AverageTime() 53 | { 54 | if (m_RecentCount) 55 | return m_AccumTime / m_DeltaTimes.size(); 56 | else 57 | return m_AccumTime / m_AccumCount; 58 | } 59 | 60 | private: 61 | static bool GetQueryDataHelper(ID3D11DeviceContext *pContext, 62 | bool loopUntilDone, 63 | ID3D11Query *query, 64 | void *data, 65 | uint32_t dataSize); 66 | 67 | std::deque m_DeltaTimes; 68 | double m_AccumTime = 0.0; 69 | size_t m_AccumCount = 0; 70 | size_t m_RecentCount = 0; 71 | size_t m_FrameID = 0; 72 | 73 | std::deque m_Queries; 74 | std::deque> m_pEndTimeQuery; 75 | Microsoft::WRL::ComPtr m_pDevice; 76 | Microsoft::WRL::ComPtr m_pImmediateContext; 77 | }; 78 | 79 | #endif // GAMETIMER_H -------------------------------------------------------------------------------- /Include/Utils/Model.h: -------------------------------------------------------------------------------- 1 | //*************************************************************************************** 2 | // Model.h by X_Jun(MKXJun) (C) 2018-2020 All Rights Reserved. 3 | // Licensed under the MIT License. 4 | // 5 | // 存放模型数据 6 | // model data storage. 7 | //*************************************************************************************** 8 | 9 | #ifndef MODEL_H 10 | #define MODEL_H 11 | 12 | #include 13 | #include 14 | #include "ObjReader.h" 15 | #include "Geometry.h" 16 | 17 | struct ModelPart 18 | { 19 | // 使用模板别名(C++11)简化类型名 20 | template 21 | using ComPtr = Microsoft::WRL::ComPtr; 22 | 23 | ModelPart() : material(), texDiffuse(), vertexBuffer(), indexBuffer(), 24 | vertexCount(), indexCount(), indexFormat() {} 25 | 26 | ModelPart(const ModelPart&) = default; 27 | ModelPart& operator=(const ModelPart&) = default; 28 | 29 | ModelPart(ModelPart&&) = default; 30 | ModelPart& operator=(ModelPart&&) = default; 31 | 32 | 33 | Material material; 34 | ComPtr texDiffuse; 35 | ComPtr texNormalMap; 36 | ComPtr vertexBuffer; 37 | ComPtr indexBuffer; 38 | UINT vertexCount; 39 | UINT indexCount; 40 | DXGI_FORMAT indexFormat; 41 | }; 42 | 43 | struct Model 44 | { 45 | // 使用模板别名(C++11)简化类型名 46 | template 47 | using ComPtr = Microsoft::WRL::ComPtr; 48 | 49 | Model(); 50 | Model(ID3D11Device * device, const ObjReader& model); 51 | // 设置缓冲区 52 | template 53 | Model(ID3D11Device * device, const Geometry::MeshData& meshData); 54 | 55 | template 56 | Model(ID3D11Device * device, const std::vector & vertices, const std::vector& indices); 57 | 58 | 59 | Model(ID3D11Device * device, const void* vertices, UINT vertexSize, UINT vertexCount, 60 | const void * indices, UINT indexCount, DXGI_FORMAT indexFormat); 61 | // 62 | // 设置模型 63 | // 64 | 65 | void SetModel(ID3D11Device * device, const ObjReader& model); 66 | 67 | // 68 | // 设置网格 69 | // 70 | template 71 | void SetMesh(ID3D11Device * device, const Geometry::MeshData& meshData); 72 | 73 | template 74 | void SetMesh(ID3D11Device * device, const std::vector & vertices, const std::vector& indices); 75 | 76 | void SetMesh(ID3D11Device * device, const void* vertices, UINT vertexSize, UINT vertexCount, 77 | const void * indices, UINT indexCount, DXGI_FORMAT indexFormat); 78 | 79 | // 80 | // 调试 81 | // 82 | 83 | // 设置调试对象名 84 | // 若模型被重新设置,调试对象名也需要被重新设置 85 | void SetDebugObjectName(const std::string& name); 86 | 87 | std::vector modelParts; 88 | DirectX::BoundingBox boundingBox; 89 | UINT vertexStride; 90 | }; 91 | 92 | 93 | 94 | 95 | template 96 | inline Model::Model(ID3D11Device * device, const Geometry::MeshData& meshData) 97 | : modelParts(), boundingBox(), vertexStride() 98 | { 99 | SetMesh(device, meshData); 100 | } 101 | 102 | template 103 | inline Model::Model(ID3D11Device * device, const std::vector & vertices, const std::vector& indices) 104 | : modelParts(), boundingBox(), vertexStride() 105 | { 106 | SetMesh(device, vertices, indices); 107 | } 108 | 109 | template 110 | inline void Model::SetMesh(ID3D11Device * device, const Geometry::MeshData& meshData) 111 | { 112 | SetMesh(device, meshData.vertexVec, meshData.indexVec); 113 | } 114 | 115 | template 116 | inline void Model::SetMesh(ID3D11Device * device, const std::vector & vertices, const std::vector& indices) 117 | { 118 | static_assert(sizeof(IndexType) == 2 || sizeof(IndexType) == 4, "The size of IndexType must be 2 bytes or 4 bytes!"); 119 | static_assert(std::is_unsigned::value, "IndexType must be unsigned integer!"); 120 | SetMesh(device, vertices.data(), sizeof(VertexType), 121 | (UINT)vertices.size(), indices.data(), (UINT)indices.size(), 122 | (sizeof(IndexType) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT)); 123 | 124 | } 125 | 126 | 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /Include/Utils/Mouse.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------- 2 | // File: Mouse.h 3 | // 4 | // Copyright (c) Microsoft Corporation. All rights reserved. 5 | // Licensed under the MIT License. 6 | // 7 | // http://go.microsoft.com/fwlink/?LinkId=248929 8 | // http://go.microsoft.com/fwlink/?LinkID=615561 9 | //-------------------------------------------------------------------------------------- 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | 16 | namespace DirectX 17 | { 18 | class Mouse 19 | { 20 | public: 21 | Mouse() noexcept(false); 22 | Mouse(Mouse&& moveFrom) noexcept; 23 | Mouse& operator= (Mouse&& moveFrom) noexcept; 24 | 25 | Mouse(Mouse const&) = delete; 26 | Mouse& operator=(Mouse const&) = delete; 27 | 28 | virtual ~Mouse(); 29 | 30 | enum Mode 31 | { 32 | MODE_ABSOLUTE = 0, 33 | MODE_RELATIVE, 34 | }; 35 | 36 | struct State 37 | { 38 | bool leftButton; 39 | bool middleButton; 40 | bool rightButton; 41 | bool xButton1; 42 | bool xButton2; 43 | int x; 44 | int y; 45 | int scrollWheelValue; 46 | Mode positionMode; 47 | }; 48 | 49 | class ButtonStateTracker 50 | { 51 | public: 52 | enum ButtonState 53 | { 54 | UP = 0, // Button is up 55 | HELD = 1, // Button is held down 56 | RELEASED = 2, // Button was just released 57 | PRESSED = 3, // Buton was just pressed 58 | }; 59 | 60 | ButtonState leftButton; 61 | ButtonState middleButton; 62 | ButtonState rightButton; 63 | ButtonState xButton1; 64 | ButtonState xButton2; 65 | 66 | #pragma prefast(suppress: 26495, "Reset() performs the initialization") 67 | ButtonStateTracker() noexcept { Reset(); } 68 | 69 | void __cdecl Update(const State& state); 70 | 71 | void __cdecl Reset() noexcept; 72 | 73 | State __cdecl GetLastState() const { return lastState; } 74 | 75 | private: 76 | State lastState; 77 | }; 78 | 79 | // Retrieve the current state of the mouse 80 | State __cdecl GetState() const; 81 | 82 | // Resets the accumulated scroll wheel value 83 | void __cdecl ResetScrollWheelValue(); 84 | 85 | // Sets mouse mode (defaults to absolute) 86 | void __cdecl SetMode(Mode mode); 87 | 88 | // Feature detection 89 | bool __cdecl IsConnected() const; 90 | 91 | // Cursor visibility 92 | bool __cdecl IsVisible() const; 93 | void __cdecl SetVisible(bool visible); 94 | 95 | #if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) && defined(WM_USER) 96 | void __cdecl SetWindow(HWND window); 97 | static void __cdecl ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam); 98 | #endif 99 | // Singleton 100 | static Mouse& __cdecl Get(); 101 | 102 | private: 103 | // Private implementation. 104 | class Impl; 105 | 106 | std::unique_ptr pImpl; 107 | }; 108 | } -------------------------------------------------------------------------------- /Include/Utils/ObjReader.h: -------------------------------------------------------------------------------- 1 | //*************************************************************************************** 2 | // ObjReader.h by X_Jun(MKXJun) (C) 2018-2020 All Rights Reserved. 3 | // Licensed under the MIT License. 4 | // 5 | // - 修正了加载出来的模型是镜像的问题(右手坐标系变换为左手坐标系) 6 | // Modified By X_Jun(MKXJun) 7 | // 2018/9/12 v1.1 8 | // 9 | // - ObjReader支持通过.obj文件引用.mtl(材质),并且.mtl(材质)支持引用纹理。 10 | // - 不支持使用/将下一行的内容连接在一起表示一行 11 | // - 不支持索引为负数 12 | // - 不支持使用类似1//2这样的顶点(即不包含纹理坐标的顶点) 13 | // - 对.mtl文件和纹理的引用必须以相对路径的形式提供,且没有支持.和..两种路径格式。 14 | // - 若.mtl材质文件不存在,则内部会使用默认材质值 15 | // - 若.mtl内部没有指定纹理文件引用,需要另外自行加载纹理 16 | // - 要求网格只能以三角形构造 17 | // - .mbo文件是一种二进制文件,用于加快模型加载的速度,内部格式是自定义的 18 | // - .mbo文件已经生成不能随意改变文件位置,若要迁移相关文件需要重新生成.mbo文件 19 | // 20 | // Created By X_Jun(MKXJun) 21 | // 2018/9/9 v1.0 22 | //*************************************************************************************** 23 | 24 | #ifndef OBJREADER_H 25 | #define OBJREADER_H 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | 38 | class MtlReader; 39 | 40 | class ObjReader 41 | { 42 | public: 43 | struct ObjPart 44 | { 45 | ObjPart() : material() {} 46 | ~ObjPart() = default; 47 | 48 | Material material; // 材质 49 | std::vector vertices; // 顶点集合 50 | std::vector indices16; // 顶点数不超过65535时使用 51 | std::vector indices32; // 顶点数超过65535时使用 52 | std::wstring texStrDiffuse; // 漫射光纹理文件名,需为相对路径,在mbo必须占260字节 53 | }; 54 | 55 | ObjReader() : vMin(), vMax() {} 56 | ~ObjReader() = default; 57 | 58 | // 指定.mbo文件的情况下,若.mbo文件存在,优先读取该文件 59 | // 否则会读取.obj文件 60 | // 若.obj文件被读取,且提供了.mbo文件的路径,则会根据已经读取的数据创建.mbo文件 61 | bool Read(const wchar_t* mboFileName, const wchar_t* objFileName); 62 | 63 | bool ReadObj(const wchar_t* objFileName); 64 | bool ReadMbo(const wchar_t* mboFileName); 65 | bool WriteMbo(const wchar_t* mboFileName); 66 | public: 67 | std::vector objParts; 68 | DirectX::XMFLOAT3 vMin, vMax; // AABB盒双顶点 69 | private: 70 | void AddVertex(const VertexPosNormalTex& vertex, DWORD vpi, DWORD vti, DWORD vni); 71 | 72 | // 缓存有v/vt/vn字符串信息 73 | std::unordered_map vertexCache; 74 | }; 75 | 76 | class MtlReader 77 | { 78 | public: 79 | bool ReadMtl(const wchar_t* mtlFileName); 80 | 81 | 82 | public: 83 | std::map materials; 84 | std::map mapKdStrs; 85 | }; 86 | 87 | 88 | #endif 89 | 90 | -------------------------------------------------------------------------------- /Include/Utils/ScreenGrab.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------- 2 | // File: ScreenGrab.h 3 | // 4 | // Function for capturing a 2D texture and saving it to a file (aka a 'screenshot' 5 | // when used on a Direct3D 11 Render Target). 6 | // 7 | // Note these functions are useful as a light-weight runtime screen grabber. For 8 | // full-featured texture capture, DDS writer, and texture processing pipeline, 9 | // see the 'Texconv' sample and the 'DirectXTex' library. 10 | // 11 | // Copyright (c) Microsoft Corporation. All rights reserved. 12 | // Licensed under the MIT License. 13 | // 14 | // http://go.microsoft.com/fwlink/?LinkId=248926 15 | // http://go.microsoft.com/fwlink/?LinkId=248929 16 | //-------------------------------------------------------------------------------------- 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | 27 | namespace DirectX 28 | { 29 | HRESULT SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext, 30 | _In_ ID3D11Resource* pSource, 31 | _In_z_ const wchar_t* fileName ); 32 | 33 | HRESULT SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext, 34 | _In_ ID3D11Resource* pSource, 35 | _In_ REFGUID guidContainerFormat, 36 | _In_z_ const wchar_t* fileName, 37 | _In_opt_ const GUID* targetFormat = nullptr, 38 | _In_opt_ std::function setCustomProps = nullptr ); 39 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Ligo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FluidSimulation-Engine 2 | 3 | 这是我的毕业设计项目,基于DirectX11开发的GPU的流体,流体模拟算法采用Position Based Fluid。 4 | 5 | ![image-20230601175401021](https://img2023.cnblogs.com/blog/1656870/202306/1656870-20230601175401270-979449644.png) 6 | 7 | ## 项目概况: 8 | 9 | 环境:VS2022 10 | 11 | 语言: 12 | 13 | - C++14/17 14 | - HLSL Shader Model 5.0 15 | 16 | 目前项目使用了下述代码库或文件: 17 | 18 | - X_Jun的DirectX11 With Windows SDK教程:[MKXJun/DirectX11-With-Windows-SDK: 现代DX11系列教程:使用Windows SDK(C++)开发Direct3D 11.x (github.com)](https://github.com/MKXJun/DirectX11-With-Windows-SDK) 19 | - [ocornut/imgui](https://github.com/ocornut/imgui) 20 | 21 | ## 构建项目 22 | 23 | - cmake构建 24 | 25 | 26 | ```powershell 27 | mkdir build 28 | cd build 29 | cmake .. 30 | ``` 31 | 32 | - xmake构建 33 | 34 | ```powershell 35 | xmake -y 36 | xmake run 37 | ``` 38 | 39 | ## 博客 40 | 41 | [DirectX11:Position Based Fluid](https://www.cnblogs.com/Ligo-Z/p/16295433.html) 42 | -------------------------------------------------------------------------------- /Src/Effect/FluidEffect.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Src/Effect/FluidEffect.cpp -------------------------------------------------------------------------------- /Src/Effect/FluidRender.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Src/Effect/FluidRender.cpp -------------------------------------------------------------------------------- /Src/Effect/NeighborSearch.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Src/Effect/NeighborSearch.cpp -------------------------------------------------------------------------------- /Src/Effect/NeighborSearchEffect.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Src/Effect/NeighborSearchEffect.cpp -------------------------------------------------------------------------------- /Src/Effect/PBFSolver.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Src/Effect/PBFSolver.cpp -------------------------------------------------------------------------------- /Src/Effect/PBFSolverEffect.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Src/Effect/PBFSolverEffect.cpp -------------------------------------------------------------------------------- /Src/Effect/SkyEffect.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // 必须晚于Effects.h和d3dUtil.h包含 4 | #include 5 | #include 6 | using namespace DirectX; 7 | 8 | 9 | // 10 | // SkyEffect::Impl 需要先于SkyEffect的定义 11 | // 12 | 13 | class SkyEffect::Impl 14 | { 15 | 16 | public: 17 | // 必须显式指定 18 | Impl() {} 19 | ~Impl() = default; 20 | 21 | public: 22 | std::unique_ptr m_pEffectHelper; 23 | std::shared_ptr m_pCurrEffectPass; 24 | 25 | ComPtr m_pVertexPosLayout; 26 | 27 | XMFLOAT4X4 m_World, m_View, m_Proj; 28 | }; 29 | 30 | // 31 | // SkyEffect 32 | // 33 | 34 | namespace 35 | { 36 | // SkyEffect单例 37 | static SkyEffect * g_pInstance = nullptr; 38 | } 39 | 40 | SkyEffect::SkyEffect() 41 | { 42 | if (g_pInstance) 43 | throw std::exception("BasicEffect is a singleton!"); 44 | g_pInstance = this; 45 | pImpl = std::make_unique(); 46 | } 47 | 48 | SkyEffect::~SkyEffect() 49 | { 50 | } 51 | 52 | SkyEffect::SkyEffect(SkyEffect && moveFrom) noexcept 53 | { 54 | pImpl.swap(moveFrom.pImpl); 55 | } 56 | 57 | SkyEffect & SkyEffect::operator=(SkyEffect && moveFrom) noexcept 58 | { 59 | pImpl.swap(moveFrom.pImpl); 60 | return *this; 61 | } 62 | 63 | SkyEffect & SkyEffect::Get() 64 | { 65 | if (!g_pInstance) 66 | throw std::exception("BasicEffect needs an instance!"); 67 | return *g_pInstance; 68 | } 69 | 70 | bool SkyEffect::InitAll(ID3D11Device * device) 71 | { 72 | if (!device) 73 | return false; 74 | 75 | if (!RenderStates::IsInit()) 76 | throw std::exception("RenderStates need to be initialized first!"); 77 | 78 | pImpl->m_pEffectHelper = std::make_unique(); 79 | pImpl->m_pEffectHelper->SetBinaryCacheDirectory(L"..\\shaders\\generated"); 80 | std::wstring shader_path = L"..\\shaders\\"; 81 | 82 | ComPtr blob; 83 | 84 | // ****************** 85 | // 创建顶点着色器 86 | // 87 | HR(pImpl->m_pEffectHelper->CreateShaderFromFile("Sky_VS", 88 | shader_path + L"Sky_VS.hlsl", 89 | device, 90 | "VS", 91 | "vs_5_0", 92 | nullptr, 93 | blob.ReleaseAndGetAddressOf())); 94 | // 创建顶点布局 95 | HR(device->CreateInputLayout(VertexPos::inputLayout, ARRAYSIZE(VertexPos::inputLayout), 96 | blob->GetBufferPointer(), blob->GetBufferSize(), pImpl->m_pVertexPosLayout.GetAddressOf())); 97 | 98 | // ****************** 99 | // 创建像素着色器 100 | // 101 | HR(pImpl->m_pEffectHelper->CreateShaderFromFile( 102 | "Sky_PS", shader_path + L"Sky_PS.hlsl", device, "PS", "ps_5_0", nullptr, blob.ReleaseAndGetAddressOf())); 103 | // ****************** 104 | // 创建通道 105 | // 106 | EffectPassDesc passDesc; 107 | passDesc.nameVS = "Sky_VS"; 108 | passDesc.namePS = "Sky_PS"; 109 | HR(pImpl->m_pEffectHelper->AddEffectPass("Sky", device, &passDesc)); 110 | 111 | pImpl->m_pEffectHelper->SetSamplerStateByName("g_Sam", RenderStates::SSLinearWrap.Get()); 112 | pImpl->m_pCurrEffectPass = pImpl->m_pEffectHelper->GetEffectPass("Sky"); 113 | pImpl->m_pCurrEffectPass->SetDepthStencilState(RenderStates::DSSLessEqual.Get(), 0); 114 | pImpl->m_pCurrEffectPass->SetRasterizerState(RenderStates::RSNoCull.Get()); 115 | 116 | // 设置调试对象名 117 | D3D11SetDebugObjectName(pImpl->m_pVertexPosLayout.Get(), "SkyEffect.VertexPosLayout"); 118 | pImpl->m_pEffectHelper->SetDebugObjectName("SkyEffect"); 119 | 120 | return true; 121 | } 122 | 123 | void SkyEffect::SetRenderDefault(ID3D11DeviceContext * deviceContext) 124 | { 125 | deviceContext->IASetInputLayout(pImpl->m_pVertexPosLayout.Get()); 126 | deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 127 | } 128 | 129 | void XM_CALLCONV SkyEffect::SetWorldMatrix(DirectX::FXMMATRIX W) 130 | { 131 | XMStoreFloat4x4(&pImpl->m_World, W); 132 | } 133 | 134 | void XM_CALLCONV SkyEffect::SetViewMatrix(DirectX::FXMMATRIX V) 135 | { 136 | XMStoreFloat4x4(&pImpl->m_View, V); 137 | } 138 | 139 | void XM_CALLCONV SkyEffect::SetProjMatrix(DirectX::FXMMATRIX P) 140 | { 141 | XMStoreFloat4x4(&pImpl->m_Proj, P); 142 | } 143 | 144 | void SkyEffect::SetTextureCube(ID3D11ShaderResourceView * m_pTextureCube) 145 | { 146 | pImpl->m_pEffectHelper->SetShaderResourceByName("g_TexCube", m_pTextureCube); 147 | } 148 | 149 | void SkyEffect::Apply(ID3D11DeviceContext * deviceContext) 150 | { 151 | XMMATRIX WVP = XMLoadFloat4x4(&pImpl->m_World) * XMLoadFloat4x4(&pImpl->m_View) * XMLoadFloat4x4(&pImpl->m_Proj); 152 | WVP = XMMatrixTranspose(WVP); 153 | pImpl->m_pEffectHelper->GetConstantBufferVariable("g_WorldViewProj")->SetFloatMatrix(4, 4, (const FLOAT*)&WVP); 154 | 155 | pImpl->m_pCurrEffectPass->Apply(deviceContext); 156 | } 157 | 158 | -------------------------------------------------------------------------------- /Src/Graphics/Buffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #pragma warning(disable: 26812) 6 | 7 | using namespace Microsoft::WRL; 8 | 9 | 10 | //void StructuredBuffer::InternalConsturct(ID3D11Device* d3dDevice, UINT size, DXGI_FORMAT format,UINT bindFlags) 11 | //{ 12 | // m_pBuffer.Reset(); 13 | // m_pShaderResourceViews.clear(); 14 | // m_p1UnorderedAccessView.clear(); 15 | // 16 | // CD3D11_BUFFER_DESC desc{ 17 | // format, 18 | // bindFlags, 19 | // 20 | // } 21 | //} 22 | -------------------------------------------------------------------------------- /Src/Graphics/Texture2D.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Src/Graphics/Texture2D.cpp -------------------------------------------------------------------------------- /Src/Graphics/Vertex.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const D3D11_INPUT_ELEMENT_DESC VertexPos::inputLayout[1] = { 4 | { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 } 5 | }; 6 | 7 | const D3D11_INPUT_ELEMENT_DESC VertexPosColor::inputLayout[2] = { 8 | { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 9 | { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 } 10 | }; 11 | 12 | const D3D11_INPUT_ELEMENT_DESC VertexPosTex::inputLayout[2] = { 13 | { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 14 | { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 } 15 | }; 16 | 17 | const D3D11_INPUT_ELEMENT_DESC VertexPosSize::inputLayout[2] = { 18 | { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 19 | { "SIZE", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 } 20 | }; 21 | 22 | const D3D11_INPUT_ELEMENT_DESC VertexPosNormalColor::inputLayout[3] = { 23 | { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 24 | { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 25 | { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 } 26 | }; 27 | 28 | const D3D11_INPUT_ELEMENT_DESC VertexPosNormalTex::inputLayout[3] = { 29 | { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 30 | { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 31 | { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 } 32 | }; 33 | 34 | const D3D11_INPUT_ELEMENT_DESC VertexPosNormalTangentTex::inputLayout[4] = { 35 | { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 36 | { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 37 | { "TANGENT", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 38 | { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D11_INPUT_PER_VERTEX_DATA, 0 } 39 | }; 40 | 41 | const D3D11_INPUT_ELEMENT_DESC PointVertexIn::inputLayout[2] = 42 | { 43 | {"POSITION",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0}, 44 | {"DENSITY",0,DXGI_FORMAT_R32_FLOAT,1,0,D3D11_INPUT_PER_VERTEX_DATA,0} 45 | }; 46 | 47 | const D3D11_INPUT_ELEMENT_DESC MeshVertexIn::inputLayout[4] = 48 | { 49 | { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 50 | { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 51 | { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 52 | { "COLOR",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,32,D3D11_INPUT_PER_VERTEX_DATA,0} 53 | }; 54 | 55 | const D3D11_INPUT_ELEMENT_DESC FluidVertexIn::inputLayout[4] = 56 | { 57 | { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 58 | { "U", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 59 | { "V", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 60 | { "W",0,DXGI_FORMAT_R32G32B32A32_FLOAT,1,32,D3D11_INPUT_PER_VERTEX_DATA,0} 61 | }; 62 | 63 | -------------------------------------------------------------------------------- /Src/Hierarchy/CameraController.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace DirectX; 6 | 7 | void CameraController::ApplyMomentum(float& oldValue, float& newValue, float deltaTime) 8 | { 9 | float blendedValue; 10 | if (fabs(newValue) > fabs(oldValue)) 11 | blendedValue = XMath::Lerp(newValue, oldValue, powf(0.6f, deltaTime * 60.0f)); 12 | else 13 | blendedValue = XMath::Lerp(newValue, oldValue, powf(0.8f, deltaTime * 60.0f)); 14 | oldValue = blendedValue; 15 | newValue = blendedValue; 16 | } 17 | 18 | void FirstPersonCameraController::Update(float deltaTime) 19 | { 20 | ImGuiIO& io = ImGui::GetIO(); 21 | 22 | float yaw = 0.0f, pitch = 0.0f, forward = 0.0f, strafe = 0.0f; 23 | if (ImGui::IsMouseDragging(ImGuiMouseButton_Right)) 24 | { 25 | 26 | yaw += io.MouseDelta.x * m_MouseSensitivityX; 27 | pitch += io.MouseDelta.y * m_MouseSensitivityY; 28 | } 29 | 30 | forward = m_MoveSpeed * ( 31 | (ImGui::IsKeyDown('W') ? deltaTime : 0.0f) + 32 | (ImGui::IsKeyDown('S') ? -deltaTime : 0.0f) 33 | ); 34 | strafe = m_StrafeSpeed * ( 35 | (ImGui::IsKeyDown('A') ? -deltaTime : 0.0f) + 36 | (ImGui::IsKeyDown('D') ? deltaTime : 0.0f) 37 | ); 38 | 39 | if (m_Momentum) 40 | { 41 | ApplyMomentum(m_LastForward, forward, deltaTime); 42 | ApplyMomentum(m_LastStrafe, strafe, deltaTime); 43 | } 44 | 45 | m_pCamera->RotateY(yaw); 46 | m_pCamera->Pitch(pitch); 47 | 48 | m_pCamera->MoveForward(forward); 49 | m_pCamera->Strafe(strafe); 50 | } 51 | 52 | void FirstPersonCameraController::InitCamera(FirstPersonCamera* pCamera) 53 | { 54 | m_pCamera = pCamera; 55 | } 56 | 57 | void FirstPersonCameraController::SlowMovement(bool enable) 58 | { 59 | m_FineMovement = enable; 60 | } 61 | 62 | void FirstPersonCameraController::SlowRotation(bool enable) 63 | { 64 | m_FineRotation = enable; 65 | } 66 | 67 | void FirstPersonCameraController::EnableMomentum(bool enable) 68 | { 69 | m_Momentum = enable; 70 | } 71 | 72 | void FirstPersonCameraController::SetMouseSensitivity(float x, float y) 73 | { 74 | m_MouseSensitivityX = x; 75 | m_MouseSensitivityY = y; 76 | } 77 | 78 | void FirstPersonCameraController::SetMoveSpeed(float speed) 79 | { 80 | m_MoveSpeed = speed; 81 | } 82 | 83 | void FirstPersonCameraController::SetStrafeSpeed(float speed) 84 | { 85 | m_StrafeSpeed = speed; 86 | } 87 | -------------------------------------------------------------------------------- /Src/Hierarchy/FluidSystem.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/Src/Hierarchy/FluidSystem.cpp -------------------------------------------------------------------------------- /Src/Main.cpp: -------------------------------------------------------------------------------- 1 | #include "GameApp.h" 2 | 3 | 4 | 5 | int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE prevInstance, 6 | _In_ LPSTR cmdLine, _In_ int showCmd) 7 | { 8 | // 这些参数不使用 9 | UNREFERENCED_PARAMETER(prevInstance); 10 | UNREFERENCED_PARAMETER(cmdLine); 11 | UNREFERENCED_PARAMETER(showCmd); 12 | // 允许在Debug版本进行运行时内存分配和泄漏检测 13 | #if defined(DEBUG) | defined(_DEBUG) 14 | _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); 15 | #endif 16 | 17 | GameApp theApp(hInstance, L"FluidSimulation-Engine", 1280, 720); 18 | 19 | if( !theApp.Init() ) 20 | return 0; 21 | 22 | return theApp.Run(); 23 | } 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Src/Utils/DXTrace.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | HRESULT WINAPI DXTraceW(_In_z_ const WCHAR* strFile, _In_ DWORD dwLine, _In_ HRESULT hr, 5 | _In_opt_ const WCHAR* strMsg, _In_ bool bPopMsgBox) 6 | { 7 | WCHAR strBufferFile[MAX_PATH]; 8 | WCHAR strBufferLine[128]; 9 | WCHAR strBufferError[300]; 10 | WCHAR strBufferMsg[1024]; 11 | WCHAR strBufferHR[40]; 12 | WCHAR strBuffer[3000]; 13 | 14 | swprintf_s(strBufferLine, 128, L"%lu", dwLine); 15 | if (strFile) 16 | { 17 | swprintf_s(strBuffer, 3000, L"%ls(%ls): ", strFile, strBufferLine); 18 | OutputDebugStringW(strBuffer); 19 | } 20 | 21 | size_t nMsgLen = (strMsg) ? wcsnlen_s(strMsg, 1024) : 0; 22 | if (nMsgLen > 0) 23 | { 24 | OutputDebugStringW(strMsg); 25 | OutputDebugStringW(L" "); 26 | } 27 | // Windows SDK 8.0起DirectX的错误信息已经集成进错误码中,可以通过FormatMessageW获取错误信息字符串 28 | // 不需要分配字符串内存 29 | FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 30 | nullptr, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 31 | strBufferError, 256, nullptr); 32 | 33 | WCHAR* errorStr = wcsrchr(strBufferError, L'\r'); 34 | if (errorStr) 35 | { 36 | errorStr[0] = L'\0'; // 擦除FormatMessageW带来的换行符(把\r\n的\r置换为\0即可) 37 | } 38 | 39 | swprintf_s(strBufferHR, 40, L" (0x%0.8x)", hr); 40 | wcscat_s(strBufferError, strBufferHR); 41 | swprintf_s(strBuffer, 3000, L"错误码含义:%ls", strBufferError); 42 | OutputDebugStringW(strBuffer); 43 | 44 | OutputDebugStringW(L"\n"); 45 | 46 | if (bPopMsgBox) 47 | { 48 | wcscpy_s(strBufferFile, MAX_PATH, L""); 49 | if (strFile) 50 | wcscpy_s(strBufferFile, MAX_PATH, strFile); 51 | 52 | wcscpy_s(strBufferMsg, 1024, L""); 53 | if (nMsgLen > 0) 54 | swprintf_s(strBufferMsg, 1024, L"当前调用:%ls\n", strMsg); 55 | 56 | swprintf_s(strBuffer, 3000, L"文件名:%ls\n行号:%ls\n错误码含义:%ls\n%ls您需要调试当前应用程序吗?", 57 | strBufferFile, strBufferLine, strBufferError, strBufferMsg); 58 | 59 | int nResult = MessageBoxW(GetForegroundWindow(), strBuffer, L"错误", MB_YESNO | MB_ICONERROR); 60 | if (nResult == IDYES) 61 | DebugBreak(); 62 | } 63 | 64 | return hr; 65 | } -------------------------------------------------------------------------------- /Src/Utils/GameTimer.cpp: -------------------------------------------------------------------------------- 1 | //*************************************************************************************** 2 | // GameTimer.cpp by Frank Luna (C) 2011 All Rights Reserved. 3 | //*************************************************************************************** 4 | 5 | #include 6 | #include 7 | 8 | GameTimer::GameTimer() 9 | : m_SecondsPerCount(0.0), m_DeltaTime(-1.0), m_BaseTime(0), m_StopTime(0), 10 | m_PausedTime(0), m_PrevTime(0), m_CurrTime(0), m_Stopped(false) 11 | { 12 | __int64 countsPerSec; 13 | QueryPerformanceFrequency((LARGE_INTEGER*)&countsPerSec); 14 | m_SecondsPerCount = 1.0 / (double)countsPerSec; 15 | } 16 | 17 | // Returns the total time elapsed since Reset() was called, NOT counting any 18 | // time when the clock is stopped. 19 | float GameTimer::TotalTime()const 20 | { 21 | // If we are stopped, do not count the time that has passed since we stopped. 22 | // Moreover, if we previously already had a pause, the distance 23 | // m_StopTime - m_BaseTime includes paused time, which we do not want to count. 24 | // To correct this, we can subtract the paused time from m_StopTime: 25 | // 26 | // |<--paused time-->| 27 | // ----*---------------*-----------------*------------*------------*------> time 28 | // m_BaseTime m_StopTime startTime m_StopTime m_CurrTime 29 | 30 | if( m_Stopped ) 31 | { 32 | return (float)(((m_StopTime - m_PausedTime)-m_BaseTime)*m_SecondsPerCount); 33 | } 34 | 35 | // The distance m_CurrTime - m_BaseTime includes paused time, 36 | // which we do not want to count. To correct this, we can subtract 37 | // the paused time from m_CurrTime: 38 | // 39 | // (m_CurrTime - m_PausedTime) - m_BaseTime 40 | // 41 | // |<--paused time-->| 42 | // ----*---------------*-----------------*------------*------> time 43 | // m_BaseTime m_StopTime startTime m_CurrTime 44 | 45 | else 46 | { 47 | return (float)(((m_CurrTime-m_PausedTime)-m_BaseTime)*m_SecondsPerCount); 48 | } 49 | } 50 | 51 | float GameTimer::DeltaTime()const 52 | { 53 | return (float)m_DeltaTime; 54 | } 55 | 56 | void GameTimer::Reset() 57 | { 58 | __int64 currTime; 59 | QueryPerformanceCounter((LARGE_INTEGER*)&currTime); 60 | 61 | m_BaseTime = currTime; 62 | m_PrevTime = currTime; 63 | m_StopTime = 0; 64 | m_PausedTime = 0; // 涉及到多次Reset的话需要将其归0 65 | m_Stopped = false; 66 | } 67 | 68 | void GameTimer::Start() 69 | { 70 | __int64 startTime; 71 | QueryPerformanceCounter((LARGE_INTEGER*)&startTime); 72 | 73 | 74 | // Accumulate the time elapsed between stop and start pairs. 75 | // 76 | // |<-------d------->| 77 | // ----*---------------*-----------------*------------> time 78 | // m_BaseTime m_StopTime startTime 79 | 80 | if( m_Stopped ) 81 | { 82 | m_PausedTime += (startTime - m_StopTime); 83 | 84 | m_PrevTime = startTime; 85 | m_StopTime = 0; 86 | m_Stopped = false; 87 | } 88 | } 89 | 90 | void GameTimer::Stop() 91 | { 92 | if( !m_Stopped ) 93 | { 94 | __int64 currTime; 95 | QueryPerformanceCounter((LARGE_INTEGER*)&currTime); 96 | 97 | m_StopTime = currTime; 98 | m_Stopped = true; 99 | } 100 | } 101 | 102 | void GameTimer::Tick() 103 | { 104 | if( m_Stopped ) 105 | { 106 | m_DeltaTime = 0.0; 107 | return; 108 | } 109 | 110 | __int64 currTime; 111 | QueryPerformanceCounter((LARGE_INTEGER*)&currTime); 112 | m_CurrTime = currTime; 113 | 114 | // Time difference between this frame and the previous. 115 | m_DeltaTime = (m_CurrTime - m_PrevTime)*m_SecondsPerCount; 116 | 117 | // Prepare for next frame. 118 | m_PrevTime = m_CurrTime; 119 | 120 | if(m_DeltaTime < 0.0) 121 | { 122 | m_DeltaTime = 0.0; 123 | } 124 | } 125 | 126 | -------------------------------------------------------------------------------- /Src/Utils/GpuTimer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void GpuTimer::Init(ID3D11Device* device, size_t recentCount) 4 | { 5 | m_pDevice = device; 6 | m_pDevice->GetImmediateContext(m_pImmediateContext.ReleaseAndGetAddressOf()); 7 | m_RecentCount = recentCount; 8 | m_AccumTime = 0.0; 9 | m_AccumCount = 0; 10 | } 11 | 12 | void GpuTimer::Reset(size_t recentCount) 13 | { 14 | m_Queries.clear(); 15 | m_DeltaTimes.clear(); 16 | m_AccumTime = 0.0; 17 | m_AccumCount = 0; 18 | if (recentCount) 19 | m_RecentCount = recentCount; 20 | } 21 | 22 | HRESULT GpuTimer::Start() 23 | { 24 | if (!m_Queries.empty() && !m_Queries.back().isStopped) 25 | return E_FAIL; 26 | 27 | GpuTimerInfo& info = m_Queries.emplace_back(); 28 | CD3D11_QUERY_DESC queryDesc(D3D11_QUERY_TIMESTAMP); 29 | m_pDevice->CreateQuery(&queryDesc, info.startQuery.GetAddressOf()); 30 | m_pDevice->CreateQuery(&queryDesc, info.stopQuery.GetAddressOf()); 31 | queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT; 32 | m_pDevice->CreateQuery(&queryDesc, info.disjointQuery.GetAddressOf()); 33 | 34 | m_pImmediateContext->Begin(info.disjointQuery.Get()); 35 | m_pImmediateContext->End(info.startQuery.Get()); 36 | return S_OK; 37 | } 38 | 39 | void GpuTimer::Stop() 40 | { 41 | GpuTimerInfo& info = m_Queries.back(); 42 | m_pImmediateContext->End(info.disjointQuery.Get()); 43 | m_pImmediateContext->End(info.stopQuery.Get()); 44 | info.isStopped = true; 45 | } 46 | 47 | bool GpuTimer::TryGetTime(double* pOut) 48 | { 49 | if (m_Queries.empty()) 50 | return false; 51 | 52 | GpuTimerInfo& info = m_Queries.front(); 53 | if (!info.isStopped) return false; 54 | if (info.disjointQuery && !GetQueryDataHelper(m_pImmediateContext.Get(), false, info.disjointQuery.Get(), &info.disjointData, sizeof(info.disjointData))) 55 | return false; 56 | info.disjointQuery.Reset(); 57 | 58 | if (info.startQuery && !GetQueryDataHelper(m_pImmediateContext.Get(), false, info.startQuery.Get(), &info.startData, sizeof(info.startData))) 59 | return false; 60 | info.startQuery.Reset(); 61 | 62 | if (info.stopQuery && !GetQueryDataHelper(m_pImmediateContext.Get(), false, info.stopQuery.Get(), &info.stopData, sizeof(info.stopData))) 63 | return false; 64 | info.stopQuery.Reset(); 65 | 66 | if (!info.disjointData.Disjoint) 67 | { 68 | double deltaTime = static_cast(info.stopData - info.startData) / info.disjointData.Frequency; 69 | if (m_RecentCount > 0) 70 | m_DeltaTimes.push_back(deltaTime); 71 | m_AccumTime += deltaTime; 72 | m_AccumCount++; 73 | if (m_DeltaTimes.size() > m_RecentCount) 74 | { 75 | m_AccumTime -= m_DeltaTimes.front(); 76 | m_DeltaTimes.pop_front(); 77 | } 78 | if (pOut) *pOut = deltaTime; 79 | } 80 | else 81 | { 82 | double deltaTime = -1.0; 83 | } 84 | 85 | m_Queries.pop_front(); 86 | return true; 87 | } 88 | 89 | double GpuTimer::GetTime() 90 | { 91 | if (m_Queries.empty()) 92 | return -1.0; 93 | 94 | GpuTimerInfo& info = m_Queries.front(); 95 | if (!info.isStopped) return -1.0; 96 | 97 | if (info.disjointQuery) 98 | { 99 | GetQueryDataHelper(m_pImmediateContext.Get(), true, info.disjointQuery.Get(), &info.disjointData, sizeof(info.disjointData)); 100 | info.disjointQuery.Reset(); 101 | } 102 | if (info.startQuery) 103 | { 104 | GetQueryDataHelper(m_pImmediateContext.Get(), true, info.startQuery.Get(), &info.startData, sizeof(info.startData)); 105 | info.startQuery.Reset(); 106 | } 107 | if (info.stopQuery) 108 | { 109 | GetQueryDataHelper(m_pImmediateContext.Get(), true, info.stopQuery.Get(), &info.stopData, sizeof(info.stopData)); 110 | info.stopQuery.Reset(); 111 | } 112 | 113 | double deltaTime = -1.0; 114 | if (!info.disjointData.Disjoint) 115 | { 116 | deltaTime = static_cast(info.stopData - info.startData) / info.disjointData.Frequency; 117 | if (m_RecentCount > 0) 118 | m_DeltaTimes.push_back(deltaTime); 119 | m_AccumTime += deltaTime; 120 | m_AccumCount++; 121 | if (m_DeltaTimes.size() > m_RecentCount) 122 | { 123 | m_AccumTime -= m_DeltaTimes.front(); 124 | m_DeltaTimes.pop_front(); 125 | } 126 | } 127 | 128 | m_Queries.pop_front(); 129 | return deltaTime; 130 | } 131 | 132 | bool GpuTimer::GetQueryDataHelper(ID3D11DeviceContext* pContext, bool loopUntilDone, ID3D11Query* query, void* data, uint32_t dataSize) 133 | { 134 | if (query == nullptr) 135 | return false; 136 | 137 | HRESULT hr = S_OK; 138 | int attempts = 0; 139 | do 140 | { 141 | hr = pContext->GetData(query, data, dataSize, 0); 142 | if (hr == S_OK) 143 | return true; 144 | attempts++; 145 | if (attempts > 100) 146 | Sleep(1); 147 | if (attempts > 1000) 148 | { 149 | assert(false); 150 | return false; 151 | } 152 | } while (loopUntilDone && (hr == S_FALSE)); 153 | return false; 154 | } -------------------------------------------------------------------------------- /Src/Utils/Model.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace DirectX; 6 | 7 | Model::Model() 8 | : modelParts(), boundingBox(), vertexStride() 9 | { 10 | } 11 | 12 | Model::Model(ID3D11Device* device, const ObjReader& model) 13 | : modelParts(), boundingBox(), vertexStride() 14 | { 15 | SetModel(device, model); 16 | } 17 | 18 | Model::Model(ID3D11Device* device, const void* vertices, UINT vertexSize, UINT vertexCount, 19 | const void* indices, UINT indexCount, DXGI_FORMAT indexFormat) 20 | : modelParts(), boundingBox(), vertexStride() 21 | { 22 | SetMesh(device, vertices, vertexSize, vertexCount, indices, indexCount, indexFormat); 23 | } 24 | 25 | void Model::SetModel(ID3D11Device* device, const ObjReader& model) 26 | { 27 | vertexStride = sizeof(VertexPosNormalTex); 28 | 29 | modelParts.resize(model.objParts.size()); 30 | 31 | // 创建包围盒 32 | BoundingBox::CreateFromPoints(boundingBox, XMLoadFloat3(&model.vMin), XMLoadFloat3(&model.vMax)); 33 | 34 | for (size_t i = 0; i < model.objParts.size(); ++i) 35 | { 36 | auto part = model.objParts[i]; 37 | 38 | modelParts[i].vertexCount = (UINT)part.vertices.size(); 39 | // 设置顶点缓冲区描述 40 | D3D11_BUFFER_DESC vbd; 41 | ZeroMemory(&vbd, sizeof(vbd)); 42 | vbd.Usage = D3D11_USAGE_IMMUTABLE; 43 | vbd.ByteWidth = modelParts[i].vertexCount * (UINT)sizeof(VertexPosNormalTex); 44 | vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER; 45 | vbd.CPUAccessFlags = 0; 46 | // 新建顶点缓冲区 47 | D3D11_SUBRESOURCE_DATA InitData; 48 | ZeroMemory(&InitData, sizeof(InitData)); 49 | InitData.pSysMem = part.vertices.data(); 50 | HR(device->CreateBuffer(&vbd, &InitData, modelParts[i].vertexBuffer.ReleaseAndGetAddressOf())); 51 | 52 | // 设置索引缓冲区描述 53 | D3D11_BUFFER_DESC ibd; 54 | ZeroMemory(&ibd, sizeof(ibd)); 55 | ibd.Usage = D3D11_USAGE_IMMUTABLE; 56 | ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; 57 | ibd.CPUAccessFlags = 0; 58 | if (modelParts[i].vertexCount > 65535) 59 | { 60 | modelParts[i].indexCount = (UINT)part.indices32.size(); 61 | modelParts[i].indexFormat = DXGI_FORMAT_R32_UINT; 62 | ibd.ByteWidth = modelParts[i].indexCount * (UINT)sizeof(DWORD); 63 | InitData.pSysMem = part.indices32.data(); 64 | 65 | } 66 | else 67 | { 68 | modelParts[i].indexCount = (UINT)part.indices16.size(); 69 | modelParts[i].indexFormat = DXGI_FORMAT_R16_UINT; 70 | ibd.ByteWidth = modelParts[i].indexCount * (UINT)sizeof(WORD); 71 | InitData.pSysMem = part.indices16.data(); 72 | } 73 | // 新建索引缓冲区 74 | HR(device->CreateBuffer(&ibd, &InitData, modelParts[i].indexBuffer.ReleaseAndGetAddressOf())); 75 | 76 | 77 | // 创建漫射光对应纹理 78 | auto& strD = part.texStrDiffuse; 79 | if (strD.size() > 4) 80 | { 81 | if (strD.substr(strD.size() - 3, 3) == L"dds") 82 | { 83 | HR(CreateDDSTextureFromFile(device, strD.c_str(), nullptr, 84 | modelParts[i].texDiffuse.GetAddressOf())); 85 | } 86 | else 87 | { 88 | HR(CreateWICTextureFromFile(device, strD.c_str(), nullptr, 89 | modelParts[i].texDiffuse.GetAddressOf())); 90 | } 91 | } 92 | 93 | modelParts[i].material = part.material; 94 | } 95 | 96 | 97 | } 98 | 99 | void Model::SetMesh(ID3D11Device* device, const void* vertices, UINT vertexSize, UINT vertexCount, const void* indices, UINT indexCount, DXGI_FORMAT indexFormat) 100 | { 101 | vertexStride = vertexSize; 102 | 103 | modelParts.resize(1); 104 | 105 | modelParts[0].vertexCount = vertexCount; 106 | modelParts[0].indexCount = indexCount; 107 | modelParts[0].indexFormat = indexFormat; 108 | 109 | modelParts[0].material.ambient = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f); 110 | modelParts[0].material.diffuse = XMFLOAT4(0.8f, 0.8f, 0.8f, 1.0f); 111 | modelParts[0].material.specular = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f); 112 | 113 | // 设置顶点缓冲区描述 114 | D3D11_BUFFER_DESC vbd; 115 | ZeroMemory(&vbd, sizeof(vbd)); 116 | vbd.Usage = D3D11_USAGE_IMMUTABLE; 117 | vbd.ByteWidth = vertexSize * vertexCount; 118 | vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER; 119 | vbd.CPUAccessFlags = 0; 120 | // 新建顶点缓冲区 121 | D3D11_SUBRESOURCE_DATA InitData; 122 | ZeroMemory(&InitData, sizeof(InitData)); 123 | InitData.pSysMem = vertices; 124 | HR(device->CreateBuffer(&vbd, &InitData, modelParts[0].vertexBuffer.ReleaseAndGetAddressOf())); 125 | 126 | // 设置索引缓冲区描述 127 | D3D11_BUFFER_DESC ibd; 128 | ZeroMemory(&ibd, sizeof(ibd)); 129 | ibd.Usage = D3D11_USAGE_IMMUTABLE; 130 | if (indexFormat == DXGI_FORMAT_R16_UINT) 131 | { 132 | ibd.ByteWidth = indexCount * (UINT)sizeof(WORD); 133 | } 134 | else 135 | { 136 | ibd.ByteWidth = indexCount * (UINT)sizeof(DWORD); 137 | } 138 | ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; 139 | ibd.CPUAccessFlags = 0; 140 | // 新建索引缓冲区 141 | InitData.pSysMem = indices; 142 | HR(device->CreateBuffer(&ibd, &InitData, modelParts[0].indexBuffer.ReleaseAndGetAddressOf())); 143 | 144 | } 145 | 146 | void Model::SetDebugObjectName(const std::string& name) 147 | { 148 | #if (defined(DEBUG) || defined(_DEBUG)) && (GRAPHICS_DEBUGGER_OBJECT_NAME) 149 | 150 | size_t modelPartSize = modelParts.size(); 151 | for (size_t i = 0; i < modelPartSize; ++i) 152 | { 153 | D3D11SetDebugObjectName(modelParts[i].vertexBuffer.Get(), name + ".part[" + std::to_string(i) + "].VertexBuffer"); 154 | D3D11SetDebugObjectName(modelParts[i].indexBuffer.Get(), name + ".part[" + std::to_string(i) + "].IndexBuffer"); 155 | } 156 | 157 | #else 158 | UNREFERENCED_PARAMETER(name); 159 | #endif 160 | } 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /cmakelists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required( VERSION 3.5 ) 2 | project ( FluidSimulation-Engine ) 3 | add_compile_options("$<$:/utf-8>") 4 | set(CMAKE_CXX_STANDARD 17) 5 | add_compile_definitions(UNICODE _UNICODE) 6 | 7 | set(TARGET_NAME FluidSimulation-Engine) 8 | #collect file 9 | file(GLOB_RECURSE ENGINE_HEADERS ${PROJECT_SOURCE_DIR}/include/*h) 10 | file(GLOB_RECURSE ENGINE_SOURCES ${PROJECT_SOURCE_DIR}/src/*cpp) 11 | #shaders 12 | file(GLOB_RECURSE HLSL_FILES ${PROJECT_SOURCE_DIR}/shaders/*.hlsl ${PROJECT_SOURCE_DIR}/shaders/*.hlsli) 13 | source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${ENGINE_HEADERS} ${ENGINE_SOURCES} ${HLSL_FILES}) 14 | #solution folders 15 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 16 | set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets") 17 | 18 | foreach(HLSL_FILE ${HLSL_FILES}) 19 | 20 | get_filename_component(HLSL_FDIR ${HLSL_FILE} DIRECTORY) 21 | get_filename_component(HLSL_FBASENAME_WE ${HLSL_FILE} NAME_WE) 22 | string(CONCAT HLSL_FNAME_WE ${HLSL_FDIR} / ${HLSL_FBASENAME_WE}) 23 | 24 | string(LENGTH ${HLSL_FBASENAME_WE} LEN_FNAME_WE) 25 | math(EXPR LEN_FNAME_WE "${LEN_FNAME_WE}-2") 26 | string(SUBSTRING ${HLSL_FBASENAME_WE} ${LEN_FNAME_WE} 2 ENTRY_POINT) 27 | string(TOLOWER ${ENTRY_POINT} SHADER_TYPE) 28 | 29 | if ("${SHADER_TYPE}" STREQUAL "vs") 30 | set(SHADER_TYPE "Vertex") 31 | elseif("${SHADER_TYPE}" STREQUAL "hs") 32 | set(SHADER_TYPE "Hull") 33 | elseif("${SHADER_TYPE}" STREQUAL "ds") 34 | set(SHADER_TYPE "Domain") 35 | elseif("${SHADER_TYPE}" STREQUAL "gs") 36 | set(SHADER_TYPE "Geometry") 37 | elseif("${SHADER_TYPE}" STREQUAL "ps") 38 | set(SHADER_TYPE "Pixel") 39 | elseif("${SHADER_TYPE}" STREQUAL "cs") 40 | set(SHADER_TYPE "Compute") 41 | endif() 42 | set_source_files_properties(${HLSL_FILE} PROPERTIES 43 | VS_SHADER_OBJECT_FILE_NAME ${PROJECT_SOURCE_DIR}/shaders/generated/${HLSL_FBASENAME_WE}.cso 44 | VS_SHADER_TYPE ${SHADER_TYPE} 45 | VS_SHADER_MODEL 5.0 46 | VS_SHADER_ENTRYPOINT ${ENTRY_POINT} 47 | VS_SHADER_DISABLE_OPTIMIZATIONS $<$:true> 48 | VS_SHADER_ENABLE_DEBUG $<$:true>) 49 | endforeach() 50 | 51 | add_executable(${TARGET_NAME} WIN32 ${ENGINE_HEADERS} ${ENGINE_SOURCES} ${HLSL_FILES}) 52 | target_link_libraries(${TARGET_NAME} PUBLIC d3d11.lib dxgi.lib dxguid.lib D3DCompiler.lib winmm.lib) 53 | 54 | #include 55 | target_include_directories( 56 | ${TARGET_NAME} 57 | PUBLIC 58 | $ 59 | ) 60 | #thirdparty 61 | add_subdirectory(thirdParty) 62 | target_link_libraries(${TARGET_NAME} PUBLIC imgui) 63 | file(COPY ${PROJECT_SOURCE_DIR}/imgui.ini DESTINATION ${PROJECT_SOURCE_DIR}/bin) 64 | 65 | #set ouput path 66 | set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME "FluidSimulation-Engine") 67 | set_target_properties(${TARGET_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/bin) 68 | set_target_properties(${TARGET_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/bin) -------------------------------------------------------------------------------- /include/GameApp.h: -------------------------------------------------------------------------------- 1 | #ifndef GAMEAPP_H 2 | #define GAMEAPP_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class GameApp: public D3DApp 14 | { 15 | public: 16 | // 摄像机模式 17 | enum class CameraMode 18 | { 19 | FirstPerson, 20 | ThirdPerson, 21 | Free 22 | }; 23 | 24 | public: 25 | GameApp(HINSTANCE hInstance, const std::wstring &windowName, int initWidth = 1280, int initHeight = 720); 26 | ~GameApp(); 27 | 28 | bool Init(); 29 | void OnResize(); 30 | void UpdateScene(float dt); 31 | void DrawScene(); 32 | 33 | private: 34 | bool InitResource(); 35 | void DrawSceneWithFluid(); 36 | void CreateParticle(ID3D11Device *device, 37 | DirectX::XMFLOAT3 lower, 38 | DirectX::XMINT3 dim, 39 | float radius, 40 | float jitter); 41 | 42 | private: 43 | DirectX::XMFLOAT3 RandomUnitVector(); 44 | void RandInit() 45 | { 46 | seed1 = 315645664; 47 | seed2 = seed1 ^ 0x13ab45fe; 48 | } 49 | 50 | inline uint32_t Rand() 51 | { 52 | seed1 = (seed2 ^ ((seed1 << 5) | (seed1 >> 27))) ^ (seed1 * seed2); 53 | seed2 = seed1 ^ ((seed2 << 12) | (seed2 >> 20)); 54 | 55 | return seed1; 56 | } 57 | inline float Randf() 58 | { 59 | uint32_t value = Rand(); 60 | uint32_t limit = 0xffffffff; 61 | 62 | return (float)value * (1.0f / (float)limit); 63 | } 64 | 65 | inline float Randf(float max) { return Randf() * max; } 66 | 67 | private: 68 | uint32_t seed1; 69 | uint32_t seed2; 70 | 71 | ObjReader m_ObjReader; 72 | 73 | std::vector m_Walls; //墙体 74 | 75 | DirectionalLight m_DirLight; //方向光源 76 | std::unique_ptr m_pBasicEffect; // 基础特效 77 | std::unique_ptr m_pSkyEffect; // 天空盒特效 78 | 79 | std::unique_ptr m_pLakeCube; // 湖泊天空盒 80 | 81 | std::shared_ptr m_pCamera; // 摄像机 82 | FirstPersonCameraController m_FPSCameraController; // 摄像机控制器 83 | 84 | std::unique_ptr m_pFluidSystem; //流体模拟系统 85 | FluidRender::ParticleParams m_ParticleParmas; //粒子的参数 86 | PBFSolver::PBFParams m_PBFParams; // 87 | 88 | std::vector m_ParticlePos; 89 | std::vector m_ParticleVec; 90 | std::vector m_ParticleIndex; 91 | 92 | bool m_DebugDepth = false; 93 | bool m_PBFRun = true; 94 | bool m_Step = false; 95 | bool m_FirstRun = true; 96 | bool m_DrawFluid = true; 97 | }; 98 | 99 | #endif -------------------------------------------------------------------------------- /include/Utils/Property.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #ifndef PROPERTY_H 5 | #define PROPERTY_H 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | template 14 | struct IsVariantMember; 15 | 16 | template 17 | struct IsVariantMember> : public std::disjunction...> {}; 18 | 19 | using Property = std::variant< 20 | int, uint32_t, float, DirectX::XMFLOAT2, DirectX::XMFLOAT3, DirectX::XMFLOAT4, DirectX::XMFLOAT4X4, 21 | std::vector, std::vector, std::vector, 22 | std::string>; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /include/Utils/WinMin.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #ifndef WINMAIN_H 5 | #define WINMAIN_H 6 | 7 | // 定义下面这些宏以去掉Windows中那些没用的组件 8 | 9 | #ifndef FULL_WINTARD 10 | #define WIN32_LEAN_AND_MEAN 11 | #define NOGDICAPMASKS 12 | #define NOSYSMETRICS 13 | #define NOMENUS 14 | #define NOICONS 15 | #define NOSYSCOMMANDS 16 | #define NORASTEROPS 17 | #define OEMRESOURCE 18 | #define NOATOM 19 | #define NOCLIPBOARD 20 | #define NOCOLOR 21 | #define NOCTLMGR 22 | #define NODRAWTEXT 23 | #define NOKERNEL 24 | // #define NONLS 25 | #define NOMEMMGR 26 | #define NOMETAFILE 27 | #define NOOPENFILE 28 | #define NOSCROLL 29 | #define NOSERVICE 30 | #define NOSOUND 31 | #define NOTEXTMETRIC 32 | #define NOWH 33 | #define NOCOMM 34 | #define NOKANJI 35 | #define NOHELP 36 | #define NOPROFILER 37 | #define NODEFERWINDOWPOS 38 | #define NOMCX 39 | #define NORPC 40 | #define NOPROXYSTUB 41 | #define NOIMAGE 42 | #define NOTAPE 43 | #endif 44 | 45 | #define NOMINMAX 46 | 47 | 48 | #include 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /include/Utils/XUtil.h: -------------------------------------------------------------------------------- 1 | //*************************************************************************************** 2 | // XUtil.h by X_Jun(MKXJun) (C) 2018-2022 All Rights Reserved. 3 | // Licensed under the MIT License. 4 | // 5 | // 实用工具集 6 | // utility tools. 7 | //*************************************************************************************** 8 | 9 | #pragma once 10 | 11 | #ifndef XUTIL_H 12 | #define XUTIL_H 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | // 21 | // 宏定义 22 | // 23 | 24 | #define LEN_AND_STR(STR) ((UINT)(sizeof(STR) - 1)), (STR) 25 | 26 | // 是否开启图形调试对象名称 27 | #if (defined(DEBUG) || defined(_DEBUG)) && !defined(GRAPHICS_DEBUGGER_OBJECT_NAME) 28 | #define GRAPHICS_DEBUGGER_OBJECT_NAME 1 29 | #endif 30 | 31 | // 32 | // 设置调试对象名称 33 | // 34 | 35 | template 36 | inline void SetDebugObjectName(IObject* pObject, std::string_view name) 37 | { 38 | pObject->SetPrivateData(WKPDID_D3DDebugObjectName, (uint32_t)name.size(), name.data()); 39 | } 40 | 41 | // 42 | // 文本转换函数 43 | // 44 | 45 | // 以下不可删除 46 | #pragma warning(push) 47 | #pragma warning(disable: 28251) 48 | extern "C" __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char* str, int cbmb, wchar_t* widestr, int cchwide); 49 | extern "C" __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t* widestr, int cchwide, char* str, int cbmb, const char* defchar, int* used_default); 50 | #pragma warning(pop) 51 | 52 | inline std::wstring UTF8ToWString(std::string_view utf8str) 53 | { 54 | if (utf8str.empty()) return std::wstring(); 55 | int cbMultiByte = static_cast(utf8str.size()); 56 | int req = MultiByteToWideChar(65001, 0, utf8str.data(), cbMultiByte, nullptr, 0); 57 | std::wstring res(req, 0); 58 | MultiByteToWideChar(65001, 0, utf8str.data(), cbMultiByte, &res[0], req); 59 | return res; 60 | } 61 | 62 | inline std::string WStringToUTF8(std::wstring_view wstr) 63 | { 64 | if (wstr.empty()) return std::string(); 65 | int cbMultiByte = static_cast(wstr.size()); 66 | int req = WideCharToMultiByte(65001, 0, wstr.data(), cbMultiByte, nullptr, 0, nullptr, nullptr); 67 | std::string res(req, 0); 68 | WideCharToMultiByte(65001, 0, wstr.data(), cbMultiByte, &res[0], req, nullptr, nullptr); 69 | return res; 70 | } 71 | 72 | // 73 | // 字符串转hash ID 74 | // 75 | 76 | using XID = size_t; 77 | inline XID StringToID(std::string_view str) 78 | { 79 | static std::hash hash; 80 | return hash(str); 81 | } 82 | 83 | // 84 | // 数学相关函数 85 | // 86 | 87 | namespace XMath 88 | { 89 | // ------------------------------ 90 | // InverseTranspose函数 91 | // ------------------------------ 92 | inline DirectX::XMMATRIX XM_CALLCONV InverseTranspose(DirectX::FXMMATRIX M) 93 | { 94 | using namespace DirectX; 95 | 96 | // 世界矩阵的逆的转置仅针对法向量,我们也不需要世界矩阵的平移分量 97 | // 而且不去掉的话,后续再乘上观察矩阵之类的就会产生错误的变换结果 98 | XMMATRIX A = M; 99 | A.r[3] = g_XMIdentityR3; 100 | 101 | return XMMatrixTranspose(XMMatrixInverse(nullptr, A)); 102 | } 103 | 104 | inline float Lerp(float a, float b, float t) 105 | { 106 | return (1.0f - t) * a + t * b; 107 | } 108 | } 109 | 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /shaders/Basic.hlsli: -------------------------------------------------------------------------------- 1 | #include "LightHelper.hlsli" 2 | 3 | Texture2D g_DiffuseMap : register(t0); 4 | Texture2D g_NormalMap : register(t1); 5 | Texture2D g_ShadowMap : register(t2); 6 | Texture2D g_SSAOMap : register(t3); 7 | TextureCube g_TexCube : register(t4); 8 | SamplerState g_Sam : register(s0); 9 | SamplerComparisonState g_SamShadow : register(s1); 10 | 11 | cbuffer CBChangesEveryInstanceDrawing : register(b0) 12 | { 13 | matrix g_World; 14 | matrix g_WorldInvTranspose; 15 | matrix g_WorldViewProj; 16 | } 17 | 18 | cbuffer CBChangesEveryObjectDrawing : register(b1) 19 | { 20 | Material g_Material; 21 | } 22 | 23 | cbuffer CBDrawingStates : register(b2) 24 | { 25 | int g_TextureUsed; 26 | int g_EnableShadow; 27 | int g_EnableSSAO; 28 | float g_Pad; 29 | } 30 | 31 | cbuffer CBChangesEveryFrame : register(b3) 32 | { 33 | matrix g_ViewProj; 34 | matrix g_ShadowTransform; // ShadowView * ShadowProj * T 35 | float3 g_EyePosW; 36 | float g_HeightScale; 37 | float g_MaxTessDistance; 38 | float g_MinTessDistance; 39 | float g_MinTessFactor; 40 | float g_MaxTessFactor; 41 | } 42 | 43 | cbuffer CBChangesRarely : register(b4) 44 | { 45 | DirectionalLight g_DirLight[5]; 46 | PointLight g_PointLight[5]; 47 | SpotLight g_SpotLight[5]; 48 | } 49 | 50 | struct VertexPosNormalTex 51 | { 52 | float3 PosL : POSITION; 53 | float3 NormalL : NORMAL; 54 | float2 Tex : TEXCOORD; 55 | }; 56 | 57 | struct VertexPosNormalTangentTex 58 | { 59 | float3 PosL : POSITION; 60 | float3 NormalL : NORMAL; 61 | float4 TangentL : TANGENT; 62 | float2 Tex : TEXCOORD; 63 | }; 64 | 65 | struct InstancePosNormalTex 66 | { 67 | float3 PosL : POSITION; 68 | float3 NormalL : NORMAL; 69 | float2 Tex : TEXCOORD; 70 | matrix World : World; 71 | matrix WorldInvTranspose : WorldInvTranspose; 72 | }; 73 | 74 | struct InstancePosNormalTangentTex 75 | { 76 | float3 PosL : POSITION; 77 | float3 NormalL : NORMAL; 78 | float4 TangentL : TANGENT; 79 | float2 Tex : TEXCOORD; 80 | matrix World : World; 81 | matrix WorldInvTranspose : WorldInvTranspose; 82 | }; 83 | 84 | struct VertexOutBasic 85 | { 86 | float4 PosH : SV_POSITION; 87 | float3 PosW : POSITION; 88 | float3 NormalW : NORMAL; 89 | float2 Tex : TEXCOORD0; 90 | float4 ShadowPosH : TEXCOORD1; 91 | float4 SSAOPosH : TEXCOORD2; 92 | }; 93 | 94 | struct VertexOutNormalMap 95 | { 96 | float4 PosH : SV_POSITION; 97 | float3 PosW : POSITION; 98 | float3 NormalW : NORMAL; 99 | float4 TangentW : TANGENT; 100 | float2 Tex : TEXCOORD0; 101 | float4 ShadowPosH : TEXCOORD1; 102 | float4 SSAOPosH : TEXCOORD2; 103 | }; 104 | 105 | struct TessVertexOut 106 | { 107 | float3 PosW : POSITION; 108 | float3 NormalW : NORMAL; 109 | float4 TangentW : TANGENT; 110 | float2 Tex : TEXCOORD0; 111 | float TessFactor : TESS; 112 | }; 113 | 114 | struct PatchTess 115 | { 116 | float EdgeTess[3] : SV_TessFactor; 117 | float InsideTess : SV_InsideTessFactor; 118 | }; 119 | 120 | struct HullOut 121 | { 122 | float3 PosW : POSITION; 123 | float3 NormalW : NORMAL; 124 | float4 TangentW : TANGENT; 125 | float2 Tex : TEXCOORD; 126 | }; 127 | -------------------------------------------------------------------------------- /shaders/BasicInstance_VS.hlsl: -------------------------------------------------------------------------------- 1 | #include "Basic.hlsli" 2 | 3 | // 顶点着色器 4 | VertexOutBasic VS(InstancePosNormalTex vIn) 5 | { 6 | VertexOutBasic vOut; 7 | 8 | vector posW = mul(float4(vIn.PosL, 1.0f), vIn.World); 9 | 10 | vOut.PosW = posW.xyz; 11 | vOut.PosH = mul(posW, g_ViewProj); 12 | vOut.NormalW = mul(vIn.NormalL, (float3x3) vIn.WorldInvTranspose); 13 | vOut.Tex = vIn.Tex; 14 | vOut.ShadowPosH = mul(posW, g_ShadowTransform); 15 | 16 | // 从NDC坐标[-1, 1]^2变换到纹理空间坐标[0, 1]^2 17 | // u = 0.5x + 0.5 18 | 19 | // v = -0.5y + 0.5 20 | // ((xw, yw, zw, w) + (w, w, 0, 0)) * (0.5, -0.5, 1, 1) = ((0.5x + 0.5)w, (-0.5y + 0.5)w, zw, w) 21 | // = (uw, vw, zw, w) 22 | // => (u, v, z, 1) 23 | vOut.SSAOPosH = (vOut.PosH + float4(vOut.PosH.ww, 0.0f, 0.0f)) * float4(0.5f, -0.5f, 1.0f, 1.0f); 24 | return vOut; 25 | } 26 | -------------------------------------------------------------------------------- /shaders/BasicObject_VS.hlsl: -------------------------------------------------------------------------------- 1 | #include "Basic.hlsli" 2 | 3 | // 顶点着色器 4 | VertexOutBasic VS(VertexPosNormalTex vIn) 5 | { 6 | VertexOutBasic vOut; 7 | 8 | vector posW = mul(float4(vIn.PosL, 1.0f), g_World); 9 | 10 | vOut.PosW = posW.xyz; 11 | vOut.PosH = mul(float4(vIn.PosL, 1.0f), g_WorldViewProj); 12 | vOut.NormalW = mul(vIn.NormalL, (float3x3) g_WorldInvTranspose); 13 | vOut.Tex = vIn.Tex; 14 | vOut.ShadowPosH = mul(posW, g_ShadowTransform); 15 | 16 | // 从NDC坐标[-1, 1]^2变换到纹理空间坐标[0, 1]^2 17 | // u = 0.5x + 0.5 18 | // v = -0.5y + 0.5 19 | // ((xw, yw, zw, w) + (w, w, 0, 0)) * (0.5, -0.5, 1, 1) = ((0.5x + 0.5)w, (-0.5y + 0.5)w, zw, w) 20 | // = (uw, vw, zw, w) 21 | // => (u, v, z, 1) 22 | vOut.SSAOPosH = (vOut.PosH + float4(vOut.PosH.ww, 0.0f, 0.0f)) * float4(0.5f, -0.5f, 1.0f, 1.0f); 23 | return vOut; 24 | } 25 | -------------------------------------------------------------------------------- /shaders/Basic_PS.hlsl: -------------------------------------------------------------------------------- 1 | #include "Basic.hlsli" 2 | 3 | // 像素着色器(3D) 4 | float4 PS(VertexOutBasic pIn) : SV_Target 5 | { 6 | // 若不使用纹理,则使用默认白色 7 | float4 texColor = float4(1.0f, 1.0f, 1.0f, 1.0f); 8 | 9 | if (g_TextureUsed) 10 | { 11 | texColor = g_DiffuseMap.Sample(g_Sam, pIn.Tex); 12 | // 提前进行Alpha裁剪,对不符合要求的像素可以避免后续运算 13 | clip(texColor.a - 0.1f); 14 | } 15 | 16 | // 标准化法向量 17 | pIn.NormalW = normalize(pIn.NormalW); 18 | 19 | // 求出顶点指向眼睛的向量,以及顶点与眼睛的距离 20 | float3 toEyeW = normalize(g_EyePosW - pIn.PosW); 21 | float distToEye = distance(g_EyePosW, pIn.PosW); 22 | 23 | // 初始化为0 24 | float4 ambient = float4(0.0f, 0.0f, 0.0f, 0.0f); 25 | float4 diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f); 26 | float4 spec = float4(0.0f, 0.0f, 0.0f, 0.0f); 27 | float4 A = float4(0.0f, 0.0f, 0.0f, 0.0f); 28 | float4 D = float4(0.0f, 0.0f, 0.0f, 0.0f); 29 | float4 S = float4(0.0f, 0.0f, 0.0f, 0.0f); 30 | int i; 31 | 32 | float shadow[5] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; 33 | // 仅第一个方向光用于计算阴影 34 | shadow[0] = CalcShadowFactor(g_SamShadow, g_ShadowMap, pIn.ShadowPosH); 35 | 36 | // 完成纹理投影变换并对SSAO图采样 37 | pIn.SSAOPosH /= pIn.SSAOPosH.w; 38 | float ambientAccess = 1.0f; 39 | [flatten] 40 | if (g_EnableSSAO) 41 | ambientAccess = g_SSAOMap.SampleLevel(g_Sam, pIn.SSAOPosH.xy, 0.0f).r; 42 | 43 | [unroll] 44 | for (i = 0; i < 5; ++i) 45 | { 46 | ComputeDirectionalLight(g_Material, g_DirLight[i], pIn.NormalW, toEyeW, A, D, S); 47 | ambient += ambientAccess * A; 48 | diffuse += shadow[i] * D; 49 | spec += shadow[i] * S; 50 | } 51 | 52 | [unroll] 53 | for (i = 0; i < 5; ++i) 54 | { 55 | ComputePointLight(g_Material, g_PointLight[i], pIn.PosW, pIn.NormalW, toEyeW, A, D, S); 56 | ambient += A; 57 | diffuse += D; 58 | spec += S; 59 | } 60 | 61 | [unroll] 62 | for (i = 0; i < 5; ++i) 63 | { 64 | ComputeSpotLight(g_Material, g_SpotLight[i], pIn.PosW, pIn.NormalW, toEyeW, A, D, S); 65 | ambient += A; 66 | diffuse += D; 67 | spec += S; 68 | } 69 | 70 | float4 litColor = texColor * (ambient + diffuse) + spec; 71 | litColor.a = texColor.a * g_Material.Diffuse.a; 72 | return litColor; 73 | } 74 | -------------------------------------------------------------------------------- /shaders/DisplacementMapInstance_VS.hlsl: -------------------------------------------------------------------------------- 1 | #include "Basic.hlsli" 2 | 3 | // 顶点着色器 4 | TessVertexOut VS(InstancePosNormalTangentTex vIn) 5 | { 6 | TessVertexOut vOut; 7 | 8 | vOut.PosW = mul(float4(vIn.PosL, 1.0f), vIn.World).xyz; 9 | vOut.NormalW = mul(vIn.NormalL, (float3x3) vIn.WorldInvTranspose); 10 | vOut.TangentW = mul(vIn.TangentL, vIn.World); 11 | vOut.Tex = vIn.Tex; 12 | 13 | float d = distance(vOut.PosW, g_EyePosW); 14 | 15 | // 标准化曲面细分因子 16 | // TessFactor = 17 | // 0, d >= g_MinTessDistance 18 | // (g_MinTessDistance - d) / (g_MinTessDistance - g_MaxTessDistance), g_MinTessDistance <= d <= g_MaxTessDistance 19 | // 1, d <= g_MaxTessDistance 20 | float tess = saturate((g_MinTessDistance - d) / (g_MinTessDistance - g_MaxTessDistance)); 21 | 22 | // [0, 1] --> [g_MinTessFactor, g_MaxTessFactor] 23 | vOut.TessFactor = g_MinTessFactor + tess * (g_MaxTessFactor - g_MinTessFactor); 24 | 25 | return vOut; 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /shaders/DisplacementMapObject_VS.hlsl: -------------------------------------------------------------------------------- 1 | #include "Basic.hlsli" 2 | 3 | // 顶点着色器 4 | TessVertexOut VS(VertexPosNormalTangentTex vIn) 5 | { 6 | TessVertexOut vOut; 7 | 8 | vOut.PosW = mul(float4(vIn.PosL, 1.0f), g_World).xyz; 9 | vOut.NormalW = mul(vIn.NormalL, (float3x3) g_WorldInvTranspose); 10 | vOut.TangentW = mul(vIn.TangentL, g_World); 11 | vOut.Tex = vIn.Tex; 12 | 13 | float d = distance(vOut.PosW, g_EyePosW); 14 | 15 | // 标准化曲面细分因子 16 | // TessFactor = 17 | // 0, d >= g_MinTessDistance 18 | // (g_MinTessDistance - d) / (g_MinTessDistance - g_MaxTessDistance), g_MinTessDistance <= d <= g_MaxTessDistance 19 | // 1, d <= g_MaxTessDistance 20 | float tess = saturate((g_MinTessDistance - d) / (g_MinTessDistance - g_MaxTessDistance)); 21 | 22 | // [0, 1] --> [g_MinTessFactor, g_MaxTessFactor] 23 | vOut.TessFactor = g_MinTessFactor + tess * (g_MaxTessFactor - g_MinTessFactor); 24 | 25 | return vOut; 26 | } 27 | -------------------------------------------------------------------------------- /shaders/DisplacementMap_DS.hlsl: -------------------------------------------------------------------------------- 1 | #include "Basic.hlsli" 2 | 3 | [domain("tri")] 4 | VertexOutNormalMap DS(PatchTess patchTess, 5 | float3 bary : SV_DomainLocation, 6 | const OutputPatch tri) 7 | { 8 | VertexOutNormalMap dOut; 9 | 10 | // 对面片属性进行插值以生成顶点 11 | dOut.PosW = bary.x * tri[0].PosW + bary.y * tri[1].PosW + bary.z * tri[2].PosW; 12 | dOut.NormalW = bary.x * tri[0].NormalW + bary.y * tri[1].NormalW + bary.z * tri[2].NormalW; 13 | dOut.TangentW = bary.x * tri[0].TangentW + bary.y * tri[1].TangentW + bary.z * tri[2].TangentW; 14 | dOut.Tex = bary.x * tri[0].Tex + bary.y * tri[1].Tex + bary.z * tri[2].Tex; 15 | 16 | // 对插值后的法向量进行标准化 17 | dOut.NormalW = normalize(dOut.NormalW); 18 | 19 | // 20 | // 位移映射 21 | // 22 | 23 | // 基于摄像机到顶点的距离选取mipmap等级;特别地,对每个MipInterval单位选择下一个mipLevel 24 | // 然后将mipLevel限制在[0, 6] 25 | const float MipInterval = 20.0f; 26 | float mipLevel = clamp((distance(dOut.PosW, g_EyePosW) - MipInterval) / MipInterval, 0.0f, 6.0f); 27 | 28 | // 对高度图采样(存在法线贴图的alpha通道) 29 | float h = g_NormalMap.SampleLevel(g_Sam, dOut.Tex, mipLevel).a; 30 | 31 | // 沿着法向量进行偏移 32 | dOut.PosW += (g_HeightScale * (h - 1.0f)) * dOut.NormalW; 33 | 34 | // 生成投影纹理坐标 35 | dOut.ShadowPosH = mul(float4(dOut.PosW, 1.0f), g_ShadowTransform); 36 | 37 | // 投影到齐次裁减空间 38 | dOut.PosH = mul(float4(dOut.PosW, 1.0f), g_ViewProj); 39 | 40 | // 从NDC坐标[-1, 1]^2变换到纹理空间坐标[0, 1]^2 41 | // u = 0.5x + 0.5 42 | // v = -0.5y + 0.5 43 | // ((xw, yw, zw, w) + (w, w, 0, 0)) * (0.5, -0.5, 1, 1) = ((0.5x + 0.5)w, (-0.5y + 0.5)w, zw, w) 44 | // = (uw, vw, zw, w) 45 | // => (u, v, z, 1) 46 | dOut.SSAOPosH = (dOut.PosH + float4(dOut.PosH.ww, 0.0f, 0.0f)) * float4(0.5f, -0.5f, 1.0f, 1.0f); 47 | 48 | return dOut; 49 | } 50 | -------------------------------------------------------------------------------- /shaders/DisplacementMap_HS.hlsl: -------------------------------------------------------------------------------- 1 | #include "Basic.hlsli" 2 | 3 | PatchTess PatchHS(InputPatch patch, 4 | uint patchID : SV_PrimitiveID) 5 | { 6 | PatchTess pt; 7 | 8 | // 对每条边的曲面细分因子求平均值,并选择其中一条边的作为其内部的 9 | // 曲面细分因子。基于边的属性来进行曲面细分因子的计算非常重要,这 10 | // 样那些与多个三角形共享的边将会拥有相同的曲面细分因子,否则会导 11 | // 致间隙的产生 12 | pt.EdgeTess[0] = 0.5f * (patch[1].TessFactor + patch[2].TessFactor); 13 | pt.EdgeTess[1] = 0.5f * (patch[2].TessFactor + patch[0].TessFactor); 14 | pt.EdgeTess[2] = 0.5f * (patch[0].TessFactor + patch[1].TessFactor); 15 | pt.InsideTess = pt.EdgeTess[0]; 16 | 17 | return pt; 18 | } 19 | 20 | // 外壳着色器 21 | [domain("tri")] 22 | [partitioning("fractional_odd")] 23 | [outputtopology("triangle_cw")] 24 | [outputcontrolpoints(3)] 25 | [patchconstantfunc("PatchHS")] 26 | HullOut HS(InputPatch patch, 27 | uint i : SV_OutputControlPointID, 28 | uint patchId : SV_PrimitiveID) 29 | { 30 | HullOut hOut; 31 | 32 | // 直传 33 | hOut.PosW = patch[i].PosW; 34 | hOut.NormalW = patch[i].NormalW; 35 | hOut.TangentW = patch[i].TangentW; 36 | hOut.Tex = patch[i].Tex; 37 | 38 | return hOut; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /shaders/Fluid/AddDeltaPosition_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "PBFSolverCommon.hlsli" 2 | 3 | 4 | [numthreads(THREAD_NUM_X, 1, 1)] 5 | void CS( uint3 DTid : SV_DispatchThreadID) 6 | { 7 | if (DTid.x >= g_ParticleNums) 8 | { 9 | return; 10 | } 11 | 12 | uint totalNeighborNum = g_ContactCounts[DTid.x]; 13 | float factor = max(g_SOR * totalNeighborNum, 1.0f); 14 | float3 resPos = g_sortedNewPosition[DTid.x] + g_DeltaPosition[DTid.x] * (1 / factor); 15 | 16 | g_sortedNewPosition[DTid.x] = resPos; 17 | } -------------------------------------------------------------------------------- /shaders/Fluid/BlurDepth_PS.hlsl: -------------------------------------------------------------------------------- 1 | #include "FliudCommon.hlsli" 2 | 3 | 4 | float4 PS(PassThoughVertexOut ptIn) : SV_Target 5 | { 6 | float4 position = ptIn.PosH; 7 | float2 texCoord[1] = { ptIn.TexCoord }; 8 | 9 | //eye-space depth of center sample 10 | float depth = g_DepthTexture.Load(int3(position.xy, 0)).x; 11 | 12 | float blurDepthFalloff = 5.5f; 13 | float maxBlurRadius = 5.0f; 14 | 15 | //discontinuities between different tap counts are visible. to avoid this we 16 | //use fractional contributions between #taps = ceil(radius) and floor(radius) 17 | float radius = min(maxBlurRadius, g_BlurScale * (g_BlurRadiusWorld / depth)); 18 | float radiusInv = 1.0f / radius; 19 | float taps = ceil(radius); 20 | float frac = taps - radius; 21 | 22 | float sum = 0.0f; 23 | float wsum = 0.0f; 24 | float count = 0.0f; 25 | 26 | for (float y = -taps; y <= taps; y += 1.0f) 27 | { 28 | for (float x = -taps; x <= taps; x += 1.0f) 29 | { 30 | float2 offset = float2(x, y); 31 | float sample = g_DepthTexture.Load(int3(position.xy + offset, 0)).x; 32 | 33 | //spatial domain 34 | float r1 = length(float2(x, y)) * radiusInv; 35 | float w = exp(-(r1 * r1)); 36 | 37 | //range domain (based on depth difference) 38 | float r2 = (sample - depth) * blurDepthFalloff; 39 | float g = exp(-(r2 * r2)); 40 | 41 | //fractional radius contribution 42 | float wBoundaty = step(radius, max(abs(x), abs(y))); 43 | float wFrac = 1.0 - wBoundaty * frac; 44 | 45 | sum += sample * w * g * wFrac; 46 | wsum += w * g * wFrac; 47 | count += g * wFrac; 48 | } 49 | } 50 | 51 | if (wsum > 0.0f) 52 | { 53 | sum /= wsum; 54 | } 55 | 56 | float blend = count / sqr(2.0f * radius + 1.0f); 57 | float res = lerp(depth, sum, blend); 58 | return float4(res, res, res, 1.0f); 59 | } 60 | -------------------------------------------------------------------------------- /shaders/Fluid/CalcAnisotropy_CS.hlsl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/shaders/Fluid/CalcAnisotropy_CS.hlsl -------------------------------------------------------------------------------- /shaders/Fluid/CalcBoundsFinalize_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "NerghborSearchCommon.hlsli" 2 | 3 | groupshared float3 boundmin[THREAD_BOUNDS_X]; 4 | groupshared float3 boundmax[THREAD_BOUNDS_X]; 5 | 6 | [numthreads(THREAD_BOUNDS_X, 1, 1)] 7 | void CS(uint3 DTid : SV_DispatchThreadID, uint GI : SV_GroupIndex, uint3 GId : SV_GroupID) 8 | { 9 | if (g_BoundsFinalizeNums == 1) 10 | { 11 | //only one 12 | if (GI==0) 13 | { 14 | g_Bounds[0] = g_WriteBoundsLower[0] - float3(g_CellSize, g_CellSize, g_CellSize); 15 | g_Bounds[1] = g_WriteBoundsUpper[0] + float3(g_CellSize, g_CellSize, g_CellSize); 16 | } 17 | } 18 | else 19 | { 20 | float3 currBoundmin = float3(0.0f, 0.0f, 0.0f); 21 | float3 currBoundmax = float3(0.0f, 0.0f, 0.0f); 22 | if (DTid.x < g_BoundsFinalizeNums) 23 | { 24 | currBoundmin = g_WriteBoundsLower[DTid.x]; 25 | currBoundmax = g_WriteBoundsUpper[DTid.x]; 26 | } 27 | else 28 | { 29 | currBoundmin = g_WriteBoundsLower[g_BoundsFinalizeNums - 1]; 30 | currBoundmax = g_WriteBoundsUpper[g_BoundsFinalizeNums - 1]; 31 | } 32 | boundmin[GI] = currBoundmin; 33 | boundmax[GI] = currBoundmax; 34 | 35 | uint d = 0; 36 | uint offset = 1; 37 | uint totalNum = THREAD_BOUNDS_X; 38 | //min 39 | for (d = totalNum >> 1; d > 0; d >>= 1) 40 | { 41 | GroupMemoryBarrierWithGroupSync(); 42 | if (GI < d) 43 | { 44 | uint ai = offset * (2 * GI + 1) - 1; 45 | uint bi = offset * (2 * GI + 2) - 1; 46 | 47 | boundmin[bi] = min(boundmin[ai], boundmin[bi]); 48 | boundmax[bi] = max(boundmax[ai], boundmax[bi]); 49 | } 50 | offset *= 2; 51 | } 52 | 53 | GroupMemoryBarrierWithGroupSync(); 54 | if (GI == 0) 55 | { 56 | g_Bounds[0] = boundmin[totalNum - 1] - float3(g_CellSize, g_CellSize, g_CellSize); 57 | g_Bounds[1] = boundmax[totalNum - 1] + float3(g_CellSize, g_CellSize, g_CellSize); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /shaders/Fluid/CalcBoundsGroup_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "NerghborSearchCommon.hlsli" 2 | 3 | //0:min 1:max 4 | groupshared float3 boundmin[THREAD_BOUNDS_X]; 5 | groupshared float3 boundmax[THREAD_BOUNDS_X]; 6 | 7 | [numthreads(THREAD_BOUNDS_X, 1, 1)] 8 | void CS(uint3 DTid : SV_DispatchThreadID, uint GI : SV_GroupIndex, uint3 GId : SV_GroupID) 9 | { 10 | float3 currBoundmin = float3(0.0f, 0.0f, 0.0f); 11 | float3 currBoundmax = float3(0.0f, 0.0f, 0.0f); 12 | if (DTid.x < g_BoundsGroups) 13 | { 14 | currBoundmin = g_ReadBoundsLower[DTid.x]; 15 | currBoundmax = g_ReadBoundsUpper[DTid.x]; 16 | } 17 | else 18 | { 19 | currBoundmin = g_ReadBoundsLower[g_BoundsGroups-1]; 20 | currBoundmax = g_ReadBoundsUpper[g_BoundsGroups-1]; 21 | } 22 | boundmin[GI] = currBoundmin; 23 | boundmax[GI] = currBoundmax; 24 | 25 | uint d = 0; 26 | uint offset = 1; 27 | uint totalNum = THREAD_BOUNDS_X; 28 | //min 29 | for (d = totalNum >> 1; d > 0; d >>= 1) 30 | { 31 | GroupMemoryBarrierWithGroupSync(); 32 | if (GI < d) 33 | { 34 | uint ai = offset * (2 * GI + 1) - 1; 35 | uint bi = offset * (2 * GI + 2) - 1; 36 | 37 | boundmin[bi] = min(boundmin[ai], boundmin[bi]); 38 | boundmax[bi] = max(boundmax[ai], boundmax[bi]); 39 | } 40 | offset *= 2; 41 | } 42 | GroupMemoryBarrierWithGroupSync(); 43 | if (GI == 0) 44 | { 45 | g_WriteBoundsLower[GId.x] = boundmin[totalNum - 1]; 46 | g_WriteBoundsUpper[GId.x] = boundmax[totalNum - 1]; 47 | } 48 | } -------------------------------------------------------------------------------- /shaders/Fluid/CalcBounds_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "NerghborSearchCommon.hlsli" 2 | 3 | //0:min 1:max 4 | groupshared float3 boundmin[THREAD_BOUNDS_X]; 5 | groupshared float3 boundmax[THREAD_BOUNDS_X]; 6 | 7 | [numthreads(THREAD_BOUNDS_X, 1, 1)] 8 | void CS( uint3 DTid : SV_DispatchThreadID,uint GI:SV_GroupIndex,uint3 GId:SV_GroupID) 9 | { 10 | 11 | float3 currPos = float3(0.0f, 0.0f, 0.0f); 12 | if (DTid.x < g_ParticleNums) 13 | { 14 | currPos = g_ParticlePosition[DTid.x]; 15 | } 16 | else 17 | { 18 | currPos = g_ParticlePosition[g_ParticleNums - 1]; 19 | 20 | } 21 | boundmin[GI] = currPos; 22 | boundmax[GI] = currPos; 23 | 24 | 25 | uint d = 0; 26 | uint offset = 1; 27 | uint totalNum = THREAD_BOUNDS_X; 28 | //min 29 | for (d = totalNum >> 1; d > 0; d >>= 1) 30 | { 31 | GroupMemoryBarrierWithGroupSync(); 32 | if (GI < d) 33 | { 34 | uint ai = offset * (2 * GI + 1) - 1; 35 | uint bi = offset * (2 * GI + 2) - 1; 36 | 37 | boundmin[bi] = min(boundmin[ai], boundmin[bi]); 38 | boundmax[bi] = max(boundmax[ai], boundmax[bi]); 39 | } 40 | offset *= 2; 41 | } 42 | GroupMemoryBarrierWithGroupSync(); 43 | 44 | if (GI == 0) 45 | { 46 | float3 min = boundmin[totalNum - 1]; 47 | float3 max = boundmax[totalNum - 1]; 48 | g_ReadBoundsLower[GId.x] = min; 49 | g_ReadBoundsUpper[GId.x] = max; 50 | } 51 | } -------------------------------------------------------------------------------- /shaders/Fluid/CalcDisplacement_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "PBFSolverCommon.hlsli" 2 | 3 | 4 | [numthreads(THREAD_NUM_X, 1, 1)] 5 | void CS( uint3 DTid : SV_DispatchThreadID ) 6 | { 7 | if (DTid.x >= g_ParticleNums) 8 | { 9 | return; 10 | } 11 | 12 | //curr particle pos 13 | float3 currPos = g_sortedNewPosition[DTid.x]; 14 | //curr neighbor count 15 | uint neightborCount = g_ContactCounts[DTid.x]; 16 | 17 | float currLambda = g_LambdaMultiplier[DTid.x]; 18 | float poly6Q = WSpiky(g_DeltaQ, g_sphSmoothLength); 19 | 20 | float3 deltaPos = float3(0.0f, 0.0f, 0.0f); 21 | uint i = 0; 22 | for (i = 0; i < neightborCount; ++i) 23 | { 24 | //get the cell particle pos 25 | uint neightborParticleIndex = g_Contacts[DTid.x * g_MaxNeighborPerParticle + i]; 26 | float neighborLambda = g_LambdaMultiplier[neightborParticleIndex]; 27 | //get the cell particle pos 28 | float3 neighborParticlePos = g_sortedNewPosition[neightborParticleIndex]; 29 | //r=p_i-p_j 30 | float3 r = currPos - neighborParticlePos; 31 | float poly6 = WSpiky(r, g_sphSmoothLength); 32 | float diffPoly = poly6 / poly6Q; 33 | float scorr = -g_ScorrK * pow(abs(diffPoly), g_ScorrN); 34 | float coff_j = currLambda + neighborLambda + scorr; 35 | 36 | float3 currGrad = WSpikyGrad(r, g_sphSmoothLength); 37 | deltaPos += coff_j * currGrad; 38 | } 39 | 40 | deltaPos = deltaPos * g_InverseDensity_0; 41 | g_DeltaPosition[DTid.x] = deltaPos; 42 | } -------------------------------------------------------------------------------- /shaders/Fluid/CalcHash_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "NerghborSearchCommon.hlsli" 2 | 3 | [numthreads(THREAD_NUM_X, 1, 1)] 4 | void CS(uint3 DTid : SV_DispatchThreadID ) 5 | { 6 | if (DTid.x < g_ParticleNums) 7 | { 8 | float3 currPos = g_ParticlePosition[DTid.x]; 9 | int3 cellPos = floor((currPos - g_Bounds[0]) / g_CellSize); 10 | g_cellHash[DTid.x] = GetCellHash(cellPos); 11 | g_cellIndexs[DTid.x] = g_acticeIndexs[DTid.x]; 12 | } 13 | else 14 | { 15 | g_cellHash[DTid.x] = -1; 16 | g_cellIndexs[DTid.x] = -1; 17 | } 18 | } -------------------------------------------------------------------------------- /shaders/Fluid/CalcLagrangeMultiplier_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "PBFSolverCommon.hlsli" 2 | 3 | 4 | [numthreads(THREAD_NUM_X, 1, 1)] 5 | void CS( uint3 DTid : SV_DispatchThreadID ) 6 | { 7 | if (DTid.x >= g_ParticleNums) 8 | { 9 | return; 10 | } 11 | 12 | //curr particle pos 13 | float3 currPos = g_sortedNewPosition[DTid.x]; 14 | //curr neighbor count 15 | uint neightborCount = g_ContactCounts[DTid.x]; 16 | 17 | //clac density 18 | float density = 0; 19 | //clac Lagrange multiplier 20 | float3 gradSum_i = float3(0.0f, 0.0f, 0.0f); 21 | float gradSum_j = 0; 22 | 23 | uint i = 0; 24 | for (i = 0; i < neightborCount; ++i) 25 | { 26 | //get the cell particle pos 27 | uint neightborParticleIndex = g_Contacts[DTid.x * g_MaxNeighborPerParticle + i]; 28 | float3 neighborPartclePos = g_sortedNewPosition[neightborParticleIndex]; 29 | //r=p_i-p_j 30 | float3 r = currPos - neighborPartclePos; 31 | density += WPoly6(r, g_sphSmoothLength); 32 | 33 | float3 currGrad = WSpikyGrad(r, g_sphSmoothLength); 34 | currGrad *= g_InverseDensity_0; 35 | gradSum_i += currGrad; 36 | 37 | if (neightborParticleIndex != DTid.x) 38 | { 39 | gradSum_j += dot(currGrad, currGrad); 40 | } 41 | 42 | } 43 | 44 | 45 | g_Density[DTid.x] = density; 46 | float gradSumTotal = gradSum_j + dot(gradSum_i, gradSum_i); 47 | // evaluate density constraint 48 | float constraint = max(density * g_InverseDensity_0 - 1.0f, 0.0f); 49 | float lambda = -constraint / (gradSumTotal + g_LambdaEps); 50 | 51 | g_LambdaMultiplier[DTid.x] = lambda; 52 | } -------------------------------------------------------------------------------- /shaders/Fluid/CalcVorticity_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "PBFSolverCommon.hlsli" 2 | 3 | 4 | //Clac curl 5 | [numthreads(THREAD_NUM_X, 1, 1)] 6 | void CS( uint3 DTid : SV_DispatchThreadID ) 7 | { 8 | if (DTid.x >= g_ParticleNums) 9 | { 10 | return; 11 | } 12 | 13 | //curr neighbor count 14 | uint neightborCount = g_ContactCounts[DTid.x]; 15 | 16 | //curr particle pos 17 | float3 currPos = g_sortedNewPosition[DTid.x]; 18 | float3 currVec = g_UpdatedVelocity[DTid.x]; 19 | float3 currOmega = float3(0.0f, 0.0f, 0.0f); 20 | 21 | uint i = 0; 22 | for (i = 0; i < neightborCount; ++i) 23 | { 24 | //get the cell particle pos 25 | uint neightborParticleIndex = g_Contacts[DTid.x * g_MaxNeighborPerParticle + i]; 26 | //get the cell particle pos 27 | float3 neighborParticlePos = g_sortedNewPosition[neightborParticleIndex]; 28 | //r=p_i-p_j 29 | float3 r = currPos - neighborParticlePos; 30 | //v_j-v_i 31 | float3 deltaVelocity = g_UpdatedVelocity[neightborParticleIndex] - currVec; 32 | float3 currGrad = WSpikyGrad(r, g_sphSmoothLength); 33 | //calc omega 34 | float3 omega_j = cross(deltaVelocity, currGrad); 35 | currOmega += omega_j; 36 | } 37 | 38 | 39 | float curlLength = length(currOmega); 40 | g_Curl[DTid.x] = float4(currOmega.xyz, curlLength); 41 | 42 | } -------------------------------------------------------------------------------- /shaders/Fluid/CollisionParticle_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "PBFSolverCommon.hlsli" 2 | 3 | 4 | //Find Neighbor Paticle 5 | [numthreads(THREAD_NUM_X, 1, 1)] 6 | void CS( uint3 DTid : SV_DispatchThreadID ) 7 | { 8 | 9 | if (DTid.x >= g_ParticleNums) 10 | { 11 | return; 12 | } 13 | 14 | //curr particle pos 15 | float3 currPos = g_sortedNewPosition[DTid.x]; 16 | float3 sceneMin = g_Bounds[0]; 17 | int3 currCellPos = floor((currPos - sceneMin) / g_CellSize); 18 | 19 | //curr particle index 20 | //uint currParitcleIndex = g_ParticleIndex[DTid.x]; 21 | 22 | int neighborCount = 0; 23 | int x = 0, y = 0, z = 0; 24 | [unroll(3)] 25 | for (z = -1; z <= 1; ++z) 26 | { 27 | [unroll(3)] 28 | for (y = -1; y <= 1; ++y) 29 | { 30 | [unroll(3)] 31 | for (x = -1; x <= 1; ++x) 32 | { 33 | //find 27 cell neighbor particle 34 | int3 neighCellPos = currCellPos + int3(x, y, z); 35 | if (neighCellPos.x < 0.0f || neighCellPos.y < 0.0f || neighCellPos.z < 0.0f) 36 | { 37 | continue; 38 | } 39 | uint cellHash = GetCellHash(neighCellPos); 40 | uint neighborCellStart = g_CellStart[cellHash]; 41 | uint neighborCellEnd = g_CellEnd[cellHash]; 42 | if (neighborCellStart >= neighborCellEnd) 43 | { 44 | continue; 45 | } 46 | for (uint index = neighborCellStart; index < neighborCellEnd; ++index) 47 | { 48 | //get the cell particle pos 49 | float3 neighborPartclePos = g_sortedNewPosition[index]; 50 | float3 distance = currPos - neighborPartclePos; 51 | float distancesq = dot(distance, distance); 52 | if (distancesq < g_ParticleRadiusSq) 53 | { 54 | //contact 55 | int contactsIndex = DTid.x * g_MaxNeighborPerParticle + neighborCount; 56 | g_Contacts[contactsIndex] = index; 57 | neighborCount++; 58 | } 59 | if (neighborCount == g_MaxNeighborPerParticle) 60 | { 61 | g_ContactCounts[DTid.x] = neighborCount; 62 | return; 63 | } 64 | } 65 | 66 | } 67 | } 68 | } 69 | 70 | g_ContactCounts[DTid.x] = neighborCount; 71 | 72 | } -------------------------------------------------------------------------------- /shaders/Fluid/CollisionPlane_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "PBFSolverCommon.hlsli" 2 | 3 | [numthreads(THREAD_NUM_X, 1, 1)] 4 | void CS( uint3 DTid : SV_DispatchThreadID ) 5 | { 6 | if (DTid.x >= g_ParticleNums) 7 | { 8 | return; 9 | } 10 | 11 | float3 currPos = g_sortedNewPosition[DTid.x]; 12 | 13 | int count = 0; 14 | int i = 0; 15 | [unroll] 16 | for (i = 0; i < g_PlaneNums; ++i) 17 | { 18 | float distance = sdfPlane(currPos, g_Plane[i].xyz, g_Plane[i].w) - g_CollisionDistance; 19 | if (distance < g_CollisionThreshold && count < g_MaxCollisionPlanes) 20 | { 21 | int index = DTid.x * g_MaxCollisionPlanes + count; 22 | g_CollisionPlanes[index] = g_Plane[i]; 23 | count++; 24 | } 25 | } 26 | 27 | g_CollisionCounts[DTid.x] = count; 28 | 29 | } -------------------------------------------------------------------------------- /shaders/Fluid/Composite_PS.hlsl: -------------------------------------------------------------------------------- 1 | #include "FliudCommon.hlsli" 2 | 3 | struct PixelOut 4 | { 5 | float4 result : SV_Target0; 6 | float4 normal : SV_Target1; 7 | float depthOut : SV_Depth; 8 | }; 9 | 10 | PixelOut PS(PassThoughVertexOut ptIn) 11 | { 12 | //flip y-coordinate 13 | float2 uvCoord = float2(ptIn.TexCoord.x, 1.0f - ptIn.TexCoord.y); 14 | float eyeZ = g_DepthTexture.Sample(g_TexSampler, uvCoord).x; 15 | if (eyeZ <= 0.0f) 16 | discard; 17 | 18 | PixelOut pOut; 19 | 20 | //reconstruct eye space form depth 21 | float3 eyePos = viewPortToEyeSpace(uvCoord, eyeZ); 22 | 23 | //finite difference approx for normals, 24 | float3 zl = eyePos - viewPortToEyeSpace(uvCoord - float2(g_InvTexScale.x, 0.0), g_DepthTexture.Sample(g_TexSampler, uvCoord - float2(g_InvTexScale.x, 0.0)).x); 25 | float3 zr = viewPortToEyeSpace(uvCoord + float2(g_InvTexScale.x, 0.0), g_DepthTexture.Sample(g_TexSampler, uvCoord + float2(g_InvTexScale.x, 0.0)).x) - eyePos; 26 | 27 | 28 | float3 zt = viewPortToEyeSpace(uvCoord + float2(0.0, g_InvTexScale.y), g_DepthTexture.Sample(g_TexSampler, uvCoord + float2(0.0, g_InvTexScale.y)).x) - eyePos; 29 | float3 zb = eyePos - viewPortToEyeSpace(uvCoord - float2(0.0, g_InvTexScale.y), g_DepthTexture.Sample(g_TexSampler, uvCoord - float2(0.0, g_InvTexScale.y)).x); 30 | 31 | float3 dx = -zl; 32 | float3 dy = -zt; 33 | 34 | if (abs(zr.z) < abs(zl.z)) 35 | dx = -zr; 36 | 37 | if (abs(zb.z) < abs(zt.z)) 38 | dy = -zb; 39 | 40 | float4 worldPos = mul(float4(eyePos, 1.0), g_WorldViewInv); 41 | 42 | float shadow = 0.1f; 43 | 44 | float3 l = mul(float4(g_DirLight[0].Direction,0.0f),g_WorldView).xyz; 45 | float3 v = -normalize(eyePos); 46 | 47 | //float3 normal = normalize(cross(dx, dy)); 48 | 49 | float3 normal = normalize(cross(dx, dy)); 50 | 51 | pOut.normal = float4(-normal * 0.5f + 0.5f, 1.0f); 52 | 53 | float3 n = normal; 54 | float3 h = normalize(v + l); 55 | 56 | 57 | float3 skyColor = float3(0.1, 0.2, 0.3) * 1.2; 58 | float3 groundColor = float3(0.1, 0.1, 0.3); 59 | 60 | float fresnel = 0.1 + (1.0 - 0.1) * cube(1.0 - max(dot(n, v), 0.0)); 61 | 62 | 63 | 64 | float3 rEye = reflect(-v, n).xyz; 65 | float3 rWorld = mul(float4(rEye, 0.0), g_WorldViewInv).xyz; 66 | 67 | float2 texScale = float2(0.75, 1.0); // to account for backbuffer aspect ratio (todo: pass in) 68 | 69 | float refractScale = g_Ior * 0.025; 70 | float reflectScale = g_Ior * 0.1; 71 | 72 | // attenuate refraction near ground (hack) 73 | refractScale *= smoothstep(0.1, 0.4, worldPos.y); 74 | 75 | float2 refractCoord = uvCoord + n.xy * refractScale * texScale; 76 | 77 | // read thickness from refracted coordinate otherwise we get halos around objectsw 78 | float thickness = max(g_ThicknessTexture.Sample(g_TexSampler, refractCoord).x,0.8f); 79 | 80 | //vec3 transmission = exp(-(vec3(1.0)-color.xyz)*thickness); 81 | float3 transmission = (1.0 - (1.0 - g_Color.xyz) * thickness * 0.8) * g_Color.w; 82 | float3 refract = g_SceneTexture.Sample(g_TexSampler, refractCoord).xyz * transmission; 83 | 84 | float2 sceneReflectCoord = uvCoord - rEye.xy * texScale * reflectScale / eyePos.z; 85 | float3 sceneReflect = g_SceneTexture.Sample(g_TexSampler, sceneReflectCoord).xyz * shadow; 86 | //vec3 planarReflect = texture2D(reflectTex, gl_TexCoord[0].xy).xyz; 87 | float3 planarReflect = float3(0.0, 0.0, 0.0); 88 | 89 | // fade out planar reflections above the ground 90 | //float3 reflect = lerp(planarReflect, sceneReflect, smoothstep(0.05, 0.3, worldPos.y)) + lerp(groundColor, skyColor, smoothstep(0.15, 0.25, rWorld.y)*shadow); 91 | //float3 reflect = sceneReflect + lerp(groundColor, skyColor, smoothstep(0.15, 0.25, rWorld.y) * shadow); 92 | float3 reflect = lerp(groundColor, skyColor, smoothstep(0.15, 0.25, rWorld.y)); 93 | // lighting 94 | //float3 diffuse = color.xyz * lerp(float3(0.29, 0.379, 0.59), float3(1.0, 1.0, 1.0), (ln * 0.5 + 0.5) * max(shadow, 0.4)) * (1.0 - color.w); 95 | float3 diffuse = 0.0f; 96 | float specular = 1.2 * pow(max(dot(h, n), 0.0), 400.0); 97 | 98 | // write valid z 99 | float4 clipPos = mul(float4(0.0, 0.0, eyeZ, 1.0),g_Proj); 100 | clipPos.z /= clipPos.w; 101 | pOut.depthOut = clipPos.z; 102 | 103 | //Color 104 | 105 | float4 res= float4(diffuse + (lerp(refract, reflect, fresnel) + specular) * g_Color.w, 1.0f); 106 | pOut.result = res; 107 | 108 | return pOut; 109 | } -------------------------------------------------------------------------------- /shaders/Fluid/EllipsoidDepth_GS.hlsl: -------------------------------------------------------------------------------- 1 | #include "FliudCommon.hlsli" 2 | 3 | [maxvertexcount(4)] 4 | void GS(point FluidVertexOut input[1], inout TriangleStream triStream) 5 | { 6 | const float4 ndcPos = input[0].ndcPos; 7 | // frustrum culling 8 | const float ndcBound = 1.0; 9 | if (any(abs(ndcPos.xy) > ndcBound)) 10 | { 11 | return; 12 | } 13 | 14 | float4 bounds = input[0].bounds; 15 | 16 | const float4 invQuad0 = input[0].invQ0; 17 | const float4 invQuad1 = input[0].invQ1; 18 | const float4 invQuad2 = input[0].invQ2; 19 | const float4 invQuad3 = input[0].invQ3; 20 | 21 | float xmin = bounds.x; 22 | float xmax = bounds.y; 23 | float ymin = bounds.z; 24 | float ymax = bounds.w; 25 | 26 | FluidGeoOut output; 27 | 28 | output.Position = float4(xmin, ymax, 0.5, 1.0); 29 | output.invQ0 = invQuad0; 30 | output.invQ1 = invQuad1; 31 | output.invQ2 = invQuad2; 32 | output.invQ3 = invQuad3; 33 | triStream.Append(output); 34 | 35 | output.Position = float4(xmin, ymin, 0.5, 1.0); 36 | output.invQ0 = invQuad0; 37 | output.invQ1 = invQuad1; 38 | output.invQ2 = invQuad2; 39 | output.invQ3 = invQuad3; 40 | triStream.Append(output); 41 | 42 | output.Position = float4(xmax, ymax, 0.5, 1.0); 43 | output.invQ0 = invQuad0; 44 | output.invQ1 = invQuad1; 45 | output.invQ2 = invQuad2; 46 | output.invQ3 = invQuad3; 47 | triStream.Append(output); 48 | 49 | output.Position = float4(xmax, ymin, 0.5, 1.0); 50 | output.invQ0 = invQuad0; 51 | output.invQ1 = invQuad1; 52 | output.invQ2 = invQuad2; 53 | output.invQ3 = invQuad3; 54 | triStream.Append(output); 55 | } -------------------------------------------------------------------------------- /shaders/Fluid/EllipsoidDepth_PS.hlsl: -------------------------------------------------------------------------------- 1 | #include "FliudCommon.hlsli" 2 | 3 | struct PSOUT 4 | { 5 | float4 res : SV_TARGET; 6 | float depthOut : SV_Depth; 7 | }; 8 | 9 | PSOUT PS(FluidGeoOut input) 10 | { 11 | //const float3 invViewport = gParams.invViewport; 12 | const float4 position = input.Position; 13 | 14 | matrix invQuadric; 15 | invQuadric._m00_m01_m02_m03 = input.invQ0; 16 | invQuadric._m10_m11_m12_m13 = input.invQ1; 17 | invQuadric._m20_m21_m22_m23 = input.invQ2; 18 | invQuadric._m30_m31_m32_m33 = input.invQ3; 19 | 20 | float4 ndcPos = float4(position.x * g_InvViewport.x * 2.0f - 1.0f, (1.0f - position.y * g_InvViewport.y) * 2.0f - 1.0f, 0.0f, 1.0); 21 | float4 viewDir = mul(ndcPos, g_ProjInv); 22 | 23 | // ray to parameter space 24 | float4 dir = mul(float4(viewDir.xyz, 0.0), invQuadric); 25 | float4 origin = invQuadric._m30_m31_m32_m33; 26 | 27 | // set up quadratric equation 28 | float a = sqr(dir.x) + sqr(dir.y) + sqr(dir.z); 29 | float b = dir.x * origin.x + dir.y * origin.y + dir.z * origin.z - dir.w * origin.w; 30 | float c = sqr(origin.x) + sqr(origin.y) + sqr(origin.z) - sqr(origin.w); 31 | 32 | float minT = 0.0f; 33 | float maxT = 0.0f; 34 | 35 | if (!solveQuadraticPS(a, 2.0 * b, c, minT, maxT)) 36 | { 37 | discard; 38 | } 39 | 40 | float3 eyePos = viewDir.xyz * minT; 41 | ndcPos = mul(float4(eyePos, 1.0), g_Proj); 42 | ndcPos.z /= ndcPos.w; 43 | 44 | if (ndcPos.z<0.0f) 45 | { 46 | discard; 47 | 48 | } 49 | PSOUT pOut; 50 | pOut.depthOut = ndcPos.z; 51 | 52 | pOut.res = float4(eyePos.z, eyePos.z, eyePos.z, 1.0f); 53 | return pOut; 54 | } -------------------------------------------------------------------------------- /shaders/Fluid/EllipsoidDepth_VS.hlsl: -------------------------------------------------------------------------------- 1 | #include "FliudCommon.hlsli" 2 | 3 | 4 | 5 | FluidVertexOut VS(FluidVertexIn FIn) 6 | { 7 | const float4 q1 = FIn.q1; 8 | const float4 q2 = FIn.q2; 9 | const float4 q3 = FIn.q3; 10 | float3 worldPos = FIn.PosL.xyz; 11 | 12 | // construct quadric matrix 13 | matrix q; 14 | q[0] = float4(q1.xyz * q1.w, 0.0); 15 | q[1] = float4(q2.xyz * q2.w, 0.0); 16 | q[2] = float4(q3.xyz * q3.w, 0.0); 17 | q[3] = float4(worldPos, 1.0); 18 | 19 | // transforms a normal to parameter space (inverse transpose of (q*modelview)^-T) 20 | 21 | matrix invclip = transpose(mul(q, g_WVP)); 22 | 23 | // solve for the right hand bounds in homogenous clip space 24 | float a1 = DotInvW(invclip[3], invclip[3]); 25 | float b1 = -2.0f * DotInvW(invclip[0], invclip[3]); 26 | float c1 = DotInvW(invclip[0], invclip[0]); 27 | 28 | float xmin = 0.0f; 29 | float xmax = 0.0f; 30 | solveQuadraticVS(a1, b1, c1, xmin, xmax); 31 | 32 | // solve for the right hand bounds in homogenous clip space 33 | float a2 = DotInvW(invclip[3], invclip[3]); 34 | float b2 = -2.0f * DotInvW(invclip[1], invclip[3]); 35 | float c2 = DotInvW(invclip[1], invclip[1]); 36 | 37 | float ymin = 0.0f; 38 | float ymax = 0.0f; 39 | 40 | solveQuadraticVS(a2, b2, c2, ymin, ymax); 41 | 42 | FluidVertexOut output; 43 | output.PosL = float4(worldPos.xyz, 1.0f); 44 | output.bounds = float4(xmin, xmax, ymin, ymax); 45 | 46 | // construct inverse quadric matrix (used for ray-casting in parameter space) 47 | matrix invq; 48 | invq[0] = float4(q1.xyz / q1.w, 0.0); 49 | invq[1] = float4(q2.xyz / q2.w, 0.0); 50 | invq[2] = float4(q3.xyz / q3.w, 0.0); 51 | invq[3] = float4(0.0, 0.0, 0.0, 1.0); 52 | 53 | //invq = transpose(invq); 54 | invq[3] = -(mul(output.PosL, invq)); 55 | 56 | // transform a point from view space to parameter space 57 | invq = mul(g_WorldViewInv, invq); 58 | 59 | // pass down 60 | output.invQ0 = invq[0]; 61 | output.invQ1 = invq[1]; 62 | output.invQ2 = invq[2]; 63 | output.invQ3 = invq[3]; 64 | 65 | // compute ndc pos for frustrum culling in GS 66 | float4 projPos = mul(float4(worldPos.xyz, 1.0), g_WVP); 67 | output.ndcPos = projPos / projPos.w; 68 | return output; 69 | 70 | } -------------------------------------------------------------------------------- /shaders/Fluid/FindCellStart_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "NerghborSearchCommon.hlsli" 2 | 3 | //load hashid at pos+1 4 | groupshared uint sharedHash[THREAD_NUM_X+1]; 5 | 6 | [numthreads(THREAD_NUM_X, 1, 1)] 7 | void CS( uint3 DTid : SV_DispatchThreadID,uint GI:SV_GroupIndex ) 8 | { 9 | uint hashValue = 0; 10 | if (DTid.x < g_ParticleNums) 11 | { 12 | hashValue = g_cellHash[DTid.x]; 13 | sharedHash[GI + 1] = hashValue; 14 | 15 | if (GI == 0 && DTid.x > 0) 16 | { 17 | sharedHash[0] = g_cellHash[DTid.x - 1]; 18 | } 19 | } 20 | 21 | GroupMemoryBarrierWithGroupSync(); 22 | 23 | if (DTid.x < g_ParticleNums) 24 | { 25 | //If It's equal to the last one 26 | if (DTid.x == 0 || hashValue != sharedHash[GI]) 27 | { 28 | g_CellStart[hashValue] = DTid.x; 29 | if (DTid.x > 0) 30 | { 31 | //the last cell end pos 32 | g_CellEnd[sharedHash[GI]] = DTid.x; 33 | } 34 | } 35 | //thread the last one output 36 | if (DTid.x == g_ParticleNums - 1) 37 | { 38 | g_CellEnd[hashValue] = DTid.x + 1; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /shaders/Fluid/FliudCommon.hlsli: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/shaders/Fluid/FliudCommon.hlsli -------------------------------------------------------------------------------- /shaders/Fluid/NerghborSearchCommon.hlsli: -------------------------------------------------------------------------------- 1 | 2 | StructuredBuffer g_ParticlePosition : register(t0); 3 | StructuredBuffer g_acticeIndexs : register(t1); 4 | 5 | RWStructuredBuffer g_ReadBoundsLower : register(u0); 6 | RWStructuredBuffer g_ReadBoundsUpper : register(u1); 7 | RWStructuredBuffer g_WriteBoundsLower : register(u2); 8 | RWStructuredBuffer g_WriteBoundsUpper : register(u3); 9 | RWStructuredBuffer g_Bounds : register(u4); 10 | //calc hash and index 11 | 12 | RWStructuredBuffer g_cellHash : register(u5); 13 | RWStructuredBuffer g_cellIndexs : register(u6); 14 | 15 | //GPU Radix sort get the local counter(1 phase) and global dispatch(3 phase) 16 | RWStructuredBuffer g_SrcCounters : register(u7); 17 | RWStructuredBuffer g_SrcPrefix : register(u8); 18 | 19 | //GPU Radix sort calc prefix block sum(2 phase) 20 | RWStructuredBuffer g_DstCounters : register(u9); 21 | 22 | //GPU Radix sort calc global position to output des(3 phase) 23 | RWStructuredBuffer g_DstKey:register(u10); 24 | RWStructuredBuffer g_DstVal:register(u11); 25 | 26 | //find the cell start 27 | RWStructuredBuffer g_CellStart:register(u12); 28 | RWStructuredBuffer g_CellEnd:register(u13); 29 | 30 | #define RADIX_D 4 31 | #define RADIX_R 16 32 | #define THREAD_NUM_X 1024 33 | #define THREAD_BOUNDS_X THREAD_NUM_X/4 34 | 35 | cbuffer NerghborSearchConstant : register(b0) 36 | { 37 | float g_CellSize; 38 | int g_CurrIteration; 39 | uint g_KeyNums; 40 | uint g_CounterNums; 41 | 42 | uint g_ParticleNums; 43 | uint g_BlocksNums; 44 | uint g_BoundsGroups; 45 | uint g_BoundsFinalizeNums; 46 | } 47 | 48 | //calculate hash 49 | uint hashFunc(int3 key) 50 | { 51 | int p1 = 73856093 * key.x; 52 | int p2 = 19349663 * key.y; 53 | int p3 = 83492791 * key.z; 54 | return p1 ^ p2 ^ p3; 55 | } 56 | 57 | 58 | uint GetCellHash(int3 cellPos) 59 | { 60 | //uint bitmask1 = (1 << 14) - 1; 61 | //uint bitmask2 = (1 << 7) - 1; 62 | //uint hash = ((cellPos.z << 14) & (~bitmask1)) + ((cellPos.y << 7) & (~bitmask2)) + cellPos.x; 63 | //uint hash = (cellPos.z << 14) + (cellPos.y << 7) + cellPos.x; 64 | uint hash = hashFunc(cellPos); 65 | return hash % (2 * g_ParticleNums); 66 | } 67 | //get LSD 4-bit (4) 68 | uint4 get4Bits(uint4 num,int i) 69 | { 70 | return ((num >> i*4) & 0xf); 71 | } 72 | 73 | //get LSD 4-bit 74 | uint get4Bits(uint num,int i) 75 | { 76 | return ((num >> i*4) & 0xf); 77 | } 78 | -------------------------------------------------------------------------------- /shaders/Fluid/PBFFinalize_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "PBFSolverCommon.hlsli" 2 | 3 | 4 | [numthreads(THREAD_NUM_X, 1, 1)] 5 | void CS( uint3 DTid : SV_DispatchThreadID ) 6 | { 7 | if (DTid.x >= g_ParticleNums) 8 | { 9 | return; 10 | } 11 | 12 | uint prevIndex = g_Particleindex[DTid.x]; 13 | 14 | g_SolveredPosition[prevIndex] = g_sortedNewPosition[DTid.x]; 15 | 16 | float3 currVec = g_UpdatedVelocity[DTid.x]; 17 | float3 impulse = g_Impulses[DTid.x]; 18 | float3 oldVec = g_oldVelocity[prevIndex]; 19 | float3 deltaVec = currVec + impulse - oldVec; 20 | float deltaVecLengthsq = dot(deltaVec, deltaVec); 21 | if (deltaVecLengthsq > (g_MaxVeclocityDelta * g_MaxVeclocityDelta)) 22 | { 23 | deltaVec = deltaVec * rsqrt(deltaVecLengthsq) * g_MaxVeclocityDelta; 24 | } 25 | float3 finVec = oldVec + deltaVec; 26 | g_SolveredVelocity[prevIndex] = finVec; 27 | } -------------------------------------------------------------------------------- /shaders/Fluid/PBFSolverCommon.hlsli: -------------------------------------------------------------------------------- 1 | struct Anisotropy 2 | { 3 | float4 q1; 4 | float4 q2; 5 | float4 q3; 6 | }; 7 | 8 | //Predict pos 9 | StructuredBuffer g_oldPosition : register(t0); 10 | StructuredBuffer g_oldVelocity : register(t1); 11 | RWStructuredBuffer g_PredPosition : register(u0); 12 | RWStructuredBuffer g_newVelocity : register(u1); 13 | //reorder particle 14 | StructuredBuffer g_ParticleIndex : register(t2); 15 | StructuredBuffer g_Bounds : register(t3); 16 | RWStructuredBuffer g_sortedOldPosition : register(u2); 17 | RWStructuredBuffer g_sortedNewPosition : register(u3); 18 | RWStructuredBuffer g_sortedVelocity : register(u4); 19 | 20 | //contact and collision 21 | StructuredBuffer g_CellStart : register(t4); 22 | StructuredBuffer g_CellEnd : register(t5); 23 | RWStructuredBuffer g_Contacts : register(u5); 24 | RWStructuredBuffer g_ContactCounts : register(u6); 25 | RWStructuredBuffer g_CollisionCounts : register(u7); 26 | RWStructuredBuffer g_CollisionPlanes : register(u8); 27 | 28 | //calclagrangeMUltiplier 29 | RWStructuredBuffer g_Density : register(u9); 30 | RWStructuredBuffer g_LambdaMultiplier:register(u10); 31 | //calcDisplacement 32 | RWStructuredBuffer g_DeltaPosition:register(u11); 33 | //ADDDeltaPosition 34 | RWStructuredBuffer g_UpdatedPosition : register(u12); 35 | //UpdateVeclosity 36 | RWStructuredBuffer g_UpdatedVelocity:register(u13); 37 | RWStructuredBuffer g_Curl : register(u14); 38 | RWStructuredBuffer g_Impulses : register(u15); 39 | //UpdatePosition 40 | StructuredBuffer g_Particleindex:register(t8); 41 | RWStructuredBuffer g_SolveredPosition:register(u16); 42 | RWStructuredBuffer g_SolveredVelocity : register(u17); 43 | //anisotropy 44 | RWStructuredBuffer g_SmoothPosition : register(u18); 45 | RWStructuredBuffer g_Anisortopy : register(u19); 46 | 47 | 48 | #define THREAD_NUM_X 256 49 | 50 | 51 | cbuffer PBFConstant : register(b0) 52 | { 53 | uint g_ParticleNums; 54 | float g_CellSize; 55 | float g_ScorrK; //seem surface tension k=0.1 56 | float g_ScorrN; //n = 4 57 | 58 | float g_Poly6Coff; 59 | float g_SpikyCoff; 60 | float g_SpikyGradCoff; 61 | float g_InverseDensity_0; // 1/p_0 62 | 63 | 64 | float g_VorticityConfinement; //epsilon The strength of the turbine control force (user set) 65 | float g_VorticityC; //c=0.01 66 | float g_sphSmoothLength; 67 | float g_DeltaQ; //delta q=0.1h,...,0.3h 68 | 69 | float3 g_Gravity; 70 | int g_MaxNeighborPerParticle; 71 | 72 | float g_CollisionDistance; 73 | float g_CollisionThreshold; 74 | float g_ParticleRadiusSq; 75 | float g_SOR; //successive over-relaxation (SOR) 76 | 77 | float g_MaxSpeed; 78 | float g_MaxVeclocityDelta; 79 | float g_Restituion; 80 | float g_LaplacianSmooth; 81 | 82 | float g_AnisotropyScale; //AnisotropyScale 83 | float g_AnisotropyMin; 84 | float g_AnisotropyMax; 85 | float g_Pad0; 86 | 87 | float g_StaticFriction; 88 | float g_DynamicFriction; 89 | float g_Pad11[2]; 90 | } 91 | 92 | cbuffer PBFChanges : register(b1) 93 | { 94 | float g_DeltaTime; 95 | float g_InverseDeltaTime; 96 | float g_LambdaEps; //Relaxation parameter(soft constraint use) 97 | float g_pad1; 98 | } 99 | 100 | cbuffer PBFBoundary : register(b2) 101 | { 102 | float4 g_Plane[6]; 103 | int g_PlaneNums; 104 | int g_MaxCollisionPlanes; 105 | float g_pad2[2]; 106 | } 107 | 108 | 109 | //W_poly6(r,h)=315/(64*PI*h^3) * (1-r^2/h^2)^3 110 | float WPoly6(float3 r, float h) 111 | { 112 | float radius = length(r); 113 | float res = 0.0f; 114 | if (radius <= h && radius >= 0) 115 | { 116 | float item = 1 - pow(radius / h, 2); 117 | res = g_Poly6Coff * pow(item, 3); 118 | } 119 | return res; 120 | } 121 | 122 | //W_Spiky(r,h)=15/(PI*h^3) * (1-r/h)^6 123 | float WSpiky(float3 r, float h) 124 | { 125 | float radius = length(r); 126 | float res = 0.0f; 127 | if (radius <= h && radius >= 0) 128 | { 129 | float item = 1 - (radius / h); 130 | res = g_SpikyCoff * pow(item, 6); 131 | } 132 | return res; 133 | } 134 | 135 | //W_Spiky_Grad(r,h)= -45/(PI*h^4) * (1-r/h)^2*(r/|r|); 136 | float3 WSpikyGrad(float3 r, float h) 137 | { 138 | float radius = length(r); 139 | float3 res = float3(0.0f, 0.0f, 0.0f); 140 | if (radius < h && radius > 0) 141 | { 142 | float item = 1 - (radius / h); 143 | res = g_SpikyGradCoff * pow(item, 2) * normalize(r); 144 | } 145 | return res; 146 | } 147 | 148 | 149 | //calculate hash 150 | uint hashFunc(uint3 key) 151 | { 152 | uint p1 = 73856093 * key.x; 153 | uint p2 = 19349663 * key.y; 154 | uint p3 = 83492791 * key.z; 155 | return p1 ^ p2 ^ p3; 156 | } 157 | 158 | 159 | 160 | uint GetCellHash(int3 cellPos) 161 | { 162 | //uint hash = ((cellPos.z << 14) & (~bitmask1)) + ((cellPos.y << 7) & (~bitmask2)) + cellPos.x; 163 | //uint hash = (cellPos.z << 14) + (cellPos.y << 7) + cellPos.x; 164 | uint hash = hashFunc(cellPos); 165 | return hash % (2 * g_ParticleNums); 166 | } 167 | 168 | //sdf plane function 169 | float sdfPlane(float3 p, float3 n, float h) 170 | { 171 | return dot(p, n) + h; 172 | } 173 | 174 | 175 | float sqr(float3 ele) 176 | { 177 | return ele.x * ele.x + ele.y * ele.y + ele.z * ele.z; 178 | } 179 | 180 | float Wsmooth(float3 r,float h) 181 | { 182 | float radius = length(r); 183 | float res = 0.0f; 184 | if (radius < h && radius > 0) 185 | { 186 | float item = radius / h; 187 | res = 1 - pow(item, 3); 188 | } 189 | return res; 190 | } -------------------------------------------------------------------------------- /shaders/Fluid/PassThrough_VS.hlsl: -------------------------------------------------------------------------------- 1 | #include "FliudCommon.hlsli" 2 | 3 | PassThoughVertexOut VS(MeshVertexIn MvIn) 4 | { 5 | PassThoughVertexOut ptVout; 6 | 7 | ptVout.PosH = float4(MvIn.PosW, 1.0f); 8 | ptVout.TexCoord = MvIn.TexCoord; 9 | return ptVout; 10 | } -------------------------------------------------------------------------------- /shaders/Fluid/PointSpriteDepth_PS.hlsl: -------------------------------------------------------------------------------- 1 | #include "FliudCommon.hlsli" 2 | 3 | //only calculate Depth 4 | float4 PS(PointGeoOut pIn) : SV_Target 5 | { 6 | //calculate normal from texture coordinates 7 | float3 normal; 8 | normal.xy = pIn.texCoord * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f); 9 | float mag = dot(normal.xy, normal.xy); 10 | if (mag > 1.0f) 11 | { 12 | discard; //kill pixel outside circle 13 | } 14 | 15 | normal.z = sqrt(1.0f - mag); 16 | 17 | //calculate depth 18 | float4 pixelPos = float4(pIn.PosV + normal * g_PointRadius, 1.0f); 19 | float4 clipSpacePos = mul(pixelPos, g_Proj); 20 | float fragDepth = clipSpacePos.z / clipSpacePos.w; 21 | 22 | return float4(fragDepth, fragDepth, fragDepth, 1.0f); 23 | } -------------------------------------------------------------------------------- /shaders/Fluid/PointSpriteThickness_PS.hlsl: -------------------------------------------------------------------------------- 1 | #include "FliudCommon.hlsli" 2 | 3 | //only calculate Thickness 4 | float4 PS(PointGeoOut pIn) : SV_Target 5 | { 6 | //calculate normal from texture coordinates 7 | float3 normal; 8 | normal.xy = pIn.texCoord * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f); 9 | float mag = dot(normal.xy, normal.xy); 10 | if (mag > 1.0f) 11 | { 12 | discard; //kill pixel outside circle 13 | } 14 | 15 | normal.z = -sqrt(1.0f - mag); 16 | 17 | //calc thickness 18 | float temp = -normal.z * 0.005f; 19 | 20 | return float4(temp, 0.0f, 0.0f, 1.0f); 21 | } -------------------------------------------------------------------------------- /shaders/Fluid/PointSprite_GS.hlsl: -------------------------------------------------------------------------------- 1 | #include "FliudCommon.hlsli" 2 | 3 | 4 | [maxvertexcount(4)] 5 | void GS(point PointVertexOut input[1],inout TriangleStream output) 6 | { 7 | const float4 viewPosition = float4(input[0].PosV, 1.0f); //view-sytem 8 | const float spriteSize = g_PointRadius * 2.0f; 9 | 10 | PointGeoOut gOut; 11 | [unroll] 12 | for (int i = 0; i < 4; ++i) 13 | { 14 | float4 eyePos = viewPosition; 15 | eyePos.xy += spriteSize * (g_TexCoord[i] - float2(0.5f, 0.5f)); 16 | 17 | gOut.PosH = mul(eyePos, g_Proj); 18 | gOut.texCoord = float2(g_TexCoord[i].x, 1.0f - g_TexCoord[i].y); 19 | gOut.PosV = eyePos.xyz; 20 | gOut.PosW = input[0].PosW; 21 | gOut.reflectance = float4(lerp(g_Color.xyz * 2.0, float3(1.0f, 1.0f, 1.0f), 0.1f), 0.0f); 22 | output.Append(gOut); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /shaders/Fluid/PointSprite_PS.hlsl: -------------------------------------------------------------------------------- 1 | #include "FliudCommon.hlsli" 2 | 3 | 4 | 5 | float4 PS(PointGeoOut pIn) : SV_Target 6 | { 7 | //calculate normal from texture coordinates 8 | float3 normal; 9 | normal.xy = pIn.texCoord * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f); 10 | float mag = dot(normal.xy, normal.xy); 11 | if (mag > 1.0f) 12 | { 13 | discard; //kill pixel outside circle 14 | } 15 | 16 | 17 | normal.z = sqrt(1.0f - mag); 18 | 19 | 20 | float3 diffuse = float3(0.9f, 0.9f, 0.9f); 21 | float3 reflectance = pIn.reflectance.xyz; 22 | 23 | matrix modelViewMatrix = mul(g_World, g_View); 24 | float3 viewLightDir = normalize(mul(modelViewMatrix, float4(g_DirLight[0].Direction, 0.0f)).xyz); 25 | float3 lo = diffuse * reflectance * max(0.0f, sqr(-dot(viewLightDir, normal) * 0.5 + 0.5)) * 0.2f; 26 | 27 | const float tmp = 1.0f / 2.2f; 28 | 29 | return float4(pow(abs(lo), float3(tmp, tmp, tmp)), 1.0f); 30 | 31 | } -------------------------------------------------------------------------------- /shaders/Fluid/PointSprite_VS.hlsl: -------------------------------------------------------------------------------- 1 | #include "FliudCommon.hlsli" 2 | 3 | PointVertexOut VS(PointVertexIn vIn) 4 | { 5 | 6 | PointVertexOut vOut; 7 | vOut.PosW = mul(float4(vIn.PosL, 1.0f), g_World).xyz; 8 | vOut.PosV = mul(float4(vIn.PosL, 1.0f), g_WorldView).xyz; //calculate view-space point size 9 | vOut.density = vIn.density; 10 | return vOut; 11 | } -------------------------------------------------------------------------------- /shaders/Fluid/PredictPosition_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "PBFSolverCommon.hlsli" 2 | 3 | 4 | [numthreads(THREAD_NUM_X, 1, 1)] 5 | void CS( uint3 DTid : SV_DispatchThreadID ) 6 | { 7 | if (DTid.x > g_ParticleNums) 8 | { 9 | return; 10 | } 11 | 12 | //now only gravity 13 | //vi<=vi+ deltaT * g 14 | float3 vec = g_oldVelocity[DTid.x] + g_DeltaTime * g_Gravity; 15 | //xi*<=xi+ deltaT * v 16 | //g_PredPosition[DTid.x]=g_oldPosition[DTid.x]+g_DeltaTime*vec; 17 | float3 pos = g_oldPosition[DTid.x] + g_DeltaTime * vec; 18 | 19 | g_PredPosition[DTid.x] = pos; 20 | //update v 21 | g_newVelocity[DTid.x] = vec; 22 | } -------------------------------------------------------------------------------- /shaders/Fluid/RadixSortCount_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "NerghborSearchCommon.hlsli" 2 | 3 | 4 | groupshared uint localPrefix[THREAD_NUM_X]; 5 | 6 | //excusive scan 7 | void PresumLocal(uint GI : SV_GroupIndex) 8 | { 9 | //up sweep 10 | uint d = 0; 11 | uint i = 0; 12 | uint offset = 1; 13 | uint totalNum = THREAD_NUM_X; 14 | [unroll] 15 | for (d = totalNum>>1; d > 0; d >>= 1) 16 | { 17 | GroupMemoryBarrierWithGroupSync(); 18 | if (GI < d) 19 | { 20 | uint ai = offset * (2 * GI + 1) - 1; 21 | uint bi = offset * (2 * GI + 2) - 1; 22 | 23 | localPrefix[bi] += localPrefix[ai]; 24 | } 25 | offset *= 2; 26 | } 27 | 28 | //clear the last element 29 | if (GI == 0) 30 | { 31 | localPrefix[totalNum-1] = 0; 32 | } 33 | GroupMemoryBarrierWithGroupSync(); 34 | 35 | //Down-sweep 36 | [unroll] 37 | for (d = 1; d < totalNum; d *= 2) 38 | { 39 | offset >>= 1; 40 | GroupMemoryBarrierWithGroupSync(); 41 | 42 | if (GI < d) 43 | { 44 | uint ai = offset * (2 * GI + 1) - 1; 45 | uint bi = offset * (2 * GI + 2) - 1; 46 | 47 | uint tmp = localPrefix[ai]; 48 | localPrefix[ai] = localPrefix[bi]; 49 | localPrefix[bi] += tmp; 50 | } 51 | } 52 | GroupMemoryBarrierWithGroupSync(); 53 | } 54 | 55 | //one thread process one element 56 | [numthreads(THREAD_NUM_X, 1, 1)] 57 | void CS(uint GI : SV_GroupIndex, uint3 DTid : SV_DispatchThreadID 58 | ,uint3 Gid:SV_GroupID ) 59 | { 60 | //get curr digit correspend to 4-bit LSD 61 | uint digit = get4Bits(g_cellHash[DTid.x], g_CurrIteration); 62 | 63 | //counter 64 | [unroll(RADIX_R)] 65 | for (uint r = 0; r < RADIX_R; ++r) 66 | { 67 | //load to share memory 68 | localPrefix[GI] = (digit == r ? 1 : 0); 69 | GroupMemoryBarrierWithGroupSync(); 70 | 71 | //prefix sum according to r in this blocks 72 | PresumLocal(GI); 73 | 74 | //ouput the total sum to counter 75 | if (GI == THREAD_NUM_X - 1) 76 | { 77 | uint counterIndex = r * g_BlocksNums + Gid.x; 78 | uint counter=localPrefix[GI]; 79 | //output prefix sum according to r 80 | if (digit == r) 81 | { 82 | counter++; 83 | } 84 | g_SrcCounters[counterIndex] = counter; 85 | } 86 | 87 | //output prefix sum according to r 88 | if(digit==r) 89 | { 90 | g_SrcPrefix[DTid.x] = localPrefix[GI]; 91 | } 92 | 93 | GroupMemoryBarrierWithGroupSync(); 94 | } 95 | } 96 | 97 | 98 | -------------------------------------------------------------------------------- /shaders/Fluid/RadixSortCountersPrefix_CS.hlsl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ligo04/FluidSimulation-Engine/cad5b1e2533cfce72a124160bc97e02f8e314413/shaders/Fluid/RadixSortCountersPrefix_CS.hlsl -------------------------------------------------------------------------------- /shaders/Fluid/RadixSortDispatch_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "NerghborSearchCommon.hlsli" 2 | 3 | 4 | [numthreads(THREAD_NUM_X, 1, 1)] 5 | void CS(uint3 DTid : SV_DispatchThreadID,uint3 Gid:SV_GroupID) 6 | { 7 | //get curr digit 8 | uint digit = get4Bits(g_cellHash[DTid.x], g_CurrIteration); 9 | 10 | 11 | //global dispatch 12 | uint counterIndex = digit * g_BlocksNums + Gid.x; 13 | uint globalPos = g_SrcPrefix[DTid.x] + g_DstCounters[counterIndex]; 14 | g_DstKey[globalPos] = g_cellHash[DTid.x]; 15 | g_DstVal[globalPos] = g_cellIndexs[DTid.x]; 16 | } -------------------------------------------------------------------------------- /shaders/Fluid/ReorderParticle_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "PBFSolverCommon.hlsli" 2 | 3 | [numthreads(THREAD_NUM_X, 1, 1)] 4 | void CS( uint3 DTid : SV_DispatchThreadID ) 5 | { 6 | if (DTid.x >= g_ParticleNums) 7 | { 8 | return; 9 | } 10 | 11 | int pos=g_ParticleIndex[DTid.x]; 12 | g_sortedOldPosition[DTid.x] = g_oldPosition[pos]; 13 | g_sortedNewPosition[DTid.x] = g_PredPosition[pos]; 14 | g_sortedVelocity[DTid.x] = g_newVelocity[pos]; 15 | } -------------------------------------------------------------------------------- /shaders/Fluid/SmoothPosition_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "PBFSolverCommon.hlsli" 2 | 3 | [numthreads(THREAD_NUM_X, 1, 1)] 4 | void CS(uint3 DTid : SV_DispatchThreadID) 5 | { 6 | if (DTid.x >= g_ParticleNums) 7 | { 8 | return; 9 | } 10 | 11 | float3 currPos = g_sortedNewPosition[DTid.x]; 12 | 13 | uint neightborCounter = g_ContactCounts[DTid.x]; 14 | 15 | float wTotal = 0.0f; 16 | float3 smoothNeighPos = float3(0.0f, 0.0f, 0.0f); 17 | 18 | for (uint i = 0; i < neightborCounter;++i) 19 | { 20 | //get the cell particle pos 21 | uint neightborParticleIndex = g_Contacts[DTid.x * g_MaxNeighborPerParticle + i]; 22 | float3 neighborPartclePos = g_sortedNewPosition[neightborParticleIndex]; 23 | 24 | float3 deltaPos = currPos - neighborPartclePos; 25 | float W_ij = Wsmooth(deltaPos, g_sphSmoothLength); 26 | wTotal += W_ij; 27 | //wij *x_j 28 | smoothNeighPos += W_ij * neighborPartclePos; 29 | } 30 | 31 | float3 smoothPos = 0.0f; 32 | if (wTotal != 0) 33 | { 34 | smoothNeighPos = smoothNeighPos / wTotal; 35 | 36 | float smooth = min(wTotal / 3.50f, 1.0f) * g_LaplacianSmooth; 37 | 38 | smoothPos = (1 - smooth) * currPos + smooth * smoothNeighPos; 39 | } 40 | 41 | 42 | g_SmoothPosition[DTid.x] = smoothPos; 43 | } 44 | -------------------------------------------------------------------------------- /shaders/Fluid/SolveContact_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "PBFSolverCommon.hlsli" 2 | 3 | 4 | 5 | [numthreads(THREAD_NUM_X, 1, 1)] 6 | void CS( uint3 DTid : SV_DispatchThreadID ) 7 | { 8 | 9 | if (DTid.x >= g_ParticleNums) 10 | { 11 | return; 12 | } 13 | 14 | float3 currPos = g_sortedNewPosition[DTid.x]; 15 | float3 oldPos = g_sortedOldPosition[DTid.x]; 16 | 17 | int collisionCount = g_CollisionCounts[DTid.x]; 18 | int i = 0; 19 | for (i = 0; i < collisionCount; ++i) 20 | { 21 | int index = DTid.x * g_MaxCollisionPlanes + i; 22 | float4 currPlane = g_CollisionPlanes[index]; 23 | float distance = sdfPlane(currPos, currPlane.xyz, currPlane.w) - g_CollisionDistance; //d 24 | if (distance < 0.0f) 25 | { 26 | float3 sdfPos = (-distance) * currPlane.xyz; 27 | 28 | //friction model 29 | float3 deltaPos = currPos - oldPos; 30 | float deltaX = dot(deltaPos, currPlane.xyz); 31 | float3 deltaDistane = (-deltaX) * currPlane.xyz + deltaPos; //DeltaX 32 | float deltaLength = dot(deltaDistane, deltaDistane); 33 | [flatten] 34 | if (deltaLength <= (g_StaticFriction * distance)) //|deltaX|< u_s*disctance 35 | { 36 | sdfPos -= deltaDistane; 37 | } 38 | else 39 | { 40 | float dynamicFriction = min((-distance) * 0.01f * rsqrt(deltaLength), 1.0f); // 41 | sdfPos -= dynamicFriction * (deltaDistane); 42 | } 43 | currPos += sdfPos; 44 | } 45 | } 46 | 47 | g_UpdatedPosition[DTid.x] = currPos; 48 | } -------------------------------------------------------------------------------- /shaders/Fluid/SolverVelocities_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "PBFSolverCommon.hlsli" 2 | 3 | 4 | [numthreads(THREAD_NUM_X, 1, 1)] 5 | void CS( uint3 DTid : SV_DispatchThreadID ) 6 | { 7 | if (DTid.x >= g_ParticleNums) 8 | { 9 | return; 10 | } 11 | 12 | float3 currPos = g_sortedNewPosition[DTid.x]; 13 | float3 currVec = g_UpdatedVelocity[DTid.x]; 14 | float3 oldVec = g_sortedVelocity[DTid.x]; 15 | 16 | 17 | uint counter = g_ContactCounts[DTid.x]; 18 | 19 | float3 deltaTotalVec = float3(0.0f, 0.0f, 0.0f); 20 | float3 etaTotal = float3(0.0f, 0.0f, 0.0f); 21 | float density; 22 | for (uint i = 0; i < counter; ++i) 23 | { 24 | //get the cell particle pos 25 | uint neightborParticleIndex = g_Contacts[DTid.x * g_MaxNeighborPerParticle + i]; 26 | //get the cell particle pos 27 | float3 neighborParticlePos = g_sortedNewPosition[neightborParticleIndex]; 28 | //r=p_i-p_j 29 | float3 r = currPos - neighborParticlePos; 30 | //v_j-v_i 31 | float3 deltaVelocity = g_UpdatedVelocity[neightborParticleIndex] - currVec; 32 | 33 | float3 currGrad = WSpikyGrad(r, g_sphSmoothLength); 34 | 35 | 36 | //vorsitory confinement 37 | float neighCurlLength = g_Curl[neightborParticleIndex].w; 38 | etaTotal += currGrad * neighCurlLength; //r4 39 | 40 | //XSPH 41 | float3 deltaVec_j = deltaVelocity * WSpiky(r, g_sphSmoothLength); 42 | deltaTotalVec += deltaVec_j; 43 | 44 | //density 45 | density += WPoly6(r, g_sphSmoothLength); 46 | 47 | } 48 | 49 | float3 impulse = float3(0.0f, 0.0f, 0.0f); 50 | //vorticity Confinement 51 | if (length(etaTotal) > 0.0f && g_VorticityConfinement > 0.0f && density>0.0f) 52 | { 53 | float epsilon = g_DeltaTime * g_DeltaTime * g_InverseDensity_0 * g_VorticityConfinement; 54 | 55 | float3 currCurl = g_Curl[DTid.x].xyz; //r2 56 | 57 | float3 N = normalize(etaTotal); 58 | float3 force = cross(N, currCurl); 59 | 60 | impulse += epsilon * force; 61 | 62 | } 63 | 64 | //XSPH 65 | impulse += g_VorticityC * deltaTotalVec; 66 | 67 | // solve plane 68 | uint planeCounts = g_CollisionCounts[DTid.x]; 69 | uint resCounts = 0; 70 | float3 restitutionVec = float3(0.0f, 0.0f, 0.0f); 71 | for (uint j = 0; j < planeCounts; ++j) 72 | { 73 | float4 plane = g_CollisionPlanes[DTid.x * g_MaxCollisionPlanes + j]; 74 | float distance = sdfPlane(currPos, plane.xyz, plane.w) - 1.001f * g_CollisionDistance; 75 | 76 | float oldVecD = dot(oldVec, plane.xyz); 77 | if (distance < 0.0f && oldVecD < 0.0f) 78 | { 79 | float currVecD = dot(currVec, plane.xyz); 80 | float restitutionD = oldVecD * g_Restituion + currVecD; 81 | restitutionVec += plane.xyz * (-restitutionD); 82 | resCounts++; 83 | } 84 | } 85 | resCounts = max(resCounts, 1); 86 | restitutionVec /= resCounts; 87 | 88 | 89 | impulse += restitutionVec; 90 | g_Impulses[DTid.x] = impulse; 91 | } -------------------------------------------------------------------------------- /shaders/Fluid/UpdateVelocity_CS.hlsl: -------------------------------------------------------------------------------- 1 | #include "PBFSolverCommon.hlsli" 2 | 3 | 4 | [numthreads(THREAD_NUM_X, 1, 1)] 5 | void CS( uint3 DTid : SV_DispatchThreadID ) 6 | { 7 | if (DTid.x >= g_ParticleNums) 8 | { 9 | return; 10 | } 11 | 12 | float3 oldPos = g_sortedOldPosition[DTid.x]; 13 | float3 updatePos = g_sortedNewPosition[DTid.x]; 14 | 15 | float3 newVec = g_InverseDeltaTime * (updatePos - oldPos); 16 | g_UpdatedVelocity[DTid.x] = newVec; 17 | } -------------------------------------------------------------------------------- /shaders/NormalMapInstance_VS.hlsl: -------------------------------------------------------------------------------- 1 | #include "Basic.hlsli" 2 | 3 | // 顶点着色器 4 | VertexOutNormalMap VS(InstancePosNormalTangentTex vIn) 5 | { 6 | VertexOutNormalMap vOut; 7 | 8 | vector posW = mul(float4(vIn.PosL, 1.0f), vIn.World); 9 | 10 | vOut.PosW = posW.xyz; 11 | vOut.PosH = mul(posW, g_ViewProj); 12 | vOut.NormalW = mul(vIn.NormalL, (float3x3) vIn.WorldInvTranspose); 13 | vOut.TangentW = mul(vIn.TangentL, vIn.World); 14 | vOut.Tex = vIn.Tex; 15 | vOut.ShadowPosH = mul(posW, g_ShadowTransform); 16 | 17 | // 从NDC坐标[-1, 1]^2变换到纹理空间坐标[0, 1]^2 18 | // u = 0.5x + 0.5 19 | // v = -0.5y + 0.5 20 | // ((xw, yw, zw, w) + (w, w, 0, 0)) * (0.5, -0.5, 1, 1) = ((0.5x + 0.5)w, (-0.5y + 0.5)w, zw, w) 21 | // = (uw, vw, zw, w) 22 | // => (u, v, z, 1) 23 | vOut.SSAOPosH = (vOut.PosH + float4(vOut.PosH.ww, 0.0f, 0.0f)) * float4(0.5f, -0.5f, 1.0f, 1.0f); 24 | return vOut; 25 | } 26 | -------------------------------------------------------------------------------- /shaders/NormalMapObject_VS.hlsl: -------------------------------------------------------------------------------- 1 | #include "Basic.hlsli" 2 | 3 | // 顶点着色器 4 | VertexOutNormalMap VS(VertexPosNormalTangentTex vIn) 5 | { 6 | VertexOutNormalMap vOut; 7 | 8 | vector posW = mul(float4(vIn.PosL, 1.0f), g_World); 9 | 10 | vOut.PosW = posW.xyz; 11 | vOut.PosH = mul(float4(vIn.PosL, 1.0f), g_WorldViewProj); 12 | vOut.NormalW = mul(vIn.NormalL, (float3x3) g_WorldInvTranspose); 13 | vOut.TangentW = mul(vIn.TangentL, g_World); 14 | vOut.Tex = vIn.Tex; 15 | vOut.ShadowPosH = mul(posW, g_ShadowTransform); 16 | // 从NDC坐标[-1, 1]^2变换到纹理空间坐标[0, 1]^2 17 | // u = 0.5x + 0.5 18 | // v = -0.5y + 0.5 19 | // ((xw, yw, zw, w) + (w, w, 0, 0)) * (0.5, -0.5, 1, 1) = ((0.5x + 0.5)w, (-0.5y + 0.5)w, zw, w) 20 | // = (uw, vw, zw, w) 21 | // => (u, v, z, 1) 22 | vOut.SSAOPosH = (vOut.PosH + float4(vOut.PosH.ww, 0.0f, 0.0f)) * float4(0.5f, -0.5f, 1.0f, 1.0f); 23 | return vOut; 24 | } 25 | -------------------------------------------------------------------------------- /shaders/NormalMap_PS.hlsl: -------------------------------------------------------------------------------- 1 | #include "Basic.hlsli" 2 | 3 | // 像素着色器(3D) 4 | float4 PS(VertexOutNormalMap pIn) : SV_Target 5 | { 6 | // 若不使用纹理,则使用默认白色 7 | float4 texColor = float4(1.0f, 1.0f, 1.0f, 1.0f); 8 | 9 | if (g_TextureUsed) 10 | { 11 | texColor = g_DiffuseMap.Sample(g_Sam, pIn.Tex); 12 | // 提前进行Alpha裁剪,对不符合要求的像素可以避免后续运算 13 | clip(texColor.a - 0.1f); 14 | } 15 | 16 | // 标准化法向量 17 | pIn.NormalW = normalize(pIn.NormalW); 18 | 19 | // 求出顶点指向眼睛的向量,以及顶点与眼睛的距离 20 | float3 toEyeW = normalize(g_EyePosW - pIn.PosW); 21 | float distToEye = distance(g_EyePosW, pIn.PosW); 22 | 23 | // 法线映射 24 | float3 normalMapSample = g_NormalMap.Sample(g_Sam, pIn.Tex).rgb; 25 | float3 bumpedNormalW = NormalSampleToWorldSpace(normalMapSample, pIn.NormalW, pIn.TangentW); 26 | 27 | // 初始化为0 28 | float4 ambient = float4(0.0f, 0.0f, 0.0f, 0.0f); 29 | float4 diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f); 30 | float4 spec = float4(0.0f, 0.0f, 0.0f, 0.0f); 31 | float4 A = float4(0.0f, 0.0f, 0.0f, 0.0f); 32 | float4 D = float4(0.0f, 0.0f, 0.0f, 0.0f); 33 | float4 S = float4(0.0f, 0.0f, 0.0f, 0.0f); 34 | int i; 35 | 36 | float shadow[5] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; 37 | // 仅第一个方向光用于计算阴影 38 | if (g_EnableShadow) 39 | { 40 | shadow[0] = CalcShadowFactor(g_SamShadow, g_ShadowMap, pIn.ShadowPosH); 41 | } 42 | // 完成纹理投影变换并对SSAO图采样 43 | float ambientAccess = 1.0f; 44 | if (g_EnableSSAO) 45 | { 46 | pIn.SSAOPosH /= pIn.SSAOPosH.w; 47 | ambientAccess = g_SSAOMap.SampleLevel(g_Sam, pIn.SSAOPosH.xy, 0.0f).r; 48 | } 49 | 50 | [unroll] 51 | for (i = 0; i < 5; ++i) 52 | { 53 | ComputeDirectionalLight(g_Material, g_DirLight[i], bumpedNormalW, toEyeW, A, D, S); 54 | ambient += ambientAccess * A; 55 | diffuse += shadow[i] * D; 56 | spec += shadow[i] * S; 57 | } 58 | 59 | //[unroll] 60 | //for (i = 0; i < 5; ++i) 61 | //{ 62 | // ComputePointLight(g_Material, g_PointLight[i], pIn.PosW, bumpedNormalW, toEyeW, A, D, S); 63 | // ambient += A; 64 | // diffuse += D; 65 | // spec += S; 66 | //} 67 | 68 | //[unroll] 69 | //for (i = 0; i < 5; ++i) 70 | //{ 71 | // ComputeSpotLight(g_Material, g_SpotLight[i], pIn.PosW, bumpedNormalW, toEyeW, A, D, S); 72 | // ambient += A; 73 | // diffuse += D; 74 | // spec += S; 75 | //} 76 | 77 | float4 litColor = texColor * (ambient + diffuse) + spec; 78 | litColor.a = texColor.a * g_Material.Diffuse.a; 79 | return litColor; 80 | } 81 | -------------------------------------------------------------------------------- /shaders/Sky.hlsli: -------------------------------------------------------------------------------- 1 | 2 | TextureCube g_TexCube : register(t0); 3 | SamplerState g_Sam : register(s0); 4 | 5 | cbuffer CBChangesEveryFrame : register(b0) 6 | { 7 | matrix g_WorldViewProj; 8 | } 9 | 10 | struct VertexPos 11 | { 12 | float3 PosL : POSITION; 13 | }; 14 | 15 | struct VertexPosHL 16 | { 17 | float4 PosH : SV_POSITION; 18 | float3 PosL : POSITION; 19 | }; 20 | 21 | 22 | -------------------------------------------------------------------------------- /shaders/Sky_PS.hlsl: -------------------------------------------------------------------------------- 1 | #include "Sky.hlsli" 2 | 3 | float4 PS(VertexPosHL pIn) : SV_Target 4 | { 5 | return g_TexCube.Sample(g_Sam, pIn.PosL); 6 | } 7 | -------------------------------------------------------------------------------- /shaders/Sky_VS.hlsl: -------------------------------------------------------------------------------- 1 | #include "Sky.hlsli" 2 | 3 | VertexPosHL VS(VertexPos vIn) 4 | { 5 | VertexPosHL vOut; 6 | 7 | // 设置z = w使得z/w = 1(天空盒保持在远平面) 8 | float4 posH = mul(float4(vIn.PosL, 1.0f), g_WorldViewProj); 9 | vOut.PosH = posH.xyww; 10 | vOut.PosL = vIn.PosL; 11 | return vOut; 12 | } -------------------------------------------------------------------------------- /thirdParty/cmakelists.txt: -------------------------------------------------------------------------------- 1 | set(third_party_folder "thirdParty") 2 | 3 | if(NOT TARGET imgui) 4 | include(imgui.cmake) 5 | set_target_properties(imgui PROPERTIES FOLDER ${third_party_folder}/imgui) 6 | endif() -------------------------------------------------------------------------------- /thirdParty/imgui.cmake: -------------------------------------------------------------------------------- 1 | set(imgui_SOURCE_DIR_ ${CMAKE_CURRENT_SOURCE_DIR}/imgui) 2 | 3 | file(GLOB imgui_sources CONFIGURE_DEPENDS "${imgui_SOURCE_DIR_}/*.cpp") 4 | file(GLOB imgui_impl CONFIGURE_DEPENDS 5 | "${imgui_SOURCE_DIR_}/imgui_impl_dx11.cpp" 6 | "${imgui_SOURCE_DIR_}/imgui_impl_dx11.h") 7 | add_library(imgui STATIC ${imgui_sources} ${imgui_impl}) 8 | target_include_directories(imgui PUBLIC $) -------------------------------------------------------------------------------- /thirdParty/imgui/imgui_impl_dx11.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for DirectX11 2 | // This needs to be used along with a Platform Backend (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. 7 | 8 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 9 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 10 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 11 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 12 | 13 | #pragma once 14 | #include "imgui.h" // IMGUI_IMPL_API 15 | 16 | struct ID3D11Device; 17 | struct ID3D11DeviceContext; 18 | 19 | IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); 20 | IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); 21 | IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); 22 | IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); 23 | 24 | // Use if you want to reset your rendering device without losing Dear ImGui state. 25 | IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); 26 | IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); 27 | -------------------------------------------------------------------------------- /thirdParty/imgui/imgui_impl_win32.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications) 2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) 3 | 4 | // Implemented features: 5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) 6 | // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] 7 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 8 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 9 | 10 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 11 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 12 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 13 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 14 | 15 | #pragma once 16 | #include "imgui.h" // IMGUI_IMPL_API 17 | 18 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); 19 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); 20 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); 21 | 22 | // Win32 message handler your application need to call. 23 | // - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper. 24 | // - You should COPY the line below into your .cpp code to forward declare the function and then you can call it. 25 | #if 0 26 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 27 | #endif 28 | 29 | // DPI-related helpers (optional) 30 | // - Use to enable DPI awareness without having to create an application manifest. 31 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. 32 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. 33 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, 34 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. 35 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness(); 36 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd 37 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor 38 | 39 | // Transparency related helpers (optional) [experimental] 40 | // - Use to enable alpha compositing transparency with the desktop. 41 | // - Use together with e.g. clearing your framebuffer with zero-alpha. 42 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd 43 | -------------------------------------------------------------------------------- /thirdParty/xmake.lua: -------------------------------------------------------------------------------- 1 | set_group("thirdparty") 2 | target("imgui") 3 | _config_project({ 4 | project_kind = "static", 5 | enable_exception = true, 6 | batch_size=8 7 | }) 8 | add_includedirs("imgui", { 9 | public = true 10 | }) 11 | if is_plat("windows") then 12 | add_defines("IMGUI_API=__declspec(dllexport)") 13 | end 14 | add_headerfiles("imgui/**.h") 15 | add_files("imgui/**.cpp") 16 | target_end() -------------------------------------------------------------------------------- /xmake.lua: -------------------------------------------------------------------------------- 1 | set_xmakever("2.7.9") 2 | set_version("1.0.0") 3 | add_rules("mode.release", "mode.debug") 4 | set_toolchains("msvc") 5 | set_languages("c99", "cxx17") 6 | set_exceptions("none") 7 | set_encodings("utf-8") 8 | rule("dx_lib") 9 | on_load(function (target) 10 | target:add("syslinks","d3d11","dxgi","dxguid","D3DCompiler","winmm","kernel32","user32","gdi32","winspool","shell32","ole32","oleaut32","uuid","comdlg32","advapi32") 11 | bin_path = path.join(os.projectdir(),"bin") 12 | end) 13 | rule_end() 14 | 15 | rule("imguiini") 16 | after_build(function () 17 | imguiini_file=path.join(os.projectdir(),"imgui.ini") 18 | bin_path = path.join(os.projectdir(),"bin") 19 | if not os.isdir(bin_path) then 20 | os.mkdir(bin_path) 21 | end 22 | if os.isfile(imguiini_file) then 23 | os.mv(imguiini_file,bin_path) 24 | end 25 | end) 26 | rule_end() 27 | 28 | if is_arch("x64", "x86_64", "arm64") then 29 | -- disable ccache in-case error 30 | set_policy("build.ccache", true) 31 | includes("xmake_func.lua") 32 | includes("thirdparty") 33 | 34 | target("FluidSimulation-Engine") 35 | add_rules("imguiini") 36 | add_rules("hlsl_shader_complier") 37 | -- set bin dir 38 | set_targetdir("bin") 39 | _config_project({ 40 | project_kind = "binary", 41 | enable_exception = true, 42 | --batch_size=8 43 | }) 44 | add_deps("imgui") 45 | add_rules("dx_lib") 46 | add_includedirs("include") 47 | add_headerfiles("include/**.h") 48 | add_files("src/**.cpp") 49 | --shader 50 | add_headerfiles("shaders/**.hlsl|shaders/**.hlsli") 51 | add_files("shaders/**.hlsl|shaders/**.hlsli") 52 | target_end() 53 | end 54 | -------------------------------------------------------------------------------- /xmake_func.lua: -------------------------------------------------------------------------------- 1 | rule("hlsl_shader_complier") 2 | set_extensions(".hlsl",".hlsli") 3 | on_buildcmd_files(function (target,batchcmds,sourcebatch, opt) 4 | import("lib.detect.find_program") 5 | local msvc = target:toolchain("msvc") 6 | local runenvs = msvc:runenvs() 7 | local fxcopt = {} 8 | fxcopt.envs = runenvs 9 | fxcopt.force = true 10 | fxcopt.check = opt.check or function () end 11 | fxc = find_program(opt.program or "fxc", fxcopt) 12 | 13 | hlsl_generated_dir=path.join(os.projectdir(),"\\shaders\\generated") 14 | if not os.isdir(hlsl_generated_dir) then 15 | os.mkdir(hlsl_generated_dir) 16 | end 17 | 18 | for _,sourcefile_hlsl in ipairs(sourcebatch.sourcefiles) do 19 | local ext = path.extension(sourcefile_hlsl) 20 | if ext==".hlsl" then 21 | local hlsl_basename = path.basename(sourcefile_hlsl) 22 | local hlsl_output_path = path.join(hlsl_generated_dir,hlsl_basename..".cso") 23 | local hlsl_shader_entrypoint = string.sub(hlsl_basename,-2) 24 | batchcmds:show_progress(opt.progress, "${color.build.object}compiling.hlsl %s", sourcefile_hlsl) 25 | if is_mode("debug") then 26 | batchcmds:vrunv(fxc,{sourcefile_hlsl,"/Zi","/Od","/E",hlsl_shader_entrypoint,"/Fo",hlsl_output_path,"/T",string.lower(hlsl_shader_entrypoint).."_5_0","/nologo"}) 27 | else 28 | batchcmds:vrunv(fxc,{sourcefile_hlsl,"/E",hlsl_shader_entrypoint,"/Fo",hlsl_output_path,"/T",string.lower(hlsl_shader_entrypoint).."_5_0","/nologo"}) 29 | end 30 | end 31 | end 32 | end) 33 | rule_end() 34 | 35 | 36 | rule("engine_basic_settings") 37 | on_config(function(target) 38 | local _, cc = target:tool("cxx") 39 | if is_plat("linux") then 40 | -- Linux should use -stdlib=libc++ 41 | -- https://github.com/LuisaGroup/LuisaCompute/issues/58 42 | if (cc == "clang" or cc == "clangxx" or cc == "gcc" or cc == "gxx") then 43 | target:add("cxflags", "-stdlib=libc++", { 44 | force = true 45 | }) 46 | end 47 | end 48 | end) 49 | on_load(function(target) 50 | local _get_or = function(name, default_value) 51 | local v = target:values(name) 52 | if v == nil then 53 | return default_value 54 | end 55 | return v 56 | end 57 | local project_kind = _get_or("project_kind", "phony") 58 | target:set("kind", project_kind) 59 | local c_standard = target:values("c_standard") 60 | local cxx_standard = target:values("cxx_standard") 61 | if type(c_standard) == "string" and type(cxx_standard) == "string" then 62 | target:set("languages", c_standard, cxx_standard) 63 | else 64 | target:set("languages", "c11", "cxx17") 65 | end 66 | 67 | local enable_exception = _get_or("enable_exception", nil) 68 | if enable_exception then 69 | target:set("exceptions", "cxx") 70 | else 71 | target:set("exceptions", "no-cxx") 72 | end 73 | if is_mode("debug") then 74 | target:add("defines","_DEBUG","DEBUGE") 75 | target:set("runtimes", "MDd") 76 | target:set("optimize", "none") 77 | target:set("warnings", "none") 78 | target:add("cxflags", "/GS", "/W3","/Gd","/Ob1","/Od",{ 79 | tools = {"msvc"} 80 | }) 81 | target:add("cxflags", "/Zc:preprocessor", { 82 | tools = {"msvc"} 83 | }); 84 | else 85 | target:set("defines","NODEBUG") 86 | target:set("runtimes", "MD") 87 | target:set("optimize", "fast") 88 | target:set("warnings", "none") 89 | target:add("cxflags", "/Oy", "/GS-", "/Gd", "/Oi", "/Ot", "/GT", "/Ob2", { 90 | tools = {"msvc"} 91 | }) 92 | target:add("cxflags", "/Zc:preprocessor", { 93 | tools = {"msvc"} 94 | }) 95 | end 96 | target:add("defines","UNICODE","_UNICODE","_WIN32","_WINDOWS") 97 | end) 98 | rule_end() 99 | -- In-case of submod, when there is override rules, do not overload 100 | if _config_rules == nil then 101 | _config_rules = {"engine_basic_settings"} 102 | end 103 | if _disable_unity_build == nil then 104 | _disable_unity_build = not get_config("enable_unity_build") 105 | end 106 | 107 | if _configs == nil then 108 | _configs = {} 109 | end 110 | function _config_project(config) 111 | if type(_configs) == "table" then 112 | for k, v in pairs(_configs) do 113 | set_values(k, v) 114 | end 115 | end 116 | if type(_config_rules) == "table" then 117 | add_rules(_config_rules) 118 | end 119 | if type(config) == "table" then 120 | for k, v in pairs(config) do 121 | set_values(k, v) 122 | end 123 | end 124 | local batch_size = config["batch_size"] 125 | if type(batch_size) == "number" and batch_size > 1 and (not _disable_unity_build) then 126 | add_rules("c.unity_build", { 127 | batchsize = batch_size 128 | }) 129 | add_rules("c++.unity_build", { 130 | batchsize = batch_size 131 | }) 132 | end 133 | end --------------------------------------------------------------------------------