42 Commits

Author SHA1 Message Date
4266a0b570 add Console panel; fix the problem when cs set Rotation the direction not update; fix some little bug; add simple texture material Edit system;some treaks 2026-03-27 18:02:57 +08:00
ef4ea45edc add simple runtime; fix the issue of crashing when creating file and folder; some tweaks 2026-03-25 21:36:38 +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
892 changed files with 37068 additions and 2707 deletions

6
.gitignore vendored
View File

@ -16,4 +16,8 @@ cmake-build-*/
build/
# Files
*.user
*.user
# dotnet project
[Bb]in/
[Oo]bj/

18
.gitmodules vendored
View File

@ -17,3 +17,21 @@
[submodule "Prism/vendor/ImGuizmo"]
path = Prism/vendor/ImGuizmo
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
if(MSVC)
# config
string(REPLACE "/showIncludes" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
# temp config
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251")
@ -23,4 +23,5 @@ endif ()
add_subdirectory(Prism)
add_subdirectory(Sandbox)
add_subdirectory(Editor)
add_subdirectory(Editor)
add_subdirectory(PrismRuntime)

View File

@ -1,13 +1,22 @@
project(PrismEditor)
file(GLOB ASSETS assets)
file(COPY ${ASSETS} DESTINATION ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_BINARY_DIR ${CMAKE_BINARY_DIR}/bin)
file(GLOB_RECURSE SRC_SOURCE ./**.cpp)
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 ./Editor/**.cpp)
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
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

@ -5,7 +5,10 @@
#ifndef EDITORLAYER_H
#define EDITORLAYER_H
#include "Panels/ConsolePanel.h"
#include "Prism.h"
#include "Prism/Editor/ContentBrowserPanel.h"
#include "Prism/Editor/ObjectsPanel.h"
#include "Prism/Editor/SceneHierachyPanel.h"
namespace Prism
@ -26,24 +29,48 @@ namespace Prism
bool OnKeyPressedEvent(KeyPressedEvent& 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:
std::pair<float, float> GetMouseViewportSpace() const;
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:
Scope<SceneHierarchyPanel> m_SceneHierarchyPanel;
Scope<ContentBrowserPanel> m_ContentBrowserPanel;
Scope<ObjectsPanel> m_ObjectsPanel;
Ref<Scene> m_Scene;
Ref<Scene> m_SphereScene;
Ref<Scene> m_ActiveScene;
Ref<Scene> m_CurrentScene;
Ref<Scene> m_RuntimeScene, m_EditorScene;
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_MeshMaterial;
std::vector<Ref<MaterialInstance>> m_MetalSphereMaterialInstances;
@ -54,21 +81,16 @@ namespace Prism
glm::vec2 m_ViewportBounds[2] = {};
int m_GizmoType = -1; // -1 = no gizmo
float m_SnapValue = 0.5f;
float m_RotationSnapValue = 45.0f;
struct SelectedSubmesh
enum class SelectionMode
{
Submesh* Mesh;
float Distance;
None = 0, Entity = 1, SubMesh = 2
};
std::vector<SelectedSubmesh> m_SelectedSubmeshes;
glm::mat4* m_CurrentlySelectedTransform = nullptr;
SelectionMode m_SelectionMode = SelectionMode::Entity;
// configure button
bool m_AllowViewportCameraEvents = false;
bool m_DrawOnTopBoundingBoxes = false;
bool m_UIShowBoundingBoxes = false;
bool m_UIShowBoundingBoxesOnTop = false;
std::vector<SelectedSubmesh> m_SelectionContext;
glm::mat4* m_RelativeTransform = nullptr;
struct AlbedoInput
@ -78,14 +100,14 @@ namespace Prism
bool SRGB = true;
bool UseTexture = false;
};
AlbedoInput m_AlbedoInput;
// AlbedoInput m_AlbedoInput;
struct NormalInput
{
Ref<Texture2D> TextureMap;
bool UseTexture = false;
};
NormalInput m_NormalInput;
// NormalInput m_NormalInput;
struct MetalnessInput
{
@ -93,21 +115,26 @@ namespace Prism
Ref<Texture2D> TextureMap;
bool UseTexture = false;
};
MetalnessInput m_MetalnessInput;
// MetalnessInput m_MetalnessInput;
struct RoughnessInput
{
float Value = 0.5f;
float Value = 1.0f;
Ref<Texture2D> TextureMap;
bool UseTexture = false;
};
RoughnessInput m_RoughnessInput;
// RoughnessInput m_RoughnessInput;
// 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
{
@ -115,8 +142,18 @@ namespace Prism
};
SceneType m_SceneType;
// Editor resources
Ref<Texture2D> m_CheckerboardTex;
bool m_ViewportPanelHovered = false;
bool m_ViewportPanelFocused = false;
bool m_ShowPhysicsSettings = false;
enum class SceneState
{
Edit = 0, Play = 1, Pause = 2
};
SceneState m_SceneState = SceneState::Edit;
private:
Scope<ConsolePanel> m_ConsolePanel;
};
}

View File

@ -0,0 +1,66 @@
//
// Created by Atdunbg on 2026/3/26.
//
#include "ConsolePanel.h"
namespace Prism
{
ConsolePanel::ConsolePanel()
{
// 预留一些空间
m_Messages.reserve(1000);
}
void ConsolePanel::OnImGuiRender()
{
ImGui::Begin("Console");
// 工具栏
if (ImGui::Button("Clear"))
{
std::lock_guard<std::mutex> lock(m_Mutex);
m_Messages.clear();
}
ImGui::SameLine();
ImGui::Checkbox("Auto-scroll", &m_AutoScroll);
ImGui::SameLine();
m_Filter.Draw("Filter", 200);
// 消息列表区域
ImGui::BeginChild("ScrollingRegion", ImVec2(0, 0), ImGuiChildFlags_Borders, ImGuiWindowFlags_HorizontalScrollbar);
{
std::lock_guard<std::mutex> lock(m_Mutex);
for (const auto& [msg, color] : m_Messages)
{
if (m_Filter.PassFilter(msg.c_str()))
{
ImGui::PushStyleColor(ImGuiCol_Text, color);
ImGui::TextUnformatted(msg.c_str());
ImGui::PopStyleColor();
}
}
if (m_ScrollToBottom)
{
ImGui::SetScrollHereY(1.0f);
m_ScrollToBottom = false;
}
}
ImGui::EndChild();
ImGui::End();
}
void ConsolePanel::AddMessage(const std::string& message, ImVec4 color)
{
std::lock_guard<std::mutex> lock(m_Mutex);
m_Messages.emplace_back(message, color);
while (m_Messages.size() > 5000)
m_Messages.erase(m_Messages.begin());
if (m_AutoScroll && !m_ScrollToBottom)
m_ScrollToBottom = true;
}
}

View File

@ -0,0 +1,31 @@
//
// Created by Atdunbg on 2026/3/26.
//
#ifndef PRISM_CONSOLEPANEL_H
#define PRISM_CONSOLEPANEL_H
#include <mutex>
#include <vector>
#include "imgui.h"
namespace Prism
{
class ConsolePanel
{
public:
ConsolePanel();
void OnImGuiRender();
void AddMessage(const std::string& message, ImVec4 color = ImVec4(1,1,1,1));
private:
std::vector<std::pair<std::string, ImVec4>> m_Messages;
ImGuiTextFilter m_Filter;
bool m_AutoScroll = true;
bool m_ScrollToBottom = false;
std::mutex m_Mutex;
};
}
#endif //PRISM_CONSOLEPANEL_H

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,336 @@
Scene: Scene Name
Environment:
AssetHandle: 5211537204242875091
Entities:
- Entity: 8293051279669100759
Parent: 0
Children:
[]
TagComponent:
Tag: Cube
TransformComponent:
Position: [1.736814, 1.4724115, -4.2181306]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
MeshComponent:
AssetID: 18328012085543462741
AssetPath: assets/meshes/Default/Cube.fbx
RigidBodyComponent:
BodyType: 1
Mass: 1
LinearDrag: 0
AngularDrag: 0.05
DisableGravity: false
IsKinematic: false
Layer: 0
Constraints:
LockPositionX: false
LockPositionY: false
LockPositionZ: false
LockRotationX: false
LockRotationY: false
LockRotationZ: false
BoxColliderComponent:
Offset: [0, 0, 0]
Size: [2, 2, 2]
IsTrigger: false
Material: 0
MaterialPath: ""
- Entity: 5834225236589765516
Parent: 0
Children:
[]
TagComponent:
Tag: Cube
TransformComponent:
Position: [-2.6417403, 1.4724115, -7.9285727]
Rotation: [0.52199936, 0, 0]
Scale: [1, 1.0000001, 1.0000001]
MeshComponent:
AssetID: 18328012085543462741
AssetPath: assets/meshes/Default/Cube.fbx
RigidBodyComponent:
BodyType: 1
Mass: 1
LinearDrag: 0
AngularDrag: 0.05
DisableGravity: false
IsKinematic: false
Layer: 0
Constraints:
LockPositionX: false
LockPositionY: false
LockPositionZ: false
LockRotationX: false
LockRotationY: false
LockRotationZ: false
BoxColliderComponent:
Offset: [0, 0, 0]
Size: [2, 2, 2]
IsTrigger: false
Material: 0
MaterialPath: ""
- Entity: 8234256119181302872
Parent: 0
Children:
[]
TagComponent:
Tag: Cube
TransformComponent:
Position: [1.736814, 1.4724115, -7.9285727]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
MeshComponent:
AssetID: 18328012085543462741
AssetPath: assets/meshes/Default/Cube.fbx
RigidBodyComponent:
BodyType: 1
Mass: 1
LinearDrag: 0
AngularDrag: 0.05
DisableGravity: false
IsKinematic: false
Layer: 0
Constraints:
LockPositionX: false
LockPositionY: false
LockPositionZ: false
LockRotationX: false
LockRotationY: false
LockRotationZ: false
BoxColliderComponent:
Offset: [0, 0, 0]
Size: [2, 2, 2]
IsTrigger: false
Material: 0
MaterialPath: ""
- Entity: 12935252585493481950
Parent: 0
Children:
[]
TagComponent:
Tag: Cube
TransformComponent:
Position: [-1.5106764, 6.237644, -4.2181306]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
MeshComponent:
AssetID: 18328012085543462741
AssetPath: assets/meshes/Default/Cube.fbx
RigidBodyComponent:
BodyType: 1
Mass: 1
LinearDrag: 0
AngularDrag: 0.05
DisableGravity: false
IsKinematic: false
Layer: 0
Constraints:
LockPositionX: false
LockPositionY: false
LockPositionZ: false
LockRotationX: false
LockRotationY: false
LockRotationZ: false
BoxColliderComponent:
Offset: [0, 0, 0]
Size: [2, 2, 2]
IsTrigger: false
Material: 0
MaterialPath: ""
- Entity: 3328246672296261054
Parent: 0
Children:
[]
TagComponent:
Tag: Cube
TransformComponent:
Position: [1.736814, 1.4724115, -0.88378817]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
MeshComponent:
AssetID: 18328012085543462741
AssetPath: assets/meshes/Default/Cube.fbx
RigidBodyComponent:
BodyType: 1
Mass: 1
LinearDrag: 0
AngularDrag: 0.05
DisableGravity: false
IsKinematic: false
Layer: 0
Constraints:
LockPositionX: false
LockPositionY: false
LockPositionZ: false
LockRotationX: false
LockRotationY: false
LockRotationZ: false
BoxColliderComponent:
Offset: [0, 0, 0]
Size: [2, 2, 2]
IsTrigger: false
Material: 0
MaterialPath: ""
- Entity: 4208267561919679628
Parent: 0
Children:
[]
TagComponent:
Tag: Cube
TransformComponent:
Position: [-2.6417403, 1.4724115, -4.8956265]
Rotation: [-0.4034239, 0, 0]
Scale: [1, 0.99999994, 0.99999994]
MeshComponent:
AssetID: 18328012085543462741
AssetPath: assets/meshes/Default/Cube.fbx
RigidBodyComponent:
BodyType: 1
Mass: 1
LinearDrag: 0
AngularDrag: 0.05
DisableGravity: true
IsKinematic: false
Layer: 0
Constraints:
LockPositionX: false
LockPositionY: false
LockPositionZ: false
LockRotationX: false
LockRotationY: false
LockRotationZ: false
BoxColliderComponent:
Offset: [0, 0, 0]
Size: [2, 2, 2]
IsTrigger: false
Material: 0
MaterialPath: ""
- Entity: 8114736924719261351
Parent: 0
Children:
[]
TagComponent:
Tag: Camera
TransformComponent:
Position: [0, 0.8097433, 4.573171]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
CameraComponent:
Camera:
ProjectionType: 0
PerspectiveFOV: 45
PerspectiveNear: 0.01
PerspectiveFar: 10000
OrthographicSize: 10
OrthographicNear: -1
OrthographicFar: 1
Primary: true
- Entity: 9267298328378270409
Parent: 0
Children:
[]
TagComponent:
Tag: Player
TransformComponent:
Position: [0, 0.70693016, 0]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
ScriptComponent:
ModuleName: FPSExample.FPSPlayer
StoredFields:
- Name: WalkingSpeed
Type: 1
Data: 2
- Name: RunSpeed
Type: 1
Data: 5
- Name: JumpForce
Type: 1
Data: 1
- Name: MouseSensitivity
Type: 1
Data: 10
- Name: CameraForwardOffset
Type: 1
Data: -2
- Name: CameraYOffset
Type: 1
Data: 2
MeshComponent:
AssetID: 3043502408333723884
AssetPath: assets/meshes/Default/Capsule.fbx
RigidBodyComponent:
BodyType: 1
Mass: 1
LinearDrag: 0
AngularDrag: 0.05
DisableGravity: false
IsKinematic: false
Layer: 0
Constraints:
LockPositionX: false
LockPositionY: false
LockPositionZ: false
LockRotationX: true
LockRotationY: false
LockRotationZ: true
MeshColliderComponent:
IsConvex: true
IsTrigger: false
OverrideMesh: false
Material: 0
MaterialPath: ""
- Entity: 10732070446010033158
Parent: 0
Children:
[]
TagComponent:
Tag: Cube
TransformComponent:
Position: [0, -2.6466873, 0]
Rotation: [0, 0, 0]
Scale: [100, 1, 100]
MeshComponent:
AssetID: 18328012085543462741
AssetPath: assets/meshes/Default/Cube.fbx
RigidBodyComponent:
BodyType: 0
Mass: 1
LinearDrag: 0
AngularDrag: 0.05
DisableGravity: false
IsKinematic: false
Layer: 0
Constraints:
LockPositionX: false
LockPositionY: false
LockPositionZ: false
LockRotationX: false
LockRotationY: false
LockRotationZ: false
BoxColliderComponent:
Offset: [0, 0, 0]
Size: [2, 2, 2]
IsTrigger: false
Material: 0
MaterialPath: ""
- Entity: 5099152432245948441
Parent: 0
Children:
[]
TagComponent:
Tag: venice_dawn_1_4k
TransformComponent:
Position: [0, 0, 0]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
SkyLightComponent:
EnvironmentMap: 5211537204242875091
EnvironmentAssetPath: assets/env/venice_dawn_1_4k.hdr
Intensity: 1
Angle: 0
DynamicSky: false
TurbidityAzimuthInclination: [2, 0, 0]
PhysicsLayers:
[]

View File

@ -0,0 +1,64 @@
Scene: Scene Name
Environment:
AssetHandle: 6095149963749185931
Entities:
- Entity: 6421668200759325475
Parent: 0
Children:
[]
TagComponent:
Tag: M1911Materials
TransformComponent:
Position: [0, 3.159583, 0]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
MeshComponent:
AssetID: 7219694555758922702
AssetPath: assets/models/m1911/M1911Materials.fbx
- Entity: 16992665426857995732
Parent: 0
Children:
[]
TagComponent:
Tag: Cube
TransformComponent:
Position: [0, 0, 0]
Rotation: [0, 0, 0]
Scale: [50, 1, 50]
MeshComponent:
AssetID: 18328012085543462741
AssetPath: assets/meshes/Default/Cube.fbx
- Entity: 18182275256052989728
Parent: 0
Children:
[]
TagComponent:
Tag: Sky Light
TransformComponent:
Position: [0, 0, 0]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
SkyLightComponent:
EnvironmentMap: 6095149963749185931
EnvironmentAssetPath: ""
Intensity: 1
Angle: 0
DynamicSky: true
TurbidityAzimuthInclination: [2, 0.15, 0.71]
- 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.9
PhysicsLayers:
[]

View File

@ -0,0 +1,36 @@
Scene: Scene Name
Environment:
AssetHandle: 5211537204242875091
Entities:
- Entity: 15706224176559717512
Parent: 0
Children:
[]
TagComponent:
Tag: Cube
TransformComponent:
Position: [0, 0, 0]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
MeshComponent:
AssetID: 18328012085543462741
AssetPath: assets/meshes/Default/Cube.fbx
- Entity: 8041206185299282567
Parent: 0
Children:
[]
TagComponent:
Tag: venice_dawn_1_4k
TransformComponent:
Position: [0, 0, 0]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
SkyLightComponent:
EnvironmentMap: 5211537204242875091
EnvironmentAssetPath: assets/env/venice_dawn_1_4k.hdr
Intensity: 1
Angle: 0
DynamicSky: false
TurbidityAzimuthInclination: [2, 0, 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; // 亮度阈值
void main()
{
float Pi = 6.28318530718; // 2*PI
float Directions = 32.0; // 模糊方向数
float Quality = 6.0; // 每个方向上的采样质量(采样次数)
float Size = 16.0; // 模糊半径
vec2 Radius = 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 / Directions)
{
for (float i = 1.0 / Quality; i <= 1.0; i += 1.0 / 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,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,8 +1,8 @@
// -----------------------------
// -- 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.
// Currently heavily updated.
// Currently heavily updated.
//
// References upon which this is based:
// - Unreal Engine 4 PBR notes (https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf)
@ -21,19 +21,25 @@ layout(location = 4) in vec2 a_TexCoord;
layout(location = 5) in ivec4 a_BoneIndices;
layout(location = 6) in vec4 a_BoneWeights;
uniform mat4 u_ViewProjectionMatrix;
uniform mat4 u_Transform;
const int MAX_BONES = 100;
uniform mat4 u_BoneTransforms[100];
uniform mat4 u_ViewProjectionMatrix;
uniform mat4 u_ViewMatrix;
uniform mat4 u_Transform;
uniform mat4 u_LightSpaceMatrix;
out VertexOutput
{
vec3 WorldPosition;
vec3 WorldPosition;
vec3 Normal;
vec2 TexCoord;
mat3 WorldNormals;
vec3 Binormal;
vec2 TexCoord;
mat3 WorldNormals;
mat3 WorldTransform;
vec3 Binormal;
vec3 ViewPosition;
vec4 FragPosLightSpace;
} vs_Output;
void main()
@ -43,15 +49,21 @@ void main()
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);
vec4 localPosition = boneTransform * vec4(a_Position, 1.0);
vs_Output.WorldPosition = vec3(u_Transform * boneTransform * vec4(a_Position, 1.0));
vs_Output.WorldPosition = vec3(u_Transform * boneTransform * vec4(a_Position, 1.0));
vs_Output.Normal = mat3(u_Transform) * mat3(boneTransform) * a_Normal;
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.Binormal = mat3(boneTransform) * a_Binormal;
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.WorldTransform = mat3(u_Transform);
vs_Output.Binormal = a_Binormal;
gl_Position = u_ViewProjectionMatrix * u_Transform * localPosition;
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;
}
#type fragment
@ -61,102 +73,121 @@ const float PI = 3.141592;
const float Epsilon = 0.00001;
const int LightCount = 1;
// Constant normal incidence Fresnel factor for all dielectrics.
const vec3 Fdielectric = vec3(0.04);
struct Light {
vec3 Direction;
vec3 Radiance;
float Multiplier;
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;
};
in VertexOutput
{
vec3 WorldPosition;
vec3 WorldPosition;
vec3 Normal;
vec2 TexCoord;
mat3 WorldNormals;
vec3 Binormal;
vec2 TexCoord;
mat3 WorldNormals;
mat3 WorldTransform;
vec3 Binormal;
vec3 ViewPosition;
vec4 FragPosLightSpace;
} 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;
// 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_NormalTexture;
uniform sampler2D u_MetalnessTexture;
uniform sampler2D u_RoughnessTexture;
// Environment maps
// environment
uniform samplerCube u_EnvRadianceTex;
uniform samplerCube u_EnvIrradianceTex;
// BRDF LUT
uniform sampler2D u_BRDFLUTTexture;
uniform vec3 u_AlbedoColor;
uniform float u_IBLContribution;
uniform float u_BloomThreshold;
uniform float u_EnvMapRotation;
// baseColor
uniform vec3 u_AlbedoColor;
uniform float u_Metalness;
uniform float u_Roughness;
uniform float u_EnvMapRotation;
// Toggles
uniform float u_RadiancePrefilter;
// textureToggle
uniform float u_AlbedoTexToggle;
uniform float u_NormalTexToggle;
uniform float u_MetalnessTexToggle;
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;
struct PBRParameters
{
vec3 Albedo;
float Roughness;
float Metalness;
vec3 Normal;
vec3 View;
float NdotV;
vec3 Albedo;
float Roughness;
float Metalness;
vec3 Normal;
vec3 View;
float NdotV;
};
PBRParameters m_Params;
// GGX/Towbridge-Reitz normal distribution function.
// Uses Disney's reparametrization of alpha = roughness^2
// ---------- PBR param func ----------
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);
}
// 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 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 k = (r * r) / 8.0;
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
@ -166,165 +197,275 @@ float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
float NdotL = max(dot(N, L), 0.0);
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2;
}
// Shlick's approximation of the Fresnel factor.
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);
}
vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness)
{
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
}
// ---------------------------------------------------------------------------------------------------
// The following code (from Unreal Engine 4's paper) shows how to filter the environment map
// 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);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
}
vec2 Hammersley(uint i, uint N)
// ---------- direction light ----------
vec3 ComputeDirectionalLight(DirectionalLight light, vec3 F0, PBRParameters params)
{
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
vec3 L = normalize(-light.Direction);
vec3 Lradiance = light.Radiance * light.Intensity;
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;
}
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N)
vec3 ComputePointLight(PointLight light, vec3 F0, PBRParameters params, vec3 worldPos)
{
float a = Roughness * Roughness;
float Phi = 2 * PI * Xi.x;
float CosTheta = sqrt( (1 - Xi.y) / ( 1 + (a*a - 1) * Xi.y ) );
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;
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;
}
float TotalWeight = 0.0;
vec3 PrefilterEnvMap(float Roughness, vec3 R)
vec3 ComputeSpotLight(SpotLight light, vec3 F0, PBRParameters params, vec3 worldPos)
{
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 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)); // 光方向指向外,所以用 -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;
}
// ---------------------------------------------------------------------------------------------------
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 result = vec3(0.0);
for(int i = 0; i < LightCount; i++)
{
vec3 Li = -lights.Direction;
vec3 Lradiance = lights.Radiance * lights.Multiplier;
vec3 Lh = normalize(Li + m_Params.View);
vec3 result = vec3(0.0);
for(int i = 0; i < LightCount; i++)
{
vec3 Li = u_DirectionalLights.Direction;
vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.Intensity;
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 cosLh = max(0.0, dot(m_Params.Normal, Lh));
float cosLi = max(0.0, dot(m_Params.Normal, Li));
float cosLh = max(0.0, dot(m_Params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, m_Params.View)));
float D = ndfGGX(cosLh, m_Params.Roughness);
float G = gaSchlickGGX(cosLi, m_Params.NdotV, m_Params.Roughness);
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, m_Params.View)));
float D = ndfGGX(cosLh, 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 diffuseBRDF = kd * m_Params.Albedo;
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
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;
}
return result;
result += (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
}
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 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb;
vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
vec3 diffuseIBL = m_Params.Albedo * irradiance;
vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb;
vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness);
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
vec3 diffuseIBL = m_Params.Albedo * irradiance;
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
float NoV = clamp(m_Params.NdotV, 0.0, 1.0);
vec3 R = 2.0 * dot(m_Params.View, m_Params.Normal) * m_Params.Normal - m_Params.View;
vec3 specularIrradiance = textureLod(u_EnvRadianceTex, RotateVectorAboutY(u_EnvMapRotation, Lr), (m_Params.Roughness) * u_EnvRadianceTexLevels).rgb;
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
vec3 specularIrradiance = textureLod(
u_EnvRadianceTex,
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;
vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y);
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg;
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()
{
// Standard PBR inputs
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor;
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 = max(m_Params.Roughness, 0.05); // Minimum roughness of 0.05 to keep specular highlight
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor;
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 = max(m_Params.Roughness, 0.05);
// Normals (either from vertex or map)
m_Params.Normal = normalize(vs_Input.Normal);
if (u_NormalTexToggle > 0.5)
{
m_Params.Normal = normalize(2.0 * texture(u_NormalTexture, vs_Input.TexCoord).rgb - 1.0);
m_Params.Normal = normalize(vs_Input.WorldNormals * m_Params.Normal);
}
// normal
m_Params.Normal = normalize(vs_Input.Normal);
if (u_NormalTexToggle > 0.5)
{
m_Params.Normal = normalize(2.0 * texture(u_NormalTexture, vs_Input.TexCoord).rgb - 1.0);
m_Params.Normal = normalize(vs_Input.WorldNormals * m_Params.Normal);
}
m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition);
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;
m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition);
m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0);
// Fresnel reflectance, metals use albedo
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness);
vec3 Lr = 2.0 * m_Params.NdotV * m_Params.Normal - m_Params.View;
vec3 lightContribution = Lighting(F0);
vec3 iblContribution = IBL(F0, Lr);
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness);
color = vec4(lightContribution + iblContribution, 1.0);
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;
}
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;
color = vec4(lightContribution + iblContribution, 1.0);
// 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,8 +1,8 @@
// -----------------------------
// -- 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.
// Currently heavily updated.
// Currently heavily updated.
//
// References upon which this is based:
// - Unreal Engine 4 PBR notes (https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf)
@ -19,27 +19,36 @@ layout(location = 3) in vec3 a_Binormal;
layout(location = 4) in vec2 a_TexCoord;
uniform mat4 u_ViewProjectionMatrix;
uniform mat4 u_ViewMatrix;
uniform mat4 u_Transform;
uniform mat4 u_LightSpaceMatrix;
out VertexOutput
{
vec3 WorldPosition;
vec3 Normal;
vec3 Normal;
vec2 TexCoord;
mat3 WorldNormals;
mat3 WorldTransform;
vec3 Binormal;
vec3 ViewPosition;
vec4 FragPosLightSpace;
} vs_Output;
void main()
{
vs_Output.WorldPosition = vec3(u_Transform * vec4(a_Position, 1.0));
vs_Output.Normal = mat3(u_Transform) * a_Normal;
vs_Output.Normal = mat3(u_Transform) * a_Normal;
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.WorldTransform = mat3(u_Transform);
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);
}
@ -50,63 +59,101 @@ const float PI = 3.141592;
const float Epsilon = 0.00001;
const int LightCount = 1;
// Constant normal incidence Fresnel factor for all dielectrics.
const vec3 Fdielectric = vec3(0.04);
struct Light {
struct DirectionalLight {
vec3 Direction;
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
{
vec3 WorldPosition;
vec3 Normal;
vec3 Normal;
vec2 TexCoord;
mat3 WorldNormals;
mat3 WorldTransform;
vec3 Binormal;
vec3 ViewPosition;
vec4 FragPosLightSpace;
} vs_Input;
layout(location = 0) out vec4 color;
layout(location = 1) out vec4 o_BloomColor;
uniform DirectionalLight u_DirectionalLights;
uniform int u_PointLightCount;
uniform PointLight u_PointLights;
uniform int u_SpotLightCount;
uniform SpotLight u_SpotLights;
uniform Light lights;
uniform vec3 u_CameraPosition;
// PBR texture inputs
// PBR
uniform sampler2D u_AlbedoTexture;
uniform sampler2D u_NormalTexture;
uniform sampler2D u_MetalnessTexture;
uniform sampler2D u_RoughnessTexture;
// Environment maps
// environment
uniform samplerCube u_EnvRadianceTex;
uniform samplerCube u_EnvIrradianceTex;
// BRDF LUT
uniform sampler2D u_BRDFLUTTexture;
uniform vec3 u_AlbedoColor;
uniform float u_IBLContribution;
uniform float u_BloomThreshold;
uniform float u_EnvMapRotation;
// baseColor
uniform vec3 u_AlbedoColor;
uniform float u_Metalness;
uniform float u_Roughness;
uniform float u_EnvMapRotation;
// Toggles
uniform float u_RadiancePrefilter;
// textureToggle
uniform float u_AlbedoTexToggle;
uniform float u_NormalTexToggle;
uniform float u_MetalnessTexToggle;
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;
struct PBRParameters
{
vec3 Albedo;
float Roughness;
float Metalness;
vec3 Normal;
vec3 View;
float NdotV;
@ -114,53 +161,33 @@ struct PBRParameters
PBRParameters m_Params;
// GGX/Towbridge-Reitz normal distribution function.
// Uses Disney's reparametrization of alpha = roughness^2
// ---------- PBR param func ----------
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);
}
// 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 r = (roughness + 1.0);
float k = (r*r) / 8.0;
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
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;
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;
}
// Shlick's approximation of the Fresnel factor.
vec3 fresnelSchlick(vec3 F0, float cosTheta)
{
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
@ -168,77 +195,97 @@ vec3 fresnelSchlick(vec3 F0, float cosTheta)
vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness)
{
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
}
// ---------------------------------------------------------------------------------------------------
// The following code (from Unreal Engine 4's paper) shows how to filter the environment map
// 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);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
}
vec2 Hammersley(uint i, uint N)
// ---------- direction light ----------
vec3 ComputeDirectionalLight(DirectionalLight light, vec3 F0, PBRParameters params)
{
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
vec3 L = normalize(-light.Direction);
vec3 Lradiance = light.Radiance * light.Intensity;
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;
}
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N)
vec3 ComputePointLight(PointLight light, vec3 F0, PBRParameters params, vec3 worldPos)
{
float a = Roughness * Roughness;
float Phi = 2 * PI * Xi.x;
float CosTheta = sqrt( (1 - Xi.y) / ( 1 + (a*a - 1) * Xi.y ) );
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;
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;
}
float TotalWeight = 0.0;
vec3 PrefilterEnvMap(float Roughness, vec3 R)
vec3 ComputeSpotLight(SpotLight light, vec3 F0, PBRParameters params, vec3 worldPos)
{
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 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;
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;
// 距离衰减
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)); // 光方向指向外,所以用 -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;
}
vec3 Lighting(vec3 F0)
@ -246,22 +293,20 @@ vec3 Lighting(vec3 F0)
vec3 result = vec3(0.0);
for(int i = 0; i < LightCount; i++)
{
vec3 Li = -lights.Direction;
vec3 Lradiance = lights.Radiance * lights.Multiplier;
vec3 Li = u_DirectionalLights.Direction;
vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.Intensity;
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 cosLh = max(0.0, dot(m_Params.Normal, Lh));
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, m_Params.View)));
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 diffuseBRDF = kd * m_Params.Albedo;
// Cook-Torrance
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * m_Params.NdotV);
result += (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
@ -269,35 +314,109 @@ vec3 Lighting(vec3 F0)
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 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb;
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 diffuseIBL = m_Params.Albedo * irradiance;
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
float NoV = clamp(m_Params.NdotV, 0.0, 1.0);
vec3 R = 2.0 * dot(m_Params.View, m_Params.Normal) * m_Params.Normal - m_Params.View;
vec3 specularIrradiance = textureLod(u_EnvRadianceTex, RotateVectorAboutY(u_EnvMapRotation, Lr), (m_Params.Roughness) * u_EnvRadianceTexLevels).rgb;
vec3 specularIrradiance = textureLod(
u_EnvRadianceTex,
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;
vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y);
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()
{
// Standard PBR inputs
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor;
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor;
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 = max(m_Params.Roughness, 0.05); // Minimum roughness of 0.05 to keep specular highlight
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);
// Normals (either from vertex or map)
// normal
m_Params.Normal = normalize(vs_Input.Normal);
if (u_NormalTexToggle > 0.5)
{
@ -307,16 +426,32 @@ void main()
m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition);
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;
// Fresnel reflectance, metals use albedo
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness);
vec3 lightContribution = Lighting(F0);
vec3 iblContribution = IBL(F0, Lr);
// Shadow
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;
}
// directional light with with shadow
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;
color = vec4(lightContribution + iblContribution, 1.0);
// color = vec4(iblContribution, 1.0);
// 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

@ -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 = 1) in vec4 a_Color;
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;
uniform mat4 u_ViewProjection;
out vec4 v_Color;
out vec2 v_TexCoord;
out float v_TexIndex;
flat out int v_TexIndex;
out float v_TilingFactor;
void main()
@ -32,12 +32,17 @@ layout(location = 0) out vec4 color;
in vec4 v_Color;
in vec2 v_TexCoord;
in float v_TexIndex;
flat in int v_TexIndex;
in float v_TilingFactor;
uniform sampler2D u_Textures[32];
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

@ -17,20 +17,53 @@ void main()
#version 430
layout(location = 0) out vec4 o_Color;
layout(location = 1) out vec4 o_BloomTexture;
in vec2 v_TexCoord;
uniform sampler2DMS u_Texture;
uniform float u_Exposure;
uniform sampler2D u_BloomTexture;
uniform bool u_EnableAutoExposure;
uniform float u_ManualExposure;
layout(std430, binding = 2) buffer Exposure
{
float u_Exposure;
};
uniform int u_TextureSamples;
vec4 MultiSampleTexture(sampler2DMS tex, ivec2 texCoord, int samples)
uniform bool u_EnableBloom;
uniform float u_BloomThreshold;
const float uFar = 1.0;
vec4 SampleTexture(sampler2D tex, vec2 texCoord)
{
return texture(tex, texCoord);
}
vec4 MultiSampleTexture(sampler2DMS tex, vec2 tc)
{
ivec2 texSize = textureSize(tex);
ivec2 texCoord = ivec2(tc * texSize);
vec4 result = vec4(0.0);
for (int i = 0; i < samples; i++)
for (int i = 0; i < u_TextureSamples; i++)
result += texelFetch(tex, texCoord, i);
result /= float(samples);
result /= float(u_TextureSamples);
return result;
}
float MultiSampleDepth(sampler2DMS tex, vec2 tc)
{
ivec2 texSize = textureSize(tex);
ivec2 texCoord = ivec2(tc * texSize);
float result = 0.0;
for (int i = 0; i < u_TextureSamples; i++)
result += texelFetch(tex, texCoord, i).r;
result /= float(u_TextureSamples);
return result;
}
@ -39,10 +72,20 @@ void main()
const float gamma = 2.2;
const float pureWhite = 1.0;
ivec2 texSize = textureSize(u_Texture);
ivec2 texCoord = ivec2(v_TexCoord * texSize);
vec4 msColor = MultiSampleTexture(u_Texture, texCoord, u_TextureSamples);
vec3 color = msColor.rgb * u_Exposure;//texture(u_Texture, v_TexCoord).rgb * u_Exposure;
// Tonemapping
vec4 msColor = MultiSampleTexture(u_Texture, v_TexCoord);
vec3 color = msColor.rgb;
if (u_EnableBloom)
{
vec3 bloomColor = texture(u_BloomTexture, v_TexCoord).rgb;
color += bloomColor;
}
if(u_EnableAutoExposure)
color *= u_Exposure;
else
color *= u_ManualExposure;
// Reinhard tonemapping operator.
// see: "Photographic Tone Reproduction for Digital Images", eq. 4
@ -54,4 +97,8 @@ void main()
// Gamma correction.
o_Color = vec4(pow(mappedColor, vec3(1.0 / gamma)), 1.0);
}
// Show over-exposed areas
// if (o_Color.r > 1.0 || o_Color.g > 1.0 || o_Color.b > 1.0)
// o_Color.rgb *= vec3(1.0, 0.25, 0.25);
}

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 float u_TextureLod;
uniform float u_SkyIntensity;
in vec3 v_Position;
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);
}

108
Editor/imgui.ini Normal file
View File

@ -0,0 +1,108 @@
[Window][DockSpace Demo]
Pos=0,0
Size=1920,1080
Collapsed=0
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][Scene Hierarchy]
Pos=1449,24
Size=471,385
Collapsed=0
DockId=0x00000009,0
[Window][Properties]
Pos=1449,411
Size=471,669
Collapsed=0
DockId=0x0000000A,0
[Window][Scene Renderer]
Pos=0,585
Size=481,495
Collapsed=0
DockId=0x00000006,0
[Window][Materials]
Pos=0,24
Size=481,559
Collapsed=0
DockId=0x00000005,0
[Window][Script Engine Debug]
Pos=1449,411
Size=471,669
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=964,647
Collapsed=0
DockId=0x0000000B,0
[Window][Environment]
Pos=1449,411
Size=471,669
Collapsed=0
DockId=0x0000000A,1
[Window][Project]
Pos=483,707
Size=964,373
Collapsed=0
DockId=0x0000000C,0
[Window][Objects]
Pos=483,707
Size=964,373
Collapsed=0
DockId=0x0000000C,1
[Window][Physics]
Pos=189,113
Size=468,371
Collapsed=0
[Window][##tool_bar]
Pos=483,24
Size=964,32
Collapsed=0
DockId=0x00000001,0
[Window][Console]
Pos=483,707
Size=964,373
Collapsed=0
DockId=0x0000000C,2
[Docking][Data]
DockSpace ID=0xC0DFADC4 Window=0xD0388BC8 Pos=268,189 Size=1920,1056 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