41 Commits

Author SHA1 Message Date
57700da217 now using deferred rendering instead of forward rendering; some little problem: grid not render, shadow not impl 2026-03-18 14:28:02 +08:00
f1de5df4de add bloom;some treaks 2026-03-17 16:20:22 +08:00
28d9a7dfb6 add Preetham sky; add point light and spot light; 2026-03-16 01:44:23 +08:00
3f56a6878d remove some useless include; add include <filesystem> for entrypoint 2026-03-15 00:49:10 +08:00
a6fb4bdcea add args for entry Application; using efsw to replace custom filewatcher; remove some useless code; move FileOpenSelector from Application to FileSystem;some tweaks 2026-03-15 00:46:47 +08:00
5cb9b04ab0 add compute shader to auto calculate screen exposure, add SSBO impl 2026-03-12 23:42:52 +08:00
8ba00467fd add README.md 2026-03-11 17:31:32 +08:00
79e6631c50 add Physics2D class; For Physics2D add DistanceJoint RevoluteJoint PrismaticJoint WeldJoint Component and serialize/deserialize code; use template to Copy Component from entity to entity; remove useless code, fix some error code 2026-03-11 16:13:38 +08:00
a265e71e1a add AnimationComponent, Skeleton, AnimationClip; add single Renderer3D class, remove some useless code; problem now renderer2D cannot blend with Renderer3D 2026-03-11 09:19:05 +08:00
eb0a463370 fix environment texture drag to viewport didn't create SkylightComponent; fix PhysicsWrappers::CreateConvexMesh collier worng scale;some tweaks 2026-03-09 01:03:35 +08:00
c1bb8f9fba readd Sprite Renderer render and panel edit; in renderer scene, add icon for camera and light; improve a user-friendly EditorCamera, is more like UE Editor Camera; fix woring build m_ProjectionMatrix for SceneCamera::Orthographic 2026-03-08 19:27:00 +08:00
79f56b60a0 replace mesh load texture from native create to AssetsManager::GetAsset; renderer.h add Submit::pFunc->~FuncT(); fix PhysicsWrappers::CreateTriamgleMesh() error collider collect; remove unused ChildrenComponent; AssetEditorPanel now will auto save(serialize) when the window closed 2026-03-08 00:26:39 +08:00
57e14bc3d2 add ImViewzmo, add floating window for QWER(select, translate, rotate, scale) , and add new debug button to floating (Experimental) 2026-03-02 17:10:03 +08:00
a0086020c1 add infiniteGrid, rewrote the shadow , now the shadow is a simple hardware shadow 2026-03-01 17:03:40 +08:00
56da5ebef7 add auto exposure 2026-02-26 18:17:12 +08:00
99bbf1eb5a fix the child position incorrect while parenting node; add camera focus func; treat icons to the asset and using AssetsManager::GetAsset to load it 2026-02-17 21:38:43 +08:00
2bbe332532 lots of asset manager changes. using meta to manage asset, add twoside material flag for grid 2026-02-15 16:17:23 +08:00
896d3c7f97 add file watcher using widows api for windows platform, using handles to import and manager assets, some little tweaks 2026-01-21 23:25:41 +08:00
cf3a46bae1 add trace for imgui.ini, add assets manager system and objects manager system, add some icons, add entity tree node for scene Hierachy's entities, add convert blend file process(but not actual use it, just implement) BUGS: file copy not work 2026-01-21 12:30:47 +08:00
2bfde2dfb0 add circle2d collider renderer, fixed a bug for renderer 2 value properties 2026-01-20 02:04:16 +08:00
323d646611 default mesh collider are generated by default mesh, add camera info serialization, using error info instead of assert to process missing filepath when deserializing scene, move cullface into internal renderer api, fixed dynamic vertex buffer bug 2026-01-19 13:05:24 +08:00
81b52abf0f update cursor load 2026-01-12 19:18:07 +08:00
bed57f18d3 add serialize for RigidbodyComponent linear/angular drag and gravity, change the physx API for c++ and c#, fixed rotate bug(using radians to storage), some little code tweaks 2026-01-12 18:58:11 +08:00
f857d8e791 move imgui property code and Pysics Actor code to a single file 2026-01-10 14:48:17 +08:00
9e1474e643 add directional light component and skylight component, add PCSS and hard shadow 2026-01-02 22:46:29 +08:00
abf0a65bd6 update transformComponent style, and change the position of button 'Add Component' 2026-01-01 00:57:23 +08:00
faecfe21ab fixed layer problem, remove 'default' layer to serialize, remove Transform class, using translation rotation scale instead 2025-12-31 23:56:49 +08:00
960eeaf94b add transform class, some code tweaks 2025-12-29 23:11:14 +08:00
ce41e348f8 add physX settings through the setting window for editor 2025-12-29 13:44:00 +08:00
9a44dd8d79 add overlapBox/Sphere/Capsule function, fixed OnWake/OnSleep not work 2025-12-28 22:40:48 +08:00
d0eed3a33d add c# debug (mono debug) 2025-12-25 17:39:50 +08:00
f747db4e27 add physX colliders ,add trigger, colliders now can visible, some rotation for cs and native cpp connection 2025-12-24 10:10:24 +08:00
00d3993a77 add PhysX SDK and some tweaks 2025-12-17 12:39:20 +08:00
57ca6c30f5 use pipelines to replace vertexArray 2025-12-15 11:01:30 +08:00
0f7eb7cc95 add custom fonts to support 中文, add material edit for selected mesh 2025-12-14 16:48:40 +08:00
c92c831d02 add box2D colliders simple impl, some little tweaks, fixed camera bug 2025-12-13 22:42:03 +08:00
4140a5b4be add 2D physics (use box2d), fixed some little bugs 2025-12-12 16:47:04 +08:00
804c1d84ce upload correct mono lib for linux, set mono runtime to 8.0. (current mono lib version windows/linux 8.0.22) 2025-12-10 15:30:47 +08:00
5444f42c2c add submodule box2D, add mono lib for linux and some minor code tweaks 2025-12-09 21:41:39 +08:00
dc53f9517a add serialization (use yaml-cpp), add stencil to render outline for selected entity, add play mode, UUIDS, add orthographic and perspective camera, add editor camera 2025-12-09 16:30:53 +08:00
3ffb4cc449 add mono c# (using dotnet9.0 from https://github.com/dotnet/runtime), add ECS (entt), add some c# code, add fastNoise 2025-12-08 23:38:22 +08:00
880 changed files with 35390 additions and 2665 deletions

4
.gitignore vendored
View File

@ -17,3 +17,7 @@ build/
# Files # Files
*.user *.user
# dotnet project
[Bb]in/
[Oo]bj/

18
.gitmodules vendored
View File

@ -17,3 +17,21 @@
[submodule "Prism/vendor/ImGuizmo"] [submodule "Prism/vendor/ImGuizmo"]
path = Prism/vendor/ImGuizmo path = Prism/vendor/ImGuizmo
url = https://github.com/CedricGuillemet/ImGuizmo.git url = https://github.com/CedricGuillemet/ImGuizmo.git
[submodule "Prism/vendor/EnTT"]
path = Prism/vendor/EnTT
url = https://github.com/skypjack/entt.git
[submodule "Prism/vendor/yaml-cpp"]
path = Prism/vendor/yaml-cpp
url = https://github.com/jbeder/yaml-cpp
[submodule "Prism/vendor/Box2D"]
path = Prism/vendor/Box2D
url = https://github.com/erincatto/box2d.git
[submodule "Prism/vendor/PhysX"]
path = Prism/vendor/PhysX
url = https://github.com/NVIDIA-Omniverse/PhysX.git
[submodule "Prism/vendor/ImViewGuizmo"]
path = Prism/vendor/ImViewGuizmo
url = https://github.com/Ka1serM/ImViewGuizmo
[submodule "Prism/vendor/efsw"]
path = Prism/vendor/efsw
url = https://github.com/SpartanJ/efsw

View File

@ -10,7 +10,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# set MSVC output directory # set MSVC output directory
if(MSVC) if(MSVC)
# config # config
string(REPLACE "/showIncludes" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
# temp config # temp config
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251")

View File

@ -1,13 +1,22 @@
project(PrismEditor) project(PrismEditor)
file(GLOB ASSETS assets) set(CMAKE_BINARY_DIR ${CMAKE_BINARY_DIR}/bin)
file(COPY ${ASSETS} DESTINATION ${CMAKE_BINARY_DIR}/bin)
file(GLOB ASSETS "assets")
file(COPY ${ASSETS} DESTINATION ${CMAKE_BINARY_DIR})
# imgui.ini file
file(GLOB IMGUI_INI imgui.ini)
file(COPY ${IMGUI_INI} DESTINATION ${CMAKE_BINARY_DIR})
file(GLOB DOTNET_LIBRARY library)
file(COPY ${DOTNET_LIBRARY} DESTINATION ${CMAKE_BINARY_DIR})
file(GLOB_RECURSE SRC_SOURCE ./**.cpp) file(GLOB_RECURSE SRC_SOURCE ./**.cpp)
add_executable(${PROJECT_NAME} ${SRC_SOURCE}) add_executable(${PROJECT_NAME} ${SRC_SOURCE})
target_link_libraries(${PROJECT_NAME} PRIVATE Prism-shared) target_link_libraries(${PROJECT_NAME} PRIVATE Prism-static)
# Enable ImGui Docking space # Enable ImGui Docking space
target_compile_definitions(${PROJECT_NAME} PRIVATE ENABLE_DOCKSPACE) target_compile_definitions(${PROJECT_NAME} PRIVATE ENABLE_DOCKSPACE)

View File

@ -23,7 +23,7 @@ public:
}; };
Prism::Application* Prism::CreateApplication() Prism::Application* Prism::CreateApplication(const CommandArgs args)
{ {
return new Editor({"hello wrold", 1920, 1080}); return new Editor({"hello world", 1920, 1080, args});
} }

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,8 @@
#define EDITORLAYER_H #define EDITORLAYER_H
#include "Prism.h" #include "Prism.h"
#include "Prism/Editor/ContentBrowserPanel.h"
#include "Prism/Editor/ObjectsPanel.h"
#include "Prism/Editor/SceneHierachyPanel.h" #include "Prism/Editor/SceneHierachyPanel.h"
namespace Prism namespace Prism
@ -26,24 +28,48 @@ namespace Prism
bool OnKeyPressedEvent(KeyPressedEvent& e); bool OnKeyPressedEvent(KeyPressedEvent& e);
bool OnMouseButtonPressedEvent(MouseButtonPressedEvent& e); bool OnMouseButtonPressedEvent(MouseButtonPressedEvent& e);
void ShowBoundingBoxes(bool show, bool onTop = false); void ShowBoundingBoxes(bool show);
void SelectEntity(Entity entity);
void UpdateWindowTitle(const std::string& sceneName);
private: private:
std::pair<float, float> GetMouseViewportSpace() const; std::pair<float, float> GetMouseViewportSpace() const;
std::pair<glm::vec3, glm::vec3> CastRay(float mx, float my); std::pair<glm::vec3, glm::vec3> CastRay(float mx, float my);
struct SelectedSubmesh
{
Prism::Entity Entity;
Submesh* Mesh = nullptr;
float Distance = 0.0f;
};
void OnSelected(const SelectedSubmesh& selectionContext);
void OnEntityDeleted(Entity e);
Ray CastMouseRay();
void NewScene();
void OpenScene();
void OpenScene(const std::string& filepath);
void SaveScene();
void SaveSceneAs();
void OnScenePlay();
void OnSceneStop();
float GetSnapValue() const;
private: private:
Scope<SceneHierarchyPanel> m_SceneHierarchyPanel; Scope<SceneHierarchyPanel> m_SceneHierarchyPanel;
Scope<ContentBrowserPanel> m_ContentBrowserPanel;
Scope<ObjectsPanel> m_ObjectsPanel;
Ref<Scene> m_Scene; Ref<Scene> m_CurrentScene;
Ref<Scene> m_SphereScene; Ref<Scene> m_RuntimeScene, m_EditorScene;
Ref<Scene> m_ActiveScene; std::string m_SceneFilePath;
Entity* m_MeshEntity = nullptr; bool m_ReloadScriptOnPlay = false;
EditorCamera m_EditorCamera;
Ref<Mesh> m_PlaneMesh;
Ref<Material> m_SphereBaseMaterial; Ref<Material> m_SphereBaseMaterial;
Ref<Material> m_MeshMaterial; Ref<Material> m_MeshMaterial;
std::vector<Ref<MaterialInstance>> m_MetalSphereMaterialInstances; std::vector<Ref<MaterialInstance>> m_MetalSphereMaterialInstances;
@ -54,21 +80,16 @@ namespace Prism
glm::vec2 m_ViewportBounds[2] = {}; glm::vec2 m_ViewportBounds[2] = {};
int m_GizmoType = -1; // -1 = no gizmo int m_GizmoType = -1; // -1 = no gizmo
float m_SnapValue = 0.5f; float m_SnapValue = 0.5f;
float m_RotationSnapValue = 45.0f;
struct SelectedSubmesh enum class SelectionMode
{ {
Submesh* Mesh; None = 0, Entity = 1, SubMesh = 2
float Distance;
}; };
std::vector<SelectedSubmesh> m_SelectedSubmeshes; SelectionMode m_SelectionMode = SelectionMode::Entity;
glm::mat4* m_CurrentlySelectedTransform = nullptr;
// configure button std::vector<SelectedSubmesh> m_SelectionContext;
bool m_AllowViewportCameraEvents = false; glm::mat4* m_RelativeTransform = nullptr;
bool m_DrawOnTopBoundingBoxes = false;
bool m_UIShowBoundingBoxes = false;
bool m_UIShowBoundingBoxesOnTop = false;
struct AlbedoInput struct AlbedoInput
@ -78,14 +99,14 @@ namespace Prism
bool SRGB = true; bool SRGB = true;
bool UseTexture = false; bool UseTexture = false;
}; };
AlbedoInput m_AlbedoInput; // AlbedoInput m_AlbedoInput;
struct NormalInput struct NormalInput
{ {
Ref<Texture2D> TextureMap; Ref<Texture2D> TextureMap;
bool UseTexture = false; bool UseTexture = false;
}; };
NormalInput m_NormalInput; // NormalInput m_NormalInput;
struct MetalnessInput struct MetalnessInput
{ {
@ -93,21 +114,26 @@ namespace Prism
Ref<Texture2D> TextureMap; Ref<Texture2D> TextureMap;
bool UseTexture = false; bool UseTexture = false;
}; };
MetalnessInput m_MetalnessInput; // MetalnessInput m_MetalnessInput;
struct RoughnessInput struct RoughnessInput
{ {
float Value = 0.5f; float Value = 1.0f;
Ref<Texture2D> TextureMap; Ref<Texture2D> TextureMap;
bool UseTexture = false; bool UseTexture = false;
}; };
RoughnessInput m_RoughnessInput; // RoughnessInput m_RoughnessInput;
// PBR params // PBR params
bool m_RadiancePrefilter = false;
float m_EnvMapRotation = 0.0f; // Editor resources
Ref<Texture2D> m_CheckerboardTex;
Ref<Texture2D> m_PlayButtonTex, m_StopButtonTex, m_PauseButtonTex;
bool m_UIShowBoundingBoxes = false;
enum class SceneType : uint32_t enum class SceneType : uint32_t
{ {
@ -115,8 +141,15 @@ namespace Prism
}; };
SceneType m_SceneType; SceneType m_SceneType;
// Editor resources bool m_ViewportPanelHovered = false;
Ref<Texture2D> m_CheckerboardTex; bool m_ViewportPanelFocused = false;
bool m_ShowPhysicsSettings = false;
enum class SceneState
{
Edit = 0, Play = 1, Pause = 2
};
SceneState m_SceneState = SceneState::Edit;
}; };
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,49 @@
Scene: Scene Name
Environment:
AssetHandle: 10549690553241162923
Light:
Direction: [-0.314, -0.941, -0.209]
Radiance: [0, 0, 0]
Multiplier: 1
Entities:
- Entity: 17803125207910630398
Parent: 0
Children:
[]
TagComponent:
Tag: Directional Light
TransformComponent:
Position: [0, 0, 0]
Rotation: [-0.4810984, -0.20606127, 2.9545484]
Scale: [1.0000023, 1.0000007, 0.9999998]
DirectionalLightComponent:
Radiance: [1, 1, 1]
CastShadows: true
SoftShadows: true
LightSize: 0.5
- Entity: 4315886439647742331
Parent: 0
Children:
[]
TagComponent:
Tag: Cube
TransformComponent:
Position: [0, 2.048974, 0]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
MeshComponent:
AssetID: 3580169978473467053
- Entity: 16992665426857995732
Parent: 0
Children:
[]
TagComponent:
Tag: Cube
TransformComponent:
Position: [0, 0, 0]
Rotation: [0, 0, 0]
Scale: [50, 1, 50]
MeshComponent:
AssetID: 3580169978473467053
PhysicsLayers:
[]

View File

@ -0,0 +1,24 @@
Scene: Scene Name
Environment:
AssetHandle: 17073147362577408906
Light:
Direction: [-0.314, -0.941, -0.209]
Radiance: [0, 0, 0]
Multiplier: 1
Entities:
- Entity: 3696833073589069488
Parent: 0
Children:
[]
TagComponent:
Tag: venice_dawn_1_4k
TransformComponent:
Position: [0, 0, 0]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
SkyLightComponent:
EnvironmentMap: 17073147362577408906
Intensity: 1
Angle: 0
PhysicsLayers:
[]

View File

@ -0,0 +1,63 @@
#type vertex
#version 430
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec2 a_TexCoord;
out vec2 v_TexCoord;
void main()
{
vec4 position = vec4(a_Position.xy, 0.0, 1.0);
v_TexCoord = a_TexCoord;
gl_Position = position;
}
#type fragment
#version 430
layout(location = 0) out vec4 o_Color;
in vec2 v_TexCoord;
uniform sampler2D u_SceneTexture;
uniform sampler2D u_BloomTexture;
uniform float u_Exposure;
uniform bool u_EnableBloom;
void main()
{
#if 1
const float gamma = 2.2;
const float pureWhite = 1.0;
// Tonemapping
vec3 color = texture(u_SceneTexture, v_TexCoord).rgb;
if (u_EnableBloom)
{
vec3 bloomColor = texture(u_BloomTexture, v_TexCoord).rgb;
color += bloomColor;
}
// Reinhard tonemapping
float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
float mappedLuminance = (luminance * (1.0 + luminance / (pureWhite * pureWhite))) / (1.0 + luminance);
// Scale color by ratio of average luminances.
vec3 mappedColor = (mappedLuminance / luminance) * color* u_Exposure;
// Gamma correction.
o_Color = vec4(mappedColor, 1.0);
#else
const float gamma = 2.2;
vec3 hdrColor = texture(u_SceneTexture, v_TexCoord).rgb;
vec3 bloomColor = texture(u_BloomTexture, v_TexCoord).rgb;
hdrColor += bloomColor; // additive blending
// tone mapping
vec3 result = vec3(1.0) - exp(-hdrColor * u_Exposure);
// also gamma correct while we're at it
result = pow(result, vec3(1.0 / gamma));
o_Color = vec4(result, 1.0);
#endif
}

View File

@ -0,0 +1,84 @@
#type vertex
#version 430
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec2 a_TexCoord;
out vec2 v_TexCoord;
void main()
{
vec4 position = vec4(a_Position.xy, 0.0, 1.0);
v_TexCoord = a_TexCoord;
gl_Position = position;
}
#type fragment
#version 430
layout(location = 0) out vec4 o_Color;
in vec2 v_TexCoord;
uniform sampler2D u_Texture;
uniform bool u_Horizontal; // 未使用,可保留或移除
uniform bool u_FirstPass; // 是否进行阈值处理
uniform float u_Threshold; // 亮度阈值
uniform int u_Quality;
uniform float u_Directions; // 模糊方向数
uniform float u_Size; // 模糊半径
void main()
{
float Pi = 6.28318530718; // 2*PI
vec2 Radius = u_Size / textureSize(u_Texture, 0);
// 中心像素采样
vec3 centerColor = texture(u_Texture, v_TexCoord).rgb;
float centerLum = dot(centerColor, vec3(0.2126, 0.7152, 0.0722));
// 如果启用第一次处理且中心像素亮度低于阈值,则直接输出黑色(不进行模糊)
if (u_FirstPass && centerLum <= u_Threshold)
{
o_Color = vec4(0.0, 0.0, 0.0, 1.0);
return;
}
vec3 result = centerColor; // 先累加中心像素
float totalSamples = 1.0; // 有效采样计数(中心像素已计入)
// 周围像素采样
for (float d = 0.0; d < Pi; d += Pi / u_Directions)
{
for (float i = 1.0 / u_Quality; i <= 1.0; i += 1.0 / u_Quality)
{
vec2 offset = vec2(cos(d), sin(d)) * Radius * i;
vec3 sampleColor = texture(u_Texture, v_TexCoord + offset).rgb;
if (u_FirstPass)
{
float lum = dot(sampleColor, vec3(0.2126, 0.7152, 0.0722));
if (lum <= u_Threshold)
{
// 低于阈值则贡献黑色,但采样点仍计入分母?这里选择不计入有效采样数
// 若希望保持模糊能量,可以 continue 跳过累加,但需调整分母
// 为简单起见,此处设为黑色并计入计数(分母不变),也可选择跳过
sampleColor = vec3(0.0);
// 如果希望忽略该采样点,可以 continue 并减少 totalSamples
// 但为了效果平滑,这里保留为黑色并计入计数
}
}
result += sampleColor;
totalSamples += 1.0;
}
}
// 归一化:除以总采样数(包括中心像素)
// 若之前选择忽略低于阈值的采样点continue则需相应调整 totalSamples
result /= totalSamples;
o_Color = vec4(result, 1.0);
}

View File

@ -0,0 +1,24 @@
// Collider Shader
#type vertex
#version 450
layout(location = 0) in vec3 a_Position;
uniform mat4 u_ViewProjection;
uniform mat4 u_Transform;
void main()
{
gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
}
#type fragment
#version 450
layout(location = 0) out vec4 color;
void main()
{
color = vec4(0.1, 1.0, 0.1, 1.0);
}

View File

@ -0,0 +1,63 @@
#type compute
#version 460 core
layout(local_size_x = 1, local_size_y = 1) in;
layout(binding = 0, std430) buffer Histogram {
uint bins[64];
};
layout(binding = 1, std430) buffer Exposure {
float exposure;
};
uniform float u_SpeedUp;
uniform float u_SpeedDown;
uniform float u_Key;
uniform float u_LowPercent;
uniform float u_HighPercent;
uniform float u_MinExposure;
uniform float u_MaxExposure;
uniform float u_DeltaTime;
uniform float u_LogMin;
uniform float u_LogMax;
void main() {
float currentExposure = exposure;
uint total = 0;
uint prefix[64];
for (int i = 0; i < 64; i++) {
total += bins[i];
prefix[i] = total;
}
float lowCount = u_LowPercent * 0.01 * total;
float highCount = u_HighPercent * 0.01 * total;
int lowBin = 0, highBin = 63;
for (int i = 0; i < 64; i++) {
if (prefix[i] < lowCount) lowBin = i + 1;
if (prefix[i] < highCount) highBin = i + 1;
}
lowBin = clamp(lowBin, 0, 63);
highBin = clamp(highBin, 0, 63);
float sumLum = 0.0;
uint count = 0;
for (int i = lowBin; i <= highBin; i++) {
float t = (float(i) + 0.5) / 64.0;
float logLum = u_LogMin + t * (u_LogMax - u_LogMin);
float lum = exp2(logLum);
sumLum += lum * float(bins[i]);
count += bins[i];
}
float avgLum = count > 0 ? sumLum / count : 0.18;
float targetExposure = u_Key / max(avgLum, 0.0001);
targetExposure = clamp(targetExposure, u_MinExposure, u_MaxExposure);
float speed = (targetExposure > currentExposure) ? u_SpeedUp : u_SpeedDown;
float adaptFactor = 1.0 - exp(-speed * u_DeltaTime);
float newExposure = mix(currentExposure, targetExposure, adaptFactor);
newExposure = clamp(newExposure, u_MinExposure, u_MaxExposure);
exposure = newExposure;
}

View File

@ -1,45 +0,0 @@
// Grid Shader
#type vertex
#version 430
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec2 a_TexCoord;
uniform mat4 u_ViewProjection;
uniform mat4 u_Transform;
out vec2 v_TexCoord;
void main()
{
vec4 position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
gl_Position = position;
v_TexCoord = a_TexCoord;
}
#type fragment
#version 430
layout(location = 0) out vec4 color;
uniform float u_Scale;
uniform float u_Res;
in vec2 v_TexCoord;
float grid(vec2 st, float res)
{
vec2 grid = fract(st);
return step(res, grid.x) * step(res, grid.y);
}
void main()
{
float scale = u_Scale;
float resolution = u_Res;
float x = grid(v_TexCoord * scale, resolution);
color = vec4(vec3(0.2), 0.5) * (1.0 - x);
}

View File

@ -0,0 +1,26 @@
#type compute
#version 460 core
layout(local_size_x = 16, local_size_y = 16) in;
layout(binding = 0) uniform sampler2D u_SceneColor;
layout(binding = 1, std430) buffer Histogram {
uint bins[64];
};
uniform float u_LogMin;
uniform float u_LogMax;
void main() {
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
ivec2 size = textureSize(u_SceneColor, 0);
if (texel.x >= size.x || texel.y >= size.y) return;
vec3 color = texelFetch(u_SceneColor, texel, 0).rgb;
float lum = max(dot(color, vec3(0.2126, 0.7152, 0.0722)), 0.0001);
float logLum = log2(lum);
float invLogRange = 1.0 / (u_LogMax - u_LogMin);
float t = (logLum - u_LogMin) * invLogRange;
int bin = int(clamp(t * 64.0, 0.0, 63.0));
atomicAdd(bins[bin], 1u);
}

View File

@ -0,0 +1,224 @@
// Infinite Grid Shader
// Based on "The Best Darn Grid Shader (Yet)" by Ben Golus
#type vertex
#version 450 core
layout(location = 0) in vec3 a_Position;
// camera
uniform mat4 u_View;
uniform mat4 u_Projection;
uniform vec3 u_CameraPosition;
out CameraData{
mat4 ViewProjection;
vec3 Position;
}CameraOutput;
out vec3 v_NearPoint;
out vec3 v_FarPoint;
vec3 unprojectPoint(float x, float y, float z) {
mat4 viewInv = inverse(u_View);
mat4 projInv = inverse(u_Projection);
vec4 unprojectedPoint = viewInv * projInv * vec4(x, y, z, 1.0);
return unprojectedPoint.xyz / unprojectedPoint.w;
}
void main() {
v_NearPoint = unprojectPoint(a_Position.x, a_Position.y, 0.0);
v_FarPoint = unprojectPoint(a_Position.x, a_Position.y, 1.0);
CameraOutput.ViewProjection = u_Projection * u_View;
CameraOutput.Position = u_CameraPosition;
gl_Position = vec4(a_Position, 1.0);
}
#type fragment
#version 450 core
layout(location = 0) out vec4 o_Color;
in vec3 v_NearPoint;
in vec3 v_FarPoint;
in CameraData{
mat4 ViewProjection;
vec3 Position;
}CameraInput;
// Grid plane: 0 = XZ (Y up), 1 = XY (Z forward), 2 = YZ (X right)
uniform int u_GridPlane;
uniform float u_GridScale;
uniform vec4 u_GridColorThin;
uniform vec4 u_GridColorThick;
uniform vec4 u_AxisColorX;
uniform vec4 u_AxisColorZ;
uniform float u_FadeDistance;
float computeDepth(vec3 pos) {
vec4 clipSpacePos = CameraInput.ViewProjection * vec4(pos, 1.0);
return clipSpacePos.z / clipSpacePos.w;
}
// Get the plane normal based on grid plane type
vec3 getPlaneNormal() {
if (u_GridPlane == 1) return vec3(0.0, 0.0, 1.0); // XY plane, Z normal
if (u_GridPlane == 2) return vec3(1.0, 0.0, 0.0); // YZ plane, X normal
return vec3(0.0, 1.0, 0.0); // XZ plane, Y normal (default)
}
// Get 2D coordinates on the plane
vec2 getPlaneCoords(vec3 pos) {
if (u_GridPlane == 1) return pos.xy; // XY plane
if (u_GridPlane == 2) return pos.yz; // YZ plane
return pos.xz; // XZ plane (default)
}
// Get the component perpendicular to the plane (for axis drawing)
vec2 getAxisCoords(vec3 pos) {
// Returns the two coordinates used for drawing axis lines
// First component -> first axis color, Second component -> second axis color
if (u_GridPlane == 1) return vec2(pos.x, pos.y); // XY: X-axis and Y-axis
if (u_GridPlane == 2) return vec2(pos.y, pos.z); // YZ: Y-axis and Z-axis
return vec2(pos.x, pos.z); // XZ: X-axis and Z-axis
}
// Calculate t for ray-plane intersection
float rayPlaneIntersection(vec3 nearPoint, vec3 farPoint) {
vec3 rayDir = farPoint - nearPoint;
if (u_GridPlane == 1) {
// XY plane (z = 0)
if (abs(rayDir.z) < 0.0001) return -1.0;
return -nearPoint.z / rayDir.z;
}
if (u_GridPlane == 2) {
// YZ plane (x = 0)
if (abs(rayDir.x) < 0.0001) return -1.0;
return -nearPoint.x / rayDir.x;
}
// XZ plane (y = 0) - default
if (abs(rayDir.y) < 0.0001) return -1.0;
return -nearPoint.y / rayDir.y;
}
// Get view angle component for normal fade
float getViewAngleComponent(vec3 viewDir) {
if (u_GridPlane == 1) return abs(viewDir.z); // XY plane
if (u_GridPlane == 2) return abs(viewDir.x); // YZ plane
return abs(viewDir.y); // XZ plane
}
// Pristine grid - single pixel line with proper AA
float pristineGridLine(vec2 uv) {
vec2 dudv = fwidth(uv);
vec2 uvMod = fract(uv);
vec2 uvDist = min(uvMod, 1.0 - uvMod);
vec2 distInPixels = uvDist / dudv;
vec2 lineAlpha = 1.0 - smoothstep(0.0, 1.0, distInPixels);
float alpha = max(lineAlpha.x, lineAlpha.y);
float density = max(dudv.x, dudv.y);
float densityFade = 1.0 - smoothstep(0.5, 1.0, density);
return alpha * densityFade;
}
// Axis line - single pixel wide
float axisLineAA(float coord, float dudv) {
float distInPixels = abs(coord) / dudv;
return 1.0 - smoothstep(0.0, 1.5, distInPixels);
}
void main() {
float t = rayPlaneIntersection(v_NearPoint, v_FarPoint);
if (t < 0.0) {
discard;
}
vec3 fragPos3D = v_NearPoint + t * (v_FarPoint - v_NearPoint);
float depth = computeDepth(fragPos3D);
if (depth > 1.0 || depth < -1.0) {
discard;
}
vec2 worldPos = getPlaneCoords(fragPos3D);
// === Fading ===
// Radial fade
float dist = length(fragPos3D - CameraInput.Position);
float radialFade = 1.0 - smoothstep(u_FadeDistance * 0.3, u_FadeDistance, dist);
// Normal fade (view angle)
vec3 viewDir = normalize(fragPos3D - CameraInput.Position);
float viewAngle = getViewAngleComponent(viewDir);
float normalFade = smoothstep(0.0, 0.15, viewAngle);
float fadeFactor = radialFade * normalFade;
if (fadeFactor < 0.001) {
discard;
}
// === Grid calculation ===
vec2 gridCoord1 = worldPos / u_GridScale;
vec2 gridCoord10 = worldPos / (u_GridScale * 10.0);
float grid1 = pristineGridLine(gridCoord1);
float grid10 = pristineGridLine(gridCoord10);
// LOD blend
vec2 deriv1 = fwidth(gridCoord1);
float lodFactor = smoothstep(20.0, 200.0, dist);
// float lodFactor = smoothstep(0.2, 0.5, max(deriv1.x, deriv1.y));
// Combine grids
float gridIntensity = mix(max(grid1, grid10 * 0.7), grid10, lodFactor);
// Grid color
vec3 gridColor = mix(u_GridColorThin.rgb, u_GridColorThick.rgb, lodFactor);
float baseAlpha = mix(u_GridColorThin.a, u_GridColorThick.a, lodFactor);
float gridAlpha = baseAlpha * gridIntensity * fadeFactor;
// === Axis lines ===
vec2 axisCoords = getAxisCoords(fragPos3D);
vec2 worldDeriv = fwidth(worldPos);
// First axis (uses AxisColorX - typically red)
float axis1Alpha = axisLineAA(axisCoords.y, worldDeriv.y) * fadeFactor;
// Second axis (uses AxisColorZ - typically blue)
float axis2Alpha = axisLineAA(axisCoords.x, worldDeriv.x) * fadeFactor;
// === Final composition ===
vec3 finalColor = gridColor;
float finalAlpha = gridAlpha;
// Blend axis colors
if (axis2Alpha > 0.001) {
float blend = axis2Alpha * u_AxisColorZ.a;
finalColor = mix(finalColor, u_AxisColorZ.rgb, blend);
finalAlpha = max(finalAlpha, blend);
}
if (axis1Alpha > 0.001) {
float blend = axis1Alpha * u_AxisColorX.a;
finalColor = mix(finalColor, u_AxisColorX.rgb, blend);
finalAlpha = max(finalAlpha, blend);
}
if (finalAlpha < 0.001) {
discard;
}
gl_FragDepth = depth * 0.5 + 0.5;
o_Color = vec4(finalColor, finalAlpha);
}

View File

@ -0,0 +1,348 @@
#type vertex
#version 430 core
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec2 a_TexCoord;
out vec2 v_TexCoord;
void main()
{
v_TexCoord = a_TexCoord;
gl_Position = vec4(a_Position.xy, 0.0, 1.0);
}
#type fragment
#version 430 core
// ==================== 输入 ====================
in vec2 v_TexCoord;
// G-buffer 纹理
uniform sampler2D u_AlbedoMetallic; // RGB: albedo, A: metallic
uniform sampler2D u_NormalRoughness; // RGB: normal (encoded), A: roughness
uniform sampler2D u_EmissiveAO; // RGB: emissive, A: AO
uniform sampler2D u_Depth; // depth
// 相机参数
uniform mat4 u_InvViewProj; // 逆视图投影矩阵,用于重建世界坐标
uniform vec3 u_CameraPosition;
// 光源结构体与你的PBR着色器一致
struct DirectionalLight {
vec3 Direction;
vec3 Radiance;
float Intensity;
bool CastShadows;
};
struct PointLight {
vec3 Position;
vec3 Radiance;
float Intensity;
float Range;
bool CastShadows;
};
struct SpotLight {
vec3 Position;
vec3 Direction;
vec3 Radiance;
float Intensity;
float Range;
float InnerConeCos;
float OuterConeCos;
bool CastShadows;
};
uniform DirectionalLight u_DirectionalLights; // 仅一个方向光
uniform int u_PointLightCount;
uniform PointLight u_PointLights[16]; // 假设最多16个点光源
uniform int u_SpotLightCount;
uniform SpotLight u_SpotLights[16]; // 最多16个聚光源
// IBL 相关
uniform samplerCube u_EnvRadianceTex;
uniform samplerCube u_EnvIrradianceTex;
uniform sampler2D u_BRDFLUTTexture;
uniform float u_IBLContribution;
uniform float u_EnvMapRotation;
// 阴影相关
uniform sampler2D u_ShadowMap;
uniform float u_ShadowBias;
uniform float u_ShadowSoftness;
uniform int u_ShadowEnabled;
uniform float u_ShadowIntensity; // 阴影强度0-1
uniform mat4 u_LightSpaceMatrix; // 方向光光源空间矩阵
// 天空盒(可选)
uniform samplerCube u_Skybox; // 如果深度为1.0则采样天空盒
uniform float u_SkyIntensity;
uniform float u_SkyTextureLod;
// 输出
layout(location = 0) out vec4 o_Color;
// ==================== 常量 ====================
const float PI = 3.14159265359;
const float Epsilon = 0.00001;
const vec3 Fdielectric = vec3(0.04);
// ==================== 工具函数 ====================
// 从深度重建世界坐标
vec3 worldPosFromDepth(vec2 uv, float depth) {
vec4 clipPos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
vec4 worldPos = u_InvViewProj * clipPos;
return worldPos.xyz / worldPos.w;
}
// 从深度重建世界空间方向(用于天空盒采样)
vec3 worldDirFromUV(vec2 uv) {
// 假设深度为1.0时,得到远平面方向
vec4 clipPos = vec4(uv * 2.0 - 1.0, 1.0, 1.0);
vec4 worldPos = u_InvViewProj * clipPos;
return normalize(worldPos.xyz / worldPos.w);
}
// 旋转向量绕Y轴
vec3 RotateVectorAboutY(float angle, vec3 vec) {
angle = radians(angle);
mat3 rotationMatrix = mat3(
vec3(cos(angle), 0.0, sin(angle)),
vec3(0.0, 1.0, 0.0),
vec3(-sin(angle), 0.0, cos(angle))
);
return rotationMatrix * vec;
}
// ==================== PBR 函数(复用你的代码) ====================
float ndfGGX(float cosLh, float roughness) {
float alpha = roughness * roughness;
float alphaSq = alpha * alpha;
float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
return alphaSq / (PI * denom * denom);
}
float GeometrySchlickGGX(float NdotV, float roughness) {
float r = (roughness + 1.0);
float k = (r * r) / 8.0;
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2;
}
vec3 fresnelSchlick(vec3 F0, float cosTheta) {
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
}
vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness) {
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
}
// ---------- 方向光 ----------
vec3 ComputeDirectionalLight(DirectionalLight light, vec3 F0, vec3 N, vec3 V, float NdotV, vec3 albedo, float roughness, float metallic) {
vec3 L = normalize(-light.Direction);
vec3 Lradiance = light.Radiance * light.Intensity;
vec3 Lh = normalize(L + V);
float cosLi = max(dot(N, L), 0.0);
float cosLh = max(dot(N, Lh), 0.0);
vec3 F = fresnelSchlick(F0, max(dot(Lh, V), 0.0));
float D = ndfGGX(cosLh, roughness);
float G = GeometrySmith(N, V, L, roughness);
vec3 kd = (1.0 - F) * (1.0 - metallic);
vec3 diffuseBRDF = kd * albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
}
// ---------- 点光源 ----------
vec3 ComputePointLight(PointLight light, vec3 F0, vec3 N, vec3 V, float NdotV, vec3 albedo, float roughness, float metallic, vec3 worldPos) {
vec3 lightVec = light.Position - worldPos;
float dist = length(lightVec);
if (dist > light.Range) return vec3(0.0);
vec3 L = lightVec / dist;
vec3 Lradiance = light.Radiance * light.Intensity;
float attenuation = 1.0 / (dist * dist + 0.0001);
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
rangeFactor = rangeFactor * rangeFactor;
attenuation *= rangeFactor;
vec3 Lh = normalize(L + V);
float cosLi = max(dot(N, L), 0.0);
float cosLh = max(dot(N, Lh), 0.0);
vec3 F = fresnelSchlick(F0, max(dot(Lh, V), 0.0));
float D = ndfGGX(cosLh, roughness);
float G = GeometrySmith(N, V, L, roughness);
vec3 kd = (1.0 - F) * (1.0 - metallic);
vec3 diffuseBRDF = kd * albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
}
// ---------- 聚光源 ----------
vec3 ComputeSpotLight(SpotLight light, vec3 F0, vec3 N, vec3 V, float NdotV, vec3 albedo, float roughness, float metallic, vec3 worldPos) {
vec3 lightVec = light.Position - worldPos;
float dist = length(lightVec);
if (dist > light.Range) return vec3(0.0);
vec3 L = lightVec / dist;
vec3 Lradiance = light.Radiance * light.Intensity;
float attenuation = 1.0 / (dist * dist + 0.0001);
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
rangeFactor = rangeFactor * rangeFactor;
attenuation *= rangeFactor;
float cosAngle = dot(-L, normalize(light.Direction));
if (cosAngle < light.OuterConeCos) return vec3(0.0);
float angleFalloff = (cosAngle - light.OuterConeCos) / (light.InnerConeCos - light.OuterConeCos);
angleFalloff = clamp(angleFalloff, 0.0, 1.0);
attenuation *= angleFalloff;
vec3 Lh = normalize(L + V);
float cosLi = max(dot(N, L), 0.0);
float cosLh = max(dot(N, Lh), 0.0);
vec3 F = fresnelSchlick(F0, max(dot(Lh, V), 0.0));
float D = ndfGGX(cosLh, roughness);
float G = GeometrySmith(N, V, L, roughness);
vec3 kd = (1.0 - F) * (1.0 - metallic);
vec3 diffuseBRDF = kd * albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
}
// ---------- IBL ----------
vec3 IBL(vec3 F0, vec3 N, vec3 V, float NdotV, float roughness, float metallic, vec3 albedo) {
vec3 irradiance = texture(u_EnvIrradianceTex, N).rgb;
vec3 F = fresnelSchlickRoughness(F0, NdotV, roughness);
vec3 kd = (1.0 - F) * (1.0 - metallic);
vec3 diffuseIBL = albedo * irradiance;
vec3 R = 2.0 * NdotV * N - V; // 反射向量
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
vec3 specularIrradiance = textureLod(
u_EnvRadianceTex,
RotateVectorAboutY(u_EnvMapRotation, R),
roughness * u_EnvRadianceTexLevels
).rgb;
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(NdotV, 1.0 - roughness)).rg;
vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y);
return kd * diffuseIBL + specularIBL;
}
// ---------- 阴影 ----------
float calculateShadow(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir) {
if (u_ShadowEnabled == 0) return 0.0;
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
projCoords = projCoords * 0.5 + 0.5;
if (projCoords.z > 1.0 || projCoords.x < 0.0 || projCoords.x > 1.0 || projCoords.y < 0.0 || projCoords.y > 1.0)
return 0.0;
float closestDepth = texture(u_ShadowMap, projCoords.xy).r;
float currentDepth = projCoords.z;
float bias = max(u_ShadowBias * (1.0 - dot(normal, lightDir)), u_ShadowBias * 0.1);
float shadow = 0.0;
vec2 texelSize = 1.0 / textureSize(u_ShadowMap, 0);
int pcfRange = int(u_ShadowSoftness);
int sampleCount = 0;
for (int x = -pcfRange; x <= pcfRange; ++x) {
for (int y = -pcfRange; y <= pcfRange; ++y) {
float pcfDepth = texture(u_ShadowMap, projCoords.xy + vec2(x, y) * texelSize).r;
shadow += (currentDepth - bias > pcfDepth) ? 1.0 : 0.0;
sampleCount++;
}
}
shadow /= float(sampleCount);
return shadow * u_ShadowIntensity; // 应用阴影强度
}
// ==================== 主函数 ====================
void main() {
vec2 uv = v_TexCoord;
float depth = texture(u_Depth, uv).r;
if (depth >= 1.0) {
vec3 dir = worldDirFromUV(uv);
vec3 skyColor = textureLod(u_Skybox, dir, u_SkyTextureLod).rgb * u_SkyIntensity;
o_Color = vec4(skyColor, 1.0);
return;
}
vec4 albedoMetal = texture(u_AlbedoMetallic, uv);
vec4 normalRough = texture(u_NormalRoughness, uv);
vec4 emissiveAO = texture(u_EmissiveAO, uv);
vec3 albedo = albedoMetal.rgb;
float metallic = albedoMetal.a;
vec3 normal = normalRough.rgb * 2.0 - 1.0;
float roughness = normalRough.a;
vec3 emissive = emissiveAO.rgb;
float ao = emissiveAO.a;
vec3 worldPos = worldPosFromDepth(uv, depth);
vec3 V = normalize(u_CameraPosition - worldPos);
float NdotV = clamp(dot(normal, V), 0.0, 1.0);
vec3 F0 = mix(Fdielectric, albedo, metallic);
vec3 Lo = vec3(0.0);
// Direction Light
if (u_DirectionalLights.Intensity > 0.0) {
Lo += ComputeDirectionalLight(u_DirectionalLights, F0, normal, V, NdotV, albedo, roughness, metallic);
}
// Point Light
for (int i = 0; i < u_PointLightCount; ++i) {
Lo += ComputePointLight(u_PointLights[i], F0, normal, V, NdotV, albedo, roughness, metallic, worldPos);
}
// Spot light
for (int i = 0; i < u_SpotLightCount; ++i) {
Lo += ComputeSpotLight(u_SpotLights[i], F0, normal, V, NdotV, albedo, roughness, metallic, worldPos);
}
float shadowFactor = 1.0;
if (u_ShadowEnabled > 0 && u_DirectionalLights.CastShadows && u_DirectionalLights.Intensity > 0.0) {
vec4 fragPosLightSpace = u_LightSpaceMatrix * vec4(worldPos, 1.0);
float shadow = calculateShadow(fragPosLightSpace, normal, u_DirectionalLights.Direction);
shadowFactor = 1.0 - shadow;
}
Lo *= shadowFactor;
// 计算 IBL
vec3 ibl = IBL(F0, normal, V, NdotV, roughness, metallic, albedo) * u_IBLContribution;
vec3 finalColor = Lo + ibl + emissive;
o_Color = vec4(finalColor, 1.0);
}

View File

@ -0,0 +1,24 @@
// Outline Shader
#type vertex
#version 430
layout(location = 0) in vec3 a_Position;
uniform mat4 u_ViewProjection;
uniform mat4 u_Transform;
void main()
{
gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
}
#type fragment
#version 430
layout(location = 0) out vec4 color;
void main()
{
color = vec4(1.0, 0.5, 0.0, 1.0);
}

View File

@ -0,0 +1,36 @@
// Outline Shader
#type vertex
#version 430
layout(location = 0) in vec3 a_Position;
layout(location = 5) in ivec4 a_BoneIndices;
layout(location = 6) in vec4 a_BoneWeights;
uniform mat4 u_ViewProjection;
uniform mat4 u_Transform;
const int MAX_BONES = 100;
uniform mat4 u_BoneTransforms[100];
void main()
{
mat4 boneTransform = u_BoneTransforms[a_BoneIndices[0]] * a_BoneWeights[0];
boneTransform += u_BoneTransforms[a_BoneIndices[1]] * a_BoneWeights[1];
boneTransform += u_BoneTransforms[a_BoneIndices[2]] * a_BoneWeights[2];
boneTransform += u_BoneTransforms[a_BoneIndices[3]] * a_BoneWeights[3];
vec4 localPosition = boneTransform * vec4(a_Position, 1.0);
gl_Position = u_ViewProjection * u_Transform * localPosition;
}
#type fragment
#version 430
layout(location = 0) out vec4 color;
void main()
{
color = vec4(1.0, 0.5, 0.0, 1.0);
}

View File

@ -1,5 +1,5 @@
// ----------------------------- // -----------------------------
// -- Hazel Engine PBR shader -- // -- Based on Hazel PBR shader --
// ----------------------------- // -----------------------------
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in. // Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
// Currently heavily updated. // Currently heavily updated.
@ -21,19 +21,25 @@ layout(location = 4) in vec2 a_TexCoord;
layout(location = 5) in ivec4 a_BoneIndices; layout(location = 5) in ivec4 a_BoneIndices;
layout(location = 6) in vec4 a_BoneWeights; layout(location = 6) in vec4 a_BoneWeights;
uniform mat4 u_ViewProjectionMatrix;
uniform mat4 u_Transform;
const int MAX_BONES = 100; const int MAX_BONES = 100;
uniform mat4 u_BoneTransforms[100]; uniform mat4 u_BoneTransforms[100];
uniform mat4 u_ViewProjectionMatrix;
uniform mat4 u_ViewMatrix;
uniform mat4 u_Transform;
uniform mat4 u_LightSpaceMatrix;
out VertexOutput out VertexOutput
{ {
vec3 WorldPosition; vec3 WorldPosition;
vec3 Normal; vec3 Normal;
vec2 TexCoord; vec2 TexCoord;
mat3 WorldNormals; mat3 WorldNormals;
mat3 WorldTransform;
vec3 Binormal; vec3 Binormal;
vec3 ViewPosition;
vec4 FragPosLightSpace;
} vs_Output; } vs_Output;
void main() void main()
@ -49,8 +55,14 @@ void main()
vs_Output.Normal = mat3(u_Transform) * mat3(boneTransform) * a_Normal; vs_Output.Normal = mat3(u_Transform) * mat3(boneTransform) * a_Normal;
vs_Output.TexCoord = vec2(a_TexCoord.x, 1.0 - a_TexCoord.y); vs_Output.TexCoord = vec2(a_TexCoord.x, 1.0 - a_TexCoord.y);
vs_Output.WorldNormals = mat3(u_Transform) * mat3(a_Tangent, a_Binormal, a_Normal); vs_Output.WorldNormals = mat3(u_Transform) * mat3(a_Tangent, a_Binormal, a_Normal);
vs_Output.Binormal = mat3(boneTransform) * a_Binormal; vs_Output.WorldTransform = mat3(u_Transform);
vs_Output.Binormal = a_Binormal;
vs_Output.FragPosLightSpace = u_LightSpaceMatrix * u_Transform * localPosition;
vs_Output.ViewPosition = vec3(u_ViewMatrix * vec4(vs_Output.WorldPosition, 1.0));
// gl_Position = u_ViewProjectionMatrix * u_Transform * vec4(a_Position, 1.0);
gl_Position = u_ViewProjectionMatrix * u_Transform * localPosition; gl_Position = u_ViewProjectionMatrix * u_Transform * localPosition;
} }
@ -61,14 +73,32 @@ const float PI = 3.141592;
const float Epsilon = 0.00001; const float Epsilon = 0.00001;
const int LightCount = 1; const int LightCount = 1;
// Constant normal incidence Fresnel factor for all dielectrics.
const vec3 Fdielectric = vec3(0.04); const vec3 Fdielectric = vec3(0.04);
struct Light { struct DirectionalLight {
vec3 Direction; vec3 Direction;
vec3 Radiance; vec3 Radiance;
float Multiplier; float Intensity;
bool CastShadows;
};
struct PointLight {
vec3 Position;
vec3 Radiance;
float Intensity;
float Range;
bool CastShadows;
};
struct SpotLight {
vec3 Position;
vec3 Direction;
vec3 Radiance;
float Intensity;
float Range;
float InnerConeCos;
float OuterConeCos;
bool CastShadows;
}; };
in VertexOutput in VertexOutput
@ -77,46 +107,72 @@ in VertexOutput
vec3 Normal; vec3 Normal;
vec2 TexCoord; vec2 TexCoord;
mat3 WorldNormals; mat3 WorldNormals;
mat3 WorldTransform;
vec3 Binormal; vec3 Binormal;
vec3 ViewPosition;
vec4 FragPosLightSpace;
} vs_Input; } vs_Input;
layout(location=0) out vec4 color; layout(location = 0) out vec4 color;
layout(location = 1) out vec4 o_BloomColor;
uniform Light lights; uniform DirectionalLight u_DirectionalLights;
uniform vec3 u_CameraPosition; uniform vec3 u_CameraPosition;
// PBR texture inputs uniform int u_PointLightCount;
uniform PointLight u_PointLights;
uniform int u_SpotLightCount;
uniform SpotLight u_SpotLights;
// PBR
uniform sampler2D u_AlbedoTexture; uniform sampler2D u_AlbedoTexture;
uniform sampler2D u_NormalTexture; uniform sampler2D u_NormalTexture;
uniform sampler2D u_MetalnessTexture; uniform sampler2D u_MetalnessTexture;
uniform sampler2D u_RoughnessTexture; uniform sampler2D u_RoughnessTexture;
// Environment maps // environment
uniform samplerCube u_EnvRadianceTex; uniform samplerCube u_EnvRadianceTex;
uniform samplerCube u_EnvIrradianceTex; uniform samplerCube u_EnvIrradianceTex;
// BRDF LUT // BRDF LUT
uniform sampler2D u_BRDFLUTTexture; uniform sampler2D u_BRDFLUTTexture;
uniform float u_IBLContribution;
uniform float u_BloomThreshold;
uniform float u_EnvMapRotation;
// baseColor
uniform vec3 u_AlbedoColor; uniform vec3 u_AlbedoColor;
uniform float u_Metalness; uniform float u_Metalness;
uniform float u_Roughness; uniform float u_Roughness;
uniform float u_EnvMapRotation; // textureToggle
// Toggles
uniform float u_RadiancePrefilter;
uniform float u_AlbedoTexToggle; uniform float u_AlbedoTexToggle;
uniform float u_NormalTexToggle; uniform float u_NormalTexToggle;
uniform float u_MetalnessTexToggle; uniform float u_MetalnessTexToggle;
uniform float u_RoughnessTexToggle; uniform float u_RoughnessTexToggle;
// shadow
uniform sampler2D u_ShadowMap;
uniform float u_ShadowBias;
uniform float u_ShadowSoftness;
uniform float u_ShadowIntensity;
uniform int u_ShadowEnabled;
// Emissive
uniform sampler2D u_EmissiveTexture;
uniform float u_EmissiveTexToggle;
uniform vec3 u_EmissiveColor;
uniform float u_EmissiveIntensity;
struct PBRParameters struct PBRParameters
{ {
vec3 Albedo; vec3 Albedo;
float Roughness; float Roughness;
float Metalness; float Metalness;
vec3 Normal; vec3 Normal;
vec3 View; vec3 View;
float NdotV; float NdotV;
@ -124,39 +180,21 @@ struct PBRParameters
PBRParameters m_Params; PBRParameters m_Params;
// GGX/Towbridge-Reitz normal distribution function. // ---------- PBR param func ----------
// Uses Disney's reparametrization of alpha = roughness^2
float ndfGGX(float cosLh, float roughness) float ndfGGX(float cosLh, float roughness)
{ {
float alpha = roughness * roughness; float alpha = roughness * roughness;
float alphaSq = alpha * alpha; float alphaSq = alpha * alpha;
float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0; float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
return alphaSq / (PI * denom * denom); return alphaSq / (PI * denom * denom);
} }
// Single term for separable Schlick-GGX below.
float gaSchlickG1(float cosTheta, float k)
{
return cosTheta / (cosTheta * (1.0 - k) + k);
}
// Schlick-GGX approximation of geometric attenuation function using Smith's method.
float gaSchlickGGX(float cosLi, float NdotV, float roughness)
{
float r = roughness + 1.0;
float k = (r * r) / 8.0; // Epic suggests using this roughness remapping for analytic lights.
return gaSchlickG1(cosLi, k) * gaSchlickG1(NdotV, k);
}
float GeometrySchlickGGX(float NdotV, float roughness) float GeometrySchlickGGX(float NdotV, float roughness)
{ {
float r = (roughness + 1.0); float r = (roughness + 1.0);
float k = (r*r) / 8.0; float k = (r * r) / 8.0;
float nom = NdotV; float nom = NdotV;
float denom = NdotV * (1.0 - k) + k; float denom = NdotV * (1.0 - k) + k;
return nom / denom; return nom / denom;
} }
@ -166,11 +204,9 @@ float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
float NdotL = max(dot(N, L), 0.0); float NdotL = max(dot(N, L), 0.0);
float ggx2 = GeometrySchlickGGX(NdotV, roughness); float ggx2 = GeometrySchlickGGX(NdotV, roughness);
float ggx1 = GeometrySchlickGGX(NdotL, roughness); float ggx1 = GeometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2; return ggx1 * ggx2;
} }
// Shlick's approximation of the Fresnel factor.
vec3 fresnelSchlick(vec3 F0, float cosTheta) vec3 fresnelSchlick(vec3 F0, float cosTheta)
{ {
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
@ -181,97 +217,117 @@ vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness)
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0); return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
} }
// --------------------------------------------------------------------------------------------------- // ---------- direction light ----------
// The following code (from Unreal Engine 4's paper) shows how to filter the environment map vec3 ComputeDirectionalLight(DirectionalLight light, vec3 F0, PBRParameters params)
// for different roughnesses. This is mean to be computed offline and stored in cube map mips,
// so turning this on online will cause poor performance
float RadicalInverse_VdC(uint bits)
{ {
bits = (bits << 16u) | (bits >> 16u); vec3 L = normalize(-light.Direction);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); vec3 Lradiance = light.Radiance * light.Intensity;
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); vec3 Lh = normalize(L + params.View);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); float cosLi = max(0.0, dot(params.Normal, L));
return float(bits) * 2.3283064365386963e-10; // / 0x100000000 float cosLh = max(0.0, dot(params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
float D = ndfGGX(cosLh, params.Roughness);
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
vec3 diffuseBRDF = kd * params.Albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
} }
vec2 Hammersley(uint i, uint N) vec3 ComputePointLight(PointLight light, vec3 F0, PBRParameters params, vec3 worldPos)
{ {
return vec2(float(i)/float(N), RadicalInverse_VdC(i)); vec3 lightVec = light.Position - worldPos;
float dist = length(lightVec);
if (dist > light.Range) return vec3(0.0);
vec3 L = lightVec / dist;
vec3 Lradiance = light.Radiance * light.Intensity;
// 距离衰减:通常使用平方衰减,但为避免分母为零,加一个小值
float attenuation = 1.0 / (dist * dist + 0.0001);
// 可选:范围平滑衰减
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
rangeFactor = rangeFactor * rangeFactor; // 平滑
attenuation *= rangeFactor;
vec3 Lh = normalize(L + params.View);
float cosLi = max(0.0, dot(params.Normal, L));
float cosLh = max(0.0, dot(params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
float D = ndfGGX(cosLh, params.Roughness);
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
vec3 diffuseBRDF = kd * params.Albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
} }
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) vec3 ComputeSpotLight(SpotLight light, vec3 F0, PBRParameters params, vec3 worldPos)
{ {
float a = Roughness * Roughness; vec3 lightVec = light.Position - worldPos;
float Phi = 2 * PI * Xi.x; float dist = length(lightVec);
float CosTheta = sqrt( (1 - Xi.y) / ( 1 + (a*a - 1) * Xi.y ) ); if (dist > light.Range) return vec3(0.0);
float SinTheta = sqrt( 1 - CosTheta * CosTheta );
vec3 H; vec3 L = lightVec / dist;
H.x = SinTheta * cos( Phi ); vec3 Lradiance = light.Radiance * light.Intensity;
H.y = SinTheta * sin( Phi );
H.z = CosTheta; // 距离衰减
vec3 UpVector = abs(N.z) < 0.999 ? vec3(0,0,1) : vec3(1,0,0); float attenuation = 1.0 / (dist * dist + 0.0001);
vec3 TangentX = normalize( cross( UpVector, N ) ); float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
vec3 TangentY = cross( N, TangentX ); rangeFactor = rangeFactor * rangeFactor;
// Tangent to world space attenuation *= rangeFactor;
return TangentX * H.x + TangentY * H.y + N * H.z;
// 角度衰减(聚光锥)
float cosAngle = dot(-L, normalize(light.Direction)); // 光方向指向外,所以用 -L
if (cosAngle < light.OuterConeCos) return vec3(0.0);
float angleFalloff = (cosAngle - light.OuterConeCos) / (light.InnerConeCos - light.OuterConeCos);
angleFalloff = clamp(angleFalloff, 0.0, 1.0);
attenuation *= angleFalloff;
vec3 Lh = normalize(L + params.View);
float cosLi = max(0.0, dot(params.Normal, L));
float cosLh = max(0.0, dot(params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
float D = ndfGGX(cosLh, params.Roughness);
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
vec3 diffuseBRDF = kd * params.Albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
} }
float TotalWeight = 0.0;
vec3 PrefilterEnvMap(float Roughness, vec3 R)
{
vec3 N = R;
vec3 V = R;
vec3 PrefilteredColor = vec3(0.0);
int NumSamples = 1024;
for(int i = 0; i < NumSamples; i++)
{
vec2 Xi = Hammersley(i, NumSamples);
vec3 H = ImportanceSampleGGX(Xi, Roughness, N);
vec3 L = 2 * dot(V, H) * H - V;
float NoL = clamp(dot(N, L), 0.0, 1.0);
if (NoL > 0)
{
PrefilteredColor += texture(u_EnvRadianceTex, L).rgb * NoL;
TotalWeight += NoL;
}
}
return PrefilteredColor / TotalWeight;
}
// ---------------------------------------------------------------------------------------------------
vec3 RotateVectorAboutY(float angle, vec3 vec)
{
angle = radians(angle);
mat3x3 rotationMatrix ={vec3(cos(angle),0.0,sin(angle)),
vec3(0.0,1.0,0.0),
vec3(-sin(angle),0.0,cos(angle))};
return rotationMatrix * vec;
}
vec3 Lighting(vec3 F0) vec3 Lighting(vec3 F0)
{ {
vec3 result = vec3(0.0); vec3 result = vec3(0.0);
for(int i = 0; i < LightCount; i++) for(int i = 0; i < LightCount; i++)
{ {
vec3 Li = -lights.Direction; vec3 Li = u_DirectionalLights.Direction;
vec3 Lradiance = lights.Radiance * lights.Multiplier; vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.Intensity;
vec3 Lh = normalize(Li + m_Params.View); vec3 Lh = normalize(Li + m_Params.View);
// Calculate angles between surface normal and various light vectors.
float cosLi = max(0.0, dot(m_Params.Normal, Li)); float cosLi = max(0.0, dot(m_Params.Normal, Li));
float cosLh = max(0.0, dot(m_Params.Normal, Lh)); float cosLh = max(0.0, dot(m_Params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, m_Params.View))); vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, m_Params.View)));
float D = ndfGGX(cosLh, m_Params.Roughness); float D = ndfGGX(cosLh, m_Params.Roughness);
float G = gaSchlickGGX(cosLi, m_Params.NdotV, m_Params.Roughness); float G = GeometrySmith(m_Params.Normal, m_Params.View, Li, m_Params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness); vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
vec3 diffuseBRDF = kd * m_Params.Albedo; vec3 diffuseBRDF = kd * m_Params.Albedo;
// Cook-Torrance
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * m_Params.NdotV); vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * m_Params.NdotV);
result += (diffuseBRDF + specularBRDF) * Lradiance * cosLi; result += (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
@ -279,6 +335,18 @@ vec3 Lighting(vec3 F0)
return result; return result;
} }
// ---------- IBL ----------
vec3 RotateVectorAboutY(float angle, vec3 vec)
{
angle = radians(angle);
mat3 rotationMatrix = mat3(
vec3(cos(angle), 0.0, sin(angle)),
vec3(0.0, 1.0, 0.0),
vec3(-sin(angle), 0.0, cos(angle))
);
return rotationMatrix * vec;
}
vec3 IBL(vec3 F0, vec3 Lr) vec3 IBL(vec3 F0, vec3 Lr)
{ {
vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb; vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb;
@ -287,26 +355,98 @@ vec3 IBL(vec3 F0, vec3 Lr)
vec3 diffuseIBL = m_Params.Albedo * irradiance; vec3 diffuseIBL = m_Params.Albedo * irradiance;
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex); int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
float NoV = clamp(m_Params.NdotV, 0.0, 1.0); vec3 specularIrradiance = textureLod(
vec3 R = 2.0 * dot(m_Params.View, m_Params.Normal) * m_Params.Normal - m_Params.View; u_EnvRadianceTex,
vec3 specularIrradiance = textureLod(u_EnvRadianceTex, RotateVectorAboutY(u_EnvMapRotation, Lr), (m_Params.Roughness) * u_EnvRadianceTexLevels).rgb; RotateVectorAboutY(u_EnvMapRotation, Lr),
m_Params.Roughness * u_EnvRadianceTexLevels
).rgb;
// Sample BRDF Lut, 1.0 - roughness for y-coord because texture was generated (in Sparky) for gloss model
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg; vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg;
vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y); vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y);
return kd * diffuseIBL + specularIBL; return kd * diffuseIBL + specularIBL;
} }
// shadow
float calculateShadow(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir)
{
// Perspective divide
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
// Transform to [0,1] range
projCoords = projCoords * 0.5 + 0.5;
// If outside shadow map bounds, assume no shadow
if(projCoords.z > 1.0 || projCoords.x < 0.0 || projCoords.x > 1.0 || projCoords.y < 0.0 || projCoords.y > 1.0)
return 0.0;
// Get closest depth value from light's perspective
float closestDepth = texture(u_ShadowMap, projCoords.xy).r;
float currentDepth = projCoords.z;
// Calculate bias based on surface angle
float bias = max(u_ShadowBias * (1.0 - dot(normal, lightDir)), u_ShadowBias * 0.1);
// PCF (Percentage Closer Filtering) for soft shadows
float shadow = 0.0;
vec2 texelSize = 1.0 / textureSize(u_ShadowMap, 0);
int pcfRange = int(u_ShadowSoftness);
int sampleCount = 0;
for(int x = -pcfRange; x <= pcfRange; ++x)
{
for(int y = -pcfRange; y <= pcfRange; ++y)
{
float pcfDepth = texture(u_ShadowMap, projCoords.xy + vec2(x, y) * texelSize).r;
shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
sampleCount++;
}
}
shadow /= float(sampleCount);
return shadow;
}
float ComputeShadow(vec4 fragPosLightSpace, float NdotL)
{
if (u_ShadowEnabled == 0) return 1.0;
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
projCoords = projCoords * 0.5 + 0.5;
if (projCoords.x < 0.0 || projCoords.x > 1.0 ||
projCoords.y < 0.0 || projCoords.y > 1.0 ||
projCoords.z > 1.0) return 1.0;
float closestDepth = texture(u_ShadowMap, projCoords.xy).r;
float currentDepth = projCoords.z;
float bias = max(u_ShadowBias * (1.0 - NdotL), u_ShadowBias * 0.5);
float shadow = (currentDepth - bias) > closestDepth ? 1.0 : 0.0;
return mix(1.0, 1.0 - u_ShadowIntensity, shadow);
}
void main() void main()
{ {
// Standard PBR inputs float alpha = 1.0;
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor; if (u_AlbedoTexToggle > 0.5) {
vec4 albedoWithAlpha = texture(u_AlbedoTexture, vs_Input.TexCoord);
m_Params.Albedo = albedoWithAlpha.rgb;
alpha = albedoWithAlpha.a;
} else {
m_Params.Albedo = u_AlbedoColor;
alpha = 1.0;
}
m_Params.Metalness = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness; m_Params.Metalness = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness;
m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness; m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
m_Params.Roughness = max(m_Params.Roughness, 0.05); // Minimum roughness of 0.05 to keep specular highlight m_Params.Roughness = max(m_Params.Roughness, 0.05);
// Normals (either from vertex or map) // normal
m_Params.Normal = normalize(vs_Input.Normal); m_Params.Normal = normalize(vs_Input.Normal);
if (u_NormalTexToggle > 0.5) if (u_NormalTexToggle > 0.5)
{ {
@ -317,14 +457,40 @@ void main()
m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition); m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition);
m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0); m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0);
// Specular reflection vector
vec3 Lr = 2.0 * m_Params.NdotV * m_Params.Normal - m_Params.View; vec3 Lr = 2.0 * m_Params.NdotV * m_Params.Normal - m_Params.View;
// Fresnel reflectance, metals use albedo
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness); vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness);
vec3 lightContribution = Lighting(F0); float shadowFactor = 1.0;
vec3 iblContribution = IBL(F0, Lr); if (u_ShadowEnabled > 0.5) {
float shadow = calculateShadow(vs_Input.FragPosLightSpace, m_Params.Normal, u_DirectionalLights.Direction);
shadowFactor = 1.0 - shadow;
}
color = vec4(lightContribution + iblContribution, 1.0);
vec3 lightContribution = u_DirectionalLights.Intensity > 0.0 ? Lighting(F0) * shadowFactor : vec3(0.0);
if(u_PointLightCount > 0)
lightContribution += ComputePointLight(u_PointLights, F0, m_Params, vs_Input.WorldPosition);
if(u_SpotLightCount > 0)
lightContribution += ComputeSpotLight(u_SpotLights, F0, m_Params, vs_Input.WorldPosition);
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;
vec3 emissive = u_EmissiveColor;
if (u_EmissiveTexToggle > 0.5) {
emissive = texture(u_EmissiveTexture, vs_Input.TexCoord).rgb;
}
emissive *= u_EmissiveIntensity;
vec3 finalRGB = lightContribution + iblContribution + emissive;
vec4 finalColor = vec4(finalRGB, alpha);
color = finalColor;
// Bloom
float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
o_BloomColor = brightness > u_BloomThreshold ? color : vec4(0.0, 0.0, 0.0, 1.0);
} }

View File

@ -1,5 +1,5 @@
// ----------------------------- // -----------------------------
// -- Hazel Engine PBR shader -- // -- Based on Hazel PBR shader --
// ----------------------------- // -----------------------------
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in. // Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
// Currently heavily updated. // Currently heavily updated.
@ -19,8 +19,11 @@ layout(location = 3) in vec3 a_Binormal;
layout(location = 4) in vec2 a_TexCoord; layout(location = 4) in vec2 a_TexCoord;
uniform mat4 u_ViewProjectionMatrix; uniform mat4 u_ViewProjectionMatrix;
uniform mat4 u_ViewMatrix;
uniform mat4 u_Transform; uniform mat4 u_Transform;
uniform mat4 u_LightSpaceMatrix;
out VertexOutput out VertexOutput
{ {
vec3 WorldPosition; vec3 WorldPosition;
@ -29,6 +32,8 @@ out VertexOutput
mat3 WorldNormals; mat3 WorldNormals;
mat3 WorldTransform; mat3 WorldTransform;
vec3 Binormal; vec3 Binormal;
vec3 ViewPosition;
vec4 FragPosLightSpace;
} vs_Output; } vs_Output;
void main() void main()
@ -40,26 +45,55 @@ void main()
vs_Output.WorldTransform = mat3(u_Transform); vs_Output.WorldTransform = mat3(u_Transform);
vs_Output.Binormal = a_Binormal; vs_Output.Binormal = a_Binormal;
vs_Output.FragPosLightSpace = u_LightSpaceMatrix * u_Transform * vec4(a_Position, 1.0);
vs_Output.ViewPosition = vec3(u_ViewMatrix * vec4(vs_Output.WorldPosition, 1.0));
gl_Position = u_ViewProjectionMatrix * u_Transform * vec4(a_Position, 1.0); gl_Position = u_ViewProjectionMatrix * u_Transform * vec4(a_Position, 1.0);
} }
#type fragment #type fragment
#version 430 core #version 430 core
layout(location = 0) out vec4 outAlbedoMetal;
layout(location = 1) out vec4 outNormalRoughness;
layout(location = 2) out vec4 outEmissiveAO;
layout(location = 3) out vec4 outColor;
layout(location = 4) out vec4 outBloomColor;
const float PI = 3.141592; const float PI = 3.141592;
const float Epsilon = 0.00001; const float Epsilon = 0.00001;
const int LightCount = 1; const int LightCount = 1;
// Constant normal incidence Fresnel factor for all dielectrics.
const vec3 Fdielectric = vec3(0.04); const vec3 Fdielectric = vec3(0.04);
struct Light { struct DirectionalLight {
vec3 Direction; vec3 Direction;
vec3 Radiance; vec3 Radiance;
float Multiplier; float Intensity;
bool CastShadows;
}; };
struct PointLight {
vec3 Position;
vec3 Radiance;
float Intensity;
float Range;
bool CastShadows;
};
struct SpotLight {
vec3 Position;
vec3 Direction;
vec3 Radiance;
float Intensity;
float Range;
float InnerConeCos;
float OuterConeCos;
bool CastShadows;
};
in VertexOutput in VertexOutput
{ {
vec3 WorldPosition; vec3 WorldPosition;
@ -68,45 +102,70 @@ in VertexOutput
mat3 WorldNormals; mat3 WorldNormals;
mat3 WorldTransform; mat3 WorldTransform;
vec3 Binormal; vec3 Binormal;
vec3 ViewPosition;
vec4 FragPosLightSpace;
} vs_Input; } vs_Input;
layout(location = 0) out vec4 color;
uniform Light lights; uniform bool u_GBufferMode;
uniform DirectionalLight u_DirectionalLights;
uniform int u_PointLightCount;
uniform PointLight u_PointLights;
uniform int u_SpotLightCount;
uniform SpotLight u_SpotLights;
uniform vec3 u_CameraPosition; uniform vec3 u_CameraPosition;
// PBR texture inputs // PBR
uniform sampler2D u_AlbedoTexture; uniform sampler2D u_AlbedoTexture;
uniform sampler2D u_NormalTexture; uniform sampler2D u_NormalTexture;
uniform sampler2D u_MetalnessTexture; uniform sampler2D u_MetalnessTexture;
uniform sampler2D u_RoughnessTexture; uniform sampler2D u_RoughnessTexture;
// Environment maps // environment
uniform samplerCube u_EnvRadianceTex; uniform samplerCube u_EnvRadianceTex;
uniform samplerCube u_EnvIrradianceTex; uniform samplerCube u_EnvIrradianceTex;
// BRDF LUT // BRDF LUT
uniform sampler2D u_BRDFLUTTexture; uniform sampler2D u_BRDFLUTTexture;
uniform float u_IBLContribution;
uniform float u_BloomThreshold;
uniform float u_EnvMapRotation;
// baseColor
uniform vec3 u_AlbedoColor; uniform vec3 u_AlbedoColor;
uniform float u_Metalness; uniform float u_Metalness;
uniform float u_Roughness; uniform float u_Roughness;
uniform float u_EnvMapRotation; // textureToggle
// Toggles
uniform float u_RadiancePrefilter;
uniform float u_AlbedoTexToggle; uniform float u_AlbedoTexToggle;
uniform float u_NormalTexToggle; uniform float u_NormalTexToggle;
uniform float u_MetalnessTexToggle; uniform float u_MetalnessTexToggle;
uniform float u_RoughnessTexToggle; uniform float u_RoughnessTexToggle;
// shadow
uniform sampler2D u_ShadowMap;
uniform float u_ShadowBias;
uniform float u_ShadowSoftness;
uniform float u_ShadowIntensity;
uniform int u_ShadowEnabled;
// Emissive
uniform sampler2D u_EmissiveTexture;
uniform float u_EmissiveTexToggle;
uniform vec3 u_EmissiveColor;
uniform float u_EmissiveIntensity;
struct PBRParameters struct PBRParameters
{ {
vec3 Albedo; vec3 Albedo;
float Roughness; float Roughness;
float Metalness; float Metalness;
vec3 Normal; vec3 Normal;
vec3 View; vec3 View;
float NdotV; float NdotV;
@ -114,39 +173,21 @@ struct PBRParameters
PBRParameters m_Params; PBRParameters m_Params;
// GGX/Towbridge-Reitz normal distribution function. // ---------- PBR param func ----------
// Uses Disney's reparametrization of alpha = roughness^2
float ndfGGX(float cosLh, float roughness) float ndfGGX(float cosLh, float roughness)
{ {
float alpha = roughness * roughness; float alpha = roughness * roughness;
float alphaSq = alpha * alpha; float alphaSq = alpha * alpha;
float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0; float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
return alphaSq / (PI * denom * denom); return alphaSq / (PI * denom * denom);
} }
// Single term for separable Schlick-GGX below.
float gaSchlickG1(float cosTheta, float k)
{
return cosTheta / (cosTheta * (1.0 - k) + k);
}
// Schlick-GGX approximation of geometric attenuation function using Smith's method.
float gaSchlickGGX(float cosLi, float NdotV, float roughness)
{
float r = roughness + 1.0;
float k = (r * r) / 8.0; // Epic suggests using this roughness remapping for analytic lights.
return gaSchlickG1(cosLi, k) * gaSchlickG1(NdotV, k);
}
float GeometrySchlickGGX(float NdotV, float roughness) float GeometrySchlickGGX(float NdotV, float roughness)
{ {
float r = (roughness + 1.0); float r = (roughness + 1.0);
float k = (r*r) / 8.0; float k = (r * r) / 8.0;
float nom = NdotV; float nom = NdotV;
float denom = NdotV * (1.0 - k) + k; float denom = NdotV * (1.0 - k) + k;
return nom / denom; return nom / denom;
} }
@ -156,11 +197,9 @@ float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
float NdotL = max(dot(N, L), 0.0); float NdotL = max(dot(N, L), 0.0);
float ggx2 = GeometrySchlickGGX(NdotV, roughness); float ggx2 = GeometrySchlickGGX(NdotV, roughness);
float ggx1 = GeometrySchlickGGX(NdotL, roughness); float ggx1 = GeometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2; return ggx1 * ggx2;
} }
// Shlick's approximation of the Fresnel factor.
vec3 fresnelSchlick(vec3 F0, float cosTheta) vec3 fresnelSchlick(vec3 F0, float cosTheta)
{ {
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
@ -171,74 +210,94 @@ vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness)
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0); return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
} }
// --------------------------------------------------------------------------------------------------- // ---------- direction light ----------
// The following code (from Unreal Engine 4's paper) shows how to filter the environment map vec3 ComputeDirectionalLight(DirectionalLight light, vec3 F0, PBRParameters params)
// for different roughnesses. This is mean to be computed offline and stored in cube map mips,
// so turning this on online will cause poor performance
float RadicalInverse_VdC(uint bits)
{ {
bits = (bits << 16u) | (bits >> 16u); vec3 L = normalize(-light.Direction);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); vec3 Lradiance = light.Radiance * light.Intensity;
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); vec3 Lh = normalize(L + params.View);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); float cosLi = max(0.0, dot(params.Normal, L));
return float(bits) * 2.3283064365386963e-10; // / 0x100000000 float cosLh = max(0.0, dot(params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
float D = ndfGGX(cosLh, params.Roughness);
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
vec3 diffuseBRDF = kd * params.Albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
} }
vec2 Hammersley(uint i, uint N) vec3 ComputePointLight(PointLight light, vec3 F0, PBRParameters params, vec3 worldPos)
{ {
return vec2(float(i)/float(N), RadicalInverse_VdC(i)); vec3 lightVec = light.Position - worldPos;
float dist = length(lightVec);
if (dist > light.Range) return vec3(0.0);
vec3 L = lightVec / dist;
vec3 Lradiance = light.Radiance * light.Intensity;
// 距离衰减:通常使用平方衰减,但为避免分母为零,加一个小值
float attenuation = 1.0 / (dist * dist + 0.0001);
// 可选:范围平滑衰减
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
rangeFactor = rangeFactor * rangeFactor; // 平滑
attenuation *= rangeFactor;
vec3 Lh = normalize(L + params.View);
float cosLi = max(0.0, dot(params.Normal, L));
float cosLh = max(0.0, dot(params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
float D = ndfGGX(cosLh, params.Roughness);
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
vec3 diffuseBRDF = kd * params.Albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
} }
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) vec3 ComputeSpotLight(SpotLight light, vec3 F0, PBRParameters params, vec3 worldPos)
{ {
float a = Roughness * Roughness; vec3 lightVec = light.Position - worldPos;
float Phi = 2 * PI * Xi.x; float dist = length(lightVec);
float CosTheta = sqrt( (1 - Xi.y) / ( 1 + (a*a - 1) * Xi.y ) ); if (dist > light.Range) return vec3(0.0);
float SinTheta = sqrt( 1 - CosTheta * CosTheta );
vec3 H;
H.x = SinTheta * cos( Phi );
H.y = SinTheta * sin( Phi );
H.z = CosTheta;
vec3 UpVector = abs(N.z) < 0.999 ? vec3(0,0,1) : vec3(1,0,0);
vec3 TangentX = normalize( cross( UpVector, N ) );
vec3 TangentY = cross( N, TangentX );
// Tangent to world space
return TangentX * H.x + TangentY * H.y + N * H.z;
}
float TotalWeight = 0.0; vec3 L = lightVec / dist;
vec3 Lradiance = light.Radiance * light.Intensity;
vec3 PrefilterEnvMap(float Roughness, vec3 R) // 距离衰减
{ float attenuation = 1.0 / (dist * dist + 0.0001);
vec3 N = R; float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
vec3 V = R; rangeFactor = rangeFactor * rangeFactor;
vec3 PrefilteredColor = vec3(0.0); attenuation *= rangeFactor;
int NumSamples = 1024;
for(int i = 0; i < NumSamples; i++)
{
vec2 Xi = Hammersley(i, NumSamples);
vec3 H = ImportanceSampleGGX(Xi, Roughness, N);
vec3 L = 2 * dot(V, H) * H - V;
float NoL = clamp(dot(N, L), 0.0, 1.0);
if (NoL > 0)
{
PrefilteredColor += texture(u_EnvRadianceTex, L).rgb * NoL;
TotalWeight += NoL;
}
}
return PrefilteredColor / TotalWeight;
}
// --------------------------------------------------------------------------------------------------- // 角度衰减(聚光锥)
float cosAngle = dot(-L, normalize(light.Direction)); // 光方向指向外,所以用 -L
if (cosAngle < light.OuterConeCos) return vec3(0.0);
float angleFalloff = (cosAngle - light.OuterConeCos) / (light.InnerConeCos - light.OuterConeCos);
angleFalloff = clamp(angleFalloff, 0.0, 1.0);
attenuation *= angleFalloff;
vec3 RotateVectorAboutY(float angle, vec3 vec) vec3 Lh = normalize(L + params.View);
{ float cosLi = max(0.0, dot(params.Normal, L));
angle = radians(angle); float cosLh = max(0.0, dot(params.Normal, Lh));
mat3x3 rotationMatrix ={vec3(cos(angle),0.0,sin(angle)),
vec3(0.0,1.0,0.0), vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
vec3(-sin(angle),0.0,cos(angle))}; float D = ndfGGX(cosLh, params.Roughness);
return rotationMatrix * vec; float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
vec3 diffuseBRDF = kd * params.Albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
} }
vec3 Lighting(vec3 F0) vec3 Lighting(vec3 F0)
@ -246,22 +305,20 @@ vec3 Lighting(vec3 F0)
vec3 result = vec3(0.0); vec3 result = vec3(0.0);
for(int i = 0; i < LightCount; i++) for(int i = 0; i < LightCount; i++)
{ {
vec3 Li = -lights.Direction; vec3 Li = u_DirectionalLights.Direction;
vec3 Lradiance = lights.Radiance * lights.Multiplier; vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.Intensity;
vec3 Lh = normalize(Li + m_Params.View); vec3 Lh = normalize(Li + m_Params.View);
// Calculate angles between surface normal and various light vectors.
float cosLi = max(0.0, dot(m_Params.Normal, Li)); float cosLi = max(0.0, dot(m_Params.Normal, Li));
float cosLh = max(0.0, dot(m_Params.Normal, Lh)); float cosLh = max(0.0, dot(m_Params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, m_Params.View))); vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, m_Params.View)));
float D = ndfGGX(cosLh, m_Params.Roughness); float D = ndfGGX(cosLh, m_Params.Roughness);
float G = gaSchlickGGX(cosLi, m_Params.NdotV, m_Params.Roughness); float G = GeometrySmith(m_Params.Normal, m_Params.View, Li, m_Params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness); vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
vec3 diffuseBRDF = kd * m_Params.Albedo; vec3 diffuseBRDF = kd * m_Params.Albedo;
// Cook-Torrance
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * m_Params.NdotV); vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * m_Params.NdotV);
result += (diffuseBRDF + specularBRDF) * Lradiance * cosLi; result += (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
@ -269,54 +326,172 @@ vec3 Lighting(vec3 F0)
return result; return result;
} }
// ---------- IBL ----------
vec3 RotateVectorAboutY(float angle, vec3 vec)
{
angle = radians(angle);
mat3 rotationMatrix = mat3(
vec3(cos(angle), 0.0, sin(angle)),
vec3(0.0, 1.0, 0.0),
vec3(-sin(angle), 0.0, cos(angle))
);
return rotationMatrix * vec;
}
vec3 IBL(vec3 F0, vec3 Lr) vec3 IBL(vec3 F0, vec3 Lr)
{ {
vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb; vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb;
vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness); vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness);
// vec3 F = fresnelSchlickR(F0, m_Params.NdotV);
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness); vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
vec3 diffuseIBL = m_Params.Albedo * irradiance; vec3 diffuseIBL = m_Params.Albedo * irradiance;
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex); int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
float NoV = clamp(m_Params.NdotV, 0.0, 1.0); vec3 specularIrradiance = textureLod(
vec3 R = 2.0 * dot(m_Params.View, m_Params.Normal) * m_Params.Normal - m_Params.View; u_EnvRadianceTex,
vec3 specularIrradiance = textureLod(u_EnvRadianceTex, RotateVectorAboutY(u_EnvMapRotation, Lr), (m_Params.Roughness) * u_EnvRadianceTexLevels).rgb; RotateVectorAboutY(u_EnvMapRotation, Lr),
m_Params.Roughness * u_EnvRadianceTexLevels
).rgb;
// Sample BRDF Lut, 1.0 - roughness for y-coord because texture was generated (in Sparky) for gloss model
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg; vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg;
vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y); vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y);
return kd * diffuseIBL + specularIBL; return kd * diffuseIBL + specularIBL;
} }
// shadow
float calculateShadow(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir)
{
// Perspective divide
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
// Transform to [0,1] range
projCoords = projCoords * 0.5 + 0.5;
// If outside shadow map bounds, assume no shadow
if(projCoords.z > 1.0 || projCoords.x < 0.0 || projCoords.x > 1.0 || projCoords.y < 0.0 || projCoords.y > 1.0)
return 0.0;
// Get closest depth value from light's perspective
float closestDepth = texture(u_ShadowMap, projCoords.xy).r;
float currentDepth = projCoords.z;
// Calculate bias based on surface angle
float bias = max(u_ShadowBias * (1.0 - dot(normal, lightDir)), u_ShadowBias * 0.1);
// PCF (Percentage Closer Filtering) for soft shadows
float shadow = 0.0;
vec2 texelSize = 1.0 / textureSize(u_ShadowMap, 0);
int pcfRange = int(u_ShadowSoftness);
int sampleCount = 0;
for(int x = -pcfRange; x <= pcfRange; ++x)
{
for(int y = -pcfRange; y <= pcfRange; ++y)
{
float pcfDepth = texture(u_ShadowMap, projCoords.xy + vec2(x, y) * texelSize).r;
shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
sampleCount++;
}
}
shadow /= float(sampleCount);
return shadow;
}
float ComputeShadow(vec4 fragPosLightSpace, float NdotL)
{
if (u_ShadowEnabled == 0) return 1.0;
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
projCoords = projCoords * 0.5 + 0.5;
if (projCoords.x < 0.0 || projCoords.x > 1.0 ||
projCoords.y < 0.0 || projCoords.y > 1.0 ||
projCoords.z > 1.0) return 1.0;
float closestDepth = texture(u_ShadowMap, projCoords.xy).r;
float currentDepth = projCoords.z;
float bias = max(u_ShadowBias * (1.0 - NdotL), u_ShadowBias * 0.5);
float shadow = (currentDepth - bias) > closestDepth ? 1.0 : 0.0;
return mix(1.0, 1.0 - u_ShadowIntensity, shadow);
}
void main() void main()
{ {
// Standard PBR inputs // === 1. 采样基础属性(所有模式都需要) ===
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor; vec4 albedoWithAlpha = texture(u_AlbedoTexture, vs_Input.TexCoord);
m_Params.Metalness = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness; vec3 albedo = u_AlbedoTexToggle > 0.5 ? albedoWithAlpha.rgb : u_AlbedoColor;
m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness; float alpha = u_AlbedoTexToggle > 0.5 ? albedoWithAlpha.a : 1.0;
m_Params.Roughness = max(m_Params.Roughness, 0.05); // Minimum roughness of 0.05 to keep specular highlight
// Normals (either from vertex or map) float metallic = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness;
m_Params.Normal = normalize(vs_Input.Normal); float roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
roughness = max(roughness, 0.05);
// === 2. 法线计算(世界空间) ===
vec3 normal = normalize(vs_Input.Normal);
if (u_NormalTexToggle > 0.5) if (u_NormalTexToggle > 0.5)
{ {
m_Params.Normal = normalize(2.0 * texture(u_NormalTexture, vs_Input.TexCoord).rgb - 1.0); vec3 tangentNormal = texture(u_NormalTexture, vs_Input.TexCoord).rgb * 2.0 - 1.0;
m_Params.Normal = normalize(vs_Input.WorldNormals * m_Params.Normal); normal = normalize(vs_Input.WorldNormals * tangentNormal);
} }
// === 3. 自发光计算 ===
vec3 emissive = u_EmissiveColor;
if (u_EmissiveTexToggle > 0.5)
emissive = texture(u_EmissiveTexture, vs_Input.TexCoord).rgb;
emissive *= u_EmissiveIntensity;
// === 4. GBuffer 模式:直接输出到多个目标 ===
if (u_GBufferMode)
{
outAlbedoMetal = vec4(albedo, metallic);
outNormalRoughness = vec4(normal * 0.5 + 0.5, roughness);
outEmissiveAO = vec4(emissive, 1.0); // AO 暂设为 1.0
return; // 提前结束
}
// === 5. 非 GBuffer 模式:继续 PBR 光照计算 ===
// 填充 PBRParameters
m_Params.Albedo = albedo;
m_Params.Metalness = metallic;
m_Params.Roughness = roughness;
m_Params.Normal = normal;
m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition); m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition);
m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0); m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0);
// Specular reflection vector
vec3 Lr = 2.0 * m_Params.NdotV * m_Params.Normal - m_Params.View; vec3 Lr = 2.0 * m_Params.NdotV * m_Params.Normal - m_Params.View;
// Fresnel reflectance, metals use albedo
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness); vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness);
vec3 lightContribution = Lighting(F0); // Shadow
vec3 iblContribution = IBL(F0, Lr); float shadowFactor = 1.0;
if (u_ShadowEnabled > 0.5) {
float shadow = calculateShadow(vs_Input.FragPosLightSpace, m_Params.Normal, u_DirectionalLights.Direction);
shadowFactor = 1.0 - shadow;
}
color = vec4(lightContribution + iblContribution, 1.0); // directional light with with shadow
// color = vec4(iblContribution, 1.0); vec3 lightContribution = u_DirectionalLights.Intensity > 0.0 ? Lighting(F0) * shadowFactor : vec3(0.0);
if(u_PointLightCount > 0)
lightContribution += ComputePointLight(u_PointLights, F0, m_Params, vs_Input.WorldPosition);
if(u_SpotLightCount > 0)
lightContribution += ComputeSpotLight(u_SpotLights, F0, m_Params, vs_Input.WorldPosition);
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;
vec3 finalRGB = lightContribution + iblContribution + emissive;
vec4 finalColor = vec4(finalRGB, alpha);
outColor = finalColor;
// Bloom
float brightness = dot(finalColor.rgb, vec3(0.2126, 0.7152, 0.0722));
outBloomColor = brightness > u_BloomThreshold ? finalColor : vec4(0.0, 0.0, 0.0, 1.0);
} }

View File

@ -0,0 +1,159 @@
#type compute
#version 450 core
const float PI = 3.141592;
layout(binding = 0, rgba32f) restrict writeonly uniform imageCube o_CubeMap;
uniform vec3 u_TurbidityAzimuthInclination;
#define PI 3.14159265359
vec3 GetCubeMapTexCoord()
{
vec2 st = gl_GlobalInvocationID.xy / vec2(imageSize(o_CubeMap));
vec2 uv = 2.0 * vec2(st.x, 1.0 - st.y) - vec2(1.0);
vec3 ret;
if (gl_GlobalInvocationID.z == 0) ret = vec3( 1.0, uv.y, -uv.x);
else if (gl_GlobalInvocationID.z == 1) ret = vec3( -1.0, uv.y, uv.x);
else if (gl_GlobalInvocationID.z == 2) ret = vec3( uv.x, 1.0, -uv.y);
else if (gl_GlobalInvocationID.z == 3) ret = vec3( uv.x, -1.0, uv.y);
else if (gl_GlobalInvocationID.z == 4) ret = vec3( uv.x, uv.y, 1.0);
else if (gl_GlobalInvocationID.z == 5) ret = vec3(-uv.x, uv.y, -1.0);
return normalize(ret);
}
float saturatedDot( in vec3 a, in vec3 b )
{
return clamp(dot(a, b), 0.0, 1.0);
}
vec3 YxyToXYZ( in vec3 Yxy )
{
float Y = Yxy.r;
float x = Yxy.g;
float y = Yxy.b;
float X = x * ( Y / y );
float Z = ( 1.0 - x - y ) * ( Y / y );
return vec3(X,Y,Z);
}
vec3 XYZToRGB( in vec3 XYZ )
{
// CIE/E
mat3 M = mat3
(
2.3706743, -0.9000405, -0.4706338,
-0.5138850, 1.4253036, 0.0885814,
0.0052982, -0.0146949, 1.0093968
);
return XYZ * M;
}
vec3 YxyToRGB( in vec3 Yxy )
{
vec3 XYZ = YxyToXYZ( Yxy );
vec3 RGB = XYZToRGB( XYZ );
return RGB;
}
void calculatePerezDistribution( in float t, out vec3 A, out vec3 B, out vec3 C, out vec3 D, out vec3 E )
{
A = vec3( 0.1787 * t - 1.4630, -0.0193 * t - 0.2592, -0.0167 * t - 0.2608 );
B = vec3( -0.3554 * t + 0.4275, -0.0665 * t + 0.0008, -0.0950 * t + 0.0092 );
C = vec3( -0.0227 * t + 5.3251, -0.0004 * t + 0.2125, -0.0079 * t + 0.2102 );
D = vec3( 0.1206 * t - 2.5771, -0.0641 * t - 0.8989, -0.0441 * t - 1.6537 );
E = vec3( -0.0670 * t + 0.3703, -0.0033 * t + 0.0452, -0.0109 * t + 0.0529 );
}
vec3 calculateZenithLuminanceYxy( in float t, in float thetaS )
{
float chi = ( 4.0 / 9.0 - t / 120.0 ) * ( PI - 2.0 * thetaS );
float Yz = ( 4.0453 * t - 4.9710 ) * tan( chi ) - 0.2155 * t + 2.4192;
float theta2 = thetaS * thetaS;
float theta3 = theta2 * thetaS;
float T = t;
float T2 = t * t;
float xz =
( 0.00165 * theta3 - 0.00375 * theta2 + 0.00209 * thetaS + 0.0) * T2 +
(-0.02903 * theta3 + 0.06377 * theta2 - 0.03202 * thetaS + 0.00394) * T +
( 0.11693 * theta3 - 0.21196 * theta2 + 0.06052 * thetaS + 0.25886);
float yz =
( 0.00275 * theta3 - 0.00610 * theta2 + 0.00317 * thetaS + 0.0) * T2 +
(-0.04214 * theta3 + 0.08970 * theta2 - 0.04153 * thetaS + 0.00516) * T +
( 0.15346 * theta3 - 0.26756 * theta2 + 0.06670 * thetaS + 0.26688);
return vec3( Yz, xz, yz );
}
vec3 calculatePerezLuminanceYxy( in float theta, in float gamma, in vec3 A, in vec3 B, in vec3 C, in vec3 D, in vec3 E )
{
float cosTheta = max(cos(theta), 1e-6);
return ( 1.0 + A * exp( B / cos( theta ) ) ) * ( 1.0 + C * exp( D * gamma ) + E * cos( gamma ) * cos( gamma ) );
}
vec3 calculateSkyLuminanceRGB( in vec3 s, in vec3 e, in float t )
{
vec3 A, B, C, D, E;
calculatePerezDistribution( t, A, B, C, D, E );
float thetaS = acos(clamp(dot(s, vec3(0,1,0)), 0.0, 1.0));
float thetaE = acos(clamp(dot(e, vec3(0,1,0)), 0.0, 1.0));
float gammaE = acos( saturatedDot( s, e ) );
vec3 Yz = calculateZenithLuminanceYxy( t, thetaS );
vec3 fThetaGamma = calculatePerezLuminanceYxy( thetaE, gammaE, A, B, C, D, E );
vec3 fZeroThetaS = calculatePerezLuminanceYxy( 0.0, thetaS, A, B, C, D, E );
vec3 Yp = Yz * ( fThetaGamma / fZeroThetaS );
return YxyToRGB( Yp );
}
layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in;
void main()
{
vec3 cubeTC = GetCubeMapTexCoord();
float turbidity = u_TurbidityAzimuthInclination.x;
float azimuth = u_TurbidityAzimuthInclination.y;;
float inclination = u_TurbidityAzimuthInclination.z;
vec3 sunDir = normalize( vec3( sin(inclination) * cos(azimuth), cos(inclination), sin(inclination) * sin(azimuth) ) );
vec3 viewDir = cubeTC;
const float SUN_ANGULAR_RADIUS = 0.03465;
const float SUN_INTENSITY = 100.0;
vec3 skyLuminance;
if (viewDir.y < 0.0) {
skyLuminance = vec3(0.02);
} else {
skyLuminance = calculateSkyLuminanceRGB(sunDir, viewDir, turbidity);
}
float cosAngle = dot(viewDir, sunDir);
float angle = acos(cosAngle);
if (angle < SUN_ANGULAR_RADIUS) {
skyLuminance = vec3(SUN_INTENSITY);
} else {
float haloWidth = 0.1;
if (angle < SUN_ANGULAR_RADIUS + haloWidth) {
float t = (angle - SUN_ANGULAR_RADIUS) / haloWidth;
float haloFactor = 1.0 - smoothstep(0.0, 1.0, t);
skyLuminance += vec3(SUN_INTENSITY * 0.1 * haloFactor);
}
}
vec4 color = vec4(skyLuminance * 0.05, 1.0);
imageStore(o_CubeMap, ivec3(gl_GlobalInvocationID), color);
}

View File

@ -6,14 +6,14 @@
layout(location = 0) in vec3 a_Position; layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec4 a_Color; layout(location = 1) in vec4 a_Color;
layout(location = 2) in vec2 a_TexCoord; layout(location = 2) in vec2 a_TexCoord;
layout(location = 3) in float a_TexIndex; layout(location = 3) in int a_TexIndex;
layout(location = 4) in float a_TilingFactor; layout(location = 4) in float a_TilingFactor;
uniform mat4 u_ViewProjection; uniform mat4 u_ViewProjection;
out vec4 v_Color; out vec4 v_Color;
out vec2 v_TexCoord; out vec2 v_TexCoord;
out float v_TexIndex; flat out int v_TexIndex;
out float v_TilingFactor; out float v_TilingFactor;
void main() void main()
@ -32,12 +32,17 @@ layout(location = 0) out vec4 color;
in vec4 v_Color; in vec4 v_Color;
in vec2 v_TexCoord; in vec2 v_TexCoord;
in float v_TexIndex; flat in int v_TexIndex;
in float v_TilingFactor; in float v_TilingFactor;
uniform sampler2D u_Textures[32]; uniform sampler2D u_Textures[32];
void main() void main()
{ {
color = texture(u_Textures[int(v_TexIndex)], v_TexCoord * v_TilingFactor) * v_Color; vec4 texColor = texture(u_Textures[v_TexIndex], v_TexCoord * v_TilingFactor) * v_Color;
if(texColor.a < 0.1)
discard;
color = texColor;
} }

View File

@ -0,0 +1,44 @@
// Basic Texture Shader
#type vertex
#version 430 core
layout(location = 0) in vec3 a_WorldPosition;
layout(location = 1) in float a_Thickness;
layout(location = 2) in vec2 a_LocalPosition;
layout(location = 3) in vec4 a_Color;
uniform mat4 u_ViewProjection;
out vec2 v_LocalPosition;
out float v_Thickness;
out vec4 v_Color;
void main()
{
v_LocalPosition = a_LocalPosition;
v_Thickness = a_Thickness;
v_Color = a_Color;
gl_Position = u_ViewProjection * vec4(a_WorldPosition, 1.0);
}
#type fragment
#version 430 core
layout(location = 0) out vec4 color;
in vec2 v_LocalPosition;
in float v_Thickness;
in vec4 v_Color;
void main()
{
float fade = 0.01;
float dist = sqrt(dot(v_LocalPosition, v_LocalPosition));
if (dist > 1.0 || dist < 1.0 - v_Thickness - fade)
discard;
float alpha = 1.0 - smoothstep(1.0f - fade, 1.0f, dist);
alpha *= smoothstep(1.0 - v_Thickness - fade, 1.0 - v_Thickness, dist);
color = v_Color;
color.a = alpha;
}

View File

@ -20,38 +20,46 @@ layout(location = 0) out vec4 o_Color;
in vec2 v_TexCoord; in vec2 v_TexCoord;
uniform sampler2DMS u_Texture; uniform sampler2D u_HDRTexture; // 来自 LightingPass 的 HDR 颜色
uniform float u_Exposure; uniform sampler2D u_BloomTexture; // 来自 BloomBlendPass 的 Bloom 纹理
uniform int u_TextureSamples;
vec4 MultiSampleTexture(sampler2DMS tex, ivec2 texCoord, int samples) uniform bool u_EnableAutoExposure;
uniform float u_ManualExposure;
layout(std430, binding = 2) buffer Exposure
{ {
vec4 result = vec4(0.0); float u_Exposure;
for (int i = 0; i < samples; i++) };
result += texelFetch(tex, texCoord, i);
result /= float(samples); uniform bool u_EnableBloom;
return result;
} const float gamma = 2.2;
const float pureWhite = 1.0;
void main() void main()
{ {
const float gamma = 2.2; // 采样 HDR 颜色(单样本)
const float pureWhite = 1.0; vec3 color = texture(u_HDRTexture, v_TexCoord).rgb;
ivec2 texSize = textureSize(u_Texture); // 混合 Bloom如果启用
ivec2 texCoord = ivec2(v_TexCoord * texSize); if (u_EnableBloom)
vec4 msColor = MultiSampleTexture(u_Texture, texCoord, u_TextureSamples); {
vec3 color = msColor.rgb * u_Exposure;//texture(u_Texture, v_TexCoord).rgb * u_Exposure; vec3 bloomColor = texture(u_BloomTexture, v_TexCoord).rgb;
color += bloomColor; // 在 HDR 空间混合
}
// Reinhard tonemapping operator. // 应用曝光
// see: "Photographic Tone Reproduction for Digital Images", eq. 4 if (u_EnableAutoExposure)
color *= u_Exposure;
else
color *= u_ManualExposure;
// Reinhard 色调映射
float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722)); float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
float mappedLuminance = (luminance * (1.0 + luminance / (pureWhite * pureWhite))) / (1.0 + luminance); float mappedLuminance = (luminance * (1.0 + luminance / (pureWhite * pureWhite))) / (1.0 + luminance);
// Scale color by ratio of average luminances. // 按亮度比例缩放颜色
vec3 mappedColor = (mappedLuminance / luminance) * color; vec3 mappedColor = (mappedLuminance / luminance) * color;
// Gamma correction. // Gamma 校正
o_Color = vec4(pow(mappedColor, vec3(1.0 / gamma)), 1.0); o_Color = vec4(pow(mappedColor, vec3(1.0 / gamma)), 1.0);
} }

View File

@ -0,0 +1,23 @@
// Shadow Map shader
#type vertex
#version 430
layout(location = 0) in vec3 a_Position;
uniform mat4 u_LightViewProjection;
uniform mat4 u_Transform;
void main()
{
gl_Position = u_LightViewProjection * u_Transform * vec4(a_Position, 1.0);
}
#type fragment
#version 430
layout(location = 0) out vec4 o_Color;
void main()
{
}

View File

@ -0,0 +1,35 @@
// Shadow Map shader
#type vertex
#version 430
layout(location = 0) in vec3 a_Position;
layout(location = 5) in ivec4 a_BoneIndices;
layout(location = 6) in vec4 a_BoneWeights;
uniform mat4 u_LightViewProjection;
uniform mat4 u_Transform;
const int MAX_BONES = 100;
uniform mat4 u_BoneTransforms[100];
void main()
{
mat4 boneTransform = u_BoneTransforms[a_BoneIndices[0]] * a_BoneWeights[0];
boneTransform += u_BoneTransforms[a_BoneIndices[1]] * a_BoneWeights[1];
boneTransform += u_BoneTransforms[a_BoneIndices[2]] * a_BoneWeights[2];
boneTransform += u_BoneTransforms[a_BoneIndices[3]] * a_BoneWeights[3];
vec4 localPosition = boneTransform * vec4(a_Position, 1.0);
gl_Position = u_LightViewProjection * u_Transform * localPosition;
}
#type fragment
#version 430
layout(location = 0) out vec4 o_Color;
void main()
{
}

View File

@ -24,10 +24,13 @@ layout(location = 0) out vec4 finalColor;
uniform samplerCube u_Texture; uniform samplerCube u_Texture;
uniform float u_TextureLod; uniform float u_TextureLod;
uniform float u_SkyIntensity;
in vec3 v_Position; in vec3 v_Position;
void main() void main()
{ {
finalColor = textureLod(u_Texture, v_Position, u_TextureLod); vec3 color = textureLod(u_Texture, v_Position, u_TextureLod).rgb * u_SkyIntensity;
finalColor = vec4(color, 1.0);
} }

102
Editor/imgui.ini Normal file
View File

@ -0,0 +1,102 @@
[Window][DockSpace Demo]
Pos=0,0
Size=2560,1566
Collapsed=0
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][Scene Hierarchy]
Pos=2089,24
Size=471,563
Collapsed=0
DockId=0x00000009,0
[Window][Properties]
Pos=2089,589
Size=471,977
Collapsed=0
DockId=0x0000000A,0
[Window][Scene Renderer]
Pos=0,843
Size=481,723
Collapsed=0
DockId=0x00000006,0
[Window][Materials]
Pos=0,24
Size=481,817
Collapsed=0
DockId=0x00000005,0
[Window][Script Engine Debug]
Pos=2089,589
Size=471,977
Collapsed=0
DockId=0x0000000A,2
[Window][Model]
Pos=1595,454
Size=471,744
Collapsed=0
DockId=0x0000000A,3
[Window][Toolbar]
Pos=483,24
Size=1110,32
Collapsed=0
DockId=0x00000001,0
[Window][Viewport]
Pos=483,58
Size=1604,955
Collapsed=0
DockId=0x0000000B,0
[Window][Environment]
Pos=2089,589
Size=471,977
Collapsed=0
DockId=0x0000000A,1
[Window][Project]
Pos=483,1015
Size=1604,551
Collapsed=0
DockId=0x0000000C,0
[Window][Objects]
Pos=483,1015
Size=1604,551
Collapsed=0
DockId=0x0000000C,1
[Window][Physics]
Pos=189,113
Size=468,371
Collapsed=0
[Window][##tool_bar]
Pos=483,24
Size=1604,32
Collapsed=0
DockId=0x00000001,0
[Docking][Data]
DockSpace ID=0xC0DFADC4 Window=0xD0388BC8 Pos=0,58 Size=2560,1542 Split=X Selected=0x0C01D6D5
DockNode ID=0x00000007 Parent=0xC0DFADC4 SizeRef=1557,1542 Split=X
DockNode ID=0x00000003 Parent=0x00000007 SizeRef=481,1542 Split=Y Selected=0x5D711C2C
DockNode ID=0x00000005 Parent=0x00000003 SizeRef=481,817 Selected=0x5D711C2C
DockNode ID=0x00000006 Parent=0x00000003 SizeRef=481,723 Selected=0x68D924E0
DockNode ID=0x00000004 Parent=0x00000007 SizeRef=1074,1542 Split=Y
DockNode ID=0x00000001 Parent=0x00000004 SizeRef=2560,32 CentralNode=1 HiddenTabBar=1 Selected=0xE8CD5B84
DockNode ID=0x00000002 Parent=0x00000004 SizeRef=2560,1508 Split=Y Selected=0xC450F867
DockNode ID=0x0000000B Parent=0x00000002 SizeRef=1401,955 HiddenTabBar=1 Selected=0xC450F867
DockNode ID=0x0000000C Parent=0x00000002 SizeRef=1401,551 Selected=0x9C21DE82
DockNode ID=0x00000008 Parent=0xC0DFADC4 SizeRef=471,1542 Split=Y Selected=0x8C72BEA8
DockNode ID=0x00000009 Parent=0x00000008 SizeRef=315,563 Selected=0xB8729153
DockNode ID=0x0000000A Parent=0x00000008 SizeRef=315,977 Selected=0x73E3D51F

Binary file not shown.

View File

@ -0,0 +1,840 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v8.0/win-x64",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v8.0": {},
".NETCoreApp,Version=v8.0/win-x64": {
"Microsoft.NETCore.App.Runtime.Mono.win-x64/8.0.22": {
"runtime": {
"System.Private.CoreLib.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"Microsoft.CSharp.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"Microsoft.VisualBasic.Core.dll": {
"assemblyVersion": "13.0.0.0",
"fileVersion": "13.0.2225.52707"
},
"Microsoft.VisualBasic.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"Microsoft.Win32.Primitives.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"Microsoft.Win32.Registry.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"mscorlib.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"netstandard.dll": {
"assemblyVersion": "2.1.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.AppContext.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Buffers.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Collections.Concurrent.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Collections.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Collections.Immutable.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Collections.NonGeneric.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Collections.Specialized.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.ComponentModel.Annotations.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.ComponentModel.DataAnnotations.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.ComponentModel.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.ComponentModel.EventBasedAsync.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.ComponentModel.Primitives.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.ComponentModel.TypeConverter.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Configuration.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Console.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Core.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Data.Common.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Data.DataSetExtensions.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Data.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Diagnostics.Contracts.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Diagnostics.Debug.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Diagnostics.DiagnosticSource.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Diagnostics.FileVersionInfo.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Diagnostics.Process.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Diagnostics.StackTrace.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Diagnostics.TextWriterTraceListener.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Diagnostics.Tools.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Diagnostics.TraceSource.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Diagnostics.Tracing.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Drawing.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Drawing.Primitives.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Dynamic.Runtime.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Formats.Asn1.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Formats.Tar.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Globalization.Calendars.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Globalization.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Globalization.Extensions.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.Compression.Brotli.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.Compression.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.Compression.FileSystem.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.Compression.ZipFile.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.FileSystem.AccessControl.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.FileSystem.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.FileSystem.DriveInfo.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.FileSystem.Primitives.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.FileSystem.Watcher.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.IsolatedStorage.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.MemoryMappedFiles.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.Pipes.AccessControl.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.Pipes.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.IO.UnmanagedMemoryStream.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Linq.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Linq.Expressions.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Linq.Parallel.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Linq.Queryable.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Memory.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.Http.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.Http.Json.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.HttpListener.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.Mail.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.NameResolution.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.NetworkInformation.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.Ping.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.Primitives.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.Quic.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.Requests.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.Security.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.ServicePoint.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.Sockets.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.WebClient.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.WebHeaderCollection.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.WebProxy.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.WebSockets.Client.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Net.WebSockets.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Numerics.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Numerics.Vectors.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.ObjectModel.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Private.DataContractSerialization.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Private.Uri.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Private.Xml.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Private.Xml.Linq.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Reflection.DispatchProxy.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Reflection.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Reflection.Emit.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Reflection.Emit.ILGeneration.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Reflection.Emit.Lightweight.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Reflection.Extensions.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Reflection.Metadata.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Reflection.Primitives.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Reflection.TypeExtensions.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Resources.Reader.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Resources.ResourceManager.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Resources.Writer.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.CompilerServices.Unsafe.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.CompilerServices.VisualC.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.Extensions.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.Handles.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.InteropServices.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.InteropServices.JavaScript.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.InteropServices.RuntimeInformation.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.Intrinsics.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.Loader.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.Numerics.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.Serialization.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.Serialization.Formatters.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.Serialization.Json.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.Serialization.Primitives.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Runtime.Serialization.Xml.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Security.AccessControl.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Security.Claims.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Security.Cryptography.Algorithms.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Security.Cryptography.Cng.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Security.Cryptography.Csp.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Security.Cryptography.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Security.Cryptography.Encoding.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Security.Cryptography.OpenSsl.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Security.Cryptography.Primitives.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Security.Cryptography.X509Certificates.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Security.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Security.Principal.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Security.Principal.Windows.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Security.SecureString.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.ServiceModel.Web.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.ServiceProcess.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Text.Encoding.CodePages.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Text.Encoding.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Text.Encoding.Extensions.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Text.Encodings.Web.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Text.Json.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Text.RegularExpressions.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Threading.Channels.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Threading.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Threading.Overlapped.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Threading.Tasks.Dataflow.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Threading.Tasks.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Threading.Tasks.Extensions.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Threading.Tasks.Parallel.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Threading.Thread.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Threading.ThreadPool.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Threading.Timer.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Transactions.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Transactions.Local.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.ValueTuple.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Web.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Web.HttpUtility.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Windows.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Xml.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Xml.Linq.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Xml.ReaderWriter.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Xml.Serialization.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Xml.XDocument.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Xml.XmlDocument.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Xml.XmlSerializer.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Xml.XPath.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"System.Xml.XPath.XDocument.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.2225.52707"
},
"WindowsBase.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "8.0.2225.52707"
}
},
"native": {
"coreclr.dll": {
"fileVersion": "8.0.2225.52707"
},
"msquic.dll": {
"fileVersion": "2.4.8.0"
},
"System.IO.Compression.Native.dll": {
"fileVersion": "8.0.2225.52707"
},
"hostpolicy.dll": {
"fileVersion": "8.0.2225.52707"
},
"Microsoft.DiaSymReader.Native.amd64.dll": {
"fileVersion": "14.42.34436.0"
}
}
}
}
},
"libraries": {
"Microsoft.NETCore.App.Runtime.Mono.win-x64/8.0.22": {
"type": "package",
"serviceable": true,
"sha512": "",
"path": "microsoft.netcore.app.runtime.mono.win-x64/8.0.22"
}
},
"runtimes": {
"win-x64": [
"win",
"any",
"base"
],
"win-x64-aot": [
"win-aot",
"win-x64",
"win",
"aot",
"any",
"base"
],
"win10-x64": [
"win10",
"win81-x64",
"win81",
"win8-x64",
"win8",
"win7-x64",
"win7",
"win-x64",
"win",
"any",
"base"
],
"win10-x64-aot": [
"win10-aot",
"win10-x64",
"win10",
"win81-x64-aot",
"win81-aot",
"win81-x64",
"win81",
"win8-x64-aot",
"win8-aot",
"win8-x64",
"win8",
"win7-x64-aot",
"win7-aot",
"win7-x64",
"win7",
"win-x64-aot",
"win-aot",
"win-x64",
"win",
"aot",
"any",
"base"
],
"win7-x64": [
"win7",
"win-x64",
"win",
"any",
"base"
],
"win7-x64-aot": [
"win7-aot",
"win7-x64",
"win7",
"win-x64-aot",
"win-aot",
"win-x64",
"win",
"aot",
"any",
"base"
],
"win8-x64": [
"win8",
"win7-x64",
"win7",
"win-x64",
"win",
"any",
"base"
],
"win8-x64-aot": [
"win8-aot",
"win8-x64",
"win8",
"win7-x64-aot",
"win7-aot",
"win7-x64",
"win7",
"win-x64-aot",
"win-aot",
"win-x64",
"win",
"aot",
"any",
"base"
],
"win81-x64": [
"win81",
"win8-x64",
"win8",
"win7-x64",
"win7",
"win-x64",
"win",
"any",
"base"
],
"win81-x64-aot": [
"win81-aot",
"win81-x64",
"win81",
"win8-x64-aot",
"win8-aot",
"win8-x64",
"win8",
"win7-x64-aot",
"win7-aot",
"win7-x64",
"win7",
"win-x64-aot",
"win-aot",
"win-x64",
"win",
"aot",
"any",
"base"
]
}
}

View File

@ -0,0 +1,5 @@
{
"runtimeOptions": {
"tfm": "net8.0"
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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