Compare commits
46 Commits
mono
...
forward-re
| Author | SHA1 | Date | |
|---|---|---|---|
| f50824bdb1 | |||
| d11f8bb0c9 | |||
| 79707b77f5 | |||
| 971f16d526 | |||
| 5058d6a3a9 | |||
| f53d9134aa | |||
| 1b5fa1002d | |||
| d6d735900a | |||
| 230957f728 | |||
| 3c64abd77e | |||
| 1f4d7eff71 | |||
| b4d9dee045 | |||
| 4266a0b570 | |||
| ef4ea45edc | |||
| f1de5df4de | |||
| 28d9a7dfb6 | |||
| 3f56a6878d | |||
| a6fb4bdcea | |||
| 5cb9b04ab0 | |||
| 8ba00467fd | |||
| 79e6631c50 | |||
| a265e71e1a | |||
| eb0a463370 | |||
| c1bb8f9fba | |||
| 79f56b60a0 | |||
| 57e14bc3d2 | |||
| a0086020c1 | |||
| 56da5ebef7 | |||
| 99bbf1eb5a | |||
| 2bbe332532 | |||
| 896d3c7f97 | |||
| cf3a46bae1 | |||
| 2bfde2dfb0 | |||
| 323d646611 | |||
| 81b52abf0f | |||
| bed57f18d3 | |||
| f857d8e791 | |||
| 9e1474e643 | |||
| abf0a65bd6 | |||
| faecfe21ab | |||
| 960eeaf94b | |||
| ce41e348f8 | |||
| 9a44dd8d79 | |||
| d0eed3a33d | |||
| f747db4e27 | |||
| 00d3993a77 |
12
.gitmodules
vendored
@ -26,3 +26,15 @@
|
|||||||
[submodule "Prism/vendor/Box2D"]
|
[submodule "Prism/vendor/Box2D"]
|
||||||
path = Prism/vendor/Box2D
|
path = Prism/vendor/Box2D
|
||||||
url = https://github.com/erincatto/box2d.git
|
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
|
||||||
|
[submodule "Prism/vendor/imgui-node-editor"]
|
||||||
|
path = Prism/vendor/imgui-node-editor
|
||||||
|
url = https://github.com/thedmd/imgui-node-editor.git
|
||||||
|
|||||||
@ -10,7 +10,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
|||||||
# set MSVC output directory
|
# set MSVC output directory
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
# config
|
# config
|
||||||
|
string(REPLACE "/showIncludes" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||||
# temp config
|
# temp config
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251")
|
||||||
|
|
||||||
@ -23,4 +23,5 @@ endif ()
|
|||||||
|
|
||||||
add_subdirectory(Prism)
|
add_subdirectory(Prism)
|
||||||
add_subdirectory(Sandbox)
|
add_subdirectory(Sandbox)
|
||||||
add_subdirectory(Editor)
|
add_subdirectory(Editor)
|
||||||
|
add_subdirectory(PrismRuntime)
|
||||||
|
|||||||
@ -2,17 +2,21 @@ project(PrismEditor)
|
|||||||
|
|
||||||
set(CMAKE_BINARY_DIR ${CMAKE_BINARY_DIR}/bin)
|
set(CMAKE_BINARY_DIR ${CMAKE_BINARY_DIR}/bin)
|
||||||
|
|
||||||
file(GLOB ASSETS assets)
|
file(GLOB ASSETS "assets")
|
||||||
file(COPY ${ASSETS} DESTINATION ${CMAKE_BINARY_DIR})
|
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(GLOB DOTNET_LIBRARY library)
|
||||||
file(COPY ${DOTNET_LIBRARY} DESTINATION ${CMAKE_BINARY_DIR})
|
file(COPY ${DOTNET_LIBRARY} DESTINATION ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
file(GLOB_RECURSE SRC_SOURCE ./**.cpp)
|
file(GLOB_RECURSE SRC_SOURCE ./Editor/**.cpp)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SRC_SOURCE})
|
add_executable(${PROJECT_NAME} ${SRC_SOURCE})
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE Prism-shared)
|
target_link_libraries(${PROJECT_NAME} PRIVATE Prism-static)
|
||||||
|
|
||||||
# Enable ImGui Docking space
|
# Enable ImGui Docking space
|
||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE ENABLE_DOCKSPACE)
|
target_compile_definitions(${PROJECT_NAME} PRIVATE ENABLE_DOCKSPACE)
|
||||||
|
|||||||
@ -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});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,10 @@
|
|||||||
#ifndef EDITORLAYER_H
|
#ifndef EDITORLAYER_H
|
||||||
#define EDITORLAYER_H
|
#define EDITORLAYER_H
|
||||||
|
|
||||||
|
#include "Panels/ConsolePanel.h"
|
||||||
#include "Prism.h"
|
#include "Prism.h"
|
||||||
|
#include "Prism/Editor/ContentBrowserPanel.h"
|
||||||
|
#include "Prism/Editor/ObjectsPanel.h"
|
||||||
#include "Prism/Editor/SceneHierachyPanel.h"
|
#include "Prism/Editor/SceneHierachyPanel.h"
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
@ -26,10 +29,14 @@ namespace Prism
|
|||||||
bool OnKeyPressedEvent(KeyPressedEvent& e);
|
bool OnKeyPressedEvent(KeyPressedEvent& e);
|
||||||
bool OnMouseButtonPressedEvent(MouseButtonPressedEvent& e);
|
bool OnMouseButtonPressedEvent(MouseButtonPressedEvent& e);
|
||||||
|
|
||||||
void ShowBoundingBoxes(bool show, bool onTop = false);
|
void ShowBoundingBoxes(bool show);
|
||||||
void SelectEntity(Entity entity);
|
void SelectEntity(Entity entity);
|
||||||
|
|
||||||
void UpdateWindowTitle(const std::string& sceneName);
|
void UpdateWindowTitle(const std::string& sceneName);
|
||||||
|
|
||||||
|
// GamePad Utils
|
||||||
|
void DrawGamepadDebugPanel(bool& p_open);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::pair<float, float> GetMouseViewportSpace() const;
|
std::pair<float, float> GetMouseViewportSpace() const;
|
||||||
std::pair<glm::vec3, glm::vec3> CastRay(float mx, float my);
|
std::pair<glm::vec3, glm::vec3> CastRay(float mx, float my);
|
||||||
@ -44,18 +51,22 @@ namespace Prism
|
|||||||
void OnEntityDeleted(Entity e);
|
void OnEntityDeleted(Entity e);
|
||||||
Ray CastMouseRay();
|
Ray CastMouseRay();
|
||||||
|
|
||||||
|
void NewScene();
|
||||||
void OpenScene();
|
void OpenScene();
|
||||||
|
void OpenScene(const std::string& filepath);
|
||||||
void SaveScene();
|
void SaveScene();
|
||||||
void SaveSceneAs();
|
void SaveSceneAs();
|
||||||
|
|
||||||
void OnScenePlay();
|
void OnScenePlay();
|
||||||
void OnSceneStop();
|
void OnSceneStop();
|
||||||
|
|
||||||
float GetSnapValue();
|
float GetSnapValue() const;
|
||||||
private:
|
private:
|
||||||
Scope<SceneHierarchyPanel> m_SceneHierarchyPanel;
|
Scope<SceneHierarchyPanel> m_SceneHierarchyPanel;
|
||||||
|
Scope<ContentBrowserPanel> m_ContentBrowserPanel;
|
||||||
|
Scope<ObjectsPanel> m_ObjectsPanel;
|
||||||
|
|
||||||
Ref<Scene> m_ActiveScene;
|
Ref<Scene> m_CurrentScene;
|
||||||
Ref<Scene> m_RuntimeScene, m_EditorScene;
|
Ref<Scene> m_RuntimeScene, m_EditorScene;
|
||||||
std::string m_SceneFilePath;
|
std::string m_SceneFilePath;
|
||||||
|
|
||||||
@ -112,7 +123,7 @@ namespace Prism
|
|||||||
|
|
||||||
struct RoughnessInput
|
struct RoughnessInput
|
||||||
{
|
{
|
||||||
float Value = 0.5f;
|
float Value = 1.0f;
|
||||||
Ref<Texture2D> TextureMap;
|
Ref<Texture2D> TextureMap;
|
||||||
bool UseTexture = false;
|
bool UseTexture = false;
|
||||||
};
|
};
|
||||||
@ -120,22 +131,14 @@ namespace Prism
|
|||||||
|
|
||||||
|
|
||||||
// PBR params
|
// PBR params
|
||||||
bool m_RadiancePrefilter = false;
|
|
||||||
|
|
||||||
float m_EnvMapRotation = 0.0f;
|
|
||||||
|
|
||||||
|
|
||||||
// Editor resources
|
// Editor resources
|
||||||
Ref<Texture2D> m_CheckerboardTex;
|
Ref<Texture2D> m_CheckerboardTex;
|
||||||
Ref<Texture2D> m_PlayButtonTex;
|
Ref<Texture2D> m_PlayButtonTex, m_StopButtonTex, m_PauseButtonTex;
|
||||||
|
|
||||||
|
|
||||||
// configure button
|
|
||||||
bool m_AllowViewportCameraEvents = false;
|
|
||||||
bool m_DrawOnTopBoundingBoxes = false;
|
|
||||||
|
|
||||||
bool m_UIShowBoundingBoxes = false;
|
bool m_UIShowBoundingBoxes = false;
|
||||||
bool m_UIShowBoundingBoxesOnTop = false;
|
|
||||||
|
|
||||||
enum class SceneType : uint32_t
|
enum class SceneType : uint32_t
|
||||||
{
|
{
|
||||||
@ -143,14 +146,19 @@ namespace Prism
|
|||||||
};
|
};
|
||||||
SceneType m_SceneType;
|
SceneType m_SceneType;
|
||||||
|
|
||||||
bool m_ViewportPanelMouseOver = false;
|
bool m_ViewportPanelHovered = false;
|
||||||
bool m_ViewportPanelFocused = false;
|
bool m_ViewportPanelFocused = false;
|
||||||
|
bool m_ShowPhysicsSettings = false;
|
||||||
|
bool m_ShowGamePadSettings = false;
|
||||||
|
|
||||||
enum class SceneState
|
enum class SceneState
|
||||||
{
|
{
|
||||||
Edit = 0, Play = 1, Pause = 2
|
Edit = 0, Play = 1, Pause = 2
|
||||||
};
|
};
|
||||||
SceneState m_SceneState = SceneState::Edit;
|
SceneState m_SceneState = SceneState::Edit;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Scope<ConsolePanel> m_ConsolePanel;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
66
Editor/Editor/Panels/ConsolePanel.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
31
Editor/Editor/Panels/ConsolePanel.h
Normal 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
|
||||||
BIN
Editor/assets/editor/Camera.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
Editor/assets/editor/PauseButton.png
Normal file
|
After Width: | Height: | Size: 119 B |
BIN
Editor/assets/editor/StopButton.png
Normal file
|
After Width: | Height: | Size: 115 B |
BIN
Editor/assets/editor/asset.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
Editor/assets/editor/back.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
Editor/assets/editor/blend.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
Editor/assets/editor/btn_back.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
Editor/assets/editor/btn_fwrd.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
Editor/assets/editor/close.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
Editor/assets/editor/csc.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
Editor/assets/editor/favourites.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
Editor/assets/editor/fbx.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
Editor/assets/editor/file.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
Editor/assets/editor/folder.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
Editor/assets/editor/folder_hierarchy.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
Editor/assets/editor/grid.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
Editor/assets/editor/light.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
Editor/assets/editor/list.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
Editor/assets/editor/model.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
Editor/assets/editor/obj.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
Editor/assets/editor/png.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
Editor/assets/editor/resource.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
Editor/assets/editor/scene.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
Editor/assets/editor/script.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
Editor/assets/editor/search.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
Editor/assets/editor/tags.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
Editor/assets/editor/texture.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
Editor/assets/editor/wav.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
Editor/assets/meshes/Default/Capsule.fbx
Normal file
BIN
Editor/assets/meshes/Default/Cone.fbx
Normal file
BIN
Editor/assets/meshes/Default/Cube.fbx
Normal file
BIN
Editor/assets/meshes/Default/Cylinder.fbx
Normal file
BIN
Editor/assets/meshes/Default/Plane.fbx
Normal file
BIN
Editor/assets/meshes/Default/Sphere.fbx
Normal file
BIN
Editor/assets/meshes/Default/Torus.fbx
Normal file
@ -1,155 +0,0 @@
|
|||||||
Scene: Scene Name
|
|
||||||
Environment:
|
|
||||||
AssetPath: assets/env/pink_sunrise_4k.hdr
|
|
||||||
Light:
|
|
||||||
Direction: [-0.787, -0.73299998, 1]
|
|
||||||
Radiance: [1, 1, 1]
|
|
||||||
Multiplier: 0.514999986
|
|
||||||
Entities:
|
|
||||||
- Entity: 12498244675852797835
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-12.0348625, 6.59647179, 9.60061925e-07]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [3.00000024, 0.300000012, 1]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 0
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [1.5, 0.150000006]
|
|
||||||
Density: 1
|
|
||||||
Friction: 1
|
|
||||||
- Entity: 5178862374589434728
|
|
||||||
TagComponent:
|
|
||||||
Tag: Camera
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-21.7406311, 9.70659542, 15]
|
|
||||||
Rotation: [0.999910355, -0.0133911213, 0, 0]
|
|
||||||
Scale: [1, 1, 1]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.BasicController
|
|
||||||
StoredFields:
|
|
||||||
- Name: Speed
|
|
||||||
Type: 1
|
|
||||||
Data: 12
|
|
||||||
CameraComponent:
|
|
||||||
Camera: some camera data...
|
|
||||||
Primary: true
|
|
||||||
- Entity: 1289165777996378215
|
|
||||||
TagComponent:
|
|
||||||
Tag: Cube
|
|
||||||
TransformComponent:
|
|
||||||
Position: [500, 0, 0]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [1200, 1, 5]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 0
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [600, 0.5]
|
|
||||||
Density: 1
|
|
||||||
Friction: 2
|
|
||||||
- Entity: 14057422478420564497
|
|
||||||
TagComponent:
|
|
||||||
Tag: Player
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-23.6932545, 1.59184527, -1.96369365e-06]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [1, 1, 1]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.PlayerCube
|
|
||||||
StoredFields:
|
|
||||||
- Name: HorizontalForce
|
|
||||||
Type: 1
|
|
||||||
Data: 0.5
|
|
||||||
- Name: MaxSpeed
|
|
||||||
Type: 5
|
|
||||||
Data: [7, 10]
|
|
||||||
- Name: JumpForce
|
|
||||||
Type: 1
|
|
||||||
Data: 3
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Sphere1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 29.2000008
|
|
||||||
CircleCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Radius: 0.5
|
|
||||||
Density: 1
|
|
||||||
Friction: 1
|
|
||||||
- Entity: 1352995477042327524
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-29.6808929, 29.7597198, 0]
|
|
||||||
Rotation: [0.707106769, 0, 0, 0.707106769]
|
|
||||||
Scale: [58.4179001, 4.47999144, 4.48000002]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 0
|
|
||||||
Mass: 3
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [29.7000008, 2.24000001]
|
|
||||||
Density: 1
|
|
||||||
Friction: 1
|
|
||||||
- Entity: 15223077898852293773
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [6.12674046, 45.5617676, 0]
|
|
||||||
Rotation: [0.977883637, 0, 0, -0.209149584]
|
|
||||||
Scale: [4.47999668, 4.47999668, 4.48000002]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [2.24000001, 2.24000001]
|
|
||||||
Density: 1
|
|
||||||
Friction: 1
|
|
||||||
- Entity: 5421735812495444456
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-20.766222, 2.29431438, 0]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [3.00000024, 0.300000012, 1]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 0
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [1.5, 0.150000006]
|
|
||||||
Density: 1
|
|
||||||
Friction: 1
|
|
||||||
- Entity: 2842299641876190180
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-16.6143265, 4.39151001, 6.43359499e-09]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [3.00000024, 0.300000012, 1]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 0
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [1.5, 0.150000006]
|
|
||||||
Density: 1
|
|
||||||
Friction: 1
|
|
||||||
389
Editor/assets/scenes/FPS.scene
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
Scene: Scene Name
|
||||||
|
Environment:
|
||||||
|
AssetHandle: 10745193190519058183
|
||||||
|
Entities:
|
||||||
|
- Entity: 4944419254382500800
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: Directional Light
|
||||||
|
TransformComponent:
|
||||||
|
Position: [0, 0, 0]
|
||||||
|
Rotation: [-2.2312348, 0, 0]
|
||||||
|
Scale: [1, 1, 1]
|
||||||
|
DirectionalLightComponent:
|
||||||
|
Radiance: [1, 1, 1]
|
||||||
|
CastShadows: true
|
||||||
|
SoftShadows: true
|
||||||
|
LightSize: 0.5
|
||||||
|
- 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: 10745193190519058183
|
||||||
|
EnvironmentAssetPath: assets/env/venice_dawn_1_4k.hdr
|
||||||
|
Intensity: 1
|
||||||
|
Angle: 0
|
||||||
|
DynamicSky: false
|
||||||
|
TurbidityAzimuthInclination: [2, 0, 0]
|
||||||
|
- Entity: 10732070446010033158
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: Cube
|
||||||
|
TransformComponent:
|
||||||
|
Position: [0, -2.6466873, 0]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [100, 1, 100]
|
||||||
|
MeshComponent:
|
||||||
|
AssetID: 14957733959243172548
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
Materials:
|
||||||
|
Slot 0:
|
||||||
|
AssetHandle: 0
|
||||||
|
AssetPath: ""
|
||||||
|
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: 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: m_Radius
|
||||||
|
Type: 1
|
||||||
|
Data: 0
|
||||||
|
- Name: WalkingSpeed
|
||||||
|
Type: 1
|
||||||
|
Data: 2
|
||||||
|
- Name: RunSpeed
|
||||||
|
Type: 1
|
||||||
|
Data: 5
|
||||||
|
- Name: JumpForce
|
||||||
|
Type: 1
|
||||||
|
Data: 1
|
||||||
|
- Name: TorqueStrength
|
||||||
|
Type: 1
|
||||||
|
Data: 0
|
||||||
|
- Name: MouseSensitivity
|
||||||
|
Type: 1
|
||||||
|
Data: 10
|
||||||
|
- Name: CameraForwardOffset
|
||||||
|
Type: 1
|
||||||
|
Data: -2
|
||||||
|
- Name: CameraYOffset
|
||||||
|
Type: 1
|
||||||
|
Data: 2
|
||||||
|
MeshComponent:
|
||||||
|
AssetID: 8763440120556133680
|
||||||
|
AssetPath: assets/meshes/Default/Capsule.fbx
|
||||||
|
Materials:
|
||||||
|
Slot 0:
|
||||||
|
AssetHandle: 0
|
||||||
|
AssetPath: ""
|
||||||
|
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: 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: 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: 14957733959243172548
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
Materials:
|
||||||
|
Slot 0:
|
||||||
|
AssetHandle: 0
|
||||||
|
AssetPath: ""
|
||||||
|
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: 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: 14957733959243172548
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
Materials:
|
||||||
|
Slot 0:
|
||||||
|
AssetHandle: 0
|
||||||
|
AssetPath: ""
|
||||||
|
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: 14957733959243172548
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
Materials:
|
||||||
|
Slot 0:
|
||||||
|
AssetHandle: 0
|
||||||
|
AssetPath: ""
|
||||||
|
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: 14957733959243172548
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
Materials:
|
||||||
|
Slot 0:
|
||||||
|
AssetHandle: 0
|
||||||
|
AssetPath: ""
|
||||||
|
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: 14957733959243172548
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
Materials:
|
||||||
|
Slot 0:
|
||||||
|
AssetHandle: 0
|
||||||
|
AssetPath: ""
|
||||||
|
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: 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: 14957733959243172548
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
Materials:
|
||||||
|
Slot 0:
|
||||||
|
AssetHandle: 0
|
||||||
|
AssetPath: ""
|
||||||
|
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: ""
|
||||||
|
PhysicsLayers:
|
||||||
|
[]
|
||||||
64
Editor/assets/scenes/FPSDemo.scene
Normal 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:
|
||||||
|
[]
|
||||||
@ -1,174 +0,0 @@
|
|||||||
Scene: Scene Name
|
|
||||||
Environment:
|
|
||||||
AssetPath: assets/env/pink_sunrise_4k.hdr
|
|
||||||
Light:
|
|
||||||
Direction: [-0.787, -0.73299998, 1]
|
|
||||||
Radiance: [1, 1, 1]
|
|
||||||
Multiplier: 0.514999986
|
|
||||||
Entities:
|
|
||||||
- Entity: 15861629587505754
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-18.2095661, 39.2518234, 0]
|
|
||||||
Rotation: [0.967056513, 0, 0, -0.254561812]
|
|
||||||
Scale: [4.47999525, 4.47999525, 4.48000002]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [2.24000001, 2.24000001]
|
|
||||||
- Entity: 15223077898852293773
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [5.37119865, 43.8762894, 0]
|
|
||||||
Rotation: [0.977883637, 0, 0, -0.209149718]
|
|
||||||
Scale: [4.47999668, 4.47999668, 4.48000002]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [2.24000001, 2.24000001]
|
|
||||||
- Entity: 2157107598622182863
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-7.60411549, 44.1442184, 0]
|
|
||||||
Rotation: [0.989285827, 0, 0, 0.145991713]
|
|
||||||
Scale: [4.47999287, 4.47999287, 4.48000002]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 0.5
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [2.24000001, 2.24000001]
|
|
||||||
- Entity: 8080964283681139153
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-0.739211679, 37.7653275, 0]
|
|
||||||
Rotation: [0.956475914, 0, 0, -0.291811317]
|
|
||||||
Scale: [5, 2, 2]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 0.25
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [2.5, 1]
|
|
||||||
- Entity: 1352995477042327524
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-8.32969856, 30.4078159, 0]
|
|
||||||
Rotation: [0.781595349, 0, 0, 0.623785794]
|
|
||||||
Scale: [14.000001, 4.47999334, 4.48000002]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 3
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [7, 2.24000001]
|
|
||||||
- Entity: 935615878363259513
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [6.88031197, 31.942337, 0]
|
|
||||||
Rotation: [0.986578286, 0, 0, 0.163288936]
|
|
||||||
Scale: [4.47999954, 4.47999954, 4.48000002]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [2.24000001, 2.24000001]
|
|
||||||
- Entity: 14057422478420564497
|
|
||||||
TagComponent:
|
|
||||||
Tag: Player
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0, 22.774044, 0]
|
|
||||||
Rotation: [0.942591429, 0, 0, -0.333948225]
|
|
||||||
Scale: [6.00000048, 6.00000048, 4.48000002]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.PlayerCube
|
|
||||||
StoredFields:
|
|
||||||
- Name: HorizontalForce
|
|
||||||
Type: 1
|
|
||||||
Data: 10
|
|
||||||
- Name: VerticalForce
|
|
||||||
Type: 1
|
|
||||||
Data: 10
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Sphere1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 1
|
|
||||||
CircleCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Radius: 3
|
|
||||||
- Entity: 1289165777996378215
|
|
||||||
TagComponent:
|
|
||||||
Tag: Cube
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0, 0, 0]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [50, 1, 50]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.Sink
|
|
||||||
StoredFields:
|
|
||||||
- Name: SinkSpeed
|
|
||||||
Type: 1
|
|
||||||
Data: 0
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 0
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [25, 0.5]
|
|
||||||
- Entity: 5178862374589434728
|
|
||||||
TagComponent:
|
|
||||||
Tag: Camera
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0, 25, 79.75]
|
|
||||||
Rotation: [0.995602965, -0.0936739072, 0, 0]
|
|
||||||
Scale: [1, 0.999999821, 0.999999821]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.BasicController
|
|
||||||
StoredFields:
|
|
||||||
- Name: Speed
|
|
||||||
Type: 1
|
|
||||||
Data: 12
|
|
||||||
CameraComponent:
|
|
||||||
Camera: some camera data...
|
|
||||||
Primary: true
|
|
||||||
- Entity: 3948844418381294888
|
|
||||||
TagComponent:
|
|
||||||
Tag: Box
|
|
||||||
TransformComponent:
|
|
||||||
Position: [-1.48028564, 49.5945244, -2.38418579e-07]
|
|
||||||
Rotation: [0.977883637, 0, 0, -0.209149733]
|
|
||||||
Scale: [1.99999976, 1.99999976, 2]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Cube1m.fbx
|
|
||||||
RigidBody2DComponent:
|
|
||||||
BodyType: 1
|
|
||||||
Mass: 1
|
|
||||||
BoxCollider2DComponent:
|
|
||||||
Offset: [0, 0]
|
|
||||||
Size: [1, 1]
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
Scene: Scene Name
|
|
||||||
Environment:
|
|
||||||
AssetPath: assets/env/birchwood_4k.hdr
|
|
||||||
Light:
|
|
||||||
Direction: [-0.5, -0.5, 1]
|
|
||||||
Radiance: [1, 1, 1]
|
|
||||||
Multiplier: 1
|
|
||||||
Entities:
|
|
||||||
- Entity: 1289165777996378215
|
|
||||||
TagComponent:
|
|
||||||
Tag: Sphere
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0, 21.9805069, -1.64006281]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [0.100000024, 0.100000024, 0.100000024]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.Sink
|
|
||||||
StoredFields:
|
|
||||||
- Name: SinkSpeed
|
|
||||||
Type: 1
|
|
||||||
Data: 5
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/Sphere1m.fbx
|
|
||||||
- Entity: 5178862374589434728
|
|
||||||
TagComponent:
|
|
||||||
Tag: Camera
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0, 14.75, 79.75]
|
|
||||||
Rotation: [0.995602965, -0.0936739072, 0, 0]
|
|
||||||
Scale: [1, 0.999999821, 0.999999821]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.BasicController
|
|
||||||
StoredFields:
|
|
||||||
- Name: Speed
|
|
||||||
Type: 1
|
|
||||||
Data: 12
|
|
||||||
CameraComponent:
|
|
||||||
Camera: some camera data...
|
|
||||||
Primary: true
|
|
||||||
- Entity: 9095450049242347594
|
|
||||||
TagComponent:
|
|
||||||
Tag: Test Entity
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0.248109579, -1.90734863e-06, -0.268640995]
|
|
||||||
Rotation: [1, 0, 0, 0]
|
|
||||||
Scale: [1, 1, 1]
|
|
||||||
ScriptComponent:
|
|
||||||
ModuleName: Example.Script
|
|
||||||
StoredFields:
|
|
||||||
- Name: VerticalSpeed
|
|
||||||
Type: 1
|
|
||||||
Data: 0
|
|
||||||
- Name: SinkRate
|
|
||||||
Type: 1
|
|
||||||
Data: 0
|
|
||||||
- Name: Speed
|
|
||||||
Type: 1
|
|
||||||
Data: 1
|
|
||||||
- Name: Rotation
|
|
||||||
Type: 1
|
|
||||||
Data: 0
|
|
||||||
- Name: Velocity
|
|
||||||
Type: 6
|
|
||||||
Data: [0, 0, 0]
|
|
||||||
MeshComponent:
|
|
||||||
AssetPath: assets/meshes/TestScene.fbx
|
|
||||||
36
Editor/assets/scenes/demo.scene
Normal 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:
|
||||||
|
[]
|
||||||
63
Editor/assets/shaders/BloomBlend.glsl
Normal 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
|
||||||
|
}
|
||||||
84
Editor/assets/shaders/BloomBlur.glsl
Normal 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);
|
||||||
|
}
|
||||||
24
Editor/assets/shaders/Collider.glsl
Normal 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);
|
||||||
|
}
|
||||||
@ -107,16 +107,16 @@ void main(void)
|
|||||||
if(gl_GlobalInvocationID.x >= outputSize.x || gl_GlobalInvocationID.y >= outputSize.y) {
|
if(gl_GlobalInvocationID.x >= outputSize.x || gl_GlobalInvocationID.y >= outputSize.y) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Solid angle associated with a single cubemap texel at zero mipmap level.
|
// Solid angle associated with a single cubemap texel at zero mipmap level.
|
||||||
// This will come in handy for importance sampling below.
|
// This will come in handy for importance sampling below.
|
||||||
vec2 inputSize = vec2(textureSize(inputTexture, 0));
|
vec2 inputSize = vec2(textureSize(inputTexture, 0));
|
||||||
float wt = 4.0 * PI / (6 * inputSize.x * inputSize.y);
|
float wt = 4.0 * PI / (6 * inputSize.x * inputSize.y);
|
||||||
|
|
||||||
// Approximation: Assume zero viewing angle (isotropic reflections).
|
// Approximation: Assume zero viewing angle (isotropic reflections).
|
||||||
vec3 N = GetCubeMapTexCoord();
|
vec3 N = GetCubeMapTexCoord();
|
||||||
vec3 Lo = N;
|
vec3 Lo = N;
|
||||||
|
|
||||||
vec3 S, T;
|
vec3 S, T;
|
||||||
computeBasisVectors(N, S, T);
|
computeBasisVectors(N, S, T);
|
||||||
|
|
||||||
|
|||||||
63
Editor/assets/shaders/Exposure.glsl
Normal 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;
|
||||||
|
}
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
26
Editor/assets/shaders/Histogram.glsl
Normal 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);
|
||||||
|
}
|
||||||
224
Editor/assets/shaders/InfiniteGrid.glsl
Normal 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);
|
||||||
|
}
|
||||||
@ -4,13 +4,10 @@
|
|||||||
#version 430
|
#version 430
|
||||||
|
|
||||||
layout(location = 0) in vec3 a_Position;
|
layout(location = 0) in vec3 a_Position;
|
||||||
layout(location = 1) in vec2 a_TexCoord;
|
|
||||||
|
|
||||||
uniform mat4 u_ViewProjection;
|
uniform mat4 u_ViewProjection;
|
||||||
uniform mat4 u_Transform;
|
uniform mat4 u_Transform;
|
||||||
|
|
||||||
out vec2 v_TexCoord;
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
|
gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
|
||||||
|
|||||||
36
Editor/assets/shaders/Outline_Anim.glsl
Normal 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);
|
||||||
|
}
|
||||||
@ -1,8 +1,8 @@
|
|||||||
// -----------------------------
|
// -----------------------------
|
||||||
// -- From Hazel Engine PBR shader --
|
// -- Based on Hazel PBR shader --
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
||||||
// Currently heavily updated.
|
// Currently heavily updated.
|
||||||
//
|
//
|
||||||
// References upon which this is based:
|
// 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)
|
// - Unreal Engine 4 PBR notes (https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf)
|
||||||
@ -21,19 +21,23 @@ layout(location = 4) in vec2 a_TexCoord;
|
|||||||
layout(location = 5) in ivec4 a_BoneIndices;
|
layout(location = 5) in ivec4 a_BoneIndices;
|
||||||
layout(location = 6) in vec4 a_BoneWeights;
|
layout(location = 6) in vec4 a_BoneWeights;
|
||||||
|
|
||||||
uniform mat4 u_ViewProjectionMatrix;
|
|
||||||
uniform mat4 u_Transform;
|
|
||||||
|
|
||||||
const int MAX_BONES = 100;
|
const int MAX_BONES = 100;
|
||||||
uniform mat4 u_BoneTransforms[100];
|
uniform mat4 u_BoneTransforms[100];
|
||||||
|
|
||||||
|
uniform mat4 u_ViewProjectionMatrix;
|
||||||
|
uniform mat4 u_ViewMatrix;
|
||||||
|
uniform mat4 u_Transform;
|
||||||
|
|
||||||
out VertexOutput
|
out VertexOutput
|
||||||
{
|
{
|
||||||
vec3 WorldPosition;
|
vec3 WorldPosition;
|
||||||
vec3 Normal;
|
vec3 Normal;
|
||||||
vec2 TexCoord;
|
vec2 TexCoord;
|
||||||
mat3 WorldNormals;
|
mat3 WorldNormals;
|
||||||
vec3 Binormal;
|
mat3 WorldTransform;
|
||||||
|
vec3 Binormal;
|
||||||
|
vec3 ViewPosition;
|
||||||
|
float ViewZ;
|
||||||
} vs_Output;
|
} vs_Output;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
@ -43,15 +47,20 @@ void main()
|
|||||||
boneTransform += u_BoneTransforms[a_BoneIndices[2]] * a_BoneWeights[2];
|
boneTransform += u_BoneTransforms[a_BoneIndices[2]] * a_BoneWeights[2];
|
||||||
boneTransform += u_BoneTransforms[a_BoneIndices[3]] * a_BoneWeights[3];
|
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.Normal = mat3(u_Transform) * mat3(boneTransform) * a_Normal;
|
||||||
vs_Output.TexCoord = vec2(a_TexCoord.x, 1.0 - a_TexCoord.y);
|
vs_Output.TexCoord = vec2(a_TexCoord.x, 1.0 - a_TexCoord.y);
|
||||||
vs_Output.WorldNormals = mat3(u_Transform) * mat3(a_Tangent, a_Binormal, a_Normal);
|
vs_Output.WorldNormals = mat3(u_Transform) * mat3(a_Tangent, a_Binormal, a_Normal);
|
||||||
vs_Output.Binormal = mat3(boneTransform) * a_Binormal;
|
vs_Output.WorldTransform = mat3(u_Transform);
|
||||||
|
vs_Output.Binormal = a_Binormal;
|
||||||
|
|
||||||
gl_Position = u_ViewProjectionMatrix * u_Transform * localPosition;
|
vs_Output.ViewPosition = vec3(u_ViewMatrix * vec4(vs_Output.WorldPosition, 1.0));
|
||||||
|
vs_Output.ViewZ = vs_Output.ViewPosition.z;
|
||||||
|
|
||||||
|
// gl_Position = u_ViewProjectionMatrix * u_Transform * vec4(a_Position, 1.0);
|
||||||
|
gl_Position = u_ViewProjectionMatrix * u_Transform * localPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
#type fragment
|
#type fragment
|
||||||
@ -61,102 +70,131 @@ const float PI = 3.141592;
|
|||||||
const float Epsilon = 0.00001;
|
const float Epsilon = 0.00001;
|
||||||
|
|
||||||
const int LightCount = 1;
|
const int LightCount = 1;
|
||||||
|
|
||||||
// Constant normal incidence Fresnel factor for all dielectrics.
|
|
||||||
const vec3 Fdielectric = vec3(0.04);
|
const vec3 Fdielectric = vec3(0.04);
|
||||||
|
|
||||||
struct Light {
|
layout(location = 0) out vec4 color;
|
||||||
vec3 Direction;
|
layout(location = 1) out vec4 o_MaterialInfo;
|
||||||
vec3 Radiance;
|
layout(location = 2) out vec4 o_BloomColor;
|
||||||
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
|
in VertexOutput
|
||||||
{
|
{
|
||||||
vec3 WorldPosition;
|
vec3 WorldPosition;
|
||||||
vec3 Normal;
|
vec3 Normal;
|
||||||
vec2 TexCoord;
|
vec2 TexCoord;
|
||||||
mat3 WorldNormals;
|
mat3 WorldNormals;
|
||||||
vec3 Binormal;
|
mat3 WorldTransform;
|
||||||
|
vec3 Binormal;
|
||||||
|
vec3 ViewPosition;
|
||||||
|
float ViewZ;
|
||||||
} vs_Input;
|
} vs_Input;
|
||||||
|
|
||||||
layout(location=0) out vec4 color;
|
|
||||||
|
|
||||||
uniform Light lights;
|
uniform DirectionalLight u_DirectionalLights;
|
||||||
uniform vec3 u_CameraPosition;
|
uniform vec3 u_CameraPosition;
|
||||||
|
|
||||||
// PBR texture inputs
|
uniform int u_PointLightCount;
|
||||||
|
uniform PointLight u_PointLights[8];
|
||||||
|
|
||||||
|
uniform int u_SpotLightCount;
|
||||||
|
uniform SpotLight u_SpotLights[8];
|
||||||
|
|
||||||
|
|
||||||
|
// PBR
|
||||||
uniform sampler2D u_AlbedoTexture;
|
uniform sampler2D u_AlbedoTexture;
|
||||||
uniform sampler2D u_NormalTexture;
|
uniform sampler2D u_NormalTexture;
|
||||||
uniform sampler2D u_MetalnessTexture;
|
uniform sampler2D u_MetalnessTexture;
|
||||||
uniform sampler2D u_RoughnessTexture;
|
uniform sampler2D u_RoughnessTexture;
|
||||||
|
|
||||||
// Environment maps
|
// environment
|
||||||
uniform samplerCube u_EnvRadianceTex;
|
uniform samplerCube u_EnvRadianceTex;
|
||||||
uniform samplerCube u_EnvIrradianceTex;
|
uniform samplerCube u_EnvIrradianceTex;
|
||||||
|
|
||||||
// BRDF LUT
|
// BRDF LUT
|
||||||
uniform sampler2D u_BRDFLUTTexture;
|
uniform sampler2D u_BRDFLUTTexture;
|
||||||
|
|
||||||
uniform vec3 u_AlbedoColor;
|
uniform float u_IBLContribution;
|
||||||
|
uniform float u_BloomThreshold;
|
||||||
|
uniform float u_EnvMapRotation;
|
||||||
|
|
||||||
|
// baseColor
|
||||||
|
uniform vec4 u_AlbedoColor;
|
||||||
uniform float u_Metalness;
|
uniform float u_Metalness;
|
||||||
uniform float u_Roughness;
|
uniform float u_Roughness;
|
||||||
|
|
||||||
uniform float u_EnvMapRotation;
|
// textureToggle
|
||||||
|
|
||||||
// Toggles
|
|
||||||
uniform float u_RadiancePrefilter;
|
|
||||||
uniform float u_AlbedoTexToggle;
|
uniform float u_AlbedoTexToggle;
|
||||||
uniform float u_NormalTexToggle;
|
uniform float u_NormalTexToggle;
|
||||||
uniform float u_MetalnessTexToggle;
|
uniform float u_MetalnessTexToggle;
|
||||||
uniform float u_RoughnessTexToggle;
|
uniform float u_RoughnessTexToggle;
|
||||||
|
|
||||||
|
// shadow
|
||||||
|
const int CSM_CASCADE_COUNT = 4;
|
||||||
|
uniform sampler2D u_ShadowMap[4];
|
||||||
|
uniform mat4 u_LightSpaceMatrix0;
|
||||||
|
uniform mat4 u_LightSpaceMatrix1;
|
||||||
|
uniform mat4 u_LightSpaceMatrix2;
|
||||||
|
uniform mat4 u_LightSpaceMatrix3;
|
||||||
|
uniform vec4 u_CascadeSplits;
|
||||||
|
uniform float u_ShadowFar;
|
||||||
|
uniform float u_ShadowNear;
|
||||||
|
uniform float u_ShadowBias;
|
||||||
|
uniform float u_ShadowSoftness;
|
||||||
|
uniform float u_ShadowIntensity;
|
||||||
|
uniform int u_ShadowEnabled;
|
||||||
|
|
||||||
struct PBRParameters
|
struct PBRParameters
|
||||||
{
|
{
|
||||||
vec3 Albedo;
|
vec4 Albedo;
|
||||||
float Roughness;
|
float Roughness;
|
||||||
float Metalness;
|
float Metalness;
|
||||||
|
vec3 Normal;
|
||||||
vec3 Normal;
|
vec3 View;
|
||||||
vec3 View;
|
float NdotV;
|
||||||
float NdotV;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PBRParameters m_Params;
|
PBRParameters m_Params;
|
||||||
|
|
||||||
// GGX/Towbridge-Reitz normal distribution function.
|
// ---------- PBR param func ----------
|
||||||
// Uses Disney's reparametrization of alpha = roughness^2
|
|
||||||
float ndfGGX(float cosLh, float roughness)
|
float ndfGGX(float cosLh, float roughness)
|
||||||
{
|
{
|
||||||
float alpha = roughness * roughness;
|
float alpha = roughness * roughness;
|
||||||
float alphaSq = alpha * alpha;
|
float alphaSq = alpha * alpha;
|
||||||
|
float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
|
||||||
float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
|
return alphaSq / (PI * denom * denom);
|
||||||
return alphaSq / (PI * denom * denom);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Single term for separable Schlick-GGX below.
|
|
||||||
float gaSchlickG1(float cosTheta, float k)
|
|
||||||
{
|
|
||||||
return cosTheta / (cosTheta * (1.0 - k) + k);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Schlick-GGX approximation of geometric attenuation function using Smith's method.
|
|
||||||
float gaSchlickGGX(float cosLi, float NdotV, float roughness)
|
|
||||||
{
|
|
||||||
float r = roughness + 1.0;
|
|
||||||
float k = (r * r) / 8.0; // Epic suggests using this roughness remapping for analytic lights.
|
|
||||||
return gaSchlickG1(cosLi, k) * gaSchlickG1(NdotV, k);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float GeometrySchlickGGX(float NdotV, float roughness)
|
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||||
{
|
{
|
||||||
float r = (roughness + 1.0);
|
float r = (roughness + 1.0);
|
||||||
float k = (r*r) / 8.0;
|
float k = (r * r) / 8.0;
|
||||||
|
float nom = NdotV;
|
||||||
float nom = NdotV;
|
|
||||||
float denom = NdotV * (1.0 - k) + k;
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
|
|
||||||
return nom / denom;
|
return nom / denom;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,165 +204,333 @@ float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
|||||||
float NdotL = max(dot(N, L), 0.0);
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||||
|
|
||||||
return ggx1 * ggx2;
|
return ggx1 * ggx2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shlick's approximation of the Fresnel factor.
|
|
||||||
vec3 fresnelSchlick(vec3 F0, float cosTheta)
|
vec3 fresnelSchlick(vec3 F0, float cosTheta)
|
||||||
{
|
{
|
||||||
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness)
|
vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness)
|
||||||
{
|
{
|
||||||
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------------
|
|
||||||
// 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.rgb;
|
||||||
|
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;
|
vec3 lightVec = light.Position - worldPos;
|
||||||
float Phi = 2 * PI * Xi.x;
|
float dist = length(lightVec);
|
||||||
float CosTheta = sqrt( (1 - Xi.y) / ( 1 + (a*a - 1) * Xi.y ) );
|
if (dist > light.Range) return vec3(0.0);
|
||||||
float SinTheta = sqrt( 1 - CosTheta * CosTheta );
|
|
||||||
vec3 H;
|
vec3 L = lightVec / dist;
|
||||||
H.x = SinTheta * cos( Phi );
|
vec3 Lradiance = light.Radiance * light.Intensity;
|
||||||
H.y = SinTheta * sin( Phi );
|
|
||||||
H.z = CosTheta;
|
// 距离衰减:通常使用平方衰减,但为避免分母为零,加一个小值
|
||||||
vec3 UpVector = abs(N.z) < 0.999 ? vec3(0,0,1) : vec3(1,0,0);
|
float attenuation = 1.0 / (dist * dist + 0.0001);
|
||||||
vec3 TangentX = normalize( cross( UpVector, N ) );
|
|
||||||
vec3 TangentY = cross( N, TangentX );
|
// 可选:范围平滑衰减
|
||||||
// Tangent to world space
|
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
|
||||||
return TangentX * H.x + TangentY * H.y + N * H.z;
|
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.rgb;
|
||||||
|
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
|
||||||
|
|
||||||
|
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
float TotalWeight = 0.0;
|
vec3 ComputeSpotLight(SpotLight light, vec3 F0, PBRParameters params, vec3 worldPos)
|
||||||
|
|
||||||
vec3 PrefilterEnvMap(float Roughness, vec3 R)
|
|
||||||
{
|
{
|
||||||
vec3 N = R;
|
vec3 lightVec = light.Position - worldPos;
|
||||||
vec3 V = R;
|
float dist = length(lightVec);
|
||||||
vec3 PrefilteredColor = vec3(0.0);
|
if (dist > light.Range) return vec3(0.0);
|
||||||
int NumSamples = 1024;
|
|
||||||
for(int i = 0; i < NumSamples; i++)
|
vec3 L = lightVec / dist;
|
||||||
{
|
vec3 Lradiance = light.Radiance * light.Intensity;
|
||||||
vec2 Xi = Hammersley(i, NumSamples);
|
|
||||||
vec3 H = ImportanceSampleGGX(Xi, Roughness, N);
|
// 距离衰减
|
||||||
vec3 L = 2 * dot(V, H) * H - V;
|
float attenuation = 1.0 / (dist * dist + 0.0001);
|
||||||
float NoL = clamp(dot(N, L), 0.0, 1.0);
|
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
|
||||||
if (NoL > 0)
|
rangeFactor = rangeFactor * rangeFactor;
|
||||||
{
|
attenuation *= rangeFactor;
|
||||||
PrefilteredColor += texture(u_EnvRadianceTex, L).rgb * NoL;
|
|
||||||
TotalWeight += NoL;
|
// 角度衰减(聚光锥)
|
||||||
}
|
float cosAngle = dot(-L, normalize(light.Direction)); // 光方向指向外,所以用 -L
|
||||||
}
|
if (cosAngle < light.OuterConeCos) return vec3(0.0);
|
||||||
return PrefilteredColor / TotalWeight;
|
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.rgb;
|
||||||
|
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 Lighting(vec3 F0)
|
||||||
{
|
{
|
||||||
vec3 result = vec3(0.0);
|
vec3 result = vec3(0.0);
|
||||||
for(int i = 0; i < LightCount; i++)
|
for(int i = 0; i < LightCount; i++)
|
||||||
{
|
{
|
||||||
vec3 Li = -lights.Direction;
|
vec3 Li = u_DirectionalLights.Direction;
|
||||||
vec3 Lradiance = lights.Radiance * lights.Multiplier;
|
vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.Intensity;
|
||||||
vec3 Lh = normalize(Li + m_Params.View);
|
vec3 Lh = normalize(Li + m_Params.View);
|
||||||
|
|
||||||
// Calculate angles between surface normal and various light vectors.
|
float cosLi = max(0.0, dot(m_Params.Normal, Li));
|
||||||
float cosLi = max(0.0, dot(m_Params.Normal, Li));
|
float cosLh = max(0.0, dot(m_Params.Normal, Lh));
|
||||||
float cosLh = max(0.0, dot(m_Params.Normal, Lh));
|
|
||||||
|
|
||||||
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, m_Params.View)));
|
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, m_Params.View)));
|
||||||
float D = ndfGGX(cosLh, m_Params.Roughness);
|
float D = ndfGGX(cosLh, m_Params.Roughness);
|
||||||
float G = gaSchlickGGX(cosLi, m_Params.NdotV, m_Params.Roughness);
|
float G = GeometrySmith(m_Params.Normal, m_Params.View, Li, m_Params.Roughness);
|
||||||
|
|
||||||
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
||||||
vec3 diffuseBRDF = kd * m_Params.Albedo;
|
vec3 diffuseBRDF = kd * m_Params.Albedo.rgb;
|
||||||
|
|
||||||
// Cook-Torrance
|
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * m_Params.NdotV);
|
||||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * m_Params.NdotV);
|
|
||||||
|
|
||||||
result += (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
|
result += (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- IBL ----------
|
||||||
|
vec3 RotateVectorAboutY(float angle, vec3 vec)
|
||||||
|
{
|
||||||
|
angle = radians(angle);
|
||||||
|
mat3 rotationMatrix = mat3(
|
||||||
|
vec3(cos(angle), 0.0, sin(angle)),
|
||||||
|
vec3(0.0, 1.0, 0.0),
|
||||||
|
vec3(-sin(angle), 0.0, cos(angle))
|
||||||
|
);
|
||||||
|
return rotationMatrix * vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 IBL(vec3 F0, vec3 Lr)
|
vec3 IBL(vec3 F0, vec3 Lr)
|
||||||
{
|
{
|
||||||
vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb;
|
vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb;
|
||||||
vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness);
|
vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness);
|
||||||
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
||||||
vec3 diffuseIBL = m_Params.Albedo * irradiance;
|
vec3 diffuseIBL = m_Params.Albedo.rgb * irradiance;
|
||||||
|
|
||||||
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
|
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
|
||||||
float NoV = clamp(m_Params.NdotV, 0.0, 1.0);
|
vec3 specularIrradiance = textureLod(
|
||||||
vec3 R = 2.0 * dot(m_Params.View, m_Params.Normal) * m_Params.Normal - m_Params.View;
|
u_EnvRadianceTex,
|
||||||
vec3 specularIrradiance = textureLod(u_EnvRadianceTex, RotateVectorAboutY(u_EnvMapRotation, Lr), (m_Params.Roughness) * u_EnvRadianceTexLevels).rgb;
|
RotateVectorAboutY(u_EnvMapRotation, Lr),
|
||||||
|
m_Params.Roughness * u_EnvRadianceTexLevels
|
||||||
|
).rgb;
|
||||||
|
|
||||||
// Sample BRDF Lut, 1.0 - roughness for y-coord because texture was generated (in Sparky) for gloss model
|
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg;
|
||||||
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg;
|
vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y);
|
||||||
vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y);
|
|
||||||
|
|
||||||
return kd * diffuseIBL + specularIBL;
|
return kd * diffuseIBL + specularIBL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shadow
|
||||||
|
int selectCascade(float viewZ)
|
||||||
|
{
|
||||||
|
float depth = -viewZ;
|
||||||
|
float linearDepth = (depth - u_ShadowNear) / (u_ShadowFar - u_ShadowNear);
|
||||||
|
if (linearDepth < u_CascadeSplits.x) return 0;
|
||||||
|
if (linearDepth < u_CascadeSplits.y) return 1;
|
||||||
|
if (linearDepth < u_CascadeSplits.z) return 2;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 getLightSpaceMatrix(int cascade)
|
||||||
|
{
|
||||||
|
if (cascade == 0) return u_LightSpaceMatrix0;
|
||||||
|
else if (cascade == 1) return u_LightSpaceMatrix1;
|
||||||
|
else if (cascade == 2) return u_LightSpaceMatrix2;
|
||||||
|
else return u_LightSpaceMatrix3;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getCascadeSplit(int cascade)
|
||||||
|
{
|
||||||
|
if (cascade == 0) return u_CascadeSplits.x;
|
||||||
|
else if (cascade == 1) return u_CascadeSplits.y;
|
||||||
|
else if (cascade == 2) return u_CascadeSplits.z;
|
||||||
|
else return u_CascadeSplits.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sampleShadow(int cascade, vec2 uv, float compareDepth, float bias)
|
||||||
|
{
|
||||||
|
float depth;
|
||||||
|
if (cascade == 0) depth = texture(u_ShadowMap[0], uv).r;
|
||||||
|
else if (cascade == 1) depth = texture(u_ShadowMap[1], uv).r;
|
||||||
|
else if (cascade == 2) depth = texture(u_ShadowMap[2], uv).r;
|
||||||
|
else depth = texture(u_ShadowMap[3], uv).r;
|
||||||
|
return (compareDepth - bias) > depth ? 1.0 : 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 getTexelSize(int cascade)
|
||||||
|
{
|
||||||
|
if (cascade == 0) return 1.0 / vec2(textureSize(u_ShadowMap[0], 0));
|
||||||
|
else if (cascade == 1) return 1.0 / vec2(textureSize(u_ShadowMap[1], 0));
|
||||||
|
else if (cascade == 2) return 1.0 / vec2(textureSize(u_ShadowMap[2], 0));
|
||||||
|
else return 1.0 / vec2(textureSize(u_ShadowMap[3], 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
float pcfShadow(int cascade, vec3 projCoords, float bias)
|
||||||
|
{
|
||||||
|
vec2 texelSize = getTexelSize(cascade);
|
||||||
|
int pcfRange = clamp(int(u_ShadowSoftness), 0, 3);
|
||||||
|
float shadow = 0.0;
|
||||||
|
int samples = 0;
|
||||||
|
|
||||||
|
for (int x = -pcfRange; x <= pcfRange; ++x)
|
||||||
|
{
|
||||||
|
for (int y = -pcfRange; y <= pcfRange; ++y)
|
||||||
|
{
|
||||||
|
vec2 offset = vec2(x, y) * texelSize;
|
||||||
|
shadow += sampleShadow(cascade, projCoords.xy + offset, projCoords.z, bias);
|
||||||
|
samples++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return shadow / float(samples);
|
||||||
|
}
|
||||||
|
|
||||||
|
float calculateCSMShadow(vec3 worldPos, vec3 normal, vec3 lightDir, float viewZ)
|
||||||
|
{
|
||||||
|
int cascade = selectCascade(viewZ);
|
||||||
|
|
||||||
|
vec4 fragPosLightSpace = getLightSpaceMatrix(cascade) * vec4(worldPos, 1.0);
|
||||||
|
|
||||||
|
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||||
|
projCoords = projCoords * 0.5 + 0.5;
|
||||||
|
|
||||||
|
if (projCoords.z > 1.0 || projCoords.x < 0.0 || projCoords.x > 1.0 ||
|
||||||
|
projCoords.y < 0.0 || projCoords.y > 1.0)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
float bias = max(u_ShadowBias * (1.0 - dot(normal, lightDir)), u_ShadowBias * 0.1);
|
||||||
|
float shadow = pcfShadow(cascade, projCoords, bias);
|
||||||
|
|
||||||
|
float cascadeEdge = 0.0;
|
||||||
|
if (cascade < CSM_CASCADE_COUNT - 1)
|
||||||
|
{
|
||||||
|
float depth = -viewZ;
|
||||||
|
float linearDepth = (depth - u_ShadowNear) / (u_ShadowFar - u_ShadowNear);
|
||||||
|
float splitDist = getCascadeSplit(cascade);
|
||||||
|
float prevSplit = (cascade > 0) ? getCascadeSplit(cascade - 1) : 0.0;
|
||||||
|
float blendStart = splitDist - (splitDist - prevSplit) * 0.1;
|
||||||
|
if (linearDepth > blendStart)
|
||||||
|
{
|
||||||
|
cascadeEdge = (linearDepth - blendStart) / (splitDist - blendStart);
|
||||||
|
|
||||||
|
int nextCascade = cascade + 1;
|
||||||
|
vec4 fragPosNext = getLightSpaceMatrix(nextCascade) * vec4(worldPos, 1.0);
|
||||||
|
|
||||||
|
vec3 projCoordsNext = fragPosNext.xyz / fragPosNext.w;
|
||||||
|
projCoordsNext = projCoordsNext * 0.5 + 0.5;
|
||||||
|
|
||||||
|
if (!(projCoordsNext.z > 1.0 || projCoordsNext.x < 0.0 || projCoordsNext.x > 1.0 ||
|
||||||
|
projCoordsNext.y < 0.0 || projCoordsNext.y > 1.0))
|
||||||
|
{
|
||||||
|
float nextShadow = pcfShadow(nextCascade, projCoordsNext, bias);
|
||||||
|
shadow = mix(shadow, nextShadow, cascadeEdge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shadow * u_ShadowIntensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// Standard PBR inputs
|
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord) : 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.Metalness = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness;
|
m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
|
||||||
m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
|
m_Params.Roughness = max(m_Params.Roughness, 0.05);
|
||||||
m_Params.Roughness = max(m_Params.Roughness, 0.05); // Minimum roughness of 0.05 to keep specular highlight
|
|
||||||
|
|
||||||
// Normals (either from vertex or map)
|
// normal
|
||||||
m_Params.Normal = normalize(vs_Input.Normal);
|
m_Params.Normal = normalize(vs_Input.Normal);
|
||||||
if (u_NormalTexToggle > 0.5)
|
if (u_NormalTexToggle > 0.5)
|
||||||
{
|
{
|
||||||
m_Params.Normal = normalize(2.0 * texture(u_NormalTexture, vs_Input.TexCoord).rgb - 1.0);
|
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.Normal = normalize(vs_Input.WorldNormals * m_Params.Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition);
|
m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition);
|
||||||
m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0);
|
m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0);
|
||||||
|
|
||||||
// Specular reflection vector
|
|
||||||
vec3 Lr = 2.0 * m_Params.NdotV * m_Params.Normal - m_Params.View;
|
|
||||||
|
|
||||||
// Fresnel reflectance, metals use albedo
|
vec3 Lr = 2.0 * m_Params.NdotV * m_Params.Normal - m_Params.View;
|
||||||
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness);
|
|
||||||
|
|
||||||
vec3 lightContribution = Lighting(F0);
|
vec3 F0 = mix(Fdielectric, m_Params.Albedo.rgb, m_Params.Metalness);
|
||||||
vec3 iblContribution = IBL(F0, Lr);
|
|
||||||
|
|
||||||
color = vec4(lightContribution + iblContribution, 1.0);
|
float shadowFactor = 1.0;
|
||||||
|
if (u_ShadowEnabled > 0.5) {
|
||||||
|
float shadow = calculateCSMShadow(vs_Input.WorldPosition, m_Params.Normal, u_DirectionalLights.Direction, vs_Input.ViewZ);
|
||||||
|
shadowFactor = 1.0 - shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 lightContribution = u_DirectionalLights.Intensity > 0.0 ? Lighting(F0) * shadowFactor : vec3(0.0);
|
||||||
|
|
||||||
|
if(u_PointLightCount > 0)
|
||||||
|
{
|
||||||
|
for( int i = 0; i < u_PointLightCount; i ++) {
|
||||||
|
lightContribution += ComputePointLight(u_PointLights[i], F0, m_Params, vs_Input.WorldPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(u_SpotLightCount > 0)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < u_SpotLightCount; i ++)
|
||||||
|
{
|
||||||
|
lightContribution += ComputeSpotLight(u_SpotLights[i], 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);
|
||||||
|
|
||||||
|
o_MaterialInfo = vec4(m_Params.Metalness, m_Params.Roughness, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
// -----------------------------
|
// -----------------------------
|
||||||
// -- From Hazel Engine PBR shader --
|
// -- Based on Hazel PBR shader --
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
||||||
// Currently heavily updated.
|
// Currently heavily updated.
|
||||||
//
|
//
|
||||||
// References upon which this is based:
|
// 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)
|
// - Unreal Engine 4 PBR notes (https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf)
|
||||||
@ -19,27 +19,33 @@ layout(location = 3) in vec3 a_Binormal;
|
|||||||
layout(location = 4) in vec2 a_TexCoord;
|
layout(location = 4) in vec2 a_TexCoord;
|
||||||
|
|
||||||
uniform mat4 u_ViewProjectionMatrix;
|
uniform mat4 u_ViewProjectionMatrix;
|
||||||
|
uniform mat4 u_ViewMatrix;
|
||||||
uniform mat4 u_Transform;
|
uniform mat4 u_Transform;
|
||||||
|
|
||||||
out VertexOutput
|
out VertexOutput
|
||||||
{
|
{
|
||||||
vec3 WorldPosition;
|
vec3 WorldPosition;
|
||||||
vec3 Normal;
|
vec3 Normal;
|
||||||
vec2 TexCoord;
|
vec2 TexCoord;
|
||||||
mat3 WorldNormals;
|
mat3 WorldNormals;
|
||||||
mat3 WorldTransform;
|
mat3 WorldTransform;
|
||||||
vec3 Binormal;
|
vec3 Binormal;
|
||||||
|
vec3 ViewPosition;
|
||||||
|
float ViewZ;
|
||||||
} vs_Output;
|
} vs_Output;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vs_Output.WorldPosition = vec3(u_Transform * vec4(a_Position, 1.0));
|
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.TexCoord = vec2(a_TexCoord.x, 1.0 - a_TexCoord.y);
|
||||||
vs_Output.WorldNormals = mat3(u_Transform) * mat3(a_Tangent, a_Binormal, a_Normal);
|
vs_Output.WorldNormals = mat3(u_Transform) * mat3(a_Tangent, a_Binormal, a_Normal);
|
||||||
vs_Output.WorldTransform = mat3(u_Transform);
|
vs_Output.WorldTransform = mat3(u_Transform);
|
||||||
vs_Output.Binormal = a_Binormal;
|
vs_Output.Binormal = a_Binormal;
|
||||||
|
|
||||||
|
vs_Output.ViewPosition = vec3(u_ViewMatrix * vec4(vs_Output.WorldPosition, 1.0));
|
||||||
|
vs_Output.ViewZ = vs_Output.ViewPosition.z;
|
||||||
|
|
||||||
gl_Position = u_ViewProjectionMatrix * u_Transform * vec4(a_Position, 1.0);
|
gl_Position = u_ViewProjectionMatrix * u_Transform * vec4(a_Position, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,63 +56,110 @@ const float PI = 3.141592;
|
|||||||
const float Epsilon = 0.00001;
|
const float Epsilon = 0.00001;
|
||||||
|
|
||||||
const int LightCount = 1;
|
const int LightCount = 1;
|
||||||
|
|
||||||
// Constant normal incidence Fresnel factor for all dielectrics.
|
|
||||||
const vec3 Fdielectric = vec3(0.04);
|
const vec3 Fdielectric = vec3(0.04);
|
||||||
|
|
||||||
struct Light {
|
layout(location = 0) out vec4 color;
|
||||||
|
layout(location = 1) out vec4 o_MaterialInfo;
|
||||||
|
layout(location = 2) out vec4 o_BloomColor;
|
||||||
|
|
||||||
|
struct DirectionalLight {
|
||||||
vec3 Direction;
|
vec3 Direction;
|
||||||
vec3 Radiance;
|
vec3 Radiance;
|
||||||
float Multiplier;
|
float Intensity;
|
||||||
|
bool CastShadows;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PointLight {
|
||||||
|
vec3 Position;
|
||||||
|
vec3 Radiance;
|
||||||
|
float Intensity;
|
||||||
|
float Range;
|
||||||
|
bool CastShadows;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SpotLight {
|
||||||
|
vec3 Position;
|
||||||
|
vec3 Direction;
|
||||||
|
vec3 Radiance;
|
||||||
|
float Intensity;
|
||||||
|
float Range;
|
||||||
|
float InnerConeCos;
|
||||||
|
float OuterConeCos;
|
||||||
|
bool CastShadows;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
in VertexOutput
|
in VertexOutput
|
||||||
{
|
{
|
||||||
vec3 WorldPosition;
|
vec3 WorldPosition;
|
||||||
vec3 Normal;
|
vec3 Normal;
|
||||||
vec2 TexCoord;
|
vec2 TexCoord;
|
||||||
mat3 WorldNormals;
|
mat3 WorldNormals;
|
||||||
mat3 WorldTransform;
|
mat3 WorldTransform;
|
||||||
vec3 Binormal;
|
vec3 Binormal;
|
||||||
|
vec3 ViewPosition;
|
||||||
|
float ViewZ;
|
||||||
} vs_Input;
|
} vs_Input;
|
||||||
|
|
||||||
layout(location = 0) out vec4 color;
|
uniform DirectionalLight u_DirectionalLights;
|
||||||
|
|
||||||
|
uniform int u_PointLightCount;
|
||||||
|
uniform PointLight u_PointLights[8];
|
||||||
|
|
||||||
|
uniform int u_SpotLightCount;
|
||||||
|
uniform SpotLight u_SpotLights[8];
|
||||||
|
|
||||||
|
|
||||||
uniform Light lights;
|
|
||||||
uniform vec3 u_CameraPosition;
|
uniform vec3 u_CameraPosition;
|
||||||
|
|
||||||
// PBR texture inputs
|
// PBR
|
||||||
uniform sampler2D u_AlbedoTexture;
|
uniform sampler2D u_AlbedoTexture;
|
||||||
uniform sampler2D u_NormalTexture;
|
uniform sampler2D u_NormalTexture;
|
||||||
uniform sampler2D u_MetalnessTexture;
|
uniform sampler2D u_MetalnessTexture;
|
||||||
uniform sampler2D u_RoughnessTexture;
|
uniform sampler2D u_RoughnessTexture;
|
||||||
|
|
||||||
// Environment maps
|
// environment
|
||||||
uniform samplerCube u_EnvRadianceTex;
|
uniform samplerCube u_EnvRadianceTex;
|
||||||
uniform samplerCube u_EnvIrradianceTex;
|
uniform samplerCube u_EnvIrradianceTex;
|
||||||
|
|
||||||
// BRDF LUT
|
// BRDF LUT
|
||||||
uniform sampler2D u_BRDFLUTTexture;
|
uniform sampler2D u_BRDFLUTTexture;
|
||||||
|
|
||||||
uniform vec3 u_AlbedoColor;
|
uniform float u_IBLContribution;
|
||||||
|
uniform float u_BloomThreshold;
|
||||||
|
uniform float u_EnvMapRotation;
|
||||||
|
|
||||||
|
// baseColor
|
||||||
|
uniform vec4 u_AlbedoColor;
|
||||||
uniform float u_Metalness;
|
uniform float u_Metalness;
|
||||||
uniform float u_Roughness;
|
uniform float u_Roughness;
|
||||||
|
|
||||||
uniform float u_EnvMapRotation;
|
// textureToggle
|
||||||
|
|
||||||
// Toggles
|
|
||||||
uniform float u_RadiancePrefilter;
|
|
||||||
uniform float u_AlbedoTexToggle;
|
uniform float u_AlbedoTexToggle;
|
||||||
uniform float u_NormalTexToggle;
|
uniform float u_NormalTexToggle;
|
||||||
uniform float u_MetalnessTexToggle;
|
uniform float u_MetalnessTexToggle;
|
||||||
uniform float u_RoughnessTexToggle;
|
uniform float u_RoughnessTexToggle;
|
||||||
|
|
||||||
|
// shadow
|
||||||
|
const int CSM_CASCADE_COUNT = 4;
|
||||||
|
uniform sampler2D u_ShadowMap[4];
|
||||||
|
uniform mat4 u_LightSpaceMatrix0;
|
||||||
|
uniform mat4 u_LightSpaceMatrix1;
|
||||||
|
uniform mat4 u_LightSpaceMatrix2;
|
||||||
|
uniform mat4 u_LightSpaceMatrix3;
|
||||||
|
uniform vec4 u_CascadeSplits;
|
||||||
|
uniform float u_ShadowFar;
|
||||||
|
uniform float u_ShadowNear;
|
||||||
|
uniform float u_ShadowBias;
|
||||||
|
uniform float u_ShadowSoftness;
|
||||||
|
uniform float u_ShadowIntensity;
|
||||||
|
uniform int u_ShadowEnabled;
|
||||||
|
|
||||||
struct PBRParameters
|
struct PBRParameters
|
||||||
{
|
{
|
||||||
vec3 Albedo;
|
vec4 Albedo;
|
||||||
float Roughness;
|
float Roughness;
|
||||||
float Metalness;
|
float Metalness;
|
||||||
|
|
||||||
vec3 Normal;
|
vec3 Normal;
|
||||||
vec3 View;
|
vec3 View;
|
||||||
float NdotV;
|
float NdotV;
|
||||||
@ -114,53 +167,33 @@ struct PBRParameters
|
|||||||
|
|
||||||
PBRParameters m_Params;
|
PBRParameters m_Params;
|
||||||
|
|
||||||
// GGX/Towbridge-Reitz normal distribution function.
|
// ---------- PBR param func ----------
|
||||||
// Uses Disney's reparametrization of alpha = roughness^2
|
|
||||||
float ndfGGX(float cosLh, float roughness)
|
float ndfGGX(float cosLh, float roughness)
|
||||||
{
|
{
|
||||||
float alpha = roughness * roughness;
|
float alpha = roughness * roughness;
|
||||||
float alphaSq = alpha * alpha;
|
float alphaSq = alpha * alpha;
|
||||||
|
|
||||||
float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
|
float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
|
||||||
return alphaSq / (PI * denom * denom);
|
return alphaSq / (PI * denom * denom);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single term for separable Schlick-GGX below.
|
|
||||||
float gaSchlickG1(float cosTheta, float k)
|
|
||||||
{
|
|
||||||
return cosTheta / (cosTheta * (1.0 - k) + k);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Schlick-GGX approximation of geometric attenuation function using Smith's method.
|
|
||||||
float gaSchlickGGX(float cosLi, float NdotV, float roughness)
|
|
||||||
{
|
|
||||||
float r = roughness + 1.0;
|
|
||||||
float k = (r * r) / 8.0; // Epic suggests using this roughness remapping for analytic lights.
|
|
||||||
return gaSchlickG1(cosLi, k) * gaSchlickG1(NdotV, k);
|
|
||||||
}
|
|
||||||
|
|
||||||
float GeometrySchlickGGX(float NdotV, float roughness)
|
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||||
{
|
{
|
||||||
float r = (roughness + 1.0);
|
float r = (roughness + 1.0);
|
||||||
float k = (r*r) / 8.0;
|
float k = (r * r) / 8.0;
|
||||||
|
float nom = NdotV;
|
||||||
float nom = NdotV;
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
float denom = NdotV * (1.0 - k) + k;
|
return nom / denom;
|
||||||
|
|
||||||
return nom / denom;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
||||||
{
|
{
|
||||||
float NdotV = max(dot(N, V), 0.0);
|
float NdotV = max(dot(N, V), 0.0);
|
||||||
float NdotL = max(dot(N, L), 0.0);
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||||
|
return ggx1 * ggx2;
|
||||||
return ggx1 * ggx2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shlick's approximation of the Fresnel factor.
|
|
||||||
vec3 fresnelSchlick(vec3 F0, float cosTheta)
|
vec3 fresnelSchlick(vec3 F0, float cosTheta)
|
||||||
{
|
{
|
||||||
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
||||||
@ -168,77 +201,97 @@ vec3 fresnelSchlick(vec3 F0, float cosTheta)
|
|||||||
|
|
||||||
vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness)
|
vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness)
|
||||||
{
|
{
|
||||||
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------------
|
|
||||||
// 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.rgb;
|
||||||
|
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;
|
vec3 lightVec = light.Position - worldPos;
|
||||||
float Phi = 2 * PI * Xi.x;
|
float dist = length(lightVec);
|
||||||
float CosTheta = sqrt( (1 - Xi.y) / ( 1 + (a*a - 1) * Xi.y ) );
|
if (dist > light.Range) return vec3(0.0);
|
||||||
float SinTheta = sqrt( 1 - CosTheta * CosTheta );
|
|
||||||
vec3 H;
|
vec3 L = lightVec / dist;
|
||||||
H.x = SinTheta * cos( Phi );
|
vec3 Lradiance = light.Radiance * light.Intensity;
|
||||||
H.y = SinTheta * sin( Phi );
|
|
||||||
H.z = CosTheta;
|
// 距离衰减:通常使用平方衰减,但为避免分母为零,加一个小值
|
||||||
vec3 UpVector = abs(N.z) < 0.999 ? vec3(0,0,1) : vec3(1,0,0);
|
float attenuation = 1.0 / (dist * dist + 0.0001);
|
||||||
vec3 TangentX = normalize( cross( UpVector, N ) );
|
|
||||||
vec3 TangentY = cross( N, TangentX );
|
// 可选:范围平滑衰减
|
||||||
// Tangent to world space
|
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
|
||||||
return TangentX * H.x + TangentY * H.y + N * H.z;
|
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.rgb;
|
||||||
|
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
|
||||||
|
|
||||||
|
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
float TotalWeight = 0.0;
|
vec3 ComputeSpotLight(SpotLight light, vec3 F0, PBRParameters params, vec3 worldPos)
|
||||||
|
|
||||||
vec3 PrefilterEnvMap(float Roughness, vec3 R)
|
|
||||||
{
|
{
|
||||||
vec3 N = R;
|
vec3 lightVec = light.Position - worldPos;
|
||||||
vec3 V = R;
|
float dist = length(lightVec);
|
||||||
vec3 PrefilteredColor = vec3(0.0);
|
if (dist > light.Range) return 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 L = lightVec / dist;
|
||||||
|
vec3 Lradiance = light.Radiance * light.Intensity;
|
||||||
|
|
||||||
vec3 RotateVectorAboutY(float angle, vec3 vec)
|
// 距离衰减
|
||||||
{
|
float attenuation = 1.0 / (dist * dist + 0.0001);
|
||||||
angle = radians(angle);
|
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
|
||||||
mat3x3 rotationMatrix ={vec3(cos(angle),0.0,sin(angle)),
|
rangeFactor = rangeFactor * rangeFactor;
|
||||||
vec3(0.0,1.0,0.0),
|
attenuation *= rangeFactor;
|
||||||
vec3(-sin(angle),0.0,cos(angle))};
|
|
||||||
return rotationMatrix * vec;
|
// 角度衰减(聚光锥)
|
||||||
|
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.rgb;
|
||||||
|
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
|
||||||
|
|
||||||
|
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 Lighting(vec3 F0)
|
vec3 Lighting(vec3 F0)
|
||||||
@ -246,22 +299,20 @@ vec3 Lighting(vec3 F0)
|
|||||||
vec3 result = vec3(0.0);
|
vec3 result = vec3(0.0);
|
||||||
for(int i = 0; i < LightCount; i++)
|
for(int i = 0; i < LightCount; i++)
|
||||||
{
|
{
|
||||||
vec3 Li = -lights.Direction;
|
vec3 Li = u_DirectionalLights.Direction;
|
||||||
vec3 Lradiance = lights.Radiance * lights.Multiplier;
|
vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.Intensity;
|
||||||
vec3 Lh = normalize(Li + m_Params.View);
|
vec3 Lh = normalize(Li + m_Params.View);
|
||||||
|
|
||||||
// Calculate angles between surface normal and various light vectors.
|
|
||||||
float cosLi = max(0.0, dot(m_Params.Normal, Li));
|
float cosLi = max(0.0, dot(m_Params.Normal, Li));
|
||||||
float cosLh = max(0.0, dot(m_Params.Normal, Lh));
|
float cosLh = max(0.0, dot(m_Params.Normal, Lh));
|
||||||
|
|
||||||
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, m_Params.View)));
|
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, m_Params.View)));
|
||||||
float D = ndfGGX(cosLh, m_Params.Roughness);
|
float D = ndfGGX(cosLh, m_Params.Roughness);
|
||||||
float G = gaSchlickGGX(cosLi, m_Params.NdotV, m_Params.Roughness);
|
float G = GeometrySmith(m_Params.Normal, m_Params.View, Li, m_Params.Roughness);
|
||||||
|
|
||||||
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
||||||
vec3 diffuseBRDF = kd * m_Params.Albedo;
|
vec3 diffuseBRDF = kd * m_Params.Albedo.rgb;
|
||||||
|
|
||||||
// Cook-Torrance
|
|
||||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * m_Params.NdotV);
|
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * m_Params.NdotV);
|
||||||
|
|
||||||
result += (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
|
result += (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
|
||||||
@ -269,35 +320,157 @@ vec3 Lighting(vec3 F0)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------- IBL ----------
|
||||||
|
vec3 RotateVectorAboutY(float angle, vec3 vec)
|
||||||
|
{
|
||||||
|
angle = radians(angle);
|
||||||
|
mat3 rotationMatrix = mat3(
|
||||||
|
vec3(cos(angle), 0.0, sin(angle)),
|
||||||
|
vec3(0.0, 1.0, 0.0),
|
||||||
|
vec3(-sin(angle), 0.0, cos(angle))
|
||||||
|
);
|
||||||
|
return rotationMatrix * vec;
|
||||||
|
}
|
||||||
|
|
||||||
vec3 IBL(vec3 F0, vec3 Lr)
|
vec3 IBL(vec3 F0, vec3 Lr)
|
||||||
{
|
{
|
||||||
vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb;
|
vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb;
|
||||||
vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness);
|
vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness);
|
||||||
// vec3 F = fresnelSchlickR(F0, m_Params.NdotV);
|
|
||||||
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
||||||
vec3 diffuseIBL = m_Params.Albedo * irradiance;
|
vec3 diffuseIBL = m_Params.Albedo.rgb * irradiance;
|
||||||
|
|
||||||
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
|
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
|
||||||
float NoV = clamp(m_Params.NdotV, 0.0, 1.0);
|
vec3 specularIrradiance = textureLod(
|
||||||
vec3 R = 2.0 * dot(m_Params.View, m_Params.Normal) * m_Params.Normal - m_Params.View;
|
u_EnvRadianceTex,
|
||||||
vec3 specularIrradiance = textureLod(u_EnvRadianceTex, RotateVectorAboutY(u_EnvMapRotation, Lr), (m_Params.Roughness) * u_EnvRadianceTexLevels).rgb;
|
RotateVectorAboutY(u_EnvMapRotation, Lr),
|
||||||
|
m_Params.Roughness * u_EnvRadianceTexLevels
|
||||||
|
).rgb;
|
||||||
|
|
||||||
// Sample BRDF Lut, 1.0 - roughness for y-coord because texture was generated (in Sparky) for gloss model
|
|
||||||
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg;
|
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg;
|
||||||
vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y);
|
vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y);
|
||||||
|
|
||||||
return kd * diffuseIBL + specularIBL;
|
return kd * diffuseIBL + specularIBL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shadow
|
||||||
|
int selectCascade(float viewZ)
|
||||||
|
{
|
||||||
|
float depth = -viewZ;
|
||||||
|
float linearDepth = (depth - u_ShadowNear) / (u_ShadowFar - u_ShadowNear);
|
||||||
|
if (linearDepth < u_CascadeSplits.x) return 0;
|
||||||
|
if (linearDepth < u_CascadeSplits.y) return 1;
|
||||||
|
if (linearDepth < u_CascadeSplits.z) return 2;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 getLightSpaceMatrix(int cascade)
|
||||||
|
{
|
||||||
|
if (cascade == 0) return u_LightSpaceMatrix0;
|
||||||
|
else if (cascade == 1) return u_LightSpaceMatrix1;
|
||||||
|
else if (cascade == 2) return u_LightSpaceMatrix2;
|
||||||
|
else return u_LightSpaceMatrix3;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getCascadeSplit(int cascade)
|
||||||
|
{
|
||||||
|
if (cascade == 0) return u_CascadeSplits.x;
|
||||||
|
else if (cascade == 1) return u_CascadeSplits.y;
|
||||||
|
else if (cascade == 2) return u_CascadeSplits.z;
|
||||||
|
else return u_CascadeSplits.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sampleShadow(int cascade, vec2 uv, float compareDepth, float bias)
|
||||||
|
{
|
||||||
|
float depth;
|
||||||
|
if (cascade == 0) depth = texture(u_ShadowMap[0], uv).r;
|
||||||
|
else if (cascade == 1) depth = texture(u_ShadowMap[1], uv).r;
|
||||||
|
else if (cascade == 2) depth = texture(u_ShadowMap[2], uv).r;
|
||||||
|
else depth = texture(u_ShadowMap[3], uv).r;
|
||||||
|
return (compareDepth - bias) > depth ? 1.0 : 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 getTexelSize(int cascade)
|
||||||
|
{
|
||||||
|
if (cascade == 0) return 1.0 / vec2(textureSize(u_ShadowMap[0], 0));
|
||||||
|
else if (cascade == 1) return 1.0 / vec2(textureSize(u_ShadowMap[1], 0));
|
||||||
|
else if (cascade == 2) return 1.0 / vec2(textureSize(u_ShadowMap[2], 0));
|
||||||
|
else return 1.0 / vec2(textureSize(u_ShadowMap[3], 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
float pcfShadow(int cascade, vec3 projCoords, float bias)
|
||||||
|
{
|
||||||
|
vec2 texelSize = getTexelSize(cascade);
|
||||||
|
int pcfRange = clamp(int(u_ShadowSoftness), 0, 3);
|
||||||
|
float shadow = 0.0;
|
||||||
|
int samples = 0;
|
||||||
|
|
||||||
|
for (int x = -pcfRange; x <= pcfRange; ++x)
|
||||||
|
{
|
||||||
|
for (int y = -pcfRange; y <= pcfRange; ++y)
|
||||||
|
{
|
||||||
|
vec2 offset = vec2(x, y) * texelSize;
|
||||||
|
shadow += sampleShadow(cascade, projCoords.xy + offset, projCoords.z, bias);
|
||||||
|
samples++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return shadow / float(samples);
|
||||||
|
}
|
||||||
|
|
||||||
|
float calculateCSMShadow(vec3 worldPos, vec3 normal, vec3 lightDir, float viewZ)
|
||||||
|
{
|
||||||
|
int cascade = selectCascade(viewZ);
|
||||||
|
|
||||||
|
vec4 fragPosLightSpace = getLightSpaceMatrix(cascade) * vec4(worldPos, 1.0);
|
||||||
|
|
||||||
|
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||||
|
projCoords = projCoords * 0.5 + 0.5;
|
||||||
|
|
||||||
|
if (projCoords.z > 1.0 || projCoords.x < 0.0 || projCoords.x > 1.0 ||
|
||||||
|
projCoords.y < 0.0 || projCoords.y > 1.0)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
float bias = max(u_ShadowBias * (1.0 - dot(normal, lightDir)), u_ShadowBias * 0.1);
|
||||||
|
float shadow = pcfShadow(cascade, projCoords, bias);
|
||||||
|
|
||||||
|
float cascadeEdge = 0.0;
|
||||||
|
if (cascade < CSM_CASCADE_COUNT - 1)
|
||||||
|
{
|
||||||
|
float depth = -viewZ;
|
||||||
|
float linearDepth = (depth - u_ShadowNear) / (u_ShadowFar - u_ShadowNear);
|
||||||
|
float splitDist = getCascadeSplit(cascade);
|
||||||
|
float prevSplit = (cascade > 0) ? getCascadeSplit(cascade - 1) : 0.0;
|
||||||
|
float blendStart = splitDist - (splitDist - prevSplit) * 0.1;
|
||||||
|
if (linearDepth > blendStart)
|
||||||
|
{
|
||||||
|
cascadeEdge = (linearDepth - blendStart) / (splitDist - blendStart);
|
||||||
|
|
||||||
|
int nextCascade = cascade + 1;
|
||||||
|
vec4 fragPosNext = getLightSpaceMatrix(nextCascade) * vec4(worldPos, 1.0);
|
||||||
|
|
||||||
|
vec3 projCoordsNext = fragPosNext.xyz / fragPosNext.w;
|
||||||
|
projCoordsNext = projCoordsNext * 0.5 + 0.5;
|
||||||
|
|
||||||
|
if (!(projCoordsNext.z > 1.0 || projCoordsNext.x < 0.0 || projCoordsNext.x > 1.0 ||
|
||||||
|
projCoordsNext.y < 0.0 || projCoordsNext.y > 1.0))
|
||||||
|
{
|
||||||
|
float nextShadow = pcfShadow(nextCascade, projCoordsNext, bias);
|
||||||
|
shadow = mix(shadow, nextShadow, cascadeEdge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shadow * u_ShadowIntensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// Standard PBR inputs
|
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord) : 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.Metalness = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness;
|
||||||
m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
|
m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
|
||||||
m_Params.Roughness = max(m_Params.Roughness, 0.05); // Minimum roughness of 0.05 to keep specular highlight
|
m_Params.Roughness = max(m_Params.Roughness, 0.05);
|
||||||
|
|
||||||
// Normals (either from vertex or map)
|
// normal
|
||||||
m_Params.Normal = normalize(vs_Input.Normal);
|
m_Params.Normal = normalize(vs_Input.Normal);
|
||||||
if (u_NormalTexToggle > 0.5)
|
if (u_NormalTexToggle > 0.5)
|
||||||
{
|
{
|
||||||
@ -307,16 +480,45 @@ void main()
|
|||||||
|
|
||||||
m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition);
|
m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition);
|
||||||
m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0);
|
m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0);
|
||||||
|
|
||||||
// Specular reflection vector
|
|
||||||
vec3 Lr = 2.0 * m_Params.NdotV * m_Params.Normal - m_Params.View;
|
vec3 Lr = 2.0 * m_Params.NdotV * m_Params.Normal - m_Params.View;
|
||||||
|
|
||||||
// Fresnel reflectance, metals use albedo
|
vec3 F0 = mix(Fdielectric, m_Params.Albedo.rgb, m_Params.Metalness);
|
||||||
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness);
|
|
||||||
|
// Shadow
|
||||||
|
float shadowFactor = 1.0;
|
||||||
|
if (u_ShadowEnabled > 0.5) {
|
||||||
|
float shadow = calculateCSMShadow(vs_Input.WorldPosition, m_Params.Normal, u_DirectionalLights.Direction, vs_Input.ViewZ);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
for( int i = 0; i < u_PointLightCount; i ++) {
|
||||||
|
lightContribution += ComputePointLight(u_PointLights[i], F0, m_Params, vs_Input.WorldPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(u_SpotLightCount > 0)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < u_SpotLightCount; i ++)
|
||||||
|
{
|
||||||
|
lightContribution += ComputeSpotLight(u_SpotLights[i], F0, m_Params, vs_Input.WorldPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;
|
||||||
|
|
||||||
vec3 lightContribution = Lighting(F0);
|
|
||||||
vec3 iblContribution = IBL(F0, Lr);
|
|
||||||
|
|
||||||
color = vec4(lightContribution + iblContribution, 1.0);
|
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);
|
||||||
|
|
||||||
|
o_MaterialInfo = vec4(m_Params.Metalness, m_Params.Roughness, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
159
Editor/assets/shaders/PreethamSky.glsl
Normal 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);
|
||||||
|
}
|
||||||
@ -6,14 +6,14 @@
|
|||||||
layout(location = 0) in vec3 a_Position;
|
layout(location = 0) in vec3 a_Position;
|
||||||
layout(location = 1) in vec4 a_Color;
|
layout(location = 1) in vec4 a_Color;
|
||||||
layout(location = 2) in vec2 a_TexCoord;
|
layout(location = 2) in vec2 a_TexCoord;
|
||||||
layout(location = 3) in float a_TexIndex;
|
layout(location = 3) in int a_TexIndex;
|
||||||
layout(location = 4) in float a_TilingFactor;
|
layout(location = 4) in float a_TilingFactor;
|
||||||
|
|
||||||
uniform mat4 u_ViewProjection;
|
uniform mat4 u_ViewProjection;
|
||||||
|
|
||||||
out vec4 v_Color;
|
out vec4 v_Color;
|
||||||
out vec2 v_TexCoord;
|
out vec2 v_TexCoord;
|
||||||
out float v_TexIndex;
|
flat out int v_TexIndex;
|
||||||
out float v_TilingFactor;
|
out float v_TilingFactor;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
@ -32,12 +32,17 @@ layout(location = 0) out vec4 color;
|
|||||||
|
|
||||||
in vec4 v_Color;
|
in vec4 v_Color;
|
||||||
in vec2 v_TexCoord;
|
in vec2 v_TexCoord;
|
||||||
in float v_TexIndex;
|
flat in int v_TexIndex;
|
||||||
in float v_TilingFactor;
|
in float v_TilingFactor;
|
||||||
|
|
||||||
uniform sampler2D u_Textures[32];
|
uniform sampler2D u_Textures[32];
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
color = texture(u_Textures[int(v_TexIndex)], v_TexCoord * v_TilingFactor) * v_Color;
|
vec4 texColor = texture(u_Textures[v_TexIndex], v_TexCoord * v_TilingFactor) * v_Color;
|
||||||
|
|
||||||
|
if(texColor.a < 0.1)
|
||||||
|
discard;
|
||||||
|
|
||||||
|
color = texColor;
|
||||||
}
|
}
|
||||||
|
|||||||
44
Editor/assets/shaders/Renderer2D_Circle.glsl
Normal 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;
|
||||||
|
}
|
||||||
207
Editor/assets/shaders/SSR.glsl
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
#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_ColorTexture;
|
||||||
|
uniform sampler2D u_DepthTexture;
|
||||||
|
uniform sampler2D u_MaterialInfoTexture;
|
||||||
|
|
||||||
|
uniform mat4 u_Projection;
|
||||||
|
uniform mat4 u_InvProjection;
|
||||||
|
|
||||||
|
uniform vec2 u_ScreenSize;
|
||||||
|
uniform float u_CameraNear;
|
||||||
|
uniform float u_CameraFar;
|
||||||
|
|
||||||
|
uniform int u_Steps = 64;
|
||||||
|
uniform float u_Thickness = 0.5;
|
||||||
|
uniform float u_MaxDistance = 30.0;
|
||||||
|
uniform float u_Intensity = 1.0;
|
||||||
|
|
||||||
|
float LinearizeDepth(float depth)
|
||||||
|
{
|
||||||
|
float z = depth * 2.0 - 1.0;
|
||||||
|
return (2.0 * u_CameraNear * u_CameraFar) / (u_CameraFar + u_CameraNear - z * (u_CameraFar - u_CameraNear));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ReconstructViewPos(vec2 tc, float depth)
|
||||||
|
{
|
||||||
|
float z = depth * 2.0 - 1.0;
|
||||||
|
vec4 clipPos = vec4(tc * 2.0 - 1.0, z, 1.0);
|
||||||
|
vec4 viewPos4 = u_InvProjection * clipPos;
|
||||||
|
return viewPos4.xyz / viewPos4.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ReconstructNormalFromDepth(vec2 tc, float depth)
|
||||||
|
{
|
||||||
|
vec2 texelSize = 1.0 / u_ScreenSize;
|
||||||
|
|
||||||
|
vec2 tcL = tc - vec2(texelSize.x, 0.0);
|
||||||
|
vec2 tcR = tc + vec2(texelSize.x, 0.0);
|
||||||
|
vec2 tcB = tc - vec2(0.0, texelSize.y);
|
||||||
|
vec2 tcT = tc + vec2(0.0, texelSize.y);
|
||||||
|
|
||||||
|
float depthL = texture(u_DepthTexture, tcL).r;
|
||||||
|
float depthR = texture(u_DepthTexture, tcR).r;
|
||||||
|
float depthB = texture(u_DepthTexture, tcB).r;
|
||||||
|
float depthT = texture(u_DepthTexture, tcT).r;
|
||||||
|
|
||||||
|
vec3 pL = ReconstructViewPos(tcL, depthL);
|
||||||
|
vec3 pR = ReconstructViewPos(tcR, depthR);
|
||||||
|
vec3 pB = ReconstructViewPos(tcB, depthB);
|
||||||
|
vec3 pT = ReconstructViewPos(tcT, depthT);
|
||||||
|
|
||||||
|
vec3 dx = pR - pL;
|
||||||
|
vec3 dy = pT - pB;
|
||||||
|
|
||||||
|
return normalize(cross(dx, dy));
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float depth = texture(u_DepthTexture, v_TexCoord).r;
|
||||||
|
|
||||||
|
if (depth >= 1.0)
|
||||||
|
{
|
||||||
|
o_Color = vec4(0.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 matInfo = texture(u_MaterialInfoTexture, v_TexCoord);
|
||||||
|
float metalness = matInfo.r;
|
||||||
|
float roughness = matInfo.g;
|
||||||
|
|
||||||
|
if (roughness > 0.9)
|
||||||
|
{
|
||||||
|
o_Color = vec4(0.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 viewPos = ReconstructViewPos(v_TexCoord, depth);
|
||||||
|
vec3 normal = ReconstructNormalFromDepth(v_TexCoord, depth);
|
||||||
|
|
||||||
|
vec3 viewDir = normalize(-viewPos);
|
||||||
|
float NdotV = max(dot(normal, viewDir), 0.0);
|
||||||
|
|
||||||
|
vec3 reflectDir = reflect(-viewDir, normal);
|
||||||
|
|
||||||
|
if (dot(reflectDir, normal) < 0.0)
|
||||||
|
{
|
||||||
|
o_Color = vec4(0.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 rayOrigin = viewPos + normal * 0.02;
|
||||||
|
vec3 rayEnd = rayOrigin + reflectDir * u_MaxDistance;
|
||||||
|
|
||||||
|
vec4 p0 = u_Projection * vec4(rayOrigin, 1.0);
|
||||||
|
vec4 p1 = u_Projection * vec4(rayEnd, 1.0);
|
||||||
|
|
||||||
|
float k0 = 1.0 / p0.w;
|
||||||
|
float k1 = 1.0 / p1.w;
|
||||||
|
|
||||||
|
p0.xyz *= k0;
|
||||||
|
p1.xyz *= k1;
|
||||||
|
|
||||||
|
vec3 v0 = rayOrigin * k0;
|
||||||
|
vec3 v1 = rayEnd * k1;
|
||||||
|
|
||||||
|
vec2 s0 = p0.xy * 0.5 + 0.5;
|
||||||
|
vec2 s1 = p1.xy * 0.5 + 0.5;
|
||||||
|
|
||||||
|
vec2 sDelta = s1 - s0;
|
||||||
|
float screenDist = length(sDelta * u_ScreenSize);
|
||||||
|
|
||||||
|
if (screenDist < 1.0)
|
||||||
|
{
|
||||||
|
o_Color = vec4(0.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float divisions = min(screenDist, float(u_Steps));
|
||||||
|
vec3 dV = (v1 - v0) / divisions;
|
||||||
|
float dK = (k1 - k0) / divisions;
|
||||||
|
vec2 dS = sDelta / divisions;
|
||||||
|
|
||||||
|
vec3 curV = v0;
|
||||||
|
float curK = k0;
|
||||||
|
vec2 curS = s0;
|
||||||
|
|
||||||
|
vec2 hitUV = vec2(0.0);
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < int(divisions); i++)
|
||||||
|
{
|
||||||
|
curV += dV;
|
||||||
|
curK += dK;
|
||||||
|
curS += dS;
|
||||||
|
|
||||||
|
if (curS.x < 0.0 || curS.x > 1.0 || curS.y < 0.0 || curS.y > 1.0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
float sampleDepth = texture(u_DepthTexture, curS).r;
|
||||||
|
float surfDepth = LinearizeDepth(sampleDepth);
|
||||||
|
float rayDepth = -curV.z / curK;
|
||||||
|
|
||||||
|
float depthDiff = rayDepth - surfDepth;
|
||||||
|
|
||||||
|
if (depthDiff > 0.0 && depthDiff < u_Thickness)
|
||||||
|
{
|
||||||
|
hitUV = curS;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
o_Color = vec4(0.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 hitNormal = ReconstructNormalFromDepth(hitUV, texture(u_DepthTexture, hitUV).r);
|
||||||
|
if (dot(hitNormal, -reflectDir) < 0.0)
|
||||||
|
{
|
||||||
|
o_Color = vec4(0.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 reflectColor = texture(u_ColorTexture, hitUV).rgb;
|
||||||
|
|
||||||
|
float dist = distance(viewPos, ReconstructViewPos(hitUV, texture(u_DepthTexture, hitUV).r));
|
||||||
|
float fadeFactor = 1.0 - smoothstep(u_MaxDistance * 0.5, u_MaxDistance, dist);
|
||||||
|
|
||||||
|
float edgeFade = 1.0;
|
||||||
|
edgeFade *= smoothstep(0.0, 0.15, hitUV.x);
|
||||||
|
edgeFade *= smoothstep(0.0, 0.15, hitUV.y);
|
||||||
|
edgeFade *= smoothstep(0.0, 0.15, 1.0 - hitUV.x);
|
||||||
|
edgeFade *= smoothstep(0.0, 0.15, 1.0 - hitUV.y);
|
||||||
|
|
||||||
|
vec3 F0 = mix(vec3(0.04), reflectColor, metalness);
|
||||||
|
vec3 Fresnel = F0 + (1.0 - F0) * pow(1.0 - NdotV, 5.0);
|
||||||
|
|
||||||
|
float roughnessFade = 1.0 - roughness * roughness;
|
||||||
|
|
||||||
|
vec3 ssrContrib = reflectColor * Fresnel * fadeFactor * edgeFade * roughnessFade * u_Intensity;
|
||||||
|
float ssrAlpha = length(Fresnel) * fadeFactor * edgeFade * roughnessFade;
|
||||||
|
|
||||||
|
o_Color = vec4(ssrContrib, ssrAlpha);
|
||||||
|
}
|
||||||
85
Editor/assets/shaders/SSRBlur.glsl
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#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_SSRTexture;
|
||||||
|
uniform sampler2D u_DepthTexture;
|
||||||
|
uniform sampler2D u_MaterialInfoTexture;
|
||||||
|
|
||||||
|
uniform vec2 u_ScreenSize;
|
||||||
|
uniform float u_BlurRadius = 4.0;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 texelSize = 1.0 / u_ScreenSize;
|
||||||
|
|
||||||
|
vec4 center = texture(u_SSRTexture, v_TexCoord);
|
||||||
|
if (center.a <= 0.001)
|
||||||
|
{
|
||||||
|
o_Color = vec4(0.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float roughness = texture(u_MaterialInfoTexture, v_TexCoord).g;
|
||||||
|
float effectiveBlurRadius = max(u_BlurRadius * roughness * roughness, 1.0);
|
||||||
|
|
||||||
|
float centerDepth = texture(u_DepthTexture, v_TexCoord).r;
|
||||||
|
vec3 result = vec3(0.0);
|
||||||
|
float totalWeight = 0.0;
|
||||||
|
|
||||||
|
const int kRadius = 6;
|
||||||
|
float sigma = effectiveBlurRadius * 0.5;
|
||||||
|
|
||||||
|
for (int x = -kRadius; x <= kRadius; x++)
|
||||||
|
{
|
||||||
|
for (int y = -kRadius; y <= kRadius; y++)
|
||||||
|
{
|
||||||
|
vec2 offset = vec2(float(x), float(y)) * texelSize * effectiveBlurRadius / float(kRadius);
|
||||||
|
vec2 sampleUV = v_TexCoord + offset;
|
||||||
|
|
||||||
|
if (sampleUV.x < 0.0 || sampleUV.x > 1.0 || sampleUV.y < 0.0 || sampleUV.y > 1.0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float sampleDepth = texture(u_DepthTexture, sampleUV).r;
|
||||||
|
float depthDiff = abs(centerDepth - sampleDepth);
|
||||||
|
|
||||||
|
float depthWeight = exp(-depthDiff * 200.0);
|
||||||
|
|
||||||
|
float spatialWeight = exp(-(float(x * x + y * y)) / (2.0 * sigma * sigma));
|
||||||
|
|
||||||
|
vec4 sampleColor = texture(u_SSRTexture, sampleUV);
|
||||||
|
|
||||||
|
float alphaWeight = sampleColor.a > 0.01 ? 1.0 : 0.0;
|
||||||
|
|
||||||
|
float weight = spatialWeight * depthWeight * alphaWeight;
|
||||||
|
|
||||||
|
result += sampleColor.rgb * weight;
|
||||||
|
totalWeight += weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalWeight > 0.0)
|
||||||
|
result /= totalWeight;
|
||||||
|
else
|
||||||
|
result = center.rgb;
|
||||||
|
|
||||||
|
o_Color = vec4(result, center.a);
|
||||||
|
}
|
||||||
@ -17,20 +17,68 @@ void main()
|
|||||||
#version 430
|
#version 430
|
||||||
|
|
||||||
layout(location = 0) out vec4 o_Color;
|
layout(location = 0) out vec4 o_Color;
|
||||||
|
layout(location = 1) out vec4 o_BloomTexture;
|
||||||
|
|
||||||
in vec2 v_TexCoord;
|
in vec2 v_TexCoord;
|
||||||
|
|
||||||
uniform sampler2DMS u_Texture;
|
uniform sampler2DMS u_Texture;
|
||||||
uniform float u_Exposure;
|
uniform sampler2DMS u_DepthTexture;
|
||||||
|
uniform sampler2D u_BloomTexture;
|
||||||
|
|
||||||
|
uniform mat4 u_InvProjection;
|
||||||
|
uniform mat4 u_InvView;
|
||||||
|
|
||||||
|
// Fog
|
||||||
|
uniform float u_FogEnabled;
|
||||||
|
uniform vec3 u_FogColor;
|
||||||
|
uniform float u_FogDensity; // 雾密度,典型值 0.01~0.05
|
||||||
|
uniform float u_FogHeight; // 雾的起始高度(世界 Y 坐标),低于此高度雾最浓
|
||||||
|
uniform float u_FogHeightFalloff; // 高度衰减系数,值越大高度影响越剧烈(典型 0.5~2.0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uniform bool u_EnableAutoExposure;
|
||||||
|
uniform float u_ManualExposure;
|
||||||
|
layout(std430, binding = 2) buffer Exposure
|
||||||
|
{
|
||||||
|
float u_Exposure;
|
||||||
|
};
|
||||||
|
|
||||||
uniform int u_TextureSamples;
|
uniform int u_TextureSamples;
|
||||||
|
|
||||||
vec4 MultiSampleTexture(sampler2DMS tex, ivec2 texCoord, int samples)
|
uniform bool u_EnableBloom;
|
||||||
|
uniform float u_BloomThreshold;
|
||||||
|
|
||||||
|
uniform bool u_EnableSSR;
|
||||||
|
uniform sampler2D u_SSRTexture;
|
||||||
|
|
||||||
|
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);
|
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 += 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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,10 +87,30 @@ void main()
|
|||||||
const float gamma = 2.2;
|
const float gamma = 2.2;
|
||||||
const float pureWhite = 1.0;
|
const float pureWhite = 1.0;
|
||||||
|
|
||||||
ivec2 texSize = textureSize(u_Texture);
|
// Tonemapping
|
||||||
ivec2 texCoord = ivec2(v_TexCoord * texSize);
|
vec4 msColor = MultiSampleTexture(u_Texture, v_TexCoord);
|
||||||
vec4 msColor = MultiSampleTexture(u_Texture, texCoord, u_TextureSamples);
|
vec3 color = msColor.rgb;
|
||||||
vec3 color = msColor.rgb * u_Exposure;//texture(u_Texture, v_TexCoord).rgb * u_Exposure;
|
|
||||||
|
if (u_EnableBloom)
|
||||||
|
{
|
||||||
|
vec3 bloomColor = texture(u_BloomTexture, v_TexCoord).rgb;
|
||||||
|
color += bloomColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u_EnableSSR)
|
||||||
|
{
|
||||||
|
vec4 ssrSample = texture(u_SSRTexture, v_TexCoord);
|
||||||
|
color += ssrSample.rgb * ssrSample.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float exposure = 1.0f;
|
||||||
|
if(u_EnableAutoExposure)
|
||||||
|
exposure = u_Exposure;
|
||||||
|
else
|
||||||
|
exposure = u_ManualExposure;
|
||||||
|
color *= exposure;
|
||||||
|
|
||||||
|
|
||||||
// Reinhard tonemapping operator.
|
// Reinhard tonemapping operator.
|
||||||
// see: "Photographic Tone Reproduction for Digital Images", eq. 4
|
// see: "Photographic Tone Reproduction for Digital Images", eq. 4
|
||||||
@ -52,6 +120,53 @@ void main()
|
|||||||
// Scale color by ratio of average luminances.
|
// Scale color by ratio of average luminances.
|
||||||
vec3 mappedColor = (mappedLuminance / luminance) * color;
|
vec3 mappedColor = (mappedLuminance / luminance) * color;
|
||||||
|
|
||||||
|
if (u_FogEnabled > 0.5)
|
||||||
|
{
|
||||||
|
// 1. 获取深度并重建视空间坐标
|
||||||
|
float depth = MultiSampleDepth(u_DepthTexture, v_TexCoord);
|
||||||
|
vec4 clipPos = vec4(v_TexCoord * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
||||||
|
vec4 viewPos4 = u_InvProjection * clipPos;
|
||||||
|
viewPos4 /= viewPos4.w;
|
||||||
|
vec3 viewPos = viewPos4.xyz; // 视空间坐标(相机为原点,Z 轴向内)
|
||||||
|
|
||||||
|
// 2. 距离雾因子(指数雾)
|
||||||
|
float distance = length(viewPos);
|
||||||
|
float distanceFactor = 1.0 - exp(-distance * u_FogDensity);
|
||||||
|
// 可选:指数平方雾(更平滑)
|
||||||
|
// float distanceFactor = 1.0 - exp(-pow(distance * u_FogDensity, 2.0));
|
||||||
|
|
||||||
|
// 3. 高度雾因子(基于世界 Y)
|
||||||
|
// 将视空间坐标转换到世界空间
|
||||||
|
vec4 worldPos4 = u_InvView* vec4(viewPos, 1.0);
|
||||||
|
vec3 worldPos = worldPos4.xyz / worldPos4.w;
|
||||||
|
float worldY = worldPos.y;
|
||||||
|
|
||||||
|
float heightFactor = 0.0;
|
||||||
|
if (worldY < u_FogHeight)
|
||||||
|
{
|
||||||
|
// 低于起始高度:雾最浓,因子为 1
|
||||||
|
heightFactor = 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 高于起始高度:指数衰减,高度越高雾越淡
|
||||||
|
float deltaY = worldY - u_FogHeight;
|
||||||
|
heightFactor = exp(-deltaY * u_FogHeightFalloff);
|
||||||
|
}
|
||||||
|
// 可选:使用 clamp 限制范围
|
||||||
|
heightFactor = clamp(heightFactor, 0.0, 1.0);
|
||||||
|
|
||||||
|
// 4. 综合雾因子(可相乘,也可取最大值,通常相乘)
|
||||||
|
float fogFactor = distanceFactor * heightFactor;
|
||||||
|
|
||||||
|
// 5. 混合雾颜色(雾颜色直接使用 u_FogColor,已在 LDR 空间)
|
||||||
|
mappedColor = mix(mappedColor, u_FogColor, fogFactor);
|
||||||
|
}
|
||||||
|
|
||||||
// Gamma correction.
|
// Gamma correction.
|
||||||
o_Color = vec4(pow(mappedColor, vec3(1.0 / gamma)), 1.0);
|
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);
|
||||||
|
}
|
||||||
|
|||||||
23
Editor/assets/shaders/ShadowMap.glsl
Normal 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()
|
||||||
|
{
|
||||||
|
}
|
||||||
35
Editor/assets/shaders/ShadowMap_Anim.glsl
Normal 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()
|
||||||
|
{
|
||||||
|
}
|
||||||
@ -24,10 +24,13 @@ layout(location = 0) out vec4 finalColor;
|
|||||||
|
|
||||||
uniform samplerCube u_Texture;
|
uniform samplerCube u_Texture;
|
||||||
uniform float u_TextureLod;
|
uniform float u_TextureLod;
|
||||||
|
uniform float u_SkyIntensity;
|
||||||
|
|
||||||
in vec3 v_Position;
|
in vec3 v_Position;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
finalColor = textureLod(u_Texture, v_Position, u_TextureLod);
|
vec3 color = textureLod(u_Texture, v_Position, u_TextureLod).rgb * u_SkyIntensity;
|
||||||
|
finalColor = vec4(color, 1.0);
|
||||||
|
|
||||||
}
|
}
|
||||||
108
Editor/imgui.ini
Normal 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
|
||||||
|
|
||||||